Policy and the recipient list
A batch is two things, and keeping them apart explains most of its behaviour.
A policy change never revisits anyone already called, and calls already in
flight finish under the policy they were dispatched with.
Creating one
userdata key. Numbers are normalized against the region of the number you are
dialling from, the same rule as a single outbound
call.
Personalization is userdata
Each recipient carries to plus a flat map of strings that becomes that call’s
session state. {{userdata.first_name}} in the agent’s prompt or greeting is
that person’s name.
Values are strings on purpose: substitution is textual, and a spreadsheet cell
reading 007 is a reference number, not the integer seven. An empty value is
dropped rather than stored, so {{userdata.first_name}} on a row with no name
resolves to nothing and the greeting still reads as written.
There are no per-recipient overrides of anything else. One batch is one
agent, one number, one clock. If half your list needs a different agent, that is
two batches.
vars exists too — one bag copied onto every call the campaign
places, for configuring the session rather than describing the person. It is
fixed at create; PATCH cannot change it.
Scheduling
A window may cross midnight, and the days then name the evening it starts
on:
21:00–06:00 on days: [5] runs Friday 21:00 through Saturday 06:00.
Saturday evening is closed.
So a list uploaded at 23:00 with a 10:00–18:00 weekday window starts at
10:00 the next working morning, stops at 18:00, and resumes at 10:00 the day
after, untouched in between. next_dial_at says exactly when.
next_dial_at is null when the batch is dialling now, when a human paused it,
or when it is over — all three of which the status already tells you.
Limits and defaults
Retries, by outcome
Whether a recipient is tried again depends on how the last attempt ended. The close reason is on the recipient row aslast_close_reason, with a plain
sentence in last_close_reason_label.
A dial that could not even be placed still spends an attempt — otherwise a
permanently broken row would retry for ever.
A completed call is terminal forever. That outranks every retry rule, and it
is what guarantees nobody on your list is called twice.
The circuit breaker
A batch stops itself after ten consecutive setup-style failures. The count is rolling, not cumulative, and any success resets it to zero — so a batch that ran cleanly for 5,000 rows and then met an expired credential still stops after ten, rather than burning the other 5,000. What counts: a carrier fault, a configuration problem, a platform fault, or an ending nothing has mapped. Also the failures that happen before a recipient is even claimed — an unpublished agent, a deleted number, a carrier account that is no longer ready. What never counts: busy signals and unanswered phones. A run of those is a phone list, not a fault, and stopping the batch over it would be the breaker firing on the very thing it exists to protect. When it trips, the batch goes tofailed and failure_reason carries the last
thing that went wrong. Recipients that were never attempted read as canceled.
Running out of credit
Running out of credit stops a batch dialling. It does not fail it, it does
not move it to
paused, and it does not spend an attempt on anybody — the check
is per pass, not per recipient.running, dials nothing, and failure_reason says the
workspace is out of credits. Top up and it resumes on its own; there is no
button to press, and the reason clears on the next successful dial. This is
deliberately not a breaker case: being out of credit fixes itself with a
payment, and failing the batch permanently would mean a top-up could not undo
it.
Steering a running batch
There is no delete. A batch is the record of money spent, and cancel is the
end of the road.
Adding people to a running batch
POST /v1/calls/batches/{batch_id}/recipients appends, including to a batch
that is already dialling. The new rows are called after the existing ones.
Numbers the batch already holds are skipped and reported, not rejected — so
re-uploading a list you exported again from your CRM never calls anyone twice.
Watching it
GET /v1/calls/batches/{batch_id} carries live counts and, when something is
wrong, failure_reason.
The batch runs as the person who created it
Every dialling pass re-authorizes as the batch’s creator, exactly as an HTTP request from them would.Statuses
Batch
Recipient
A recipient of a cancelled batch reads
canceled even though its row was never
touched. A row still dialing when you cancel keeps that status: the call is
real and still on the phone.
Pinning a version instead
If you create a batch with any of the per-call configuration fields —agent_version, agent_override, an inline agent or an agent_team — that
cast is resolved and frozen when the batch is created, and a republish does
not reach it. That is the opposite of the default behaviour in the warning at
the top of this page, and it is the one way to hold a campaign steady across a
publish. Re-pointing a batch at a different agent_id with PATCH clears any
such cast and returns it to “the current published version”. See per-call
configuration.
Next
Outbound lead qualification
A campaign end to end, from CSV to results.
Call analysis
Summaries, outcomes and structured fields across a whole batch.