Place an outbound AI phone call
Places an outbound AI voice call and returns immediately with the call in queued status; the dial runs asynchronously, so poll GET /v1/phone/calls/{id} or subscribe to call.status_changed to follow it to a terminal state.
Places an outbound AI voice call and returns immediately with the call in queued status; the dial runs asynchronously, so poll GET /v1/phone/calls/{id} or subscribe to call.status_changed to follow it to a terminal state. to and from are required E.164 numbers — from must be a number this account owns with status: "active", otherwise the request is a 400 — and instructions (required, up to 8,000 characters) tells the agent what to accomplish. {{name}} placeholders in instructions and greeting are filled from variables when the call is created (a placeholder with no matching variable stays as written). Every call runs on Dairo Live: model is optional and only dairo-live is accepted — any other value is a 400. Set voice to one of the 22 Dairo Live voice ids from the phone voice catalog (default marin; any other value is a 400) and language to the ISO code the agent speaks, like de; maxDurationSeconds caps the call between 30 and 780 seconds (default 600); and voicemailMessage (≤500 characters) is left on a voicemail — without it the agent hangs up silently when a mailbox answers. Pass up to 10 questions and the agent works them into the call, landing structured answers on the row afterward. Every connected call is recorded, and the agent hangs up by itself once the person says goodbye. Supply an Idempotency-Key header or idempotencyKey body field (≤128 characters) so a retried request returns the original call instead of dialing the person twice; a header that disagrees with the body field is a 400. The call emits a call.status_changed webhook to your subscribed endpoints when it is answered and when it reaches a terminal status. Price: $0.09 per minute for Dairo Live plus the destination's telephony rate, per started minute; a call that never connects is free. Requires the phone:call scope.
Scope: phone:call. Send the API key as a bearer token; Scopes lists what each one reaches.
Request
Headers
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key | string | no | Optional idempotency key for safe retries of side-effecting operations. (max length 128) |
Body
Required, application/json: PhoneCallCreateRequest.
Calls are always recorded. To follow a call's progress subscribe a webhook to the call.status_changed event. The agent hangs up by itself when the person says goodbye.
| Field | Type | Required | Description |
|---|---|---|---|
to | string | yes | Destination, E.164. A real phone rings here. |
from | string | yes | Caller id, E.164. MUST be a number this account owns with status active. |
instructions | string | yes | What the agent should accomplish. {{name}} placeholders are filled from variables when the call is created; unknown placeholders stay as written. (max length 8000) |
greeting | string | no | Opening line spoken when the callee answers. Supports {{name}} placeholders filled from variables. |
voice | "marin", "cedar", "alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "quartz", "ripple", "vesper", "willow", "stone", "gleam", "meridian", "bossa", "tempo", "beacon", "delta", "cinder" | no | A Dairo Live voice id. marin (default), cedar, alloy, ash, ballad, coral, echo, sage, shimmer and verse are multilingual; quartz, ripple (Australian English), vesper (British English), willow, stone (Irish English), gleam, meridian (North American English), bossa, tempo (Brazilian Portuguese), beacon (Filipino English), delta, cinder (Southern U.S. English). Any other value is a 400. Browse them with GET /v1/phone/voices. (default "marin") |
model | "dairo-live" | no | The call model. Phone calls run on Dairo Live; dairo-live is the only accepted value (any other value is a 400). (default "dairo-live") |
language | string | no | ISO language code the agent speaks (e.g. en, de). |
maxDurationSeconds | integer | no | Hard cap on call length in seconds (30-780). (minimum 30, maximum 780, default 600) |
variables | object | no | Values for {{name}} placeholders in instructions and greeting, filled in at create time. Placeholders without a value stay as written. |
voicemailMessage | string | no | Message the agent leaves when the call reaches a voicemail. Without it the agent hangs up silently on a voicemail. (max length 500) |
metadata | object | no | |
idempotencyKey | string | no | A retried request returns the original call rather than dialing the human twice. |
Response
201 Created. Body: application/json, PhoneCall.
| Field | Type | Required | Description |
|---|---|---|---|
object | "phone_call" | yes | |
id | string (uuid) | yes | |
direction | "outbound", "inbound" | yes | outbound for calls placed with POST /v1/phone/calls, inbound for calls answered by a number's inbound agent. |
status | "queued", "initiating", "ringing", "in_progress", "completed", "failed", "no_answer", "busy", "canceled" | yes | Terminal: completed, failed, no_answer, busy, canceled. |
fromNumber | string | yes | |
toNumber | string | yes | |
instructions | string or null | no | |
greeting | string or null | no | |
voice | string or null | no | The Dairo Live voice id. |
model | string or null | no | Always dairo-live. |
language | string or null | no | |
maxDurationSeconds | integer or null | no | |
voicemailMessage | string or null | no | |
queuedAt | string (date-time) or null | no | |
startedAt | string (date-time) or null | no | |
answeredAt | string (date-time) or null | no | |
endedAt | string (date-time) or null | no | |
durationSeconds | integer or null | no | |
hangupCause | string or null | no | |
answeredBy | string or null | no | human or machine, from answering-machine detection. |
summary | string or null | no | |
notes | array of PhoneCallNote or null | no | Inbound calls: the caller's structured notes (tasks, notes, reminders, messages). |
costUsd | number or null | no | Billed per started minute: the $0.09/min Dairo Live rate plus the destination's telephony rate. Calls that never connect are free. |
error | string or null | no | |
metadata | object | no | |
idempotencyKey | string or null | no | |
createdAt | string (date-time) | yes |
Errors
Every error has the same body, {"error": {"type", "code", "message", "param"}}; branch on code. Errors lists every code.
| Status | Meaning |
|---|---|
400 | The request is malformed or a value is invalid (invalid_request, invalid_domain, idempotency_key_mismatch). |
401 | The API key is missing or invalid. |
403 | The key lacks the scope this endpoint needs (scope_missing) or may not do this (not_permitted). |
404 | No such resource in this account (resource_not_found). |
409 | The resource already exists or its state does not allow this (duplicate_resource or a condition-specific code). |
429 | Rate limit, plan limit, budget or spend cap reached (rate_limited, plan_limit_reached, budget_exceeded, spend_cap_reached). |
500 | An unexpected error; retry with backoff, then contact support (internal_error). |