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

# Dictation Basic Usage

> Create a Dictation transcription session, stream audio over WebSocket, receive transcript frames, and end the session when capture finishes

<Info>
  **This guide covers:** Audio Dictation [REST and WebSocket APIs](/api-reference/audio-transcription/create-session).

  * For a **browser** app, use the [Web SDK for Audio Dictation](/web-sdk/dictation-overview) or the [Dictation SDK](/dictation-sdk/introduction) <Badge color="yellow" size="sm" icon="sparkles">Beta</Badge> instead of building this REST and WebSocket flow yourself.
  * For wire format, handshake rules, and troubleshooting, refer to the [Dictation streaming](/documentation/how-to/audio-streaming/dictation-streaming) guide.
</Info>

This guide walks you through how to build a standalone Audio Dictation workflow with the Audio Dictation REST APIs. In this workflow, you:

* Create an Audio Dictation session.
* Stream audio over WebSocket.
* Receive transcript updates.
* End the session when Dictation is complete.

Before you start, register the provider and get an **`sdp_suki_token`**. Refer to [Provider authentication](/api-reference/provider-authentication) and [Partner authentication](/documentation/how-to/partner-authentication) for more information.

## What to build in your product

Build **Speak** as a focused Dictation control that lets a clinician speak into a specific chart field or note section.

Your application owns the user experience around Dictation, including:

* The microphone and recording controls
* Which chart field or note section is focused
* Where the final transcript is inserted
* When the updated content is saved to the EHR

### UI and application responsibilities

| UI element             | Clinician action                                   | Your application responsibility                                                                                                                                   |
| :--------------------- | :------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Field or section**   | Selects HPI, Assessment and Plan, or another field | Track the target field in your UI. This can be a field ID, LOINC, or another identifier used by your application. Dictation APIs do not receive a section target. |
| **Speak / microphone** | Starts or stops Dictation                          | Create the Dictation session, open `/ws/transcribe`, stream audio, and end the session. Disable Speak while Ambient is recording or generating a note.            |
| **Live transcript**    | Speaks into the microphone                         | Optionally display partial transcript text. Use **final transcript frames** when writing text into the focused field.                                             |
| **Save**               | Reviews and saves the text                         | Save the updated field through your existing EHR or application workflow. Dictation does not provide an Ambient-style completion webhook.                         |

### If your product also supports Ambient

If the same visit supports both Ambient and Dictation, use Ambient first to capture the visit and generate the note.

After the ambient session reaches **`completed`** and the generated note is available, enable **Speak** for the sections where the clinician needs to add or replace exact wording.

The workflow is:

```mermaid actions={false} theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#FFF394','primaryTextColor':'#111827','primaryBorderColor':'#FFE148','lineColor':'#FFE148','secondaryColor':'#FFF394','tertiaryColor':'#FFFADE','mainBkg':'#FFF394','secondBkg':'#FFFADE','tertiaryBorderColor':'#FFE148','border1':'#FFE148','border2':'#FFE148','arrowheadColor':'#FFE148','fontFamily':'Inter, system-ui, sans-serif','fontSize':'14px','nodeBorder':'#FFE148','edgeLabelBackground':'#FFE148','clusterBkg':'#FFFADE','clusterBorder':'#FFE148','defaultLinkColor':'#FFE148','titleColor':'#111827','nodeTextColor':'#111827'}}}%%
flowchart LR
    A[Ambient] --> B[Note ready]
    B --> C[Select section]
    C --> D[Speak]
    D --> E[Insert final<br/>transcript]
    E --> F[Save]

    style A fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style B fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style C fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style D fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style E fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
    style F fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827
```

Refer to [Decide if you also need Ambient](/documentation/concepts/dictation/dictation#decide-before-you-build-your-workflow) guide to determine whether your workflow needs both products.

## How the Audio Dictation works

The Dictation workflow uses both REST APIs and a WebSocket connection.

1. Authenticate and create a session with the REST API.
2. Stream audio to the session over WebSocket and process transcript updates.
3. End the session.

## Create a Dictation session

Create a parent transcription session before you open the WebSocket connection. The response includes a **`transcription_session_id`**, which identifies the session across the workflow.

Use the **`transcription_session_id`** when you:

* Connect to **`/ws/transcribe`**.
* End the Dictation session with [End Dictation session](/api-reference/audio-transcription/end-session).

Call <Badge color="blue" size="sm">POST</Badge> [Create Dictation session](/api-reference/audio-transcription/create-session):

```bash theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
curl --request POST \
  --url https://sdp.suki-stage.com/api/v1/transcription/session/create \
  --header 'Content-Type: application/json' \
  --header 'sdp_suki_token: <sdp_suki_token>' \
  --header 'sdp_provider_id: <sdp_provider_id>' \
  --data '{
    "audio_config": {
      "audio_encoding": "LINEAR16",
      "audio_language": "en-US",
      "sample_rate_hertz": 16000
    }
  }'
```

Example response:

```json theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
{
  "transcription_session_id": "123dfg-456dfg-789dfg-012dfg"
}
```

The API returns **`201 Created`** when the session is created successfully.

### Request details

* Include **`sdp_suki_token`** in every REST request and during the WebSocket handshake.
* **`transcription_session_id`** is optional in the create request. If you omit it, Suki generates one.
* **`audio_config`** is optional. If you omit it, the session uses **LINEAR16** at **16 kHz**, and **`audio_language`** defaults to **`English`**.
* When you send **`audio_config`**, **`audio_encoding`** must be **`LINEAR16`**.
* Supported **`audio_language`** values are **`English`** and **`Multilingual`**. Dictation does not have a separate auto-detect setting. If you set **`English`** and the speaker uses Spanish, the transcript can still return in Spanish. Do not reuse Ambient multilingual rules here. Ambient multilingual is documented on [Multilingual](/api-reference/capabilities/multilingual).

<Note>
  Dictation returns transcript text you insert in your UI. Ambient [Personalization](/api-reference/capabilities/personalization) (verbosity and section format) does not change Dictation transcripts.
</Note>

## Stream audio over WebSocket

After you create the session, connect to <Badge color="green" size="sm">GET</Badge> **`wss://sdp.suki-stage.com/ws/transcribe`**.

If you reconnect too soon after the previous utterance, the handshake can fail with **`FailedPrecondition`**. For push-to-talk and the wait after **`EOF`**, see [Stream Dictation audio](/documentation/how-to/audio-streaming/dictation-streaming).

<Tip>
  Authenticate during the WebSocket handshake instead of sending credentials with each message.
</Tip>

### Authentication

For non-browser clients, send these headers during the upgrade request:

* `sdp_suki_token`.
* `transcription_session_id`.

For browser clients, use **`Sec-WebSocket-Protocol`**:

```bash theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
Sec-WebSocket-Protocol: SukiAmbientAuth,<sdp_suki_token>,<transcription_session_id>
```

### Send audio messages

Send audio data as JSON text frames.

Example audio message:

```json theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
{ "type": "AUDIO", "audioData": "<base64-encoded PCM_S16LE bytes>" }
```

After you finish streaming audio on the connection, send:

```json theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
{ "type": "EVENT", "event": "AUDIO_END" }
```

### Streaming requirements

* Send one JSON object per WebSocket **`send`**.
* Do not send raw binary frames.
* Use **`audioData`** for Dictation audio payloads.
* Base64-encode **PCM\_S16LE** audio bytes in **`audioData`**.
* Do not use ambient streaming fields such as **`data`** or **`RU9G`**.

For wire format details, refer to [WebSocket streaming wire format](/documentation/how-to/audio-streaming/websocket-streaming-wire-format-dictation).

### Receive transcript events

Parse transcript messages from **`event.data`** in your WebSocket **`onmessage`** handler. Refer to [Stream audio to Dictation session](/api-reference/audio-transcription/stream-transcription) for Python and TypeScript code examples, and [Read Dictation transcript frames](/documentation/how-to/audio-streaming/dictation-streaming-transcripts) for partial and final frames, **`EOF`**, and filtering rules.

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 transcript_id
}
```

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": "speaker_1" } },
      { "word": "patient", "speaker": { "id": "speaker_1" } }
    ]
  },
  "is_final": true,
  "transcript_id": "01J9XWXYZABCDEFGHJKMNPQRSTUV" // example transcript_id
}
```

* **`is_final: false`**: partial (interim) text that may change in later messages.
* **`is_final: true`**: final text for that segment. Insert this text in your UI. End REST does not return the transcript.
* After the speech stream ends, the server sends **`{ "transcript": { "transcript": "EOF" } }`**. Treat that as end-of-results for that WebSocket.

<Tip>
  The canonical inbound contract, including word timestamps, is on [Read Dictation transcript frames](/documentation/how-to/audio-streaming/dictation-streaming-transcripts).
</Tip>

<Note>
  Do not dedupe messages by **`transcript_id`**. The server assigns a new ID per frame, including partials.
</Note>

## End the Dictation session

When Dictation is complete:

1. Send **`AUDIO_END`**.
2. Read remaining WebSocket frames, including finals and **`EOF`**.
3. Close the WebSocket connection.
4. End the session with the REST API.

Call <Badge color="blue" size="sm">POST</Badge> [End Dictation session](/api-reference/audio-transcription/end-session):

```bash theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
curl --request POST \
  --url https://sdp.suki-stage.com/api/v1/transcription/session/<transcription_session_id>/end \
  --header 'sdp_suki_token: <sdp_suki_token>' \
  --header 'sdp_provider_id: <sdp_provider_id>'
```

The API returns **`200 OK`**. The HTTP body is **empty**. Do not read `final_transcript` from End. Use live WebSocket frames where **`is_final`** is **`true`** as the transcript for the session.

## Common integration patterns and use cases

### Pattern 1: Standard Audio Dictation flow

A typical Audio Dictation workflow follows these steps:

<Steps>
  <Step title="Authenticate">
    Obtain an **`sdp_suki_token`** for the provider.
  </Step>

  <Step title="Create the Session">
    Call [Create Dictation session](/api-reference/audio-transcription/create-session) and save the **`transcription_session_id`**.
  </Step>

  <Step title="Stream Audio">
    Open a WebSocket connection to **`/ws/transcribe`**. Send **`AUDIO`** messages, handle partial and final inbound frames, and finish with **`AUDIO_END`**.
  </Step>

  <Step title="Process Transcripts">
    Update the UI with partial and final transcript updates from incoming WebSocket messages.
  </Step>

  <Step title="End the Session">
    Call [End Dictation session](/api-reference/audio-transcription/end-session) to close the session. The End body is empty. Keep the transcript from WebSocket **`is_final`** frames.
  </Step>
</Steps>

### Pattern 2: Push-to-talk or reconnect

Reuse one **`transcription_session_id`** for more than one utterance, such as push-to-talk. One speech stream can be open on that session at a time.

For each utterance:

1. Open **`/ws/transcribe`**.
2. Stream audio, then send **`AUDIO_END`**.
3. Wait for **`EOF`**, then close the WebSocket.
4. Wait about **5 seconds** before you open the next WebSocket on the same session.

If the connection drops mid-utterance, use the same wait, then open a new WebSocket with the same **`transcription_session_id`** and **`sdp_suki_token`**. Do not poll `READY` / `IDLE`. There is no partner status API. If you reconnect too soon, the handshake fails with **`FailedPrecondition`**.

Call [End Dictation session](/api-reference/audio-transcription/end-session) only when the clinician is done with the full Dictation workflow, not after every utterance. For the wait and handshake rules, see [Stream Dictation audio](/documentation/how-to/audio-streaming/dictation-streaming).

### Pattern 3: Configure audio settings

Pass **`audio_config`** in the create request when you need to specify:

* Audio encoding.
* Language (`English` or `Multilingual`).
* Sample rate.

<Note>
  If you omit `audio_config`, language defaults to **`English`**. Ensure that the streamed audio format matches the configuration you provide.
</Note>

### Pattern 4: Stream audio in chunks

For lower latency, send smaller **`AUDIO`** messages as audio becomes available instead of buffering the entire recording.

After the final audio chunk, send **`AUDIO_END`**.

## What you can build

<CardGroup cols={2}>
  <Card title="Live Dictation Experiences" icon="microphone">
    Display partial and final transcript updates in real time while the provider speaks.
  </Card>

  <Card title="Server-Side Transcription Pipelines" icon="server">
    Capture audio on a backend service, stream it through **`/ws/transcribe`**, and store the final transcript output.
  </Card>

  <Card title="Telehealth and In-Person Workflows" icon="video">
    Add transcription workflows to virtual or in-person clinical experiences without ambient note generation.
  </Card>

  <Card title="EHR and Form Integrations" icon="file-lines">
    Send transcript output into forms, notes, or downstream clinical systems after the session ends.
  </Card>
</CardGroup>

## Related API references

<CardGroup cols={3}>
  <Card title="Create Dictation Session" icon="code" href="/api-reference/audio-transcription/create-session" arrow={true}>
    Create a transcription session
  </Card>

  <Card title="Stream Audio for Dictation" icon="wifi" href="/api-reference/audio-transcription/stream-transcription" arrow={true}>
    Connect and stream audio over WebSocket
  </Card>

  <Card title="End Dictation Session" icon="circle-xmark" href="/api-reference/audio-transcription/end-session" arrow={true}>
    End a Dictation session
  </Card>
</CardGroup>

## Best practices

<Tip>
  * **Stream audio in small chunks** to reduce latency.
  * **Reuse the same `transcription_session_id`** when reconnecting WebSocket sessions.
  * **End sessions** after Dictation completes to release resources.
  * **Match streamed audio settings** to your configured sample rate and encoding.
  * **Validate audio quality** before production deployment.
</Tip>

## FAQs

<Accordion title="What's the Difference Between Audio Dictation and Clinical Documentation?">
  | Feature                        | Description                                                                                  |
  | :----------------------------- | :------------------------------------------------------------------------------------------- |
  | Audio Dictation                | Converts speech into transcript text with formatting such as punctuation and capitalization. |
  | Ambient clinical documentation | Transcribes conversations and generates structured clinical documentation outputs.           |
</Accordion>

<Accordion title="How Is /ws/transcribe Different from Ambient /ws/stream?">
  Dictation uses **`/ws/transcribe`** with **`audioData`** payloads and **`AUDIO_END`** events.

  Ambient clinical documentation uses **`/ws/stream`** with different authentication flows and message formats.

  For more information, refer to [Audio streaming](/documentation/how-to/audio-streaming/audio-stream) and [Dictation streaming](/documentation/how-to/audio-streaming/dictation-streaming).
</Accordion>
