Skip to main content

Overview

Send an audio clip in a single HTTP call and get back the verbatim transcript together with an LLM-rewritten version of it. The rewrite is on by default: with no configuration, it removes disfluencies and leaves every other word exactly as spoken. Set llm_instruction to reshape the transcript into something else instead — a chart note, a booking confirmation, or whatever shape you describe. The verbatim transcript always comes back alongside the rewrite. Dictation accepts up to 120 seconds of audio per call. You can send the audio after the recording finishes, or upload it as it is captured so most of the transfer happens while the user is still speaking — see Uploading while recording.
Dictation is a separate service from Sync, Pre-recorded, and Streaming STT. It has its own hostname (dictation.assemblyai.com) and its own request shape. The Python SDK wraps it as DictationTranscriber from version 1.5.1; in every other language, call it over HTTP.

Before you begin

To call the Dictation API, you need:
  • An API key — browse to API Keys in your dashboard and copy your key.
  • An audio clip in WAV format, or raw 16-bit PCM. Maximum 120 seconds.
  • A client — either the AssemblyAI Python SDK (pip install "assemblyai>=1.5.1"), or any HTTP client: cURL, Python 3.8+ with requests or httpx, or Node.js 18+ with fetch.

Endpoint

Send the parts in order — config first, then audio. The endpoint reads the body as it arrives, so you can start the request while the user is still speaking and upload the audio as it is captured; see Uploading while recording. /v1/transcribe/stream is the path this endpoint shipped under and still reaches the same handler. There is no unversioned alias.

Authentication

Pass your AssemblyAI API key in the Authorization header as the raw key, with no Bearer prefix:
An invalid API key returns 404 Not Found with {"detail": "Invalid API key"}, not 401. Treat any 404 from this endpoint as an auth failure.

Request

The body is multipart/form-data with two parts, in this order: Config comes first, and is required, because the server starts transcribing the audio as it arrives and cannot begin without it. An audio part that arrives before config, or a request with no config part at all, is rejected with 400. WAV and raw PCM only. Compressed formats — MP3, M4A, FLAC, OGG, WebM — are rejected with 415.

Config parameters

Every field except llm_instruction controls transcription. llm_instruction customizes the transcript rewrite, which is applied by default — see Rewriting the transcript. Over HTTP, unknown fields are forwarded to the transcription engine as-is, so transcription parameters added in the future work without dictation-side changes.
DictationConfig in the Python SDK is stricter: it accepts exactly the fields in the table above and rejects anything else with a validation error, rather than passing it through. That turns a typo, or a Sync-only option used by mistake, into an error instead of a setting that quietly does nothing. To send a field the SDK does not know about yet, build the config part over HTTP.

Rewriting the transcript

The rewrite is applied by default. Omitting llm_instruction — or the whole config part — runs the default cleanup task, which removes disfluencies only (filler sounds and phrases, false starts, stammered repeats). Every kept word, its spelling, and its punctuation stay exactly as spoken. To customize the rewrite, set llm_instruction to a plain-English description of the task you want (max 2048 characters). It replaces the default cleanup task:
The rewrite never replaces the transcription. text is always the verbatim transcript, and the rewritten version arrives separately in llm_response. See Transcript rewriting for how to write a good instruction, what the service enforces for you, and why dictated commands are never carried out.

Uploading while recording

The endpoint transcribes the audio it has while the rest is still arriving, so a client that uploads during the recording gets its transcript sooner. What the user waits for after they stop speaking is the last stretch of audio rather than the whole clip. The saving grows with clip length; on a clip of a few seconds there is little uploaded-but-unprocessed audio to save. Three rules apply to a chunked upload:
  • The config part must arrive before the first audio byte.
  • Don’t let the connection go silent for long stretches mid-body — an abandoned upload is timed out rather than held open.
  • A chunked body can’t be replayed. Keep the audio in memory if you want to retry a failed request.
Raw PCM is the easiest format to stream, since it needs no container header — declare sample_rate and channels in config and send frames as they come off the microphone. The Python SDK does the framing for you. transcribe_live() takes an iterator of audio chunks, and open_live() takes audio pushed in from a callback — a microphone library, a WebRTC track, a telephony media stream:
AsyncDictationTranscriber is the asyncio counterpart, with the same two methods. Call transcriber.warm() when you know audio is coming — as the user reaches for the record button — to pay the DNS, TCP and TLS setup before the first byte rather than in front of it. Without the SDK, frame the multipart body yourself:
Passing a generator to data= makes requests send the body with chunked transfer encoding, which is what lets the upload start before the audio is complete. A body with a Content-Length is also accepted, and still streams — the server does not wait for the full body before it begins.

Response

A successful call returns 200 with JSON:
Rewrites are best-effort. A rewrite failure still returns 200 with the transcription. If llm_response is null and text is present, use text. Never treat a non-null llm_error as a failed request.

Errors

Most errors return {"error": "...", "error_code": "..."}. The ones relayed from the transcription service, an invalid API key (404) and an unsupported audio format (415), use a {"status", "title", "detail"} body instead, so read both shapes. Note that an invalid API key returns 404 rather than 401. Set the HTTP client timeout to 90 seconds. Typical short clips respond in under one second. The rewrite has a 5-second internal deadline, after which the response returns with llm_error: "timeout" and the transcription intact. See Error handling for the full status code table and retry guidance.

Examples

The knobs do different jobs. stt_prompt and keyterms_prompt steer the ASR model while it writes the transcript down — the first describes the situation, the second lists the exact terms to expect. llm_instruction tells the LLM what to do with that transcript after it is written.

Clinical dictation

A doctor dictating a visit note. stt_prompt tells the model what kind of audio this is, keyterms_prompt pins the exact drug names, and llm_instruction turns the spoken rambling into a chart-ready note.

Travel booking summary

A travel agent dictating a client booking summary. keyterms_prompt pins the specific destination and airline names, and llm_instruction reshapes the transcript into a confirmation the client can read.

Next steps