Skip to content
TriedDocs
Batch calls

Create batch call

Queue outbound calls from one of your numbers to a list of recipients, now, later or as a draft.

POSThttps://api.tried.com.au/create-batch-call

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.

Note

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:

  1. It skips the batch when the current time in call_time_window.timezone is outside the allowed days and windows.
  2. 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.
  3. It moves a planned batch to ongoing and dials pending tasks in list order until the slots run out.
  4. When no pending tasks are left, the batch becomes sent.

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.timezone defaults to Australia/Sydney, and a window may wrap past midnight.
  • Tasks accept to_number, retell_llm_dynamic_variables, metadata and override_agent_id only. Other task fields are ignored.
  • draft, honor_internal_dnc, and the status, sent, picked_up, successful and reserved_concurrency response fields are Tried additions.