zoxaAI
Homepage
API ReferenceCalls

Get a call

GET /api/v1/calls/{callId} — full lifecycle for one call. Includes request snapshot, transcript, recordings, cost, per-turn latency, and raw events.

GET /api/v1/calls/{callId}

Full detail for one call — everything zoxaAI persists about that call's lifecycle. The endpoint resolves recording storage keys to signed URLs at read time so you can play audio directly from the response.

Authentication

X-API-Key: zsk_...

Path parameters

ParamTypeDescription
callIdstringThe callId returned by POST /call (e.g. call_4e4e571f8c9b3cf8e99d).

Response

Returns HTTP 200 OK. The full CallDetail shape:

{
  "callId": "call_4e4e571f8c9b3cf8e99d",
  "transport": "outbound",
  "pipelineSource": "agent",
  "status": "completed",
  "connectionStatus": "completed",
  "endedReason": "user_hangup",

  "agentId": "550e8400-...",
  "agentName": "Sales bot",
  "campaignId": null,
  "campaignName": null,

  "platformNumber": "+14155550100",
  "customerNumber": "+14155559999",
  "telephonyProvider": "twilio",
  "providerCallSid": "CAxxxxxxx",
  "callSource": "api_outbound",
  "telephonySnapshot": { "provider": "twilio", "fromNumber": "+14155550100", "toNumber": "+14155559999", "credentialsFingerprint": "a1b2c3" },
  "bindingId": null,

  "requestSnapshot": {
    "type": "outbound",
    "callConfig": { "provider": "twilio", "phoneNumber": "+14155550100" },
    "toNumber": "+14155559999",
    "agentId": "550e8400-...",
    "contextVariables": { "customerName": "Aman" }
  },

  "startedAt": "2026-06-16T10:30:12Z",
  "endedAt":   "2026-06-16T10:32:01Z",
  "durationSeconds": 109,
  "createdAt": "2026-06-16T10:30:10Z",
  "updatedAt": "2026-06-16T10:32:01Z",

  "cost": 0.0185,
  "costBreakdown": { "llm": 0.012, "tts": 0.005, "stt": 0.0015 },

  "configSnapshot": { "name": "Sales bot", "systemPrompt": "...", "llm": { "provider": "openai", "model": "gpt-5.4-mini" } },
  "contextVariables": { "customerName": "Aman" },

  "recordings": [
    { "url": "https://signed-url...", "format": "wav", "storage_backend": "minio" }
  ],
  "transcript": { "url": "https://signed-url..." },

  "logs":        { "telephony_status_callbacks": [/*...*/] },
  "usageInfo":   { "llm_tokens_in": 320, "llm_tokens_out": 410, "tts_chars": 1820, "stt_seconds": 47 },
  "analysis":    { "summary": "User confirmed appointment for next Tuesday." },
  "latencySummary": { "userToBotMs_p50": 850, "userToBotMs_p95": 1320 },

  "tags": ["api", "outbound"],

  "turns":  [/* per-turn rows, see CallTurn below */],
  "events": [/* fine-grained pipeline events, see CallEvent below */]
}

Top-level fields

Same as list item plus:

FieldTypeDescription
connectionStatusstring | nullDid the call connect — completed, or the reason it never did. See connectionStatus values.
endedReasonstring | nullWhy a connected call ended (user_hangup, agent_hangup, silence_timeout, max_duration, voicemail, transferred, pipeline_error, cancelled, unknown). null when the call never connected. See endedReason values.
providerCallSidstring | nullProvider's own call id (Twilio CallSid, Vobiz call_uuid). Use it to cross-reference in the provider console.
telephonySnapshotobject | nullProvider/number/fingerprint metadata. Credentials are stripped server-side — only the fingerprint remains.
bindingIdint | nullSet on inbound API-first calls that matched an inbound binding.
requestSnapshotobject | nullThe original API request body (auth removed). For dashboard/WebRTC calls, a composed view of agent + contextVariables + provider info. The unified "Config Snapshot" panel in the dashboard reads this.
configSnapshotobjectThe resolved Agent Config that drove the call — prompt, greeting, llm/stt/tts, tools, call guards, etc. Provider auth is NOT included (telephony credentials live separately on telephonySnapshot and are redacted; LLM/TTS/STT API keys are resolved server-side and never serialized into the snapshot).
contextVariablesobject | nullVariables substituted into the snapshot.
recordingsarray | nullOne entry per recording. url is a signed CDN URL valid for ~1 hour.
transcriptobject | null{ url: signed-url }. Format depends on storage backend; JSONL is standard.
logsobject | nullPipeline-level logs (telephony callbacks, etc.).
usageInfoobject | nullToken counts, TTS chars, STT seconds.
analysisobject | nullPost-call analysis when enabled. Includes summary and any custom extraction.
latencySummaryobject | nullAggregate latency stats across all turns.
turnsarrayPer-turn latency + token breakdown. See below.
eventsarrayFine-grained pipeline events (turn start/end, interruptions, tool calls). See below.

turns[] — per-turn breakdown

One row per conversation turn, ordered by turnNo.

FieldTypeDescription
turnNointTurn number, starting at 1.
startedAt / endedAtISO 8601 | nullTurn boundaries.
durationMsint | nullEnd − start.
wasInterruptedboolTrue if the user spoke over the agent.
userToBotMsint | nullRound-trip latency — user stops speaking → bot first audio.
llmTtfbMsint | nullTime-to-first-byte from the LLM.
ttsTtfbMsint | nullTTFB from the TTS provider.
sttTtfbMsint | nullTTFB from the STT provider on this turn.
textAggMsint | nullTime spent aggregating tokens into a sentence before TTS.
tokensIn / tokensOutint | nullLLM tokens this turn.
tokensCacheRead / tokensCacheCreate / tokensReasoningint | nullDetailed token accounting where the provider reports it.
ttsCharsInputint | nullCharacters sent to TTS this turn.
botSpeakingMsint | nullHow long the bot's TTS played.
llmModel / ttsVoice / sttModelstring | nullModels used (lets you compare cost/latency across providers).
toolCallCountintFunction calls invoked this turn.
toolCallTotalMsintTotal time spent inside tools.
payloadobjectRaw turn metadata (transcript snippet, etc.).

events[] — fine-grained pipeline events

Ordered by tMs (milliseconds since call start). Use for visualizing the timeline.

FieldTypeDescription
tMsintEvent timestamp in ms since call start.
kindstringEvent type. Examples: turn_start, turn_end, interruption, tool_call_start, tool_call_end, error.
processorstring | nullWhich pipeline processor emitted it.
turnNoint | nullAssociated turn, if any.
payloadobjectEvent-specific data.

Examples

curl https://dashboard.zoxa.ai/api/v1/calls/call_4e4e571f8c9b3cf8e99d \
  -H "X-API-Key: zsk_..."
const res = await fetch(
  `https://dashboard.zoxa.ai/api/v1/calls/${callId}`,
  { headers: { "X-API-Key": "zsk_..." } },
);
const call = await res.json();
console.log(call.connectionStatus, call.endedReason, call.durationSeconds, call.cost);
if (call.recordings?.[0]?.url) {
  // signed URL valid ~1h
  playAudio(call.recordings[0].url);
}
import httpx

call = httpx.get(
    f"https://dashboard.zoxa.ai/api/v1/calls/{call_id}",
    headers={"X-API-Key": "zsk_..."},
).json()

print(call["connectionStatus"], call["endedReason"], call["durationSeconds"], call["cost"])
for turn in call["turns"]:
    print(turn["turnNo"], "user→bot:", turn["userToBotMs"], "ms")

Errors

StatusdetailWhen
400"No organization selected"Auth missing org context.
401auth errorsSee Errors.
404"Call not found"callId doesn't exist in your organization, or belongs to another org.
{ "detail": "Call not found" }

404 covers both "id doesn't exist" and "exists in a different org" — your code treats them the same.

Notes on behavior

  • Signed URLs expire. Recording / transcript URLs are signed at read-time and expire within ~1 hour. Fetch fresh URLs by re-calling this endpoint.
  • Snapshot redaction is unconditional. telephonySnapshot.credentials and requestSnapshot.callConfig.auth are stripped server-side before serialization — even in debug mode, you'll never see raw provider tokens here.
  • turns and events can be empty for calls without per-turn observability data.

On this page