VocalDocscontracts 1.65.0

End a Call

POST /v1/calls/{call_id}/end

PropertyValue
Operationend_call
GroupCalls
Scopecalls:write
Route classcontrol
IdempotencyIdempotency-Key accepted: a retry with the same key replays the first answer
AuditAudited call.end (mutation)
Released in1.19.0
Phase 0 hostServed (the hosted api pins 1.65.0)

Ends a Call with the ended reason canceled (FR-calls-8). A Call no worker runs, scheduled or queued and not yet claimed, ends at once and its reservation is released. Otherwise the api records the request in end_requested_at and the Call event call.end_requested, then pushes it to the worker that runs the Call (1.36.0; the Call event call.end_pushed records the result, accepted, refused, no_room or no_participant, and elapsed_ms). The worker stops the agent audio at once, ends the Session with canceled and finalizes, which FR-calls-8 asks within 2 seconds (a target), and the Call event call.end_received records its receipt. The end_requested flag on the answer to the worker's next signal is the fallback: a push that LiveKit refuses or that no worker reads leaves the end to the next heartbeat, up to one heartbeat period (15 seconds, target), and the audio is cut as soon as the worker learns of it. A second request records nothing new and pushes again. A Call whose worker was already lost reads nothing: the request brings its lease forward and the sweeper ends it worker_lost, its own rule, with the request kept in the Call events. The answer is the Call as it stands once the request is recorded. A Call that has already ended answers 409 call_not_active.

Request

Set VOCAL_API to the base URL of your API and VOCAL_API_KEY to an API key with the calls:write scope (Authentication and keys). Replace each placeholder, such as agt_... or <name>, with your own value.

curl -X POST "$VOCAL_API/v1/calls/call_.../end" \
  -H "Authorization: Bearer $VOCAL_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{}'

Parameters

NameInTypeRequiredDescription
call_idpathCallIdyesThe id of a Call: call_ and the row's UUIDv7 in 26 Crockford base32 characters. Opaque and safe to log.
idempotency-keyheaderstringnoA client-chosen key, kept 24 hours per Organization, environment and route. A replay returns the stored response.

Request body

Content type application/json, required: CallEndRequest.

FieldTypeRequiredDescription
reason_codestringnoWhy the caller of the route ends the Call, as a snake_case code such as customer_request; recorded in the call.end Audit event and never free text. The ended reason is canceled whatever the code.

Responses

StatusContent typeShapeError codes
200application/jsonCall
400application/jsonErrorEnvelopeinvalid_request
401application/jsonErrorEnvelopeunauthenticated
403application/jsonErrorEnvelopeforbidden, org_suspended
404application/jsonErrorEnvelopenot_found
409application/jsonErrorEnvelopecall_not_active, idempotency_in_progress, idempotency_key_reused
429application/jsonErrorEnveloperate_limited
500application/jsonErrorEnvelopeinternal_error

Fields of the 200 answer

The shape is Call.

FieldTypeRequiredDescription
agent_idAgentId or nullyesThe Agent. Null only on an inbound phone Call refused at admission before it was resolved (1.22.0), such as a Call ended refused_no_route on a number that routes to no Agent; a reader on an older version must take 1.22.0 first.
agent_versioninteger or nullyesThe pinned Agent version. Null only on an inbound phone Call refused at admission before it was resolved (1.22.0), such as a Call ended refused_no_route on a number that routes to no Agent; a reader on an older version must take 1.22.0 first.
answered_atTimestamp or nullyes
answering_machineAnsweringMachineResult or nullnoThe answering-machine detection of an outbound phone Call (1.50.0, FR-calls-12), known once the Call is finalized, with any reviewer label; null when detection did not run (an inbound or web Call, detection off, or not finalized yet). Absent from an api before 1.50.0; a reader treats its absence as null.
attemptintegernoThe attempt number (1.61.0): 1, or 2 for a retry. Absent from an older api.
campaign_attemptinteger or nullnoThe enrollment's attempt the Call is (1.65.0); null otherwise.
campaign_enrollment_idCampaignEnrollmentId or nullnoThe enrollment (1.65.0); null otherwise. Absent from an older api.
campaign_idCampaignId or nullnoThe Campaign whose contact instance placed the Call (1.65.0); null otherwise. Absent from an api older than 1.65.0, which a reader treats as null.
capture_modeCaptureModenoWhat admission decided the Call captures (1.57.0): verbose when capture asked for it or an open capture window of the Agent applied. Absent from an api older than 1.57.0; a reader treats its absence as standard.
capture_window_idCaptureWindowId or nullnoThe capture window that made the Call verbose (1.57.0); null when none did. Absent from an api older than 1.57.0; a reader treats its absence as null.
compliance_profile_versioninteger or nullnoThe version of the Organization's Compliance profile that admission read once for the Call (1.34.0; workspace ADR 0082, decision 1): 0 for the defaults, the number the Session configuration carries as compliance_profile_version. A change of the profile applies from the next Call, so this is the profile the Call ran under. Null on a Call created before the api recorded it and on a refused inbound Call that resolved none; a reader treats its absence as null.
contact_idContactId or nullnoThe Contact the Call resolved (1.61.0), or, for an ambiguous resolution, the candidate verification bound; null when none. Absent from an api older than 1.61.0, which a reader treats as null.
contact_resolutionContactResolution or nullnoHow admission resolved the Contact (1.61.0); null on a Call admitted before 1.61.0. Absent from an older api.
created_atTimestampyes
directionCallDirectionyes
duration_msinteger or nullyesFrom answer to end, known once the Call is finalized.
end_requested_atTimestamp or nullnoWhen POST /v1/calls/{call_id}/end asked the worker to end the Call; null when no end was requested, or when the Call ended at once. Added in 1.19.0: a reader treats its absence as null.
ended_atTimestamp or nullyes
ended_reasonEndedReason or nullyes
engineEngineKind or nullyesThe engine of the pinned version. Null only on an inbound phone Call refused at admission before it was resolved (1.22.0), such as a Call ended refused_no_route on a number that routes to no Agent; a reader on an older version must take 1.22.0 first.
environmentEnvironmentyes
experimentCallExperiment or nullnoThe experiment and arm dispatch assigned the Call to at admission (1.55.0, roadmap slice 2.9), identifiers only, beside the versions it ran. Null for a Call outside every experiment: one that resolves a pinned version, whose version a pre-call hook selected, or of an Agent with no running experiment. Absent from an api older than 1.55.0, which a reader treats as null.
idCallIdyes
knowledge_versionsarray of KnowledgeVersionRefnoThe Knowledge base version each binding of the Call read (1.53.0, roadmap slice 2.8), resolved once at dispatch, beside the Policy versions it ran on: a Call reads exactly one version of each bound Knowledge base. Empty for a Call whose Agent version binds none; absent from an api older than 1.53.0, which a reader treats as none.
max_duration_sintegeryesThe duration ceiling fixed at admission. On a Call refused at admission (1.22.0) it is the ceiling admission would have fixed, or the Organization's ceiling when no Agent version was resolved.
object"call"yes
process_idProcessInstanceId or nullnoThe Process instance whose start_call node placed the Call (1.62.0); null otherwise. Absent from an api older than 1.62.0, which a reader treats as null.
process_step_idProcessStepId or nullnoThe step of that node (1.62.0); null otherwise. Absent from an older api.
prompt_versionsCallPromptVersions or nullnoThe prompt layers dispatch resolved once for the Call (1.55.0, roadmap slice 2.9): the platform base and the Organization layer version, beside the Agent layer the pinned Agent version names. Null for a Call admitted before the api resolved them; absent from an api older than 1.55.0, which a reader treats as null.
purposeCallPurposenoWhy the Call exists (1.56.0): evaluation for a test Call of an evaluation suite run or a conversation test run, which runs on the headless Engine and records engine: headless, transport: web and direction: inbound, its caller being simulated or scripted. Absent from an api before 1.56.0 and for every other Call; a reader treats its absence as conversation.
queued_atTimestampyes
retry_of_call_idCallId or nullnoThe attempt this Call retries (1.61.0); null for a first attempt.
ring_msinteger or nullnoFor an inbound phone Call (1.42.0, board #136): the ring-to-answer period, the milliseconds from the instant the inbound Call was received to the instant the Agent answered (answered_at), 0 to 60,000; the Call's recording begins with a ring tone for this duration, so a player marks the answer instant at this offset. Null for a web Call, an outbound Call and a Call that was not answered; absent from an api older than 1.42.0, which a reader treats as null.
scheduled_atTimestamp or nullnoWhen a scheduled Call's start job runs (1.61.0), aligned into its window, moved by a closed window; null for a Call started at once. Until the job admits the Call its queued_at is its creation instant, then the admission instant.
statusCallStatusyes
transportCallTransportyes
turn_countinteger or nullyesThe number of Turns, known once the Call is finalized.