Skip to main content
One serializer, two transports: the pull API returns this document and the webhook POSTs it. The schema is identical in both.
{
  "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.