Skip to main content
A campaign dials a list of contacts through one phone number, using one agent, with cap-aware concurrency.

Lifecycle

Create a campaign

The create endpoint is multipart/form-data because contacts are uploaded as a CSV file (max 10 MB ≈ 100k contacts).

CSV format

  • First row must be headers; phone_number column is required.
  • Other columns become the contact’s custom_fields (passed to the agent as variables for templating).

Concurrent budget

When you start (or resume) a campaign, the server checks:
sum of running campaigns’ max_concurrent_calls + this campaign’s max_concurrent_calls ≤ account concurrent_max
Failing this returns 409 with an explanatory message — pause another campaign or reduce max_concurrent_calls. Without this check, two campaigns at concurrency=5 on a tenant with cap=10 would starve everything else.

State transitions

Stop marks the campaign completed and skips pending contacts. In-flight calls are NOT aborted — they finish naturally. “Stop” means “no more new dials,” not “kill in-flight.”

Live metrics (SSE)

GET /api/v1/campaigns/{id}/events is a Server-Sent Events stream:
  • 2-second data: {snapshot}\n\n ticks while the campaign runs.
  • 15-second : heartbeat comments to keep proxies from idle-timing out.
  • Closes with event: end when the campaign reaches a terminal status.

Contact pagination

GET /api/v1/campaigns/{id}/contacts?status=failed&page=0 — paginated, 100 per page, optional status filter.