Get one call
The same projection GET /v1/calls returns, for a single call. A live browser test (direction=web_test) is a real call and is returned here; a call your agent placed inside a simulation-suite run is platform-synthetic and is not found here.
Request
- Base URL: https://api.skysay.ai
- URL: https://api.skysay.ai/v1/calls/{call_id}
- Auth: HTTP bearer
Path parameters
Response
Call, with where its workflow ended
What was heard after the call was answered, which is a different question from whether it was answered at all: a carrier bridges audio for a ringback replacement tune or a hold-music loop exactly as it does for a person, so the status says the line answered and this says what was on it. human means a person was heard. non_human_audio means nothing a person did was ever heard: continuous music or tones held the line, or a recording repeated the same cycle of things over and over; reason_detail names which kind. silent means the line answered and nothing at all was heard. unknown means the detector ran and reached no decision inside its window, which is deliberately NOT the same as the empty string: empty means no verdict was reported at all, on a call placed before this field shipped, on an agent whose collection is switched off, or on a call whose media never started. Detection is deliberately narrow and only claims non_human_audio for unbroken non-human audio, so a recorded announcement or an IVR menu with pauses in it reads as human or unknown rather than being classified here -- unless it repeats itself, which is the one text-based verdict, looping_recording.
Specific-call detail only. A managed workspace browser worker's frozen outcome, readable before transport completion. Empty means unknown. browser_startup_failed means the requested opening failed before observed agent output; worker_ended confirms worker teardown. Neither changes transport status or promises a refund.
The small, non-secret JSON object you supplied at call creation, without any variable the agent declares as protected or as a keypad field.
Destination (outbound) or number (inbound) country.
inbound, outbound, web_test (a live browser test), or homepage_demo (a conversation with one of your AI agents in the live demo on the Skysay homepage, recorded like a call and never billed to your wallet) for a call your agent placed or answered. A call seeded by the demo/artifact-import tooling can carry other values, such as imported, verbatim from that import.
Why the call ended. browser_startup_failed means a workspace browser test requested an opening that failed before observed agent output; it does not promise a refund. funding_exhausted means the last funded runtime allowance expired; reason_detail is insufficient_balance for a confirmed funding refusal or renewal_unavailable when renewal could not be confirmed. Holds estimate usage and do not cap the final cost. Other reasons fall into three groups. Two are the ordinary end of a call that went well: agent_completed when the agent finished the conversation and ended the call itself, which is the usual outcome of a workflow that runs to its last step, and remote_party_disconnected when the other party hung up. Six are endings the platform initiates: agent_unresponsive, described below, hangup_requested when someone ends the call from the workspace or through POST /v1/calls/{call_id}/hangup, max_call_duration_reached when the call hits its configured limit, no_caller_speech_after_answer when the call is answered but nobody ever speaks, no_human_after_answer when the call is answered but nothing on the line was a person: only music or tones were ever heard, or a recording repeated the same cycle of things over and over, and caller_unresponsive when both sides fell silent after the agent had spoken: after 30 seconds of silence the agent asks whether the caller is still there (once per silent stretch, at most three times per call), and the call ends politely 15 seconds after that question if nobody answers. This ending is rolling out: while it is in observation the platform records what it would have done and does not end calls, so the value does not yet appear. A caller who answers, even with one word, simply continues the conversation. The last two name an ending nobody chose, neither the people on the call nor the platform: media_session_lost, when the media session went away underneath a live call -- the room was deleted, or the connection to it failed -- and model_session_lost, when the conversation engine behind the call failed and could not be recovered while the media session was still up, so the platform ended the call rather than leave the line open with nobody on it. agent_unresponsive is the platform ending a call whose agent stopped answering while its engine stayed connected: the caller finished speaking and the agent produced nothing for the whole of the agent's voice_polish.model_unresponsive bound, which counts only the time the caller was NOT speaking. It reports reason_detail model_unresponsive. It says what was observed -- a silent agent -- and not that anything failed, because a voice-to-voice engine reports nothing when it stops answering. The same ending, with an empty reason_detail, closes a call whose agent could not produce its opening: when the opening fails before anything is heard, the platform asks for it once more if that cannot repeat or overlap anything already said, and if the opening still never reaches the caller it ends the call instead of leaving them in silence (on an incoming call answered by a voice-to-voice engine, which already hears and answers the caller, the call continues instead). Calls completed before 2026-09-25 reported this ending as model_session_lost with the same reason_detail. In all three, nobody hung up, no limit fired and the agent did not finish. Each reports what was observed rather than guessing at a cause, so a call that ends this way is not reported as an operator hang-up even when an operator had just asked for one; that request is answered separately and says the call was already gone. ivr_timeout is the platform ending a call that was waiting in a phone menu or a hold queue (phone menu navigation); reason_detail says why: hold_limit (the hold time ran out), navigation_limit (the time allowed in menus ran out), deadline (the call's overall maximum length was reached while waiting), menu_no_path (the menu offered no way to a person) or data_not_authorised (the menu asked for a value the call did not supply or may not give). When the other party hangs up while a call is waiting in a menu or on hold, the reason stays remote_party_disconnected and reason_detail is during_hold. no_human_after_answer can carry recorded_message_only (a recording and nothing else answered) and media_session_lost can carry navigation_detector_lost. Empty on a call that completed before this field shipped, and on a call that has not completed. A call that FAILED reports its reason in technical_failure.failure_reason_code instead; the two vocabularies are separate.
The wallet reservation estimate in minor currency units, made at admission time. This is not settled billing: some statuses hold no reservation at all (see NO_LEDGER_MOVEMENT statuses), and a completed call's real charge is settled separately from recording/artifact import.
Your own stable case/reference ID, echoed back verbatim; empty string when not set. The same value delivered in webhook event bodies.
Your owned number this call used, when applicable.
Whether a person was reached earlier in the call, as the platform's phone-menu and hold handling reported it with the ending: true when someone was spoken to before the call ended (a conversation, then a transfer into a queue that ran out of time), false when nobody was reached, and null when the call did not report it (a call that completed before this field shipped, one whose agent does not navigate phone menus, and one that ended another way). It is what separates a wait that ran out after a conversation from one that never reached anyone: ivr_timeout with hold_limit or deadline, and remote_party_disconnected with during_hold, are retried by a campaign only when this is false, and the recording of such a call counts as talk time (and the call as a pick-up) only when it is true.
The carrier/provider's own call identifier. Empty until the call is actually dialed out to the provider.
Required, free-form outbound purpose declaration -- a non-empty purpose is the compliance paper trail; a novel purpose token is never refused for being novel. Documented catalog (pick one or send your own token): appointment, booking_confirmation, callback_requested, customer_outreach, delivery_notification, ops_alert, other, payment_reminder, personal_errand, reservation, status_check, support.
Qualifies either answer_classification or ended_reason, and says which by the value. insufficient_balance and renewal_unavailable qualify only funding_exhausted: confirmed insufficient funds versus unavailable authorization, respectively. caller_tune, hold_music and looping_recording appear only with answer_classification non_human_audio, and no_audio only with silent: looping_recording means the far end said the same cycle of things over and over, a recording on repeat, rather than music or tones. model_unresponsive appears with ended_reason agent_unresponsive -- and, on calls completed before 2026-09-25, with model_session_lost -- and means the call was ended by the platform because the agent produced nothing at all for the whole of its bound of caller-free time after the caller finished speaking -- as opposed to the same reason reached because the conversation engine reported its own failure. hold_limit, navigation_limit, deadline, menu_no_path and data_not_authorised appear only with ended_reason ivr_timeout, during_hold only with remote_party_disconnected, recorded_message_only only with no_human_after_answer and navigation_detector_lost only with media_session_lost, as described on ended_reason. Empty when neither needs qualifying, which is most calls. This is not ended_reason itself: that one names the ending, this one adds to it.
Optional, never enforced or required -- outbound is not restricted to business recipients. Persisted verbatim on the call row if sent; SMS has no recipient_type column, so it is accepted but not stored there.
not_started or disabled when there is no recording yet, otherwise the latest recording's own status.
Your own per-call overrides captured at call start (e.g. instructions, first_message, language). Never provider credentials.
Always 'live' on this customer-facing route -- a simulation-suite or other synthetic room is not found here at all.
Call lifecycle status, e.g. requested, queued, dialing, ringing, answered, in_progress, media_started, completed, failed, busy, no_answer, canceled, live_blocked, policy_blocked, needs_review (held for review: never dialled, with a call.failed at once). Not a closed set: track it as an opaque string and rely on the call.* events for exact transitions.
Changes
No recorded changes to this operation across all 1 revision of this API.