## Documentation Index

Fetch the complete documentation index at: [/docs/llms.txt](/content/docs/llms.txt)

Use this file to discover all available pages before exploring further.

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:

```
{
  "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.     |

`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.

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.

## Downloading the file

```
# 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.                         |

```
{"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:

```
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"])
```

[Incremental sync](/content/docs/incremental-sync/index.html) [Errors](/content/docs/errors/index.html)
