A batch calls a list of people rather than one. It is an agent, one of your outbound-capable numbers, a list of recipients and a schedule — and it is the most expensive operation on this platform, because a single request to it can place thousands of billable calls. It is also the only way to schedule a call for later. A single call at a future time is a one-row batch.
Two things to know before you create one, because discovering either from an invoice is the version nobody forgives.
  • Answering machines are not detected. A call that reaches voicemail is answered, billed, and reported as completed — and, being completed, is never retried. There is no answering-machine detection anywhere on the platform.
  • Every call runs your agent’s current published version. Republishing mid-campaign changes every call placed after that moment, including the remainder of a batch that has been running for an hour.

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

Validation is all-or-nothing and reports every bad row at once, not the first: an unparseable number, a number that appears twice in the payload, a reserved 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.
Batch-level 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:0006: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:0018: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 as last_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 to failed 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.
The batch stays 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.
A creator who leaves the workspace, or is demoted below the editor role, stops their own batch. The next pass records a configuration failure naming them, and ten of those in a row trip the breaker. Before someone leaves, hand their running campaigns over by re-creating them under an account that will still be there.

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.