---
title: "Get Call Bundle"
method: GET
path: "/egress/calls/{call_id}/bundle"
tags: ["egress"]
---

# Get Call Bundle

`GET /egress/calls/{call_id}/bundle`

## Request

- Base URL: `https://dev.whispa.net` (the document declares no server; this is the origin it was published from)
- URL: `https://dev.whispa.net/egress/calls/{call_id}/bundle`
- Auth: none declared

One-shot, partial-tolerant context for automated call analysis.

Every text-bearing section uses the same allowlist + scrub serializer as
its individual endpoint. Missing, malformed, upstream-failed, or
scrub-failed sections are withheld and named in ``omitted``; one optional
artifact can therefore never hide the rest of a call from the analyzer.

## Path parameters

- `call_id` string, uuid, required

## Response `200`

Successful Response

- EgressCallBundle: One-shot, PII-scrubbed analysis context for a call. Latency is intentionally included even though the cookie-auth call-detail API restricts it to admins: egress is separately machine-authenticated and latency is a first-class debugging signal. The value is a numeric rollup produced by ``calls.latency_rollup`` and requires no text scrubbing.
  - `call_id` string, uuid, required
  - `metadata` EgressCallMetadata, required: Allowlisted call metadata (no customer identity, no audio).
    - `id` string, uuid, required
    - `scenario` string, nullable, required
    - `call_mode` 'training' | 'production' | 'ai_agent', required: Call mode enumeration.
    - `call_source` 'live' | 'uploaded', required: Call source enumeration.
    - `call_direction` 'incoming' | 'outgoing' | 'internal', required: Direction of the call. - INCOMING: Customer called agent - OUTGOING: Agent called customer - INTERNAL: Extension-to-extension call
    - `status` 'ongoing' | 'completed' | 'unanswered' | 'error', required: Call lifecycle state. - ONGOING: Call is currently in progress - COMPLETED: Call finished (regardless of whether it was answered) - ERROR: Technical error/exception during call processing - UNANSWERED: DEPRECATED - Use status=COMPLETED + telephony_result=NO_ANSWER instead. Kept for backwards compatibility with existing database records.
    - `started_at` string, date-time, required
    - `ended_at` string, date-time, nullable, required
    - `duration_seconds` integer, nullable, required
    - `conversation_outcome` 'engaged' | 'refused' | 'wrong_person' | 'other', required: AI-classified judgement of what kind of conversation occurred. Only applicable when answered_by=HUMAN. Runtime actions such as scheduling a callback or transferring the caller are recorded independently in ``WorkflowDisposition`` and must never overwrite this judgement.
    - `workflow_disposition` 'none' | 'callback_scheduled' | 'transferred' | 'human_followup_required' | 'do_not_contact', required: Deterministic action the autonomous workflow took before finalizing. ``NONE`` is explicit for finalized autonomous calls with no special handoff/follow-up action. NULL means the dimension does not apply (human copilot, uploaded, or legacy calls), rather than overloading NULL with two meanings.
    - `agent_end_reason` 'conversation_complete' | 'existing_arrangement_claimed' | 'customer_requested_human' | 'identity_verification_failed' | 'customer_declined_to_engage' | 'customer_unavailable' | 'wrong_person' | 'do_not_contact' | 'hardship_detected' | 'dispute_raised' | 'escalation' | 'voicemail' | 'no_answer' | 'caller_hung_up' | 'caller_abandoned' | 'answer_failed' | 'answer_timeout' | 'dial_failed' | 'transfer_failed' | 'screening_timeout' | 'idle_timeout' | 'max_duration' | 'api_hangup' | 'error' | 'other', required: Normalized reason an autonomous call ended. The raw runtime string remains in ``analyzer_artifacts`` for diagnostics. This enum is the stable operational projection: semantic reasons exposed to the voice model plus bounded technical termination categories. Novel runtime endings degrade to ``OTHER`` instead of failing finalization.
    - `answered_by` 'human' | 'voicemail' | 'unclear', required: Who answered the call (AI-classified from transcript). This is the first stage of call classification - determining whether a human or voicemail answered the call.
    - `telephony_result` 'connected' | 'busy' | 'no_answer' | 'rejected' | 'failed', required: Telephony-level call connection result. Represents what happened at the telephony level before any conversation. This is typically provided by the PBX/telephony system, not AI-classified.
    - `detected_scenario` string, nullable, required
    - `client` string, nullable, required
    - `qa_score` integer, nullable, required
    - `idv_outcome` 'verified' | 'partial' | 'incomplete', required: Identity-verification outcome for a call, denormalized from the IDV analyzer. Only set when IDV was required and a verdict was produced. A NULL column can mean IDV was not applicable, is still pending, or no verdict was available; API consumers use ``idv_required`` plus call status to distinguish those states. Derived from the terminal `identity_verification_state["status"]`: - VERIFIED: status `complete` — identity confirmed per the scenario's policy. - PARTIAL: at least one identity factor was confirmed, but the scenario's completion rule was never satisfied. - INCOMPLETE: required, and not a single factor was confirmed. PARTIAL exists because "not verified" covers two operationally different calls: one where the customer engaged with verification and it ran out of road, and one where it never started. Only the second is a candidate for "the agent didn't try". Note this is *tracking* state, not an adherence grade — the leadership IDV rate deliberately reads the reviewed QA scorecard instead (see `shared.idv`), because a human reviewer can correct it and the analyzer cannot. There is deliberately no `skipped` outcome. The live state machine still has a `skipped` terminal so the analyzer stops firing on a call that is not going to verify, but as a *result* it said nothing true that `incomplete` doesn't: verification was required and did not happen. It also read as a third, ambiguous colour on any report — neither pass nor fail — while the thing a reviewer actually needs to know (was skipping appropriate here?) is a transcript judgement the tracker never made.
    - `idv_source` 'live' | 'post_call' | 'inherited', required: Which mechanism produced the call's persisted IDV state. - LIVE: the in-call IDV analyzer's terminal state (the normal path). - POST_CALL: the post-call IDV judge — runs when the live analyzer never produced a state (e.g. no scenario reached the session) or the scenario was reclassified after the call, judging the full transcript against the resolved scenario's IDV rules. - INHERITED: the origin leg of a transfer verified the customer, and this recipient leg inherits that verdict — verification travels with the conversation, not the leg (see calls.idv_resolution). The verification exchange is on the origin leg's transcript, not this one's.
    - `recording_disclosed` boolean, nullable, required
    - `tags` unknown
    - `agent_id` string, nullable, required
    - `account_id` string, uuid, nullable: Opaque Whispa account row id (the Accounts page id) the call is linked to; null when unlinked or the account was never synced
  - `outcome` EgressOutcomeResponse, required: Post-call outcome plus deterministic autonomous-runtime facts.
    - `call_id` string, uuid, required
    - `call_outcome` EgressCallOutcome, required: Structured collections commitment with transcript evidence scrubbed.
      - `commitment_shape` 'new_arrangement' | 'immediate_payment' | 'settlement' | 'arrangement_repair' | 'promise_reset' | 'deferral' | 'refused' | 'other', required: Taxonomy of commitment outcomes extracted from a collections call.
      - `commitment_horizon` 'immediate' | 'within_7d' | 'within_30d' | 'beyond_30d' | 'indefinite', required: When the committed money is expected to land.
      - `is_new_commitment` boolean, required
      - `installment_amount` number, nullable, required
      - `first_payment_amount` number, nullable, required
      - `payment_frequency` 'one_off' | 'weekly' | 'fortnightly' | 'monthly', required: Cadence of a scheduled commitment.
      - `installment_count` integer, nullable, required
      - `explicit_total_amount` number, nullable, required
      - `total_commitment_amount` number, nullable, required
      - `total_commitment_source` 'explicit' | 'derived' | 'not_available', required: Provenance of `total_commitment_amount`.
      - `confidence` number, required
      - `evidence_quote` string, required: Supporting transcript excerpt; scrubbed
    - `workflow_disposition` 'none' | 'callback_scheduled' | 'transferred' | 'human_followup_required' | 'do_not_contact', required: Deterministic action the autonomous workflow took before finalizing. ``NONE`` is explicit for finalized autonomous calls with no special handoff/follow-up action. NULL means the dimension does not apply (human copilot, uploaded, or legacy calls), rather than overloading NULL with two meanings.
    - `agent_end_reason` 'conversation_complete' | 'existing_arrangement_claimed' | 'customer_requested_human' | 'identity_verification_failed' | 'customer_declined_to_engage' | 'customer_unavailable' | 'wrong_person' | 'do_not_contact' | 'hardship_detected' | 'dispute_raised' | 'escalation' | 'voicemail' | 'no_answer' | 'caller_hung_up' | 'caller_abandoned' | 'answer_failed' | 'answer_timeout' | 'dial_failed' | 'transfer_failed' | 'screening_timeout' | 'idle_timeout' | 'max_duration' | 'api_hangup' | 'error' | 'other', required: Normalized reason an autonomous call ended. The raw runtime string remains in ``analyzer_artifacts`` for diagnostics. This enum is the stable operational projection: semantic reasons exposed to the voice model plus bounded technical termination categories. Novel runtime endings degrade to ``OTHER`` instead of failing finalization.
    - `ai_call_end_reason` string, nullable, required
    - `ai_call_identity_verified` boolean, nullable, required
    - `ai_call_agreement` EgressAiCallAgreement, required: Customer-confirmed terms recorded by the autonomous runtime.
      - `amount` string, nullable
      - `date_iso` string, nullable
      - `date_spoken` string, nullable
      - `method` string, nullable
      - `frequency` string, nullable
    - `ai_call_payment` EgressAiCallPayment, required: Safe payment status persisted by the autonomous runtime. A payable URL is intentionally not part of this schema or the underlying artifact; ``invoice_id`` is sufficient for an authorized operator to look the payment up in Glider.
      - `provider` string, nullable
      - `invoice_id` string, nullable
      - `status` string, nullable
      - `link_opened` boolean, nullable
      - `link_delivery_status` string, nullable
  - `transcript` EgressTranscriptResponse, required: Scrubbed transcript for a call.
    - `call_id` string, uuid, required
    - `chunks` EgressTranscriptChunk[], required
      - `sequence` integer, required
      - `speaker` string, required
      - `text` string, required
      - `start_time` number, nullable, required
      - `end_time` number, nullable, required
  - `summary` EgressSummaryResponse, required: Scrubbed call summary (structured JSON and/or legacy markdown).
    - `call_id` string, uuid, required
    - `summary` unknown
    - `summary_markdown` string, nullable, required
  - `coaching` EgressCoachingResponse, required: Structured, scrubbed coaching generated for a call.
    - `call_id` string, uuid, required
    - `coaching` CoachingFeedback, required: Structured coaching feedback with three evaluation dimensions.
      - `dimension_1` FeedbackDimension, required: Feedback for a specific dimension. `extra="ignore"` allows historical rows that still carry a numeric `score` field to deserialize cleanly — the value is dropped on read.
        - `title` string, required: Title of this dimension
        - `positive_feedback` string[], required: The single most important thing the agent did well in this dimension (one item; one sentence, max ~15 words)
        - `improvements` string[], required: The single most impactful, actionable improvement for this dimension (one item; one sentence, max ~20 words, starting with a verb; a second only for a separate compliance-critical issue)
      - `dimension_2` FeedbackDimension, required: Feedback for a specific dimension. `extra="ignore"` allows historical rows that still carry a numeric `score` field to deserialize cleanly — the value is dropped on read.
        - `title` string, required: Title of this dimension
        - `positive_feedback` string[], required: The single most important thing the agent did well in this dimension (one item; one sentence, max ~15 words)
        - `improvements` string[], required: The single most impactful, actionable improvement for this dimension (one item; one sentence, max ~20 words, starting with a verb; a second only for a separate compliance-critical issue)
      - `dimension_3` FeedbackDimension, required: Feedback for a specific dimension. `extra="ignore"` allows historical rows that still carry a numeric `score` field to deserialize cleanly — the value is dropped on read.
        - `title` string, required: Title of this dimension
        - `positive_feedback` string[], required: The single most important thing the agent did well in this dimension (one item; one sentence, max ~15 words)
        - `improvements` string[], required: The single most impactful, actionable improvement for this dimension (one item; one sentence, max ~20 words, starting with a verb; a second only for a separate compliance-critical issue)
  - `scorecard` EgressScorecardResponse, required: Allowlisted QA scorecard. Reviewer-identity fields on the stored artifact (``reviewed_by_name``, ``reviewed_by_user_id``) are deliberately absent — ``status`` still tells the agent whether a human reviewed it. All free text is scrubbed.
    - `call_id` string, uuid, required
    - `template_key` string, required
    - `display_name` string, required
    - `generated_at` string, date-time, required
    - `status` string, required
    - `reviewed_at` string, date-time, nullable, required
    - `overall_score` integer, nullable, required
    - `total_max_score` integer, required
    - `pass_fail_status` 'pass' | 'fail' | 'not_applicable', nullable, required
    - `auto_fail` boolean, required
    - `auto_fail_reasons` string[], required
    - `sections` EgressScorecardSection[], required
      - `key` string, required
      - `title` string, required
      - `items` EgressScorecardItem[], required
        - `key` string, required
        - `title` string, required
        - `score_type` 'pass_fail' | 'numeric', required
        - `result` 'met' | 'not_met' | 'not_applicable', required
        - `score` integer, nullable, required
        - `max_score` integer, nullable, required
        - `score_excluded` boolean, required
        - `manual_review` boolean, required
        - `comment` string, nullable: Model rationale; scrubbed
        - `evidence` string, nullable: Transcript snippet; scrubbed
      - `subtotal` integer, nullable, required
      - `subtotal_max_score` integer, nullable, required
    - `commentary` string, nullable: Overall QA commentary; scrubbed
  - `tool_calls` EgressToolCallsResponse, required: Scrubbed terminal tool calls for a call.
    - `call_id` string, uuid, required
    - `tool_calls` EgressToolCall[], required
      - `tool_call_id` string, required
      - `tool_name` string, required
      - `status` 'completed' | 'cancelled', required
      - `arguments` object, nullable, required
      - `result` object, nullable, required
      - `after_sequence` integer, required
      - `tool_index` integer, required
      - `started_elapsed_seconds` number, nullable, required
      - `completed_elapsed_seconds` number, nullable, required
  - `latency` CallLatencySummary, required: Typed admin-only latency payload stored on a completed call.
    - `vaqi_l` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
      - `p50_ms` integer, nullable, required
      - `p95_ms` integer, nullable, required
      - `worst_ms` integer, nullable, required
      - `n` integer, required
    - `legs` SuggestedResponseLatencyLegs, required
      - `stt` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
        - `p50_ms` integer, nullable, required
        - `p95_ms` integer, nullable, required
        - `worst_ms` integer, nullable, required
        - `n` integer, required
      - `commit` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
        - `p50_ms` integer, nullable, required
        - `p95_ms` integer, nullable, required
        - `worst_ms` integer, nullable, required
        - `n` integer, required
      - `ttft` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
        - `p50_ms` integer, nullable, required
        - `p95_ms` integer, nullable, required
        - `worst_ms` integer, nullable, required
        - `n` integer, required
      - `delivery` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
        - `p50_ms` integer, nullable, required
        - `p95_ms` integer, nullable, required
        - `worst_ms` integer, nullable, required
        - `n` integer, required
    - `autonomous_voice` AutonomousVoiceLatencySummary
      - `response_total` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
        - `p50_ms` integer, nullable, required
        - `p95_ms` integer, nullable, required
        - `worst_ms` integer, nullable, required
        - `n` integer, required
      - `legs` SrcCallsSchemasAutonomousVoiceLatencyLegs, required: Stages of one spoken reply, in order; on a turn they sum to its total. The stages added after the first calls were recorded are optional, so the summaries stored on those calls still load.
        - `endpointing` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
          - `p50_ms` integer, nullable, required
          - `p95_ms` integer, nullable, required
          - `worst_ms` integer, nullable, required
          - `n` integer, required
        - `turn_release` LatencyLegSummary: Percentiles for one latency leg and its contributing sample count.
          - `p50_ms` integer, nullable, required
          - `p95_ms` integer, nullable, required
          - `worst_ms` integer, nullable, required
          - `n` integer, required
        - `llm_ttft` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
          - `p50_ms` integer, nullable, required
          - `p95_ms` integer, nullable, required
          - `worst_ms` integer, nullable, required
          - `n` integer, required
        - `tool` LatencyLegSummary: Percentiles for one latency leg and its contributing sample count.
          - `p50_ms` integer, nullable, required
          - `p95_ms` integer, nullable, required
          - `worst_ms` integer, nullable, required
          - `n` integer, required
        - `speech_release` LatencyLegSummary: Percentiles for one latency leg and its contributing sample count.
          - `p50_ms` integer, nullable, required
          - `p95_ms` integer, nullable, required
          - `worst_ms` integer, nullable, required
          - `n` integer, required
        - `tts_ttfb` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
          - `p50_ms` integer, nullable, required
          - `p95_ms` integer, nullable, required
          - `worst_ms` integer, nullable, required
          - `n` integer, required
        - `transport` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
          - `p50_ms` integer, nullable, required
          - `p95_ms` integer, nullable, required
          - `worst_ms` integer, nullable, required
          - `n` integer, required
      - `turns` AutonomousVoiceTurnCounts, required
        - `total` integer, required
        - `complete` integer, required
        - `incomplete` integer, required
      - `by_kind` SrcCallsSchemasAutonomousVoiceLatencyByKind: End-to-end response time split by what answered the caller.
        - `plain` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
          - `p50_ms` integer, nullable, required
          - `p95_ms` integer, nullable, required
          - `worst_ms` integer, nullable, required
          - `n` integer, required
        - `tool` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
          - `p50_ms` integer, nullable, required
          - `p95_ms` integer, nullable, required
          - `worst_ms` integer, nullable, required
          - `n` integer, required
        - `runtime` LatencyLegSummary, required: Percentiles for one latency leg and its contributing sample count.
          - `p50_ms` integer, nullable, required
          - `p95_ms` integer, nullable, required
          - `worst_ms` integer, nullable, required
          - `n` integer, required
      - `over_target` AutonomousVoiceOverTarget
        - `target_ms` integer, required
        - `replies` integer, required
        - `over` integer, required
      - `first_speech_ms` integer, nullable
      - `tool_handler` LatencyLegSummary: Percentiles for one latency leg and its contributing sample count.
        - `p50_ms` integer, nullable, required
        - `p95_ms` integer, nullable, required
        - `worst_ms` integer, nullable, required
        - `n` integer, required
      - `llm_thinking` LatencyLegSummary: Percentiles for one latency leg and its contributing sample count.
        - `p50_ms` integer, nullable, required
        - `p95_ms` integer, nullable, required
        - `worst_ms` integer, nullable, required
        - `n` integer, required
      - `llm_tokens_per_second` number, nullable
      - `unanswered_wait` LatencyLegSummary: Percentiles for one latency leg and its contributing sample count.
        - `p50_ms` integer, nullable, required
        - `p95_ms` integer, nullable, required
        - `worst_ms` integer, nullable, required
        - `n` integer, required
      - `barge_in_stop` LatencyLegSummary: Percentiles for one latency leg and its contributing sample count.
        - `p50_ms` integer, nullable, required
        - `p95_ms` integer, nullable, required
        - `worst_ms` integer, nullable, required
        - `n` integer, required
  - `idv` IdvRecord, required
    - `version` 1
    - `rule` IdvRuleGroup[], required
      - `fields` string[], required
      - `min` integer, required
    - `on_file` object, required
    - `path` 'not_required' | 'never_started' | 'first_try_pass' | 'pass_after_retry' | 'fail_exhausted' | 'hung_up_during_idv' | 'fail_ended', required
    - `seconds_to_verify` number, nullable, required
    - `keyterms_from_turn` integer, nullable, required
    - `answers` IdvAnswer[], required
      - `turn` integer, required
      - `at` number, nullable, required
      - `asked` string[], required
      - `style` 'open' | 'readback' | 'hint', nullable, required
      - `said_on_file` string[], required
      - `split` boolean, required
      - `accepted` string[], required
      - `rejected` string[], required
      - `judged_by` string[], required
      - `dropped` 'timeout' | 'unavailable' | 'stale', nullable, required
  - `langfuse` EgressLangfuseBundle, required: Inline scrubbed traces plus a compact generation index.
    - `traces` EgressTrace[], required
      - `id` string, required
      - `name` string, nullable, required
      - `timestamp` string, nullable, required
      - `latency` number, nullable, required
      - `total_tokens` integer, nullable: Sum of observation token usage, when reported. Counts only the returned observations — a lower bound when the response is truncated.
      - `observations` EgressTraceObservation[], required
        - `id` string, nullable, required
        - `type` string, nullable, required
        - `name` string, nullable, required
        - `model` string, nullable, required
        - `start_time` string, nullable, required
        - `end_time` string, nullable, required
        - `level` string, nullable, required
        - `status_message` string, nullable, required
        - `input` string, nullable: Stringified and scrubbed
        - `output` string, nullable: Stringified and scrubbed
    - `traces_truncated` boolean, required
    - `generations` EgressLangfuseGeneration[], required
      - `generation_name` string, required
      - `trace_id` string, required
      - `trace_url` string, required
    - `session_filter` string, required: JSON filter value for Langfuse's v2 observations endpoint
  - `generated_at` string, date-time, required
  - `omitted` EgressOmittedSection[], required
    - `section` string, required
    - `reason` string, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/whispa/apis/whispa-api.md) - [All operations](https://skmtc.dev/whispa/apis/whispa-api/llms.txt) - [OpenAPI document](https://skmtc.dev/whispa/apis/whispa-api/revisions/12c2e4aca43c?raw)
