> ## Documentation Index
> Fetch the complete documentation index at: https://docs.parable.so/llms.txt
> Use this file to discover all available pages before exploring further.

# The transcript document

> The JSON document served by the pull API and pushed by webhooks

One serializer, two transports: the pull API returns this document and the
webhook POSTs it. The schema is identical in both.

```json theme={null}
{
  "id": "9f2c...",
  "workspace_id": "e880...",
  "mode": "ambient",
  "title": "Device demo and data egress discussion",
  "summary": "...",
  "started_at": "2026-07-02T17:40:12.000Z",
  "ended_at": "2026-07-02T17:58:03.000Z",
  "duration_ms": 1071000,
  "device": { "id": "cdea...", "name": "Chroma main room" },
  "participants": [
    {
      "label": "Jeff",
      "name": "Jeff Huber",
      "email": "jeff@trychroma.com",
      "matched": true,
      "match_confidence": 0.91,
      "speech_ms": 412000
    },
    {
      "label": "Unknown 1",
      "name": null,
      "email": null,
      "matched": false,
      "match_confidence": null,
      "speech_ms": 655000
    }
  ],
  "segments": [
    { "start_ms": 0, "end_ms": 4200, "speaker": "Jeff Huber", "text": "..." }
  ],
  "transcript_text": "Jeff Huber: ...\nUnknown 1: ...",
  "calendar_event": null,
  "emitted_at": "2026-07-02T18:09:41.000Z"
}
```

## Field notes

* **Timestamps** are ISO-8601 UTC instants. There is no timezone field.
* **`mode`** — `"ambient"` (device-initiated on speech) or `"manual"`
  (user-initiated recording).
* **`title` / `summary`** — model-generated after processing. `title` is
  always present (falls back to a generic label); `summary` may be `null`.
* **`participants`** — one entry per detected speaker. `matched: true`
  means the voice resolved to a workspace member; `name` / `email` are
  theirs. Unmatched speakers (guests, unenrolled members) have `null`
  name/email — `label` is the pipeline's local label for them. `speech_ms`
  is total speaking time.
* **`segments`** — the source of truth: time-ordered utterances with
  speaker attribution (`speaker` is `null` for unattributed audio).
* **`transcript_text`** — convenience plain-text rendering of the same
  segments (one speaker-labeled line per consecutive same-speaker run), so
  an ingestion agent can consume text without assembling segments.
* **`device`** — the room, in practice: devices are named after where they
  live.
* **`calendar_event`** — reserved, always `null` today. When Parable's
  Google Calendar integration lands it will carry the matched event;
  additive, no schema break.
* **`emitted_at`** — when this document was rendered.

## Snapshot vs. current state

Webhook payloads and list responses are rendered at send time — a snapshot.
Later fixes (for example a speaker rename after the fact) don't re-emit;
re-fetch `GET /api/v1/captures/:id` for current state, which always
self-heals.
