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

# Build a Web SDK Ambient Session

> Use-case tutorial: Authenticate with SukiAuthManager, initialize the Web SDK in React, and mount SukiAssistant for an Ambient encounter

<Callout icon="info-circle" color="#FFE148">
  **What you will build**

  <p className="doc-tutorial-meta" aria-label="15 min, Intermediate">
    <Badge size="sm" color="gray" icon="clock">15 min</Badge> |
    <Badge size="sm" color="gray" icon="user-graduate">Intermediate</Badge>
  </p>

  * A React page wrapped with the Web SDK provider
  * One shared auth manager and a single SDK initialize call
  * The hosted ambient UI for one patient encounter with LOINC note sections
</Callout>

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

  Copy the following prompt to add the Suki developer documentation as a skill and [MCP server](/documentation/references/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/references/ai-optimized-documentation).
</Tip>

<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/references/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/references/mcp](https://developer.suki.ai/documentation/references/mcp).
</Prompt>

In this tutorial, you build a React ambient encounter page with the Web SDK. You install the packages, wrap the app with <strong><code>SukiProvider</code></strong>, authenticate with <strong><code>SukiAuthManager</code></strong>, call <strong><code>init</code></strong>, and mount <strong><code>SukiAssistant</code></strong> with patient encounter context.

By the end of this tutorial, you will have a working React page that signs in to Suki and opens the hosted ambient UI for one encounter.

<span id="prerequisites" />

## Prerequisites

Before you begin, make sure you have:

* Completed [Partner onboarding](/documentation/get-started/partner-onboarding) and received your <code>partnerId</code> and <code>partnerToken</code>.
* A React 18+ app that can host the Web SDK UI.
* Host URLs on the Suki allowlist and a partner JWT that meets [Web SDK prerequisites](/web-sdk/prerequisites).

<Tip>
  Prefer staging credentials while you learn. Switch <code>environment</code> to <code>production</code> only when your partner configuration is ready.
</Tip>

<span id="architecture" />

## Architecture

```mermaid actions={false} theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#FFE148','primaryTextColor':'#111827','primaryBorderColor':'#D4A017','lineColor':'#6F5410','secondaryColor':'#FFF394','tertiaryColor':'#FFFADE','tertiaryTextColor':'#111827','tertiaryBorderColor':'#D4A017','arrowheadColor':'#6F5410','fontSize':'14px','edgeLabelBackground':'#FFFADE'}}}%%
flowchart LR
  A[SukiProvider] --> B[SukiAuthManager]
  B --> C[init]
  C --> D[SukiAssistant]
  D --> E[Ambient encounter UI]
```

<span id="project-setup" />

## Project setup

1. Use a React 18+ app that can host the Web SDK UI (see Prerequisites).
2. Install the required dependencies. Refer to [Web SDK installation](/web-sdk/installation).

```shell theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
# pnpm
pnpm add @suki-sdk/react @suki-sdk/core

# npm
npm install @suki-sdk/react @suki-sdk/core
```

3. Configure your credentials:

   <Callout icon="gear" color="#929292">
     * Keep `partnerId` and `partnerToken` ready for `SukiAuthManager` (prefer staging while you learn).
     * Confirm host URLs meet [Web SDK prerequisites](/web-sdk/prerequisites).
   </Callout>

<span id="tutorial-steps" />

## Tutorial steps

Work through each step in order. Read the explanation, review the code example, then continue to the next step. The full code example is available in the accordion below.

<Steps>
  <Step title="Wrap Your App with SukiProvider">
    In Web SDK v3, wrap your tree with `SukiProvider`. Run `init` in a child component, not on the provider.

    ```tsx theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
    import { SukiProvider } from "@suki-sdk/react";

    function App() {
    return (
    <SukiProvider>
      <AmbientEncounterPage />
    </SukiProvider>
    );
    }
    ```
  </Step>

  <Step title="Create SukiAuthManager and Call Init">
    Create `SukiAuthManager` once with `useMemo`, then call `init` with `authManager` from `useSuki()` when the SDK is not initialized yet.

    ```tsx theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
    import { useEffect, useMemo } from "react";
    import { SukiAuthManager } from "@suki-sdk/core";
    import { useSuki } from "@suki-sdk/react";

    function AmbientEncounterPage() {
    const authManager = useMemo(
    () =>
      new SukiAuthManager({
        partnerId: "YOUR_PARTNER_ID",
        partnerToken: "YOUR_PARTNER_TOKEN",
        providerName: "Dr. Jane Smith", // Example only — replace with the provider's full name
        providerOrgId: "YOUR_ORG_ID",
        environment: "staging", // Example — staging | production
        loginOnInitialize: true,
      }),
    [],
    );

    const { init, isInitialized } = useSuki();

    useEffect(() => {
    if (!isInitialized) {
      init({ authManager });
    }
    }, [init, isInitialized, authManager]);

    return null;
    }
    ```
  </Step>

  <Step title="Mount SukiAssistant with Encounter and Sections">
    Pass a valid `encounter` (patient identifier required; gender `MALE` | `FEMALE` | `UNKNOWN`) and `ambientOptions.sections` with LOINC codes. Keep identifiers at most 36 characters. Refer to [Note sections](/documentation/concepts/ambient-clinical-notes/note-sections).

    ```tsx theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
    import { useEffect, useMemo } from "react";
    import { SukiAuthManager } from "@suki-sdk/core";
    import { useSuki, SukiAssistant } from "@suki-sdk/react";

    function AmbientEncounterPage() {
    const authManager = useMemo(
    () =>
      new SukiAuthManager({
        partnerId: "YOUR_PARTNER_ID",
        partnerToken: "YOUR_PARTNER_TOKEN",
        providerName: "Dr. Jane Smith", // Example only — replace with the provider's full name
        providerOrgId: "YOUR_ORG_ID",
        environment: "staging", // Example — staging | production
        loginOnInitialize: true,
      }),
    [],
    );

    const { init, isInitialized } = useSuki();

    const encounter = useMemo(
    () => ({
      identifier: "6ec3920f-b0b1-499d-a4e9-889bf788e5ab", // Example only — replace with your encounter ID
      patient: {
        identifier: "905c2521-25eb-4324-9978-724636df3436", // Example only — replace with your patient ID
        name: {
          use: "official", // Example patient demographics — replace with real data
          family: "Doe",
          given: ["John"],
          suffix: [], // Required by Patient.name even when empty
        },
        birthDate: "1990-01-01", // Example only — YYYY-MM-DD
        gender: "MALE", // Example — must be "MALE" | "FEMALE" | "UNKNOWN"
      },
    }),
    [],
    );

    const ambientOptions = useMemo(
    () => ({
      sections: [
        { loinc: "51847-2" }, // Example section set — Assessment and Plan
        { loinc: "10164-2" }, // History of Present Illness
        { loinc: "10187-3" }, // Review of Systems — pick LOINCs that match your note
      ],
    }),
    [],
    );

    useEffect(() => {
    if (!isInitialized) {
      init({ authManager });
    }
    }, [init, isInitialized, authManager]);

    if (!isInitialized) {
    return <p>Initializing Suki Web SDK...</p>;
    }

    return (
    <SukiAssistant encounter={encounter} ambientOptions={ambientOptions} />
    );
    }
    ```
  </Step>
</Steps>

<span id="full-example" />

## Full code example

<div className="doc-tutorial-full-code" data-doc-tutorial-full-code data-active-lang="react">
  <Columns cols={1}>
    <Tile href="#full-example-react">
      <span className="doc-tutorial-tile-lang-icon" data-icon="react" aria-hidden="true" />
    </Tile>
  </Columns>

  <div id="full-example-react" className="doc-tutorial-lang-panel is-active" data-lang-panel="react">
    ```tsx React theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
    // Web SDK Ambient session tutorial (React)
    // Copy this file into a React app, replace YOUR_* placeholders, then render <App />.
    // Flow: SukiProvider → SukiAuthManager → init → SukiAssistant (encounter + LOINC sections)

    import { useEffect, useMemo } from "react";
    import { SukiAuthManager } from "@suki-sdk/core";
    import { SukiProvider, useSuki, SukiAssistant } from "@suki-sdk/react";

    // 1) Wrap once at the root. Call init() in a child under SukiProvider, not on the provider itself.
    function App() {
      return (
        <SukiProvider>
          <AmbientEncounterPage />
        </SukiProvider>
      );
    }

    function AmbientEncounterPage() {
      // 2) One long-lived auth manager. Recreating it every render breaks login state.
      const authManager = useMemo(
        () =>
          new SukiAuthManager({
            partnerId: "YOUR_PARTNER_ID", // Required: from partner onboarding
            partnerToken: "YOUR_PARTNER_TOKEN", // Required: keep off public clients in production
            providerName: "Dr. Jane Smith", // Example only — replace with the provider's full name
            providerOrgId: "YOUR_ORG_ID", // Required — replace with your org ID
            environment: "staging", // Example — use "production" only when ready
            loginOnInitialize: true, // Sign in as soon as the manager is created
          }),
        [],
      );

      const { init, isInitialized } = useSuki();

      // 3) Encounter + patient context. Identifiers must be at most 36 characters.
      const encounter = useMemo(
        () => ({
          identifier: "6ec3920f-b0b1-499d-a4e9-889bf788e5ab", // Example only — replace with your encounter ID (max 36 chars)
          patient: {
            identifier: "905c2521-25eb-4324-9978-724636df3436", // Example only — replace with your patient ID (max 36 chars)
            name: {
              use: "official", // Example name fields — replace with real patient name data
              family: "Doe",
              given: ["John"],
              suffix: [], // Required by Patient.name even when empty
            },
            birthDate: "1990-01-01", // Example only — YYYY-MM-DD
            gender: "MALE", // Example — must be "MALE" | "FEMALE" | "UNKNOWN"
          },
        }),
        [],
      );

      // 4) Note sections (LOINC). Required for ambient note generation.
      //    See Note sections: Assessment and Plan is 51847-2 (not 51848-0 Assessment alone).
      const ambientOptions = useMemo(
        () => ({
          sections: [
            { loinc: "51847-2" }, // Example section set — Assessment and Plan
            { loinc: "10164-2" }, // History of Present Illness
            { loinc: "10187-3" }, // Review of Systems — pick LOINCs that match your note
          ],
        }),
        [],
      );

      // 5) Initialize the SDK once when the provider tree is ready.
      useEffect(() => {
        if (!isInitialized) {
          init({ authManager });
        }
      }, [init, isInitialized, authManager]);

      // 6) Optional: receive sectioned note content when the clinician submits.
      const handleNoteSubmit = (data) => {
        console.log("Note submitted:", data.noteId, data.encounterId);
        data.contents.forEach((section) => {
          console.log(`${section.title}: ${section.content}`);
        });
      };

      if (!isInitialized) {
        return <p>Initializing Suki Web SDK...</p>;
      }

      // 7) Mount the hosted Ambient UI for this encounter.
      return (
        <SukiAssistant
          encounter={encounter}
          ambientOptions={ambientOptions}
          onNoteSubmit={handleNoteSubmit}
        />
      );
    }

    export default App;
    ```
  </div>
</div>

<span id="troubleshooting" />

## Troubleshooting

<AccordionGroup>
  <Accordion title="UI Never Opens">
    Confirm `init({ authManager })` runs once under `SukiProvider` when `isInitialized` is false.
  </Accordion>

  <Accordion title="Auth or Allowlist Failures">
    Check `partnerId` / `partnerToken` and allowlisted hosts in [Web SDK prerequisites](/web-sdk/prerequisites).
  </Accordion>

  <Accordion title="Invalid Encounter">
    Patient identifier is required; gender must be `MALE`, `FEMALE`, or `UNKNOWN`; keep identifiers at most 36 characters.
  </Accordion>
</AccordionGroup>

<span id="summary" />

## Summary

In this tutorial, you:

* Wrapped the app with `SukiProvider`.
* Authenticated with `SukiAuthManager` and called `init`.
* Mounted `SukiAssistant` with encounter context and LOINC sections.

Prefer staging credentials until your partner configuration is production-ready.

<span id="other-tutorials" />

## Other tutorials

Continue with another end-to-end tutorial.

<div className="hp-io-method-grid tut-hub-card-grid">
  <a className="hp-io-method-card tut-hub-method-card" href="/documentation/tutorials/headless-ambient-hooks">
    <div className="tut-hub-card-media" aria-hidden="true" />

    <div className="hp-io-method-card-body">
      <span className="hp-wn-badge hp-wn-badge-new">Ambient</span>
      <h3 className="hp-io-method-card-title">Build a Headless Ambient Recorder</h3>

      <p className="hp-io-method-card-desc">
        Use Headless hooks to sign in, create an ambient session, and control recording in a custom React UI.
      </p>

      <div className="hp-io-method-card-meta tut-hub-card-foot" aria-label="20 min, Intermediate">
        <div className="tut-hub-card-foot-meta">
          <span className="hp-io-method-card-meta-time">20 min</span>
          <span className="tut-hub-level">Intermediate</span>
        </div>
      </div>
    </div>
  </a>

  <a className="hp-io-method-card tut-hub-method-card" href="/documentation/tutorials/ambient-websocket-code-example">
    <div className="tut-hub-card-media" aria-hidden="true" />

    <div className="hp-io-method-card-body">
      <span className="hp-wn-badge hp-wn-badge-new">Ambient</span>
      <h3 className="hp-io-method-card-title">Build an Ambient Streaming Client</h3>

      <p className="hp-io-method-card-desc">
        Authenticate, create a session, stream PCM audio over WebSocket, and retrieve clinical note results.
      </p>

      <div className="hp-io-method-card-meta tut-hub-card-foot" aria-label="20 min, Intermediate">
        <div className="tut-hub-card-foot-meta">
          <span className="hp-io-method-card-meta-time">20 min</span>
          <span className="tut-hub-level">Intermediate</span>
        </div>
      </div>
    </div>
  </a>
</div>
