Skip to main content

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.

Quick summary
Use this guide to implement recommended patterns for pausing and submitting sessions with the useAmbientSession hook. By following these patterns, you ensure that the Suki handles audio data correctly and you avoid conflicts with the Headless Web SDK.
The useAmbientSession hook provides the pause(), setSessionContext(), submit(), and cancel() methods. The Headless Web SDK manages buffering, queuing, and upload orchestration for you. If you add custom recovery logic, you might accidentally discard valid audio or call methods in an incorrect order. Follow this guide to implement recommended patterns for pausing and submitting sessions with the useAmbientSession hook. By following these patterns, you ensure that the Suki handles audio data correctly and you avoid conflicts with the Headless Web SDK.

Built-in behavior

The Headless Web SDK manages buffering, queuing, and upload orchestration for you. You do not need to re-implement these features in your application:
  • Offline and network drops - When the session is offline, the Headless Web SDK persists audio (for example in IndexedDB) and manages the upload queue. For details, refer to Network transitions and Offline mode for more information.
  • Finalization with submit() - Use submit() to complete the session and send captured audio to the Suki backend server for processing.
  • Recoverable pause errors - A failed pause() call does not always mean session data or buffered audio is lost. Refer to Pausing a session (PauseSessionFailed) in the error handling guide for more information. This guide covers how to handle these errors.

Common mistakes to avoid

The following are common mistakes to avoid when using the useAmbientSession hook.
sessionStatus reflects the state of the last React render. If you call pause() again because the status has not updated yet, the API may return an InvalidSessionState error.Instead: Call pause() once. If the request fails, log a warning and stop. Do not use sessionStatus as an immediate source of truth right after an await pause() call.
The cancel() method is only for when a user explicitly abandons an encounter. It tears down the session and clears locally captured audio.Instead: Do not call cancel() in a catch block to recover from non-abandon errors. That pattern can lead to lost submissions during offline recording.
If you use a destructive fallback like cancel() and ignore the failure, your UI may drift away from the actual SDK session state.Instead: If you perform a destructive action, always surface failures to the user or your logging pipeline.
Follow this flow so your integration stays aligned with the Headless Web SDK:
1

Pause once

Call pause() a single time. On failure, log the error and stop.
2

Set context (best effort)

Use setSessionContext() when you have fresh visit metadata. You can still call submit() when your product rules allow it, even if this step fails.
3

Submit to finalize

Call submit() to upload queued chunks and complete the session.
4

Reserve cancel() for discard

Only call cancel() when the user confirms they want to abandon the session.

Code example

This example wraps pause, setSessionContext, and submit in a helper hook. Types follow Session context and UseAmbientSessionReturn. Swap in your own sessionContext, shouldSkipSubmit, and callbacks.
React
import { useCallback } from "react";

// Matches the SessionContext fields you send with setSessionContext (see API reference).
type SessionContext = {
  patient?: {
    dob: string;
    sex: string;
  };
  provider?: {
    specialty: string;
    role?: string;
  };
  visit?: {
    visit_type?: string;
    encounter_type?: string;
    reason_for_visit?: string;
    chief_complaint?: string;
  };
  sections?: Array<{ loinc: string }>;
  diagnoses?: {
    values: Array<{
      codes: Array<{
        code: string;
        description: string;
        type: string;
      }>;
      diagnosisNote: string;
    }>;
  };
};

// Empty success payload from setSessionContext; failures throw (see Session context types).
type SessionContextResponse = Record<string, never>;

// Methods and data passed in from your component that already called useAmbientSession.
type HandlersProps = {
  pause: () => Promise<void>;
  submit: () => Promise<void>;
  setSessionContext: (ctx: SessionContext) => Promise<SessionContextResponse>;
  sessionContext: SessionContext;
  shouldSkipSubmit: boolean;
  onSubmitSuccess: () => void;
  onSubmitError: (error: unknown) => void;
};

export function useAmbientSessionHandlers({
  pause,
  submit,
  setSessionContext,
  sessionContext,
  shouldSkipSubmit,
  onSubmitSuccess,
  onSubmitError,
}: HandlersProps) {
  const processSessionPause = useCallback(async () => {
    try {
      // One attempt only. Do not branch on stale sessionStatus and call pause() again.
      await pause();
    } catch (pauseError) {
      // Recoverable in many cases (for example stream close during a blip). Do not cancel() here.
      console.warn("[Suki] pause() failed", pauseError);
    }
  }, [pause]);

  const handleSubmit = useCallback(async () => {
    if (shouldSkipSubmit) {
      return;
    }

    try {
      // Best-effort metadata before finalize; still call submit() when your rules allow.
      await setSessionContext(sessionContext);
    } catch (contextError) {
      console.warn("[Suki] setSessionContext failed", contextError);
    }

    try {
      // Authoritative finalize path: SDK uploads queued audio, including offline-captured chunks.
      await submit();
      onSubmitSuccess();
    } catch (error) {
      onSubmitError(error);
    }
  }, [
    shouldSkipSubmit,
    setSessionContext,
    sessionContext,
    submit,
    onSubmitSuccess,
    onSubmitError,
  ]);

  return { processSessionPause, handleSubmit };
}
Pass the methods from useAmbientSession into the helper:
React
import { useAmbientSession } from "@suki-sdk/platform-react";

// ambientSessionId comes from useAmbient after session.create(); add onAudioChunkAvailable, audioBatchSize, etc. as needed.
const { pause, submit, setSessionContext } = useAmbientSession({
  ambientSessionId,
  // ...config, callbacks
});

const { processSessionPause, handleSubmit } = useAmbientSessionHandlers({
  pause,
  submit,
  setSessionContext,
  sessionContext: mySessionContext,
  shouldSkipSubmit: false,
  onSubmitSuccess: () => setSubmitted(true),
  onSubmitError: (err) => setError(String(err)),
});

Next steps

Learn how to map errors to fixes in the Error handling guide. Understand offline sessions in Offline mode.
Last modified on May 22, 2026