Campaigns.
A campaign fans one published agent out to many recipients over a single phone number, each call carrying its own vars and running at a concurrency you set. The platform paces the dialer, respects your calling window, and retires the batch when the list is drained — and every call still fires call.completed with its recording, transcript, tool log, and outcome.
Create a campaign#
/v1/campaigns| Field | Type | Description | |
|---|---|---|---|
| name | string | optional | Human label for the dashboard. Defaults to "Untitled campaign". |
| agent_id | string | required | The agent to run. Must be published — an unpublished agent returns 409 agent_not_published. |
| phone_number_id | string | required | The number every call is placed from. It must be outbound-enabled. |
| recipients | object[] | required | The call list — each entry is { to, vars }. to is an E.164 number; varsis a free-form object merged into that recipient's call and available to the agent's prompt and tools. |
| target_concurrency | integer | optional | How many calls run in parallel. Defaults to a value within your plan's included lines and is capped there — see pricing. |
| schedule | object | optional | When calls may go out: { start_at, calling_window: { tz, from, to } }. from and to are 24-hour local times (e.g. "09:00", "20:00") in the window's tz. Omitted, the campaign dials as soon as it is started. |
curl -X POST https://voice.whizztech.ai/v1/campaigns \
-H "Authorization: Bearer $WHIZZ_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "July renewals · AR",
"agent_id": "ag_7Q2c51b84a07",
"phone_number_id": "pn_5b8f0d21",
"target_concurrency": 5,
"recipients": [
{ "to": "+966500000001", "vars": { "name": "سارة", "order": "A-2291" } },
{ "to": "+966500000002", "vars": { "name": "خالد", "order": "A-2318" } }
],
"schedule": {
"start_at": "2026-07-14T07:00:00.000Z",
"calling_window": { "tz": "Asia/Riyadh", "from": "09:00", "to": "20:00" }
}
}'{
"id": "camp_3f9a1c07",
"object": "campaign",
"agent_id": "ag_7Q2c51b84a07",
"phone_number_id": "pn_5b8f0d21",
"name": "July renewals · AR",
"status": "draft",
"target_concurrency": 5,
"totals": {
"recipients": 2,
"queued": 0,
"in_progress": 0,
"completed": 0,
"failed": 0
},
"created_at": "2026-07-13T09:32:18.000Z"
}A new campaign lands in draftwith its recipients staged but nothing dialed. Add more recipients or start it when you're ready.
Add recipients#
/v1/campaigns/{id}/recipientsTop up a campaign — before or during a run — by posting more entries. The body is { recipients: [{ to, vars }] }. New entries queue behind the current list; on a running campaign they start dialing as concurrency frees up, no restart needed.
curl -X POST https://voice.whizztech.ai/v1/campaigns/camp_3f9a1c07/recipients \
-H "Authorization: Bearer $WHIZZ_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipients": [
{ "to": "+966500000003", "vars": { "name": "منى", "order": "A-2402" } },
{ "to": "+966500000004", "vars": { "name": "فهد", "order": "A-2410" } }
]
}'{
"id": "camp_3f9a1c07",
"object": "campaign",
"status": "running",
"added": 2,
"totals": {
"recipients": 4,
"queued": 2,
"in_progress": 5,
"completed": 0,
"failed": 0
}
}Start & pause#
/v1/campaigns/{id}/start/v1/campaigns/{id}/pausecurl -X POST https://voice.whizztech.ai/v1/campaigns/camp_3f9a1c07/start \
-H "Authorization: Bearer $WHIZZ_KEY"start moves the campaign from draft to running and the dialer begins pacing calls up to target_concurrency. pause holds the line — in-flight calls finish, nothing new is placed — and start resumes it. The campaign flips to completed on its own once every recipient has been attempted.
| Field | Type | Description |
|---|---|---|
| draft | status | Created, recipients staged, nothing dialed yet. |
| running | status | Dialing, paced up to target_concurrency within the calling window. |
| paused | status | Held. In-flight calls finish; no new calls are placed until you start it again. |
| completed | status | Every recipient has been attempted. Terminal — create a new campaign to call again. |
List & get#
/v1/campaignsCursor-paginated, newest-first. Filter by status.
{
"object": "list",
"data": [
{
"id": "camp_3f9a1c07",
"object": "campaign",
"agent_id": "ag_7Q2c51b84a07",
"name": "July renewals · AR",
"status": "running",
"target_concurrency": 5,
"totals": {
"recipients": 4,
"queued": 0,
"in_progress": 3,
"completed": 1,
"failed": 0
},
"created_at": "2026-07-13T09:32:18.000Z"
}
],
"has_more": false
}/v1/campaigns/{id}Returns the full campaign object. Poll it to watch the totals move — queued drains into in_progress, then into completed or failed — as the batch runs:
{
"id": "camp_3f9a1c07",
"object": "campaign",
"agent_id": "ag_7Q2c51b84a07",
"phone_number_id": "pn_5b8f0d21",
"name": "July renewals · AR",
"status": "running",
"target_concurrency": 5,
"totals": {
"recipients": 4,
"queued": 0,
"in_progress": 3,
"completed": 1,
"failed": 0
},
"created_at": "2026-07-13T09:32:18.000Z"
}Fields#
| Field | Type | Description |
|---|---|---|
| agent_id | string | The published agent every call in the campaign runs. |
| phone_number_id | string | The outbound number all calls are placed from. |
| status | string | draft · running · paused · completed. Driven by start / pause and by the list draining. |
| target_concurrency | integer | Maximum calls in flight at once. Capped by your plan's included lines. |
| totals | object | Live counters: { recipients, queued, in_progress, completed, failed }. recipients is the whole list; the rest sum to it as the run progresses. |