---
title: "Get the post-call merged transcript"
method: GET
path: "/calls/{call_id}/transcript-merged"
tags: ["calls"]
---

# Get the post-call merged transcript

`GET /calls/{call_id}/transcript-merged`

The post-call merged transcript: both sides of the call on one timeline, built from the dual-channel recording after the call ends. This is a different, fuller record than the live transcript_full rows, not a tidied-up copy of them - the recording captures the callee's channel in full, so the merged transcript routinely contains speech the live pipeline never transcribed: IVR phone trees, hold and queue announcements, anything said before the STT gate opened. If a recording plainly contains something your transcript doesn't, this endpoint is where to look.

## Path parameters

- `call_id` string, required

## Headers

- `X-API-Key` string, nullable

## Response `200`

Successful Response

- MergedTranscript — The post-call merged transcript: both sides of the call on one timeline, built from the dual-channel call recording after the call ends. A fuller record than the live transcript_full - see GET /calls/{call_id}/transcript-merged.
  - `version` integer, required
  - `duration_ms` integer, required
  - `calibration_delta_ms` number, required — 0 whenever both sides came off one recording; non-zero only on the single-channel fallback, where the two sources have to be aligned.
  - `turns` MergedTranscriptTurn[], required
    - `speaker` 'bot' | 'hostess', required — bot = the agent; hostess = the other party - staff, receptionist or IVR (the name is historical and covers every callee-side voice).
    - `start_ms` integer, required
    - `end_ms` integer, required
    - `text` string, required
    - `source` 'deepgram_batch_multichannel' | 'deepgram_live_multichannel' | 'deepgram_batch' | 'deepgram_live', required — Where the turn came from: deepgram_batch_multichannel = the dual-channel recording transcribed per channel (the normal case - exact timing on one clock); deepgram_live_multichannel = per-channel live STT; deepgram_batch = a single-channel recording (bot side only); deepgram_live = live STT (callee side).
    - `words` object[] — Per-word timings, when the source provides them.
      - `start_ms` integer
      - `end_ms` integer
      - `text` string
    - `overlap_with_next` boolean — This turn overlapped the next one in time (cross-talk). When true, end_ms has been trimmed to the next turn's start_ms; the untrimmed value is in original_end_ms.
    - `original_end_ms` integer — The pre-trim end_ms, present only when overlap_with_next is true.
    - `timing_estimated` boolean — The text is real but the milliseconds are a reading order, not a measurement - don't plot such turns on a timeline.

## Other responses

- `202` — The merger hasn't run yet - it fires seconds after the call ends. Retry after the `transcript_ready` SSE event, poll this endpoint, or request the transcript directly with POST /calls/{call_id}/transcript-merged/rebuild. Note 202 is not a promise the transcript is coming: a merge that already ran and failed answers 202 too (the automatic trigger fires once per call and is not retried), so a 202 that persists well past the call's end is the cue to force one rebuild rather than keep polling.
- `401` — Missing or invalid X-API-Key.
- `404` — Call not found or isn't yours - also returned for calls where the callee declined recording (no verbatim transcript may be served; the summary + outcome on GET /calls/{call_id} remain available).

---

[API](https://skmtc.dev/voygr/apis/voygr-calls-api.md) · [All operations](https://skmtc.dev/voygr/apis/voygr-calls-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/voygr/voygr-calls-api/revisions/a505c0ec5698/schema)
