Skip to navigation

Outbound batches

A batch is a list of phone numbers, the leads, that the platform calls on your behalf with one of your AI agents, from one of your telephony extensions. You create it and publish it; the dialer does the calling. Along the way you can watch every lead change status, stop and resume the batch, and add more leads.

Batches are managed with a secret key; changes need a key with the WRITER role.

Before you start

A batch dials from a telephony extension, and the extension decides which agent takes the calls. Set the extension’s outbound agent in the dashboard under Cloud Call Center > Settings > Extensions first. Creating a batch on an extension without one fails with 400 and "No outbound agent configured on this extension".

Create a batch

curl -X POST https://api.hams.ai/outbound-batch/batches \
-H "X-Secret-Key: $HAMS_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Renewal reminders, September",
"extension_id": "ext_…",
"scheduled_date": "2026-09-01T06:00:00Z",
"fetch_limit": 20,
"max_attempts_per_lead": 3,
"is_draft": true,
"leads": [
{ "number": "+966500000001", "dynamic_variables": { "customer_name": "Sara", "renewal_date": "5 September" } },
{ "number": "+966500000002", "dynamic_variables": { "customer_name": "Omar", "renewal_date": "7 September" } }
],
"webhook": {
"url": "https://example.com/hooks/hams",
"method": "POST",
"events": ["outbound_lead_status_changed"]
}
}'

You get 201 and the batch:

{
"id": "…",
"entity_id": "…",
"name": "Renewal reminders, September",
"extension_id": "ext_…",
"agent_id": "…",
"display_number": null,
"format_number": "none",
"status": "DRAFT",
"scheduled_date": "2026-09-01T06:00:00",
"fetch_limit": 20,
"max_attempts_per_lead": 3,
"lead_count": 2,
"created": "…",
"updated": "…",
"webhook": { "url": "https://example.com/hooks/hams", "method": "POST", "events": ["outbound_lead_status_changed"], "…": "…" }
}
FieldNotes
name1–255 characters
extension_idThe extension to call from; its outbound agent takes the calls and is copied to agent_id
scheduled_dateWhen calling may start. Must be in the future; sent with a timezone or taken as UTC
fetch_limitLeads the dialer claims from this batch per pass; default 20
max_attempts_per_leadStored with the batch; default 3. The current dialer makes one attempt per lead
leads1–10,000 per request. number is digits with an optional leading +, 7–30 characters; dynamic_variables is a map of strings the agent can use, on top of its default_dynamic_variables
webhookOptional. url, method, events (only outbound_lead_status_changed for batches), optional headers, max_retries
is_drafttrue creates the batch as DRAFT so you can review it before publishing; default false creates it ACTIVE

Send leads in the format your trunk expects. Numbers are stored as given; format_number is none unless the extension’s routing changes it.

Publish, stop, reopen

CallEffect
POST /outbound-batch/batches/{batch_id}/publishDRAFT → ACTIVE; the dialer starts claiming leads once scheduled_date has passed. Returns { "status": "ACTIVE" }
POST /outbound-batch/batches/{batch_id}/stopACTIVE → STOPPED; leads already dialing finish and get their outcome. Returns { "status": "STOPPED" }
POST /outbound-batch/batches/{batch_id}/leadsAppends leads ({ "leads": [ … ] }). A STOPPED or COMPLETED batch reopens to ACTIVE; a DRAFT stays a draft. Returns leads_added and previous_status
DELETE /outbound-batch/batches/{batch_id}Marks the batch deleted; it disappears from lists and is no longer dialed

Batch status

StatusMeaning
DRAFTCreated with is_draft, never dialed
ACTIVEThe dialer claims leads from it
STOPPEDPaused by you; the dialer skips it
COMPLETEDEvery lead reached a final status
deletedRemoved

Lead status

StatusMeaning
PENDINGWaiting to be dialed
DIALINGThe call is in flight
ANSWEREDAnswered and handled by the agent; end_reason says who hung up, USER or SYSTEM
NO_ANSWERNobody picked up
BUSYThe line was busy
FAILEDThe call could not be placed

Follow progress

curl "https://api.hams.ai/outbound-batch/batches?status=ACTIVE" \
-H "X-Secret-Key: $HAMS_SECRET_KEY"
{ "success": true, "data": [ { "id": "…", "name": "…", "status": "ACTIVE", "lead_count": 2, "…": "…" } ], "count": 1, "total": 1, "limit": 100, "offset": 0 }

GET /outbound-batch/batches/{batch_id} returns one batch with its webhook, and GET /outbound-batch/batches/{batch_id}/leads pages through its leads in the same envelope:

{
"success": true,
"data": [
{ "id": "…", "batch_id": "…", "number": "+966500000001", "dynamic_variables": { "customer_name": "Sara" }, "status": "ANSWERED", "created": "…", "updated": "…" }
],
"count": 1, "total": 2, "limit": 100, "offset": 0
}

If the batch has a webhook, outbound_lead_status_changed is delivered to it each time a lead moves to a new status, so you do not have to poll.