Skip to main content

Campaigns

A Campaign (called a "Flow" internally) is either an outbound campaign that dials a contact list, or an inbound line tied to a phone number. Campaigns reference a Voice Agent and carry the script / persona prompt configuration.

The public API uses /v1/campaigns. The internal API uses /api/voice/flows — these are the same records.

List campaigns​

GET /v1/campaigns
Scope: voice:campaigns:read

Query parameters:

ParamTypeNotes
statusstringdraft, active, paused, completed
kindstringinbound or outbound
include_metricsbooleanAttach live metrics; default false

Response:

{
"campaigns": [
{
"uuid": "flw_f1g2h3",
"kind": "outbound",
"name": "Spring Reactivation Campaign",
"status": "active",
"voice_agent_id": "agt_a1b2c3d4",
"phone_number": "+15550010000",
"branches": ["Region:West", "Segment:Lapsed"],
"start_date": "2026-05-01",
"end_date": "2026-05-31",
"time_window": { "start": "09:00", "end": "18:00", "timezone": "America/New_York" },
"metrics": {
"calls_today": 142,
"total_calls": 891,
"connect_rate": 0.61,
"avg_handle_time": "01:32",
"peak_hour": 11
},
"created_at": "2026-05-01T00:00:00Z"
}
]
}

Get campaign​

GET /v1/campaigns/{campaign_id}
Scope: voice:campaigns:read


Create campaign​

POST /api/voice/flows — Rate limit: 20/minute

Request body:

{
"kind": "outbound",
"name": "Spring Reactivation Campaign",
"provider": "nextneural",
"voice_agent_id": "agt_a1b2c3d4",
"phone_number": "+15550010000",
"branches": ["Region:West", "Segment:Lapsed"],
"start_date": "2026-05-01",
"end_date": "2026-05-31",
"time_window": { "start": "09:00", "end": "18:00", "timezone": "America/New_York" },
"config": {
"persona_prompt": "You are Aria, a friendly advisor at Luminary Home...",
"recording_disclosure": "This call is being recorded for quality purposes.",
"guardrails": ["no_price_fabrication", "no_stock_fabrication"]
},
"status": "draft"
}
FieldTypeRequiredNotes
kindstring✓inbound or outbound
namestring✓
providerstring✓TTS provider: nextneural, sarvam, elevenlabs
voice_agent_idstring—UUID of existing agent; omit to auto-create from speaker
speakerstring—Auto-create agent from this speaker name
language_codestring—e.g. hi-IN, en-US
phone_numberstring—Inbound: number to receive calls on
branchesstring[]—Contact tag filters for outbound targeting
start_date / end_datedate—Campaign date window
time_windowobject—{start, end, timezone} daily calling hours
configobject—Carries persona prompt, guardrails, lead-trigger mappings
statusstring—Default draft

Launch campaign​

POST /v1/campaigns/{campaign_id}/launch — Rate limit: 5/minute
Scope: voice:campaigns:write

Starts the outbound dialer. Filters contacts by branches tags, respects the time_window and date range, and deduplicates recently-dialled contacts.

Response:

{
"status": "launched",
"campaign_id": "flw_f1g2h3",
"contacts_queued": 284
}

Stop campaign​

POST /v1/campaigns/{campaign_id}/stop — Rate limit: 5/minute
Scope: voice:campaigns:write

Stops a running campaign. In-progress calls are not dropped.

{ "status": "stopped", "campaign_id": "flw_f1g2h3" }

Toggle campaign status​

POST /api/voice/flows/{flow_uuid}/toggle

Switches between active and paused. No body required.


Update campaign​

PATCH /api/voice/flows/{flow_uuid}

Partial update. All fields optional.


Delete campaign​

DELETE /api/voice/flows/{flow_uuid}

Stops any running campaign first, then deletes the record.