Skip to main content
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"
}
FieldTypeNotes
uuidstringThe transcript’s public identifier.
meeting_uuidstringThe meeting’s public identifier; matches the path.
formatstringAlways jsonl.
download_urlstringPresigned S3 URL for the JSONL file, valid 1 hour.
url_expires_attimestampISO-8601 UTC time when download_url expires.
generated_attimestampISO-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: one JSON object per line, ordered by line_number. Each line is one utterance:
FieldTypeNotes
line_numberinteger1-based order within the transcript.
speaker_numberintegerSpeaker diarization ordinal.
speaker_namestring | nullIdentified speaker name; null when unknown.
speaker_rolestring | nullIdentified speaker role (e.g. Mayor); null when unknown.
start_time_msintegerOffset from media start, in milliseconds.
end_time_msintegerOffset from media start, in milliseconds.
textstringThe 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"])