A batch call dials a list of numbers from one of your phone numbers. Each row becomes a call with its own dynamic variables. The scheduler places calls as concurrency allows, only inside your call time window, and stops when every row has been dialled or you stop the batch.
Use batch calls for appointment reminders, reactivation campaigns, surveys and any list where you know the numbers up front.
Create a batch in the dashboard#
Open Batch Call#
In the sidebar under Deploy, click Batch Call, then Create a batch call.
Name it and pick the number#
Enter Batch Call Name and choose From number. The hint under the field shows which agent will speak (Calls use ...), or warns This number has no outbound agent configured.
Upload recipients#
Under Recipients, drop a CSV or click Upload CSV. Click Template to download a sample file. The preview shows each column as a {{variable}}, counts valid rows, and highlights invalid numbers in red.
Choose when to send#
When to send is Send now or Schedule (pick a date and time). Set Reserved concurrency to keep slots free for other calls.
Optional limits#
Skip recipients on the do-not-call list is on by default. Turn on Call time window to only call between a start and end time, in a timezone, on selected days.
Send, schedule or save#
Click Send now or Schedule. Click Save as draft to create the batch without starting it.
CSV format#
- The first row is the header.
- The first column is the phone number. Its header name does not matter.
- Every other column becomes a dynamic variable. Header names are lower-cased and anything other than letters, digits and
_becomes_(soFirst Namebecomes{{first_name}}). - Spaces, brackets and dashes in the phone number are removed. Australian numbers written as
0412345678(10 digits starting 02, 03, 04, 07 or 08) are converted to+61412345678. - Rows whose number is not E.164 after that are skipped.
The downloadable template:
phone number,first_name,appointment_time
+61412345678,Sam,Tuesday 3pm
+61498765432,Priya,Wednesday 10amUse the variables in the agent's prompt or begin message, for example Hi {{first_name}}, I'm calling about your appointment on {{appointment_time}}.
Create a batch with the API#
POST /create-batch-call takes the recipients as tasks. CSV parsing is a dashboard feature; the API expects the rows already parsed.
curl -X POST https://api.tried.com.au/create-batch-call \
-H "Authorization: Bearer $TRIED_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "October reactivation",
"from_number": "+61255501234",
"tasks": [
{ "to_number": "+61412345678", "retell_llm_dynamic_variables": { "first_name": "Sam" } },
{ "to_number": "+61498765432", "retell_llm_dynamic_variables": { "first_name": "Priya" } }
],
"trigger_timestamp": 1792000000000,
"reserved_concurrency": 2,
"honor_internal_dnc": true,
"call_time_window": {
"windows": [{ "start": 540, "end": 1020 }],
"timezone": "Australia/Sydney",
"day": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
}
}'| Field | Type | Default | Description |
|---|---|---|---|
name |
string | "Batch call" |
Shown in the batch list. |
from_number |
string | required | A number in your workspace. |
tasks |
BatchTask[] |
required, at least 1 | One entry per recipient. |
trigger_timestamp |
number (epoch ms) | now | When the batch may start. |
reserved_concurrency |
integer, 0 or more | 0 |
Slots the batch leaves free for other calls. |
call_time_window |
object | none (any time) | Hours and days when calls may be placed. |
draft |
boolean | false |
Create without scheduling. Start it later with POST /start-batch-call/:id. |
honor_internal_dnc |
boolean | false |
Skip numbers whose contact is flagged do-not-call, checked when each task is dialled. |
BatchTask fields:
| Field | Type | Description |
|---|---|---|
to_number |
string | Destination in E.164. |
retell_llm_dynamic_variables |
object | Variables for this call. Default {}. |
metadata |
object | Stored on the call. Default {}. |
override_agent_id |
string | Use this agent for this row instead of the number's outbound agent. |
Every task needs an agent: either the number has outbound_agents, or the task has override_agent_id. Otherwise the request returns 400.
Call time window#
| Field | Type | Description |
|---|---|---|
windows |
{ start, end }[] |
Minutes after midnight, 0 to 1440. 540 to 1020 is 9:00 to 17:00. A window whose start is after its end wraps past midnight. |
timezone |
string | IANA timezone. Default Australia/Sydney. |
day |
string[] | Monday to Sunday. Omit to allow every day. |
The dashboard offers one window with these timezones: Australia/Sydney, Australia/Melbourne, Australia/Brisbane, Australia/Adelaide, Australia/Perth, Pacific/Auckland, America/New_York, America/Chicago, America/Los_Angeles, Europe/London and UTC. The API accepts several windows and any IANA name.
How the scheduler dials#
A scheduler pass runs every 5 seconds (BATCH_TICK_MS). For each batch that is planned or ongoing and whose scheduled time has passed:
- If the current time is outside
call_time_window, the batch waits. - Free capacity is the workspace concurrency limit minus
reserved_concurrencyminus calls already in progress. - Pending tasks are dialled in order, up to that capacity, through the same path as
POST /v2/create-phone-call(including the number's calls-per-second limit and allowed outbound countries). - When no pending tasks remain, the batch becomes
sent.
A task that cannot be dialled is marked failed with the error. When the credit balance runs out, the task gets a not_connected call with disconnection_reason: "no_valid_payment" so the attempt shows in Call History.
Statuses and counters#
| Status | Meaning |
|---|---|
draft |
Saved, not scheduled. Shown with a Start batch button. |
planned |
Scheduled, waiting for its time, a window or a free slot. |
ongoing |
At least one call has been placed and tasks remain. |
sent |
Every task has been dialled. |
stopped |
Stopped by you; remaining tasks were cancelled. |
The batch list shows Recipients, Sent, Picked up and Successful, with a progress bar of sent over recipients.
- Sent counts dial attempts.
- Picked up counts calls that connected. The percentage is picked up over sent.
- Successful counts calls whose post-call analysis set
call_successfulto true. The percentage is successful over picked up.
Click a row to open the drawer. View calls in Call History filters Call History to the batch. With the API, filter POST /v2/list-calls by filter_criteria.batch_call_id.
Start, stop and delete#
| Action | Dashboard | API |
|---|---|---|
| Start a draft | Start batch in the drawer | POST /start-batch-call/:id returns { batch_call_id, status }. Only drafts can be started. A past scheduled time is moved to now. |
| Stop | Stop batch, then confirm | POST /stop-batch-call/:id cancels pending tasks and returns cancelled_tasks. Calls in progress finish normally. |
| Delete | Delete batch | DELETE /delete-batch-call/:id. Pending recipients are not called. Calls already placed stay in Call History, unlinked from the batch. |
| Inspect | Drawer | GET /get-batch-call/:id returns the batch and each task's status, call_id and error. GET /list-batch-calls lists all batches. |
Cost#
Batch calls are billed at the same per-minute rate as other calls, plus $0.01 for every dial attempt (batch_dial).
Limits and gotchas#
- Batch calls count against the workspace concurrency limit and leave reserved inbound slots free. See Concurrency.
- Reserved concurrency in the dashboard accepts 0 to 50.
- The call time window is evaluated in the window's timezone, not each recipient's own timezone. Split a list by region if recipients span timezones.
trigger_timestampin the past starts the batch on the next scheduler pass.- Dialling needs LiveKit SIP. Needs keys