Tone docs
Flows

Campaign lifecycle

Draft to finished, and every state it can be in on the way.

See Campaigns for the full field reference.

#CallState after
1POST /v1/campaignsdraft
2POST /{id}/recipients — up to 500 per requestdraft
3POST /{id}/preflightdraft — nothing changes
4POST /{id}/launch with Idempotency-Keyrunning
5POST /{id}/pause / resumepaused / running
6Last recipient settles, or POST /{id}/stopcompleted

Pre-flight is free and tells you everything

It returns the exclusion buckets — invalid_number, dnc, frequency_cap, duplicate, dnd_scrub, blocked_by_gate — with each recipient counted against exactly one reason, plus the compliance checks, an estimated cost band and your balance. It changes nothing.

A block verdict makes launch a 422. A warn does not.

⚠️ duplicate always reads 0 here — duplicates are dropped when recipients are added, so the real count is in the add-recipients response.

Launch is the point of no return

🔴 Idempotency-Key is required; without it, 400. Launching twice dials the whole list twice, which is exactly the complaint pattern TCCCPR punishes.

Launch also refuses when:

  • the agent is still a draft,
  • the number routes to your own stack — refused at the button rather than as thousands of per-call 422s,
  • the calling window plus the retry tail would fall outside the legal band,
  • scrubbing fails. A scrubber outage fails the launch with a 503 rather than passing an unscrubbed list. That is the one outcome TCCCPR forbids.

Launch snapshots the agent, the number and the purpose. The run finishes on the version it launched with.

While it runs

curl -H "Authorization: Bearer $TONE_KEY" "$TONE_API/v1/campaigns/$C/outcomes"
curl -H "Authorization: Bearer $TONE_KEY" "$TONE_API/v1/calls?campaign_id=$C"

The recipient list names each recipient's last attempt. For every call including retries, filter the call log by campaign_id.

It can pause itself: below autoPauseBelowPaise it stops with pausedReason: "low_balance" and emits campaign.paused. Top up, then resume.

Changing a running campaign

You cannot. agentId can never change, and everything else freezes once the campaign leaves draft. Pause, publish your prompt change, and relaunch — or POST /{id}/duplicate, which copies the campaign and its recipients into a fresh draft.

After it finishes

POST /{id}/recipients/{recipientId}/redial queues one settled recipient for another attempt, and a completed campaign wakes up for it. POST /{id}/archive hides it from the list without deleting anything.

Was this page helpful?

On this page