Get Conversation

Beta
Retrieve a conversation by ID.

Authentication

AuthorizationBearer

Enter your API key with the Bearer prefix, e.g. ‘Bearer sk_…’.

Path parameters

conversation_idstringRequired

Conversation id (prefixed external id, conv_...).

Headers

Speechify-VersionstringOptional

Response headers

X-Request-IDstring
Unique identifier for this request, present on every response (2xx and non-2xx alike). If the caller sends an `X-Request-ID` request header the server echoes it back (sanitized and length-capped) so one logical request can be traced end-to-end; otherwise the server generates a fresh value. Log it on every response and quote it in support requests - it is the stable handle that ties your observation to Speechify's server-side logs, and it matches the `request_id` field in the error envelope.

Response

The requested conversation.
idstringformat: "^conv_[0-9a-hjkmnp-tv-z]{26}$"

Prefixed wire identifier (conv_<26 char Crockford base32>). URL paths accept only this prefixed form; legacy UUID path parameters are rejected with 404.

agent_idstringformat: "^agent_[0-9a-hjkmnp-tv-z]{26}$"

Prefixed wire identifier (agent_<26 char Crockford base32>) for the agent that answers this conversation.

statusenum
transportenum

How the caller reached the agent. web is the browser / SDK realtime path; the sip_* and phone variants come from the telephony stack.

created_atdatetime

When the conversation row was created (the call was initiated). Always present, including for conversations that never started — unlike started_at — so it is the timestamp to display and sort pending calls by.

metadatamap from strings to any
message_countinteger

Populated only on the list endpoint via a correlated subquery. Zero on single-row reads where the join cost isn’t paid.

started_atdatetime or null

Set when the first user participant joins the realtime voice session. Null between CreateConversation and the participant-joined event, and stays null if no user ever joins.

ended_atdatetime or null
duration_msinteger or null
cost_centsinteger or null
recording_urlstring or null
recording_started_atdatetime or null

When the recording file actually began capturing audio (LiveKit egress file started_at). Anchor transcript message offsets on this — not started_at — when seeking the recording: the file’s first frame trails the participant join by the egress recorder’s spin-up (~1-2s). Null when there is no recording or the row pre-dates the field.

end_reasonenum

Coarse termination category. Most reasons are assigned by the agent runtime as the call ends; caller_hangup may also be applied server-side as a post-call catch-all. The dial_* reasons are assigned server-side on a failed conversation for an outbound call that never connected.

  • voicemail_message_left — AMD machine-vm + we spoke the configured drop-message.
  • voicemail_hangup — AMD machine-vm + we terminated silently (action=hangup or empty-message bypass).
  • ivr_hangup — AMD machine-ivr + action=hangup.
  • unavailable_hangup — AMD machine-unavailable (mailbox full / disconnected).
  • agent_ended — LLM-driven end_call builtin.
  • inactivity_timeout — the call ended after the configured silence window elapsed with no activity.
  • loop_detected — a loop guard force-ended the call after several consecutive near-identical user turns (typically an IVR replaying its menu while the agent kept reacting instead of ending the call).
  • max_duration_reached - the max-call-duration limit force-ended the call at the platform ceiling (a safety bound on runaway calls).
  • over_capacity — inbound call refused because the workspace was over its active-call concurrency cap; the busy message played and the call hung up. Stamped server-side and excluded from billing.
  • caller_hangup — the caller’s leg went away. Stamped immediately when a SIP disconnect is observed; otherwise applied server-side shortly after the call ends as a catch-all (web tab close, network blip, etc.).
  • dial_no_answer — outbound dial: callee did not pick up (SIP 408/480/487, the ringing timeout expired).
  • dial_busy — outbound dial: the line was busy (SIP 486/600).
  • dial_rejected — outbound dial: the call was actively refused (SIP 401/403/407 carrier auth/permission, or 603/607/608 callee decline).
  • dial_failed — outbound dial: any other failure to connect (invalid number, carrier 5xx, malformed trunk address, TLS requirement, transport error). On a failed conversation with NULL duration_ms.
  • transferred — the caller’s leg was handed off to a phone number via SIP REFER (transfer_to_number); the carrier moved the leg and the agent’s side ended.
  • null — the termination category was not recorded. Legacy calls only; current calls always carry a reason.
caller_identitystring

Stable caller key (LiveKit participant identity) persisted at session start so the post-call memory extractor can pivot memories by (agent_id, caller_identity). Empty string for anonymous widget sessions.

from_numberstring or null

E.164 of the phone number that placed the call. For sip_outbound this is the workspace number used as the caller ID; for sip_inbound it is the external caller’s number. Null for web conversations and for older outbound rows, where the dialing caller id was not recorded before this field existed.

to_numberstring or null

E.164 of the phone number that received the call. For sip_outbound this is the external callee; for sip_inbound it is the workspace number the caller dialed. Null for web conversations and for legacy inbound rows whose room name did not embed the dialed number.

agent_snapshotobject

Frozen snapshot of the agent’s configuration at create time. Populated only on detail responses; list responses intentionally skip the column to keep the row small.

dynamic_variablesmap from strings to any

Customer-facing dynamic variables this call ran with: the agent’s stored variable defaults overlaid with the per-session dynamic_variables overrides, resolved to their values. Reserved system__* keys are excluded — they are runtime-derived and not part of the audit snapshot. Omitted for SIP inbound calls (which take no per-session variables) and for legacy conversations recorded before this field existed. Populated only on detail responses; the list endpoint skips it, mirroring agent_snapshot.

ivr_menu_idstring or nullformat: "^menu_[0-9a-hjkmnp-tv-z]{26}$"

Audit pointer at the cached IVR menu the navigator consulted on this call. NULL when the navigator never engaged OR after the referenced menu was invalidated (FK is ON DELETE SET NULL).

ivr_path_takenlist of maps from strings to any or null

Ordered log of the navigator’s per-call presses: [{fingerprint, dtmf, label}, ...]. Empty array means “navigator engaged but pressed nothing” (distinct from NULL = “navigator never engaged”).

ivr_surrender_reasonenum

Canonical code the worker emits when the IVR navigator gave up. NULL when the navigator completed cleanly OR never started a plan.

  • no_goal - the goal extractor returned empty.
  • no_cached_menu - AMD-time cache miss for the root fingerprint.
  • below_threshold - cached menu loaded but confidence < threshold.
  • fingerprint_mismatch - in-call prompt diverged from the cached menu fingerprint.
  • goal_ambiguous - cached options matched the goal more than once or not at all.
  • child_cache_miss - sub-menu fingerprint had no cached row.
  • dtmf_send_failure - DTMF press could not be delivered.
  • matched_option_missing_dtmf - defensive shape guard.
  • disabled - per-agent toggle off OR operator kill switch on.
  • repeated_prompt_max_retries - bounded press-retry on the same fingerprint hit its cap of 1.

Errors

401
Unauthorized Error
404
Not Found Error