Calls
Create one phone task and receive a structured result. Start with the Quickstart for a production example.
Check Regions & languages for supported destinations and languages.
Availability
Calls are available on the production API and in SDK 1.0. See the
migration guide when upgrading an existing call-task integration.
Calls and Goal Runs include call_outcome, result_status and transcript.
Wait while result_status is pending, not until result or error becomes non-null.
Use the complete Python and Ruby examples to persist a request and resume it. The V2 result reader reads their saved response, including unavailable results and the top-level transcript.
Call ID and Billing
The response adds a fixed call_id field for matching a telephone call to the
Call ID shown in Billing.
Code
ididentifies the API resource. Keep using it for get, cancel and event requests.call_ididentifies the actual telephone call. Use it to find the corresponding Billing entry. It isnulluntil the provider ID is recorded, including cancellation before dialing; never substituteidwhen it is null.
The field does not depend on a successful business result. GET, exact creation
replay and terminal webhook data.call_id use the same recorded identity, including
existing Calls with saved provider evidence. An ID does not mean settlement is
complete; the Billing charge may appear later. Event envelopes keep their existing
call_id as the API resource ID. In the TypeScript wrapper the new response field
is call.callId; Python and raw JSON use call["call_id"].
Request contract
POST /v2/calls prepares one phone task, then returns 202 after durable
acceptance. The request waits for preparation; dialing runs in the background
using the saved instructions.
| Input | Required | Meaning |
|---|---|---|
task | Yes | Complete instructions and facts needed for the conversation. |
phone | Yes | One E.164 number, including + and country code. |
region | No | Two-letter uppercase destination hint, such as US. Inferred from the phone when omitted. |
locale | No | Spoken language, such as en-US. Inferred from the task and available regional languages when omitted. |
result_schema | Yes | A closed object containing at most 32 scalar properties. |
Idempotency-Key header | Yes | A stable key for this logical call, 1-255 characters after trimming. See Idempotency. |
metadata | No | Application-owned correlation data, returned with the Call. |
webhook_url | No | HTTPS receiver for the final result or error. |
If region and locale pass format validation but have no supported calling
configuration, creation returns 422 unsupported_region or
422 unsupported_language. The error identifies the field to correct and
includes the rejected region and locale, whether supplied or inferred:
Code
Choose a supported region and language and resubmit with the same
idempotency key. Explicit unsupported targets are rejected before model
preparation; an inferred locale is checked after inference. Neither rejection
creates a Call or outbound telephone task. Configuration service failures still return
503 provider_unavailable.
Omitting a hint or sending null requests inference. Explicit spoken-language
instructions in task take precedence over the language used to write the task.
CALL-E returns the resolved region and locale on acceptance and keeps them
fixed for execution and retries. An explicit region conflicting with the phone,
or a language that cannot be determined unambiguously, returns
422 input_incomplete with details.missing_inputs. Correct the phone/region
or specify the spoken language before resubmitting. A supplied locale is never
silently replaced with another language.
For a phone/region conflict, details.fields identifies phone and region,
details.region is the supplied region, and details.inferred_region is the
region resolved from the number. Display details.missing_inputs to the user;
do not fix the conflict by silently changing their destination.
If essential information is missing or conflicting, creation returns
422 input_incomplete with the specific missing inputs. No Call is created,
no phone is dialed, and no terminal webhook is sent for the rejected request.
Code
Collect the missing facts in your application, update task, and submit again.
Information the call is meant to collect from the recipient is not itself a
missing prerequisite. The API does not ask clarification questions interactively.
Preparation is bounded to 25 seconds. A preparation timeout or model failure
returns 503 provider_unavailable; it is not an incomplete-input response.
Result schema
Use type: "object" and additionalProperties: false. Property values can be
strings, booleans, integers or numbers. Nested objects, arrays, null values and
schema combinators are unsupported. Use an explicit scalar such as "unknown"
when an answer can be unknown. The request and schema are frozen for execution.
For example, "type": ["string", "null"] is not supported. It returns
400 result_schema_invalid before a Call is created. Use "type": "string"
and explicitly describe an allowed "unknown" fallback in the task instead.
Result outcomes
The response uses the same result model as Goal Runs. call_outcome describes
the telephone outcome: completed, no_answer, busy, or declined. A no-answer,
busy or declined call finishes with status: "completed" and is not a technical error.
Poll while result_status is pending. available includes a validated empty
object; unavailable means the evidence did not support a schema-valid business
result; not_applicable covers cancellation and technical execution failure.
Both result and error can be null in a final unavailable result.
Include explicit missing-answer and unknown rules in task, consistent with
result_schema. CALL-E preserves those rules during extraction. Missing answers
do not automatically become false. Without a permitted fallback, the business
result remains unavailable and error stays null.
Code
status: "completed" means telephone execution ended; it does not mean the
business goal succeeded or that the result is ready. completed_at is the
execution completion time. Evaluate your own schema fields to decide business
success. Put a summary or completion flag in the schema if your application needs it.
Transcript
Every Call includes a top-level transcript array, separate from result and
result_schema. After execution ends, it contains the recorded conversation in
order, even while the business result is pending, unavailable, or failed.
Before execution ends or when no transcript is available, it is [].
Code
speaker is bot (CALL-E), user (the remote party, including automated prompts), or unknown.
offset_seconds is a nonnegative offset in seconds, or null when unavailable.
text preserves the recorded words. Missing roles or times are not inferred.
GET and terminal webhooks use the same transcript snapshot. This field does not
provide live ASR streaming, recordings, or a generated summary.
Idempotency
Persist the original request and one stable Idempotency-Key before submission.
Reuse them to recover the same logical call, not to dial again. Replay requires
the same project and authenticated owner; a key is not a global call identifier.
| Situation | Response / next action |
|---|---|
| Same key and unchanged input after acceptance | 202 with the same Call ID and its current saved state, not necessarily the original response body. Preparation and dialing are not repeated. |
| Original Call is completed, failed or canceled | Same replay behavior. A new key is required for an intentionally new call, even to the same phone. |
| Same key while the first create request is still running | 409 idempotency_conflict, with details.reason_code: "creation_in_progress". Back off and retry the original key and body. |
| Same key but changed input | 409 idempotency_conflict. Restore the original request to recover it, or use a new key only for a deliberate new call. |
| Definitive validation rejection before acceptance | Correct the input and reuse the key. For example: 400 result_schema_invalid, 422 input_incomplete, unsupported_region or unsupported_language. No Call was created. |
| Timeout, lost response or an unclassified server error | Acceptance is uncertain. Retry the same key and unchanged body; do not generate another key to bypass the error. |
The input comparison includes task, phone, region, locale, result_schema,
metadata and webhook_url. JSON object-key order is not significant, but
changing a field value is. Keep your original body rather than reconstructing
it from the response: if you omitted region or locale, continue omitting
them on retries. Copying the inferred response values into a retry changes the
request and returns 409, even when those values match the chosen destination.
Use a durable business key such as order-8472-confirmation-attempt-1. Reuse it
after a timeout; use order-8472-confirmation-attempt-2 only when your application
has intentionally decided to place another call. Store the returned Call ID and
use GET for routine status polling. These rules apply to Calls, not automatically
to legacy creation failures or Goal Run keys.
Read, events and cancellation
| Method | Path | Behavior |
|---|---|---|
| GET | /v2/calls/{call_id} | Reads committed state without dialing or running inference. |
| GET | /v2/calls/{call_id}/events | Lists persisted lifecycle events and observed speech updates. |
| POST | /v2/calls/{call_id}/cancel | Cancels before provider submission. |
Events support cursor and limit (1-100). Continue with next_cursor to read
remaining available pages. To poll for new events, retain the last returned
event's id and pass it as cursor, even when next_cursor is null. An empty
page does not mean the call ended. Cursors belong to one Call; event IDs remain
stable across retries. Events follow persistence order, so late observations
remain reachable after the previous cursor.
This endpoint returns JSON pages, not an SSE connection. Deduplicate by event
id, not turn or text. A turn can contain several distinct speech updates.
Read until next_cursor is null, then keep the last event ID for the next poll;
an empty page must not erase that saved cursor. Invalid or foreign cursors and
out-of-range limits return 400 invalid_request.
| Event | Meaning |
|---|---|
call.accepted | Instructions prepared and Call accepted. |
call.in_progress | Provider submission started. |
call.ringing / call.connected | Observed ringing or connection. |
call.asr | Callee recognition update; may be a partial fragment or a revised hypothesis. |
call.speech | Observed bot speech text. |
call.interrupted / call.dtmf | Interruption or keypad input. |
call.ended | Phone execution ended; result processing may still be pending. |
call.result_ready | The structured result is saved and can be read. |
call.completed / call.failed / call.canceled | The Call's terminal outcome. |
Speech events preserve the full observed text without truncation. They do not
guarantee a complete sentence or include an is_final flag. For example, distinct
ASR events may contain "my", "my favorite" and "my favorite color is green".
Do not concatenate every ASR event into a final transcript. One illustrative event:
Code
occurred_at is the provider timestamp when supplied, otherwise null. These
are observed events, not a guarantee that the remote party heard the bot.
Not every call emits every lifecycle event; absence of call.ringing or
call.connected alone does not establish a telephone outcome.
Historical calls without stored realtime
evidence retain their lifecycle events; missing speech is not synthesized.
Internal agent traces are not exposed. call.accepted alone does not prove the
phone rang. Reads never initiate a call, extract a result or persist new events.
Cancellation after provider submission returns 409 call_cannot_cancel.
It does not hang up an active call. Repeating cancellation on a terminal Call
returns its stored state. See the API Reference for schemas.
Limits
- One target per Call. Recipient lists, batch requests and
recipient_result_schemaare not accepted. - Calls accept immediate execution only. Scheduling and recurrence are not supported.
- Billing correlation is available through
call_id; detailed provider attempt records are not exposed. - Account concurrency, balance, regional access and other account policies still apply. Acceptance may be followed by queued work.
- Existing legacy call-task IDs must be read through their original interface; changing the URL does not convert historical records.
Failures and uncertain submissions
HTTP errors reject or fail the request itself. An accepted Call can later expose
an execution error or a result-processing error in error. The latter can
coexist with execution status completed.
| Error | Meaning / next step |
|---|---|
call_failed, timed_out | A technical execution failure; inspect the returned detail. |
result_invalid | The result did not satisfy the schema. |
result_failed | Processing or persisting the result failed. |
detail_code: authorization_expired | Execution authorization became unavailable. After submission, the provider may still complete the call. |
detail_code: submission_unknown | Provider submission could not be confirmed. |
Do not automatically create a replacement for an uncertain submission. Retain the original Call ID and reconcile it before making another call. Expiration of a client wait timeout is also not evidence that no call occurred.