> ## Documentation Index
> Fetch the complete documentation index at: https://developer.suki.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Read Dictation Transcript Frames

> Reference for Dictation /ws/transcribe inbound transcript frames: partial, final, EOF, words, and UI handling

The WebSocket sends each transcription result as a JSON text message. Parse the message in your WebSocket handler, such as **`event.data`** in the browser's **`onmessage`** callback, or use the equivalent message handler in your WebSocket library.

For complete examples, see [Stream audio to Dictation session](/api-reference/audio-transcription/stream-transcription#full-code-examples). To learn how to establish the WebSocket connection and stream audio, see [Stream Dictation audio](/documentation/how-to/audio-streaming/dictation-streaming).

## Partial and final transcripts

Use **`is_final`** to decide whether the text should be shown as draft text or committed to the transcript.

| `is_final`  | Meaning                                                                                                      |
| :---------- | :----------------------------------------------------------------------------------------------------------- |
| **`false`** | Partial, or interim, transcript. The text may change in later messages as the recognizer refines its result. |
| **`true`**  | Final transcript for that segment. The recognizer has committed to this text, and it will not be revised.    |

Example partial frame:

```json theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
{
  "transcript": {
    "transcript": "the recognized text so far",
    "words": []
  },
  "is_final": false,
  "transcript_id": "01J9XABCDEFGHJKMNPQRSTVWXYZ"
}
```

Example final frame:

```json theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
{
  "transcript": {
    "transcript": "The patient reports feeling better today",
    "words": [
      { "word": "The", "speaker": { "id": "S1" } },
      { "word": "patient", "speaker": { "id": "S1" } }
    ]
  },
  "is_final": true,
  "transcript_id": "01J9XWXYZABCDEFGHJKMNPQRSTUV"
}
```

## End of results

After the upstream stream ends, the server sends one terminal frame:

```json theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
{
  "transcript": {
    "transcript": "EOF",
    "words": []
  }
}
```

Treat **`transcript.transcript`** equal to **`EOF`** as the canonical end-of-results signal for that speech session. The WebSocket closes shortly after.

## Handle transcript updates in your UI

The Dictation WebSocket sends transcript updates as speech is processed. Each message contains the current transcript and an **`is_final`** flag that tells you whether the text is still changing or has been finalized.

### Partial and final updates

A single spoken sentence can generate multiple partial transcript frames before a single final transcript is produced. Interim frames are drafts that the recognizer can revise. The final frame is the committed text for that segment.

Your application is responsible for deciding how transcript text is displayed and stored in the editor.

| Frame                              | Recommended client behavior                                                                                                                                                                                                                        |
| :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`is_final: false`**              | Display the transcript as interim text and replace it whenever a newer interim update arrives. Do not append interim transcripts to your committed transcript. Each interim update replaces the previous one until a final transcript is received. |
| **`is_final: true`**               | Append the transcript to your editor or transcript buffer and remove any interim text. Use the **`words`** array in the final frame when you need word-level detail or speaker information.                                                        |
| **`transcript.transcript: "EOF"`** | No more transcript frames will be sent for this Dictation session. After you receive **`EOF`**, close the WebSocket if appropriate and complete the session using the REST API.                                                                    |

### Recommended client state

A common approach is to maintain two pieces of state:

* **`committedText`**: transcript that has been finalized and stored.
* **`interimText`**: the current in-progress transcript that is replaced by newer interim updates or cleared when a final transcript arrives.

<Tip>
  The server does not send empty transcript frames. Every transcript contains text except the terminal **`EOF`** frame.
</Tip>

## Insert transcript text

### Cursor and insertion point

The WebSocket returns only transcript text. It does not know your cursor position, selected text, or the surrounding content in your editor. Your application is responsible for inserting each transcript at the correct location.

### Spacing

Before inserting a transcript, determine whether a space is needed between the existing text and the incoming transcript. Insert a leading space only when the existing text does not already end with whitespace or an opening bracket or quote (`(`, `[`, `{`, `"`), the insertion point is not at the beginning of the field, and the incoming transcript does not begin with punctuation that should attach to the previous text (for example `,`, `.`, `:`, `;`, `!`, `?`).

### Capitalization

Your application is responsible for capitalization when starting a new sentence or paragraph. Do not recapitalize on every interim update.

### Examples

| Existing text   | Incoming transcript                | Result                              |
| :-------------- | :--------------------------------- | :---------------------------------- |
| *(empty field)* | `Patient reports mild chest pain.` | `Patient reports mild chest pain.`  |
| `Assessment:`   | `patient denies fever.`            | `Assessment: patient denies fever.` |
| `Pain (`        | `mild`                             | `Pain (mild`                        |
| `No`            | `,`                                | `No,`                               |

## Understand transcript ordering

### The `transcript_id` field

Every transcript frame includes a **`transcript_id`**, but the value identifies a single emitted message, not a spoken utterance. Multiple interim and final updates for the same spoken phrase can each have a different **`transcript_id`**.

* Do not use **`transcript_id`** to detect duplicate transcripts.
* Use transcript arrival order to display updates.

### The `words` array

Final transcript frames include the **`words`** array, which provides word-level metadata such as the individual word and speaker information (when available). Use it when your application shows word-level detail or distinguishes speakers. Interim frames typically contain an empty **`words`** array.

### End-of-stream (EOF) lifecycle

To finish a Dictation session cleanly:

1. Send **`AUDIO_END`**.
2. Continue reading transcript frames.
3. Wait for the terminal **`EOF`** transcript (**`transcript.transcript: "EOF"`**).
4. Close the WebSocket.
5. Complete the Dictation session using the [End Dictation session](/api-reference/audio-transcription/end-session) REST API.

## Related topics and resources

<CardGroup cols={2}>
  <Card title="Stream Dictation Audio" icon="waveform" href="/documentation/how-to/audio-streaming/dictation-streaming" arrow={true}>
    Open `/ws/transcribe`, send audio, and end with `AUDIO_END`.
  </Card>

  <Card title="Wire Format" icon="code" href="/documentation/how-to/audio-streaming/websocket-streaming-wire-format" arrow={true}>
    Outbound Dictation messages and audio format and chunking.
  </Card>

  <Card title="Complete the Session" icon="circle-check" href="/documentation/how-to/audio-streaming/websocket-streaming-complete-session" arrow={true}>
    End the Dictation session with REST after you finish reading frames.
  </Card>

  <Card title="Dictation Streaming API" icon="book" href="/api-reference/audio-transcription/stream-transcription" arrow={true}>
    API reference and code samples for transcript frames.
  </Card>
</CardGroup>

## Next steps

<Icon icon="file-lines" iconType="solid" /> Open the Dictation tab in [Complete the session after streaming](/documentation/how-to/audio-streaming/websocket-streaming-complete-session)

<Icon icon="file-lines" iconType="solid" /> Review [Audio Dictation](/documentation/concepts/dictation/dictation) for the full REST workflow
