curl --request POST \
--url https://{host}/api/v1/campaigns/{id}/pause \
--header 'Authorization: Bearer <token>'const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://{host}/api/v1/campaigns/{id}/pause', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://{host}/api/v1/campaigns/{id}/pause"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text){
"abandoned": 123,
"agent_kind": "human",
"ai_assist": true,
"answered": 123,
"caller_id": "<string>",
"completed_at": "2023-11-07T05:31:56Z",
"contact_count": 123,
"created_at": "2023-11-07T05:31:56Z",
"dialed": 123,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"kind": "voice_broadcast",
"max_abandon_pct": "<string>",
"max_attempts": 123,
"max_lines": 123,
"message_asset_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"message_text": "<string>",
"name": "<string>",
"organisation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"pacing": "balanced",
"reference": "<string>",
"result_callback_url": "<string>",
"schedule_days": [
123
],
"schedule_end": "<string>",
"schedule_start": "<string>",
"script": {},
"start_at": "2023-11-07T05:31:56Z",
"status": "draft",
"team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"timezone": "<string>",
"trunk_group_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"tts_voice": "<string>",
"virtual_agent_profile_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}Pause a campaign
Running to paused: no new calls; calls in progress finish. 409 wrong_status names the status it must be in; 422 not_ready says what is missing. Requires campaigns:write.
curl --request POST \
--url https://{host}/api/v1/campaigns/{id}/pause \
--header 'Authorization: Bearer <token>'const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://{host}/api/v1/campaigns/{id}/pause', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://{host}/api/v1/campaigns/{id}/pause"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text){
"abandoned": 123,
"agent_kind": "human",
"ai_assist": true,
"answered": 123,
"caller_id": "<string>",
"completed_at": "2023-11-07T05:31:56Z",
"contact_count": 123,
"created_at": "2023-11-07T05:31:56Z",
"dialed": 123,
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"kind": "voice_broadcast",
"max_abandon_pct": "<string>",
"max_attempts": 123,
"max_lines": 123,
"message_asset_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"message_text": "<string>",
"name": "<string>",
"organisation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"pacing": "balanced",
"reference": "<string>",
"result_callback_url": "<string>",
"schedule_days": [
123
],
"schedule_end": "<string>",
"schedule_start": "<string>",
"script": {},
"start_at": "2023-11-07T05:31:56Z",
"status": "draft",
"team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"timezone": "<string>",
"trunk_group_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"tts_voice": "<string>",
"virtual_agent_profile_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}Authorizations
Every request sends Authorization: Bearer <token>. The token is either a panel session (a JWT from /auth/login, 12 hours) or an API key ft_<id>_<secret>. An API key is accepted only from an address on its IP allowlist (403 ip_not_allowed otherwise; 403 ip_allowlist_required for an old key that has none), is limited to its rate per minute (429 rate_limited with Retry-After; X-RateLimit-Limit/Remaining/Reset on every response), and at most 60 call placements a minute.
Path Parameters
Response
The campaign
Answered with no agent free to take it. Read-only, and the figure max_abandon_pct governs.
human, virtual Stream this campaign's answered calls to an AI that writes live suggestions to the agent's screen. Off by default. It costs per minute of every answered call and streams the customer's conversation to the provider for the whole call, which in several jurisdictions is a recording and consent question rather than only a cost one. The AI is never heard: an assist session's audio is dropped at the single point all audio leaves, so it cannot speak into the call even if a provider ignores the text-only instruction. Implemented for OpenAI only; other providers refuse rather than speaking.
When it completed: nobody left to dial, or stopped.
Dialer output. Read-only.
voice_broadcast plays a message to whoever answers. auto_dial connects the answered contact to an agent.
voice_broadcast, auto_dial Exact decimal string. A COMPLIANCE setting: abandonment caps are law in most jurisdictions and 3% is the common statutory figure.
Hard ceiling on simultaneous calls. Not a tuning knob: the node allows 30 new sessions per second in total, shared with inbound traffic.
A recording to play. Works today.
What the call says, read out by a machine. May carry {{field}} placeholders filled from that contact's own data -- the columns their CSV row had -- so each person hears their own details.
Rendered to speech once into a media asset and cached on the exact text and voice, so a plain message is spoken once for ten thousand calls and a personalised one is not re-rendered when a busy contact is redialled. Generated at ANSWER, inside the pause the broadcast already takes listening for a voicemail beep, so nothing is spent on calls nobody picks up and the caller hears no extra delay.
A contact whose row is missing a field the message needs is NOT CALLED: the call sheet records missing_field:. A sentence with a hole in it would go out to everybody whose row was short a column, sound broken, and leave nothing saying which calls were affected.
balanced opens one line per free agent and abandons nobody. aggressive dials ahead on the measured answer rate, capped by max_abandon_pct.
balanced, aggressive Your own id for the campaign, on every result.
128Each contact's final outcome (campaign.contact.completed) and the campaign's end (campaign.completed) are POSTed here, signed with the organisation's callback secret; needs the secret to exist (409 no_callback_secret).
0=Sunday to 6=Saturday, matching Go's time.Weekday. NOT the ISO 1=Monday convention.
HH:MM in the campaign's timezone.
A structured brief for a virtual agent.
Earliest moment this campaign may dial. Null means as soon as it is running. A campaign whose start is in the future is 'running' and dialling nothing -- there is deliberately no separate status for it. The daily calling window still applies on top.
running means the dialer is working this campaign.
draft, running, paused, completed Must be an OUTBOUND workflow.