Creates a batch of outbound calls from one of your numbers. A scheduler dials the pending tasks once trigger_timestamp has passed, only inside call_time_window, and only while the workspace has free concurrency. Pass draft: true to save the batch without scheduling it, then start it with Start batch call.
Each task is dialled the same way as Create phone call, so live calls need the telephony provider keys described in Telephony. Each batch call carries a batch_dial line of $0.01 in its cost.
Request#
| Field | Type | Required | Description |
|---|---|---|---|
from_number |
string | Yes | E.164 number in this workspace that places the calls. |
tasks |
array of objects | Yes | One object per call. At least 1 item. See the task table below. |
name |
string | No | Label for the batch. Default "Batch call". |
trigger_timestamp |
number | No | Unix ms when dialling may begin. Defaults to now. |
reserved_concurrency |
integer | No | Concurrency slots the batch leaves free for other calls. Min 0, default 0. |
call_time_window |
object | No | Hours when the batch may dial. See the window table below. Omit to dial at any time. |
draft |
boolean | No | true creates the batch with status draft. Sending "status": "draft" has the same effect. |
honor_internal_dnc |
boolean | No | Skip numbers whose contact has do_not_call set. Checked when each task is dialled. Default false. |
Each item in tasks:
| Field | Type | Required | Description |
|---|---|---|---|
to_number |
string | Yes | Number to call. |
retell_llm_dynamic_variables |
object | No | String values for {{variables}} in the agent. Default {}. |
metadata |
object | No | Any JSON, stored on the call. Default {}. |
override_agent_id |
string | No | Agent to use for this task instead of the number's outbound agent. Must exist in the workspace. |
call_time_window:
| Field | Type | Required | Description |
|---|---|---|---|
windows |
array of { start, end } |
Yes | Minutes after local midnight, integers from 0 to 1440. A window with start greater than end wraps past midnight. An empty array means no restriction. |
timezone |
string | No | IANA time zone. Default Australia/Sydney. |
day |
array of strings | No | Any of Monday to Sunday. Omit or leave empty for every day. |
Example request#
curl -X POST https://api.tried.com.au/create-batch-call \
-H "Authorization: Bearer $TRIED_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Appointment reminders",
"from_number": "+61291234567",
"reserved_concurrency": 2,
"call_time_window": {
"windows": [{ "start": 540, "end": 1020 }],
"timezone": "Australia/Sydney",
"day": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
},
"tasks": [
{ "to_number": "+61412345678", "retell_llm_dynamic_variables": { "first_name": "Sam" } },
{ "to_number": "+61498765432", "retell_llm_dynamic_variables": { "first_name": "Priya" } }
]
}'const res = await fetch("https://api.tried.com.au/create-batch-call", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TRIED_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Appointment reminders",
from_number: "+61291234567",
reserved_concurrency: 2,
call_time_window: {
windows: [{ start: 540, end: 1020 }],
timezone: "Australia/Sydney",
day: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
},
tasks: [
{ to_number: "+61412345678", retell_llm_dynamic_variables: { first_name: "Sam" } },
{ to_number: "+61498765432", retell_llm_dynamic_variables: { first_name: "Priya" } },
],
}),
});
const batch = await res.json();import os, requests
res = requests.post(
"https://api.tried.com.au/create-batch-call",
headers={"Authorization": f"Bearer {os.environ['TRIED_API_KEY']}"},
json={
"name": "Appointment reminders",
"from_number": "+61291234567",
"reserved_concurrency": 2,
"call_time_window": {
"windows": [{"start": 540, "end": 1020}],
"timezone": "Australia/Sydney",
"day": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
},
"tasks": [
{"to_number": "+61412345678", "retell_llm_dynamic_variables": {"first_name": "Sam"}},
{"to_number": "+61498765432", "retell_llm_dynamic_variables": {"first_name": "Priya"}},
],
},
)
batch = res.json()Response#
201 Created
{
"batch_call_id": "batch_call_5f2a9c1e7b3d4a6f8e0b1c2d",
"name": "Appointment reminders",
"from_number": "+61291234567",
"scheduled_timestamp": 1760850000000,
"status": "planned",
"total_task_count": 2,
"sent": 0,
"picked_up": 0,
"successful": 0,
"reserved_concurrency": 2,
"call_time_window": {
"windows": [{ "start": 540, "end": 1020 }],
"timezone": "Australia/Sydney",
"day": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
}
}| Field | Type | Description |
|---|---|---|
scheduled_timestamp |
integer | Unix ms when dialling may begin (trigger_timestamp, or the creation time). |
status |
string | draft, planned, ongoing, sent or stopped. See How the scheduler dials. |
total_task_count |
integer | Number of tasks in the batch. |
sent |
integer | Tasks dialled so far. |
picked_up |
integer | Batch calls that connected. |
successful |
integer | Batch calls whose post-call analysis marked call_successful true. |
call_time_window |
object or null | The window you sent, with defaults applied, or null. |
How the scheduler dials#
The scheduler runs every 5 seconds by default (BATCH_TICK_MS). On each pass, for each planned or ongoing batch whose scheduled_timestamp has passed:
- It skips the batch when the current time in
call_time_window.timezoneis outside the allowed days and windows. - It computes free slots as the workspace concurrency limit, minus
reserved_concurrency, minus calls running now. With no free slots it waits for the next pass. - It moves a
plannedbatch toongoingand dialspendingtasks in list order until the slots run out. - When no
pendingtasks are left, the batch becomessent.
Each task has its own status: pending, dispatched (a call was created), failed (with an error message) or cancelled (by Stop batch call). A task refused for lack of credit still records a not_connected call with disconnection_reason no_valid_payment. Read tasks with Get batch call.
Errors#
| Status | When |
|---|---|
400 |
Body fails validation, for example tasks: Array must contain at least 1 element(s). Also <from_number> has no outbound agent and task <to_number> has no override_agent_id when a task has no agent to use. |
401 |
Missing or invalid API key. |
402 |
Spending is blocked. The body adds error_code: credit_exhausted, budget_reached, invoice_overdue or verification_needed. |
403 |
The key's IP allowlist or scopes reject the request, or the caller has the read-only member role. This route needs the calls scope. |
404 |
from_number <number> is not a number in this workspace, or Agent <id> not found for an override_agent_id. |
429 |
Rate limit exceeded. See Rate limits. |
See Errors for the body format.
Retell compatibility#
Same path and method as Retell. Differences:
call_time_window.timezonedefaults toAustralia/Sydney, and a window may wrap past midnight.- Tasks accept
to_number,retell_llm_dynamic_variables,metadataandoverride_agent_idonly. Other task fields are ignored. draft,honor_internal_dnc, and thestatus,sent,picked_up,successfulandreserved_concurrencyresponse fields are Tried additions.