Browse docs
Calls
Create a Call
Try this APIStart a web call or an outbound phone call from a single endpoint, set type to "web" or "outbound_phone".
7 min read
Endpoint
POST /api/v1/public/callsA single endpoint creates both call types. Set type to "web" to connect a browser participant to a Convoi agent over LiveKit, or "outbound_phone" to dial an E.164 number from one of your provisioned Convoi numbers.
Headers
Optional: include an Idempotency-Key header (any random UUID) to make this POST safe to retry within a 24-hour window. Repeating the same key returns the original call instead of creating a duplicate.
Idempotency-Key: 6f1c4b7e-… (any UUID)Web call: minimal
Set type to "web" and provide an agent_id (the agent that will run the call). Convoi provisions a LiveKit room, mints a participant token, and returns both in the response.
{
"type": "web",
"agent_id": "agt_b88d642dd68747f28305c428b209xxxx"
}Web call: with overrides
agent_overrides lets you tweak the agent's first message, system prompt, or any LLM/TTS/STT setting for this call only, without editing the agent itself.
{
"type": "web",
"agent_id": "agt_b88d642dd68747f28305c428b209xxxx",
"participant_name": "xyz",
"agent_overrides": {
"first_message": "Hi, how can I help?",
"system_prompt": "You are a concise support agent.",
"llm": { "model": "gpt-4o-mini", "temperature": 0.7 },
"tts": { "voice_id": "rachel", "speed": 1.0 },
"stt": { "language": "en", "model": "nova-2" },
"knowledge_base_ids": ["kb_3a1c…32hex…"]
},
"metadata": { "source": "landing-page", "user_ref": "u_42" }
}| Field | Type | Required | Notes |
|---|---|---|---|
| type | string | yes | Must be "web". |
| agent_id | string | yes | An agent on your account. |
| participant_name | string | no | Display name for the participant in LiveKit. |
| agent_overrides | object | no | Per-call overrides: first_message, system_prompt, llm, tts, stt, knowledge_base_ids. |
| metadata | object | no | Free-form key/value pairs returned with every call event. |
Web call: response
{
"id": "call_01HX…",
"object": "call",
"type": "web",
"status": "initiated",
"agent_id": "agt_…",
"room_id": "…",
"livekit": {
"url": "wss://your-livekit-host",
"token": "eyJhbGciOi…",
"participant_identity": "public-…"
},
"duration_seconds": 0.0,
"cost": { "amount": 0.0, "currency": "USD" },
"metadata": { "source": "landing-page" },
"created_at": "...",
"updated_at": "..."
}Pass livekit.url and livekit.token to the LiveKit client SDK in your browser to join the call. The agent joins automatically as soon as the participant connects. duration_seconds and cost.amount update as the call progresses.
Outbound phone call: minimal
Set type to "outbound_phone" and provide the destination number, the Convoi-managed phone_number_id to dial from, and the agent that should run the call.
{
"type": "outbound_phone",
"agent_id": "agt_b88d642dd68747f28305c428b209xxxx",
"customer": { "number": "+92310000053", "name": "xyz" },
"phone_number_id": "phn_c38155f043624745a66d2e28c185xxxx"
}Outbound phone call: full
{
"type": "outbound_phone",
"agent_id": "agt_b88d642dd68747f28305c428b209xxxx",
"customer": {
"number": "+0000000",
"name": "xyz",
"metadata": { "lead_id": "L-12345" }
},
"phone_number_id": "phn_c38155f043624745a66d2e28c185xxxx",
"agent_overrides": {
"first_message": "Hi Wasay, this is a quick callback from Convoi."
},
"metadata": { "campaign": "may-outreach" }
}| Field | Type | Required | Notes |
|---|---|---|---|
| type | string | yes | Must be "outbound_phone". |
| agent_id | string | yes* | An agent id (agt_…) or a workforce id (sqd_…). *Provide either agent_id or squad_id. |
| squad_id | string | no | Alternative place to pass a workforce id (sqd_…). |
| phone_number_id | string | yes | ID of one of your Convoi-managed numbers. |
| customer.number | string | yes | E.164 (e.g. +971501234567). |
| customer.name | string | no | Display name for transcripts and dashboards. |
| customer.metadata | object | no | Free-form per-customer attributes. |
| agent_overrides | object | no | Per-call overrides: first_message, system_prompt, llm, tts, stt, knowledge_base_ids. |
| metadata | object | no | Free-form per-call attributes. |
Outbound phone call: with a Workforce
A Workforce is a squad of agents that hand off to each other during a call. To place an outbound call handled by a Workforce, use the exact same request shape as a single-agent call, no body changes required. Wherever you pass an agent id (agt_…), you can pass a workforce id (sqd_…) instead, the API tells them apart by their prefix. You can also pass it explicitly in the squad_id field.
curl -X POST https://go.convoi.ai/backend/api/v1/public/calls \
-H "Authorization: Bearer sk_live_xxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7c1f8e9a-..." \
-d '{
"type": "outbound_phone",
"agent_id": "sqd_3fa85f6457174562b3fc2c963f66afa6",
"customer": { "number": "+9715XXXXXXXX", "name": "Ahmed" },
"phone_number_id": "phn_9b2c..."
}'The call starts with the workforce's start agent, then hands off between members automatically as the conversation requires. Sending customer.name substitutes {name} / {contact_name} placeholders in the greeting, so the call opens with e.g. "Hi Ahmed, …". If omitted, it falls back to "there".
{
"id": "call_8a7d...",
"object": "call",
"type": "outbound_phone",
"status": "initiated",
"agent_id": null,
"squad_id": "sqd_3fa85f6457174562b3fc2c963f66afa6",
"phone_number_id": "phn_9b2c...",
"customer": { "number": "+9715XXXXXXXX" },
"room_id": "…",
"created_at": "2026-06-05T10:00:00Z",
"updated_at": "2026-06-05T10:00:00Z"
}Poll GET /api/v1/public/calls/{id} for live status. A single-agent call returns agent_id populated and squad_id null; a workforce call is the reverse.
- Workforce is supported for type "outbound_phone" only. A sqd_… id sent with type "web" returns 422, web calls are single-agent.
- Workforce calls require a private key (sk_live_…); public keys (pk_live_) are rejected with 403.
- Idempotency: send an Idempotency-Key header; identical retries within 24h replay the original response.
Outbound phone call: response
The response mirrors the web-call response, except livekit and room_id are null. customer is populated; status begins at "initiated" and transitions through "active" → "completed" (or one of the terminal failure states). duration_seconds and cost.amount update as the call progresses.
Related in Calls