> ## 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 SDK Quickstart

> Get started with the Dictation SDK by installing the packages, creating the auth manager and client, and opening a dictation session

This guide walks you through the steps to integrate the Dictation SDK into your application.

**What will you do**

1. Install the Dictation SDK package for your framework (JavaScript or React)
2. Create a `SukiAuthManager` from `@suki-sdk/core` with your `partnerToken` and provider fields
3. Create a `DictationClient` from `@suki-sdk/dictation` with your auth manager
4. Mount the Dictation UI into your application using the `encounter` object.

<Tip>
  **Using an AI coding tool?**

  Copy the following prompt to add the Suki developer documentation as a skill and [MCP server](/documentation/mcp) to your tool for better AI-assisted coding during the integration process. For all AI options (contextual menu, `llms.txt`, and `skill.md`), refer to [AI-optimized documentation](/documentation/ai-optimized-documentation).

  <Prompt description="Install the Suki developer docs as a skill to get context on Suki's developer tools, APIs, and SDKs. Add the [MCP server](/documentation/mcp) for documentation search." icon="gear" iconType="regular" actions={["copy", "cursor"]}>
    Install the Suki developer docs as skill to get context on Suki's developer tools, APIs, and SDKs.

    npx skills add [https://developer.suki.ai](https://developer.suki.ai)

    Then add the Suki developer docs MCP server for access to documentation search. Follow the MCP instructions at [https://developer.suki.ai/documentation/mcp](https://developer.suki.ai/documentation/mcp).
  </Prompt>
</Tip>

## Prerequisites

Before you start, ensure you have the following:

* You have received your **`partnerId`** and **`partnerToken`** from Suki.
* Your app meets **browser**, **CSP**, and host requirements for the dictation iframe

Refer to [Prerequisites](/dictation-sdk/prerequisites) for more details.

## Recommended integration pattern

The Dictation SDK works best when you treat authentication and the dictation client as **long-lived objects** for a page or session. You should only change the specific field or surface receiving the dictation. This approach ensures that token refreshes and iframe setups remain predictable while avoiding duplicate overlays.

A common mistake is to build a new **`DictationClient`** on every React render (for example, in the component body without **`useMemo`**) or to use a separate client for each text field. The SDK assumes **one client per page scope**. If you do not follow this pattern, the session and iframe will frequently tear down and restart. This creates an unstable experience for the user.

<Tip>
  Initialize **once per session** and reuse:
</Tip>

<CardGroup cols={2}>
  <Card title="Suki Auth Manager" icon="lock">
    Create **`SukiAuthManager`** from **`@suki-sdk/core`** after the **partner token** is available.
  </Card>

  <Card title="Dictation Client" icon="cube">
    Create **`DictationClient`** with that **`authManager`**. **Reuse** this client **across** dictation fields.
  </Card>

  <Card title="Dictation Provider (React only)" icon="react">
    In React, wrap components with **`DictationProvider`** from **`@suki-sdk/dictation-react`**.
  </Card>

  <Card title="Dictation Per Active Field" icon="edit">
    Show the dictation UI **per field** or **scratchpad**. Avoid recreating **`DictationClient`** on every render or **per field**.
  </Card>
</CardGroup>

<Tip>
  The **JavaScript** and **React** tabs under **Your first dictation session** below mirror this pattern: one auth manager, one client, then **`show()`** or **`<Dictation>`** for the active target only.
</Tip>

## Field IDs

Each dictation instance needs a **stable**, **unique** **`fieldId`**. The SDK sends it back on every callback with **`text`**, so you can route results to the right control.
A common pattern is to match the target input's HTML **`id`**. Refer to [Field IDs](/dictation-sdk/guides/configuration#field-ids-in-practice) section in [Configuration](/dictation-sdk/guides/configuration) guide for more details.

## Install the packages

<Tabs>
  <Tab title="JavaScript">
    <CodeGroup title="Install @suki-sdk/dictation and @suki-sdk/core">
      ```shell pnpm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
      pnpm add @suki-sdk/dictation @suki-sdk/core
      ```

      ```shell npm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
      npm install @suki-sdk/dictation @suki-sdk/core
      ```

      ```shell yarn theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
      yarn add @suki-sdk/dictation @suki-sdk/core
      ```
    </CodeGroup>

    More detail: [Installation](/dictation-sdk/installation).
  </Tab>

  <Tab title="React">
    <CodeGroup title="Install @suki-sdk/dictation-react and @suki-sdk/core">
      ```shell pnpm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
      pnpm add @suki-sdk/dictation-react @suki-sdk/core
      ```

      ```shell npm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
      npm install @suki-sdk/dictation-react @suki-sdk/core
      ```

      ```shell yarn theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
      yarn add @suki-sdk/dictation-react @suki-sdk/core
      ```
    </CodeGroup>

    More detail: [Installation](/dictation-sdk/installation).
  </Tab>
</Tabs>

## Create your first dictation session

Apply **Recommended integration pattern** above: build **`SukiAuthManager`** and **`DictationClient`** once, then open dictation only for the target that should be active.

For **JavaScript**, give dictation a **container** (**`rootElement`**) with real height. Example markup:

```html theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
<div id="dictation-root"></div>
<textarea id="clinical-notes"></textarea>
```

<Tabs>
  <Tab title="JavaScript">
    Create the auth manager and client **once**, then call **`show()`** when the user should dictate (for example after a button click). Use **`try`** / **`catch`** so configuration or auth errors surface in your logs.

    ```javascript JavaScript expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
    import { SukiAuthManager } from "@suki-sdk/core"; // Step 1: Create the auth manager
    import { DictationClient } from "@suki-sdk/dictation"; // Step 2: Create the client

    const authManager = new SukiAuthManager({
      partnerId: "YOUR_PARTNER_ID", // replace with your partner ID - required
      partnerToken: "YOUR_PARTNER_TOKEN", // replace with your partner token - required
      environment: "staging", // optional - default is "production"
      loginOnInitialize: true, // optional - default is false
      providerName: "John doe", // optional - default is empty
      providerOrgId: "1234", // optional - default is empty
      providerId: "1234567890", // optional - default is empty
      providerSpecialty: "FAMILY_MEDICINE", // optional - default is empty
    });

    const client = new DictationClient({ authManager }); // Step 3: Create the client

    async function startDictation() {
      try {
        await client.show({
          mode: "in-field", // required - you must set this as per your use case
          fieldId: "clinical-notes", // required - you must set this to the ID of the textarea you want to dictate
          rootElement: document.getElementById("dictation-root"), // required - you must set this to the ID of the div you want to contain the dictation iframe
          initialText:
            document.getElementById("clinical-notes")?.value ?? "", // optional - you can set this to the initial text of the textarea
          onSubmit: ({ fieldId, text }) => {
            const el = document.getElementById(fieldId);
            if (el) el.value = text;
          },
          onCancel: ({ fieldId }) => {
            console.log("Cancelled", fieldId);
          },
        });
      } catch (err) {
        console.error(err);
      }
    }

    // Call startDictation() from your UI when ready.
    ```

    Your integration is working when the dictation UI appears inside **`dictation-root`**, you can dictate, and text you commit is written to the textarea in **`onSubmit`**.

    <Tip>
      For optional settings and callbacks (**`onDraft`**, **`initialText`**, scratchpad **`mode`**, and more),
      refer to [Configuration](/dictation-sdk/guides/configuration). For iframe or layout problems, refer to [Error handling](/dictation-sdk/guides/error-handling) guide for more details.
    </Tip>
  </Tab>

  <Tab title="React">
    Create **`DictationClient`** once (**`useMemo`**), wrap the tree with **`DictationProvider`**, and render **`<Dictation>`** only when that field should own the session. Unmounting **`<Dictation>`** calls **`hide()`** for you.

    ```jsx React expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
    import { useMemo, useState } from "react";
    import { SukiAuthManager } from "@suki-sdk/core"; // Step 1: Create the auth manager
    import { DictationClient } from "@suki-sdk/dictation"; // Step 2: Create the client
    import { DictationProvider, Dictation } from "@suki-sdk/dictation-react"; // Step 3: Wrap the tree with DictationProvider

    export function NotesWithDictation() {
      const client = useMemo(() => {
        const authManager = new SukiAuthManager({
          partnerId: "YOUR_PARTNER_ID", // replace with your partner ID - required
          partnerToken: "YOUR_PARTNER_TOKEN", // replace with your partner token - required
          environment: "staging", // optional - default is "production"
          loginOnInitialize: true, // optional - default is false
          providerName: "John doe", // optional - default is empty
          providerOrgId: "1234", // optional - default is empty
          providerId: "1234567890", // optional - default is empty
          providerSpecialty: "FAMILY_MEDICINE", // optional - default is empty
        });
        return new DictationClient({ authManager }); // Step 4: Create the client
      }, []); // Step 5: Create the client once and reuse it across fields

      const [notes, setNotes] = useState("");
      const [dictationActive, setDictationActive] = useState(false);

      return (
        <DictationProvider client={client}>
          <textarea
            id="clinical-notes"
            value={notes}
            onChange={(e) => setNotes(e.target.value)}
          />
          <button
            type="button"
            onClick={() => setDictationActive((v) => !v)}
          >
            {dictationActive ? "Stop dictation UI" : "Start dictation"}
          </button>
          {dictationActive && (
            <Dictation
              fieldId="clinical-notes"
              mode="in-field" // required - you must set this as per your use case
              initialText={notes} // optional - you can set this to the initial text of the textarea
              onSubmit={({ text }) => setNotes(text)}
              onCancel={() => setDictationActive(false)}
            />
          )}
        </DictationProvider>
      );
    }
    ```

    Your integration is working when turning dictation on shows the hosted UI, committed text updates **`notes`** through **`onSubmit`**, and **only one** **`<Dictation>`** is mounted at a time for that shared **`client`**.

    <Tip>
      To wire **`rootElement`** with a ref (instead of **`document.getElementById`**),
      refer to [Configuration examples](/dictation-sdk/guides/examples/configuration-examples) and [React integration](/dictation-sdk/react-integration/react) guides for more details.
    </Tip>
  </Tab>
</Tabs>

## Next steps

<Icon icon="file-lines" iconType="solid" /> Refer to the [Configuration](/dictation-sdk/guides/configuration) guide for more details on the available options and how to use them.
