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

# Transcript format

> How to fetch a meeting transcript and the structure of the JSONL artifact.

The transcript endpoint doesn't return the transcript text directly. It returns **metadata
plus a short-lived presigned URL** to download the transcript as a **JSONL** file (one
utterance per line) hosted in S3.

## Fetching a transcript

`GET /v1/meetings/{uuid}/transcript` returns the metadata envelope:

```json theme={null}
{
  "uuid": "d8e1f2a3-4b5c-6d7e-8f90-1a2b3c4d5e6f",
  "meeting_uuid": "9a1c2b3d-4e5f-6071-8293-a4b5c6d7e8f9",
  "format": "jsonl",
  "download_url": "https://hamlet-transcripts-prod.s3.us-west-1.amazonaws.com/…?X-Amz-Signature=…",
  "url_expires_at": "2026-06-22T15:30:00.000Z",
  "generated_at": "2026-05-22T09:20:00.000Z"
}
```

| Field            | Type      | Notes                                                  |
| ---------------- | --------- | ------------------------------------------------------ |
| `uuid`           | string    | The transcript's public identifier.                    |
| `meeting_uuid`   | string    | The meeting's public identifier; matches the path.     |
| `format`         | string    | Always `jsonl`.                                        |
| `download_url`   | string    | Presigned S3 URL for the JSONL file, valid **1 hour**. |
| `url_expires_at` | timestamp | ISO-8601 UTC time when `download_url` expires.         |
| `generated_at`   | timestamp | ISO-8601 UTC time when the artifact was built.         |

<Warning>
  `download_url` expires one hour after it's issued. Fetch the JSONL promptly, and request a
  fresh metadata response to get a new URL rather than caching the link.
</Warning>

<Note>
  Not every meeting has a transcript. If a meeting you're entitled to has no built artifact,
  this endpoint returns `404` (`not_found`) — never a broken link. The `has_transcript` flag
  on the meeting tells you in advance whether to call it.
</Note>

## Downloading the file

```bash theme={null}
# 1. Get the metadata + presigned URL
curl https://api.myhamlet.com/v1/meetings/9a1c…/transcript \
  -H "Authorization: Bearer hmlt_your_api_key"

# 2. Download the JSONL from the returned download_url (no auth header — the URL is presigned)
curl -o transcript.jsonl "https://hamlet-transcripts-prod.s3.us-west-1.amazonaws.com/…?X-Amz-Signature=…"
```

## JSONL line schema

The downloaded file is [JSON Lines](https://jsonlines.org/): one JSON object per line,
**ordered by `line_number`**. Each line is one utterance:

| Field            | Type           | Notes                                                        |
| ---------------- | -------------- | ------------------------------------------------------------ |
| `line_number`    | integer        | 1-based order within the transcript.                         |
| `speaker_number` | integer        | Speaker diarization ordinal.                                 |
| `speaker_name`   | string \| null | Identified speaker name; `null` when unknown.                |
| `speaker_role`   | string \| null | Identified speaker role (e.g. `Mayor`); `null` when unknown. |
| `start_time_ms`  | integer        | Offset from media start, in milliseconds.                    |
| `end_time_ms`    | integer        | Offset from media start, in milliseconds.                    |
| `text`           | string         | The utterance text.                                          |

```jsonl theme={null}
{"line_number": 1, "speaker_number": 0, "speaker_name": "Jane Doe", "speaker_role": "Mayor", "start_time_ms": 0, "end_time_ms": 4200, "text": "Call this meeting to order."}
{"line_number": 2, "speaker_number": 1, "speaker_name": null, "speaker_role": null, "start_time_ms": 4200, "end_time_ms": 9100, "text": "Present."}
```

Parse it line by line — don't load the whole file as a single JSON document:

```python theme={null}
import json, requests

meta = requests.get(
    "https://api.myhamlet.com/v1/meetings/9a1c…/transcript",
    headers={"Authorization": "Bearer hmlt_your_api_key"},
).json()

# The presigned URL needs no auth header.
resp = requests.get(meta["download_url"])
for line in resp.iter_lines():
    if line:
        utterance = json.loads(line)
        print(utterance["speaker_name"], "→", utterance["text"])
```
