API docs
Concepts
The call-request lifecycle
POST /v1/calls creates a call request — a queued instruction to dial. A background dispatcher claims it, re-checks every compliance and capacity gate at dial time, and originates the call. Statuses:
| Status | Meaning |
|---|---|
queued | Waiting to be dialed (or rescheduled to the next calling window / capacity slot). |
dialing | Claimed by the dispatcher; originating now. |
completed | Dispatched — the call was successfully placed; call_id is set. Track the call itself via GET /v1/calls/{call_id} and webhooks. |
blocked | A compliance/capacity gate refused it; error_code says why (recipient_dnd, consent_withdrawn, outside_calling_hours, insufficient_credits, no_from_number). |
failed | A technical/provider error; error_code is provider_error, error_detail has the reason. |
canceled | You canceled it while still queued. |
completedmeans dispatched, not finished. The conversation’s result arrives on the call:GET /v1/calls/{call_id}and thecall.completedwebhook.
There are no automatic dial retries — a blocked/failed request stays terminal; create a new request when appropriate (your idempotency_key controls dedupe).
external_ref
Pass your own identifier ("external_ref": "crm-lead-4821") when creating a call. It’s stored on the call, echoed in every webhook payload, and filterable: GET /v1/calls?external_ref=…. This is how you join results to your CRM without keeping a mapping table.
Idempotency
Send idempotency_key in the POST /v1/calls body (or an Idempotency-Key header — the body wins if both). Replaying the same key returns the original request with 200 (not 202) and never dials twice. Keys are unique per workspace.
Calling hours
Outbound calls are only placed inside the permitted calling window (Indian telecom regulations — typically 09:00–21:00 IST). Outside it, POST /v1/calls returns 422 outside_calling_hours — unless you pass "schedule_if_outside_hours": true, in which case the request queues and dials when the window opens. You can also schedule explicitly with "scheduled_for": "<ISO8601>".
Variables
variables (a JSON object) personalizes the conversation: they’re merged into the contact’s stored variables (yours win on conflict) and available to the agent’s prompt — e.g. {"name": "Harsh", "due_amount": "₹4,500"}.
Recordings & transcripts
GET /v1/calls/{id}/recording and /transcript are coming soon — they currently return 404 recording_not_available / 404 transcript_not_available. The call.completed payload’s summary and outcome are available today.