# A Source: https://developer.suki.ai/Glossary/a Glossary terms starting with A

A

| Term | Definition | | :---------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **ABORT** | A WebSocket streaming event that terminates the current audio stream due to interruption while keeping the session active for later resumption. Note generation continues with audio received before interruption. | | **ACO** | Accountable Care Organizations. Healthcare entities that coordinate care for a patient population and are accountable for costs and quality outcomes. | | **AES-256** | Advanced Encryption Standard with 256-bit key length. A symmetric encryption algorithm used by Suki to encrypt data at rest. | | **Allergies** | A clinical note section (LOINC: 48765-2) listing known allergic reactions and adverse responses that may affect patient care and treatment decisions. | | **Allowlist** | A security mechanism where specific domains, IPs, or URLs are explicitly permitted. Partners must allowlist Suki domains in their firewall or WAF settings for SDK and API connectivity. | | **Ambient API** | The specific set of APIs used to create clinical notes from conversations. | | **Ambient Session** | A single, time-bound instance of an ambient recording for a specific patient encounter that captures clinical conversations. | | **Auto Onboarding** | A streamlined process where new providers are automatically registered in the Suki platform during their first authentication, without requiring manual setup. | | **API** | Application Programming Interface. A set of rules and tools for building software and applications. | | **ASR** | Automatic Speech Recognition. Technology that converts spoken language into written text, used by Suki for transcribing clinical conversations. | | **Assessment** | A clinical note section (LOINC: 51848-0) containing the clinician's medical assessment of the patient's condition. | | **Assessment and Plan** | A clinical note section (LOINC: 51847-2) combining the clinician's assessment with the treatment plan. Often used as the default PBN section. | | **Audio Chunking** | The process of dividing continuous audio streams into smaller segments. Suki requires 100ms audio packets for optimal performance and latency balance. |
# B Source: https://developer.suki.ai/Glossary/b Glossary terms starting with B

B

| Term | Definition | | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Background Processing** | The capability of SDK features to run passively during consultations without disrupting the provider's workflow, such as ambient note generation. | | **BAA** | Business Associate Agreement. A contract between Suki and healthcare customers that defines how patient data is handled in compliance with HIPAA requirements. | | **Base64 Encoding** | A method of encoding binary data (like audio) into ASCII text format for transmission over text-based protocols like WebSocket. | | **Bearer Token** | An authentication token format where the token holder ("bearer") is granted access to resources. Used in HTTP Authorization headers. | | **Bitrate** | The amount of data processed per unit of time in audio streaming. Suki requires 768kbps bitrate for optimal performance. |
# C Source: https://developer.suki.ai/Glossary/c Glossary terms starting with C

C

| Term | Definition | | :--------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Callback URL** | An endpoint URL registered by a partner to receive webhook event notifications from Suki, such as session completion or note generation events. | | **CANCEL** | A WebSocket streaming event that terminates the current ambient session entirely, discarding all captured audio and preventing note generation. | | **CDN** | Content Delivery Network. A distributed network of servers that delivers web content to users based on geographic proximity, used for hosting SDK assets. | | **Chief Complaint** | A clinical note section (LOINC: 10154-3) describing the primary reason for the patient's visit in their own words. | | **Clinic** | A healthcare facility where patients receive outpatient care, often part of a larger organization in the partner structure. | | **Clinical Note** | The final structured medical documentation generated from a patient encounter, organized into standardized sections using LOINC codes. | | **Clinical Workflows** | Standardized processes and procedures used in healthcare settings to manage patient care and documentation. | | **Clinician** | A healthcare professional who provides direct patient care, including doctors, nurses, and other medical practitioners who use Suki's documentation services. | | **Context-Aware Processing** | AI technology that intelligently organizes medical conversations into appropriate clinical sections based on the context and content of the discussion. |
# D Source: https://developer.suki.ai/Glossary/d Glossary terms starting with D

D

| Term | Definition | | :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **De-identification** | The process of removing personally identifiable information (PII) from data. Suki de-identifies audio by chunking files and removes PII from transcripts for model training purposes. | | **Diagnosis** | A clinical determination of a patient's condition or disease, often encoded using standardized systems like ICD10 or SNOMED for interoperability with EHR systems. | | **Diagnosis Context** | Structured diagnosis data (including code, code type, and description) passed as session context to guide problem-based note generation. | | **Dictation** | The process of speaking aloud to create written text, often used by clinicians to create medical documentation using voice input. | | **Differential Diagnosis** | A list of possible conditions or diseases that could explain a patient's symptoms, used during clinical reasoning to narrow down to a final diagnosis. |
# E Source: https://developer.suki.ai/Glossary/e Glossary terms starting with E

E

| Term | Definition | | :------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Early Access** | A phase where new features or APIs are available to select partners before general availability, such as the Ambient Clinician Note Generation API. | | **EHR** | Electronic Health Record. A digital version of a patient's paper chart containing comprehensive health information. | | **EMR** | Electronic Medical Record. Digital version of patient medical records maintained by healthcare providers. | | **Encounter** | A single interaction between a patient and healthcare provider, typically corresponding to one visit or appointment. | | **Encounter Content** | The aggregated clinical note content for a full patient encounter, combining output from one or more ambient sessions under the same encounter ID. | | **Encounter ID** | A unique identifier for a specific patient encounter, used to group multiple ambient sessions that belong to the same visit. | | **Encounter Type** | A classification describing the nature of a patient visit (e.g., office visit, follow-up, new patient), used to guide note generation behavior. | | **Encryption at Rest** | The protection of stored data by encrypting it when saved on disk or in databases. Suki uses AES-256 encryption for data at rest. | | **Encryption in Transit** | The protection of data while it moves between systems over networks. Suki uses TLS 1.2 for data transmission encryption. | | **EOF** | End of File. A WebSocket streaming event that indicates the closure or completion of an audio stream. | | **ES6** | ECMAScript 2015, a version of JavaScript that includes modern features like arrow functions, classes, and modules. Required for browser compatibility with Suki Web SDK. |
# F Source: https://developer.suki.ai/Glossary/f Glossary terms starting with F

F

| Term | Definition | | :--------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Family History** | A clinical note section (LOINC: 10157-6) documenting relevant medical conditions and diseases among the patient's biological relatives. | | **Federated Authentication** | An authentication model where multiple systems trust a single identity provider, allowing users to access multiple services with one set of credentials. | | **FHIR** | Fast Healthcare Interoperability Resources. A standard for exchanging healthcare information electronically, developed by HL7, enabling interoperability between health IT systems. | | **Form Filling** | AI-powered capability that automatically populates clinical forms and templates based on conversation content and structured data extraction. |
# G Source: https://developer.suki.ai/Glossary/g Glossary terms starting with G

G

| Term | Definition | | :----- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | | **GA** | General Availability. The release stage where a feature, API, or SDK version is fully supported, stable, and available to all partners for production use. |
# Suki Glossary Source: https://developer.suki.ai/Glossary/glossary Browse glossary terms by category, letter, and search.

Suki Glossary

New to Suki and not sure what a term means? Browse definitions below, or open the letter pages in the sidebar for dedicated glossary pages. Use the category and letter filters to narrow the list.

# H Source: https://developer.suki.ai/Glossary/h Glossary terms starting with H

H

| Term | Definition | | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Headed SDK** | An SDK that includes pre-built User Interface (UI) components. Our Web SDK is headed. | | **Headless SDK** | An SDK that does not include pre-built UI components, allowing developers to create their own UI. Our Mobile SDK is headless. | | **HIPAA** | Health Insurance Portability and Accountability Act. U.S. legislation that provides data privacy and security provisions for safeguarding medical information. | | **HL7** | Health Level Seven International. A set of international standards for the transfer of clinical and administrative data between healthcare applications. | | **HMAC** | Hash-based Message Authentication Code. A cryptographic method used to verify the integrity and authenticity of webhook payloads sent from Suki to partner endpoints. | | **Hospital** | A healthcare institution that provides patient treatment with specialized health science and auxiliary healthcare staff and medical equipment. | | **HPI** | History of Present Illness. A clinical note section (LOINC: 10164-2) describing the chronological development of the patient's current health issue. | | **HTTPS** | HyperText Transfer Protocol Secure. An extension of HTTP that uses encryption for secure communication over a network. |
# I Source: https://developer.suki.ai/Glossary/i Glossary terms starting with I

I

| Term | Definition | | :-------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **ICD10** | International Classification of Diseases, 10th Revision. A standardized coding system maintained by the WHO for classifying diagnoses, symptoms, and medical procedures. | | **Idempotency** | A property ensuring that performing the same API operation multiple times produces the same result, preventing duplicate processing of requests. | | **IDP** | Identity Provider. An acronym for a system that manages user identities and authenticates users. Examples include Okta, Auth0, Azure AD, and custom authentication systems. | | **IMO** | Intelligent Medical Objects. A clinical terminology and mapping platform that standardizes medical concepts across healthcare systems and coding vocabularies. |
# J Source: https://developer.suki.ai/Glossary/j Glossary terms starting with J

J

| Term | Definition | | :---------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **JWT** | JSON Web Token. A compact, URL-safe means of representing claims to be transferred between two parties, commonly used for authentication and information exchange. | | **JWKS** | JSON Web Key Set. A set of keys containing the public keys used to verify any JWT issued by the authorization server. | | **JWKS Endpoint** | A publicly accessible HTTPS endpoint that hosts cryptographic public keys for JWT token verification. |
# K Source: https://developer.suki.ai/Glossary/k Glossary terms starting with K

K

| Term | Definition | | :------------- | :------------------------------------------------------------------------------------------------------------------------------ | | **Keep Alive** | A WebSocket streaming event sent every 5 seconds during paused states to maintain connection and prevent timeout disconnection. |
# L Source: https://developer.suki.ai/Glossary/l Glossary terms starting with L

L

| Term | Definition | | :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Latency** | The delay between sending audio data and receiving a response. Suki requires unloaded latency under 50ms and loaded latency under 150ms for optimal performance. | | **LINEAR16** | An uncompressed audio format with 16-bit depth, used for high-quality audio streaming to Suki's platform at 16KHz sampling rate. | | **LLM** | Large Language Model. Advanced AI models trained on vast amounts of text data to understand and generate human-like text, used by Suki for clinical note generation. | | **LOINC** | Logical Observation Identifiers Names and Codes. A standardized vocabulary for identifying clinical sections and medical concepts. |
# M Source: https://developer.suki.ai/Glossary/m Glossary terms starting with M

M

| Term | Definition | | :---------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **MCP** | Model Context Protocol. An open standard that enables AI assistants and LLMs to securely connect with external data sources and tools, used by Suki for AI-powered documentation workflows. | | **Medically-tuned Dictation** | Speech recognition technology specifically optimized for medical terminology and clinical language patterns. | | **Medications** | A clinical note section (LOINC: 10160-0) listing the patient's current medications, dosages, and any prescription changes made during the encounter. | | **Mental Status Exam** | A clinical note section (LOINC: 10190-7) documenting the assessment of a patient's cognitive and emotional functioning during an encounter. | | **Model Training** | The process of using de-identified and anonymized data to improve AI model performance. Suki uses this data to enhance clinical note generation capabilities. | | **Mono Channel** | Single-channel audio format required for Suki's platform, as opposed to stereo (dual-channel) audio. | | **Monologue** | A single-person speech recording, such as when a clinician dictates notes alone, as opposed to a conversation between clinician and patient. | | **Multilingual Support** | The capability to process clinical conversations in over 80 languages while generating the final clinical note in English. |
# N Source: https://developer.suki.ai/Glossary/n Glossary terms starting with N

N

| Term | Definition | | :------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Natural Language Voice Interaction** | Technology that allows users to interact with systems using spoken natural language commands and queries. | | **NLP** | Natural Language Processing. AI technology that helps computers understand, interpret, and generate human language. | | **Note Archive** | A Web SDK component that allows users to view and manage both current and historical clinical notes associated with a patient. | | **Note Editor** | A rich-text editing component in the Web SDK designed specifically for AI-generated clinical content, supporting editing, formatting, and section-level interaction. | | **Note Generation** | The automated process of creating structured clinical documentation from recorded patient encounters using AI technology. | | **Note ID** | It is the unique identifier for the generated note. It appears in the payload for the `onNoteSubmit` prop (React) and the `note-submission:success` event (React and JavaScript). See [Note Management](/web-sdk/guides/note-management). | | **Note Section** | A discrete, labeled portion of a clinical note identified by a LOINC code (e.g., HPI, Physical Exam, and Assessment and Plan) that organizes documentation into standardized categories. | | **Note Submission** | The action of finalizing and sending a completed clinical note to the partner's EHR system, typically triggered via an SDK callback or API event. | | **Notification Webhook** | A server-to-server HTTP callback from Suki to a partner's registered endpoint, triggered by events such as note generation completion or session status changes. |
# O Source: https://developer.suki.ai/Glossary/o Glossary terms starting with O

O

| Term | Definition | | :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **OAuth 2.0** | An industry-standard authorization framework that enables secure delegated access to resources without sharing passwords. | | **Offline Mode** | A capability that allows certain SDK features to function without an internet connection, enabling users to work in environments with limited connectivity. | | **Offline Session** | An ambient session recorded while the device has no network connectivity. Audio is stored locally and automatically uploaded when connectivity is restored. | | **OpenAPI** | A specification for describing REST APIs in a machine-readable format, used by Suki to document API endpoints, request/response schemas, and authentication requirements. | | **OpenID Connect** | An authentication layer built on top of OAuth 2.0, providing identity verification and user information access. | | **Organization** | A healthcare entity or health system that partners with Suki to provide AI-powered documentation services to their providers and clinicians. |
# P Source: https://developer.suki.ai/Glossary/p Glossary terms starting with P

P

| Term | Definition | | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Partner** | An organization or company that integrates with Suki's platform to offer AI-powered clinical documentation services to their users. | | **Partner ID** | A unique identifier assigned by Suki during onboarding that links an application to its configuration in the Suki Developer Platform. | | **Partner Token** | A secure, digitally signed JWT issued by a partner's identity provider after user authentication, passed to Suki SDK for user verification. | | **Past Medical History** | A clinical note section (LOINC: 11348-0) documenting the patient's prior medical conditions, surgeries, hospitalizations, and significant health events. | | **Past Surgical History** | A clinical note section (LOINC: 10167-5) documenting the patient's prior surgical procedures and their outcomes. | | **Patient Instructions** | A clinical note section (LOINC: 69730-0) containing care instructions, follow-up guidance, and educational materials provided to the patient. | | **PAUSE** | A WebSocket streaming event that temporarily suspends audio transmission while keeping the session active, allowing resumption later. | | **PBC** | Problem-Based Charting. A clinical documentation approach that organizes notes around specific patient problems, with each problem having its own assessment and plan. | | **PBN** | Problem-Based Note. A clinical documentation format that organizes information around specific patient problems or diagnoses rather than traditional SOAP format. | | **PCM** | Pulse-Code Modulation. A method of digitally encoding analog audio signals. Suki uses LINEAR16 PCM format at 16KHz for audio streaming. | | **Personalization** | The ability to customize note generation behavior per provider, including preferred verbosity levels, section formats (narrative or bulleted), and specialty-specific templates. | | **PHI** | Protected Health Information. Any individually identifiable health information created, received, maintained, or transmitted by a covered entity, protected under HIPAA regulations. | | **Physical Exam** | A clinical note section (LOINC: 29545-1) documenting the physical examination findings during a patient encounter. | | **PII** | Personally Identifiable Information. Data that can be used to identify a specific individual, such as names, addresses, or social security numbers. Suki de-identifies PII from transcripts. | | **Presigned URL** | A time-limited, pre-authenticated URL that grants temporary access to a specific resource (such as an audio recording) without requiring additional authentication. | | **Problem List** | A clinical note section (LOINC: 11450-4) containing an active list of the patient's diagnosed conditions and ongoing health concerns. | | **Provider** | A healthcare professional (such as a doctor or nurse) within an organization who uses Suki's services to document patient care. | | **Provider ID** | A unique identifier for a specific healthcare provider within a partner organization, used to associate sessions, notes, and preferences with the correct clinician. |
# R Source: https://developer.suki.ai/Glossary/r Glossary terms starting with R

R

| Term | Definition | | :-------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Rate Limiting** | A mechanism that restricts the number of API requests a client can make within a given time period, used to protect platform stability and ensure fair usage. | | **Real-time** | Processing and response that occurs immediately or with minimal delay, such as live audio transcription and streaming to Suki's platform. | | **Reseller Program** | A business program that allows partners to embed Suki Platform's core technology directly into their own solutions and sell applications powered by Suki's assistive technology. | | **REST API** | Representational State Transfer Application Programming Interface. An architectural style for designing networked applications using standard HTTP methods. | | **RESUME** | A WebSocket streaming event that restarts audio transmission after a pause. | | **Review of Systems (ROS)** | A clinical note section (LOINC: 10187-3) documenting a systematic review of body systems to identify signs and symptoms the patient may be experiencing. | | **RS256** | RSA Signature with SHA-256. A digital signature algorithm used for signing and verifying JWT tokens in Suki's authentication flow. | | **RSA** | An asymmetric cryptographic algorithm used for secure data transmission and digital signatures, commonly used in JWT token verification. |
# S Source: https://developer.suki.ai/Glossary/s Glossary terms starting with S

S

| Term | Definition | | :-------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Sampling Rate** | The number of audio samples captured per second, measured in Hertz. Suki requires 16KHz sampling rate for optimal audio quality. | | **SDK** | Software Development Kit. A collection of tools, libraries, and documentation to help developers build applications for a specific platform. | | **Service Contract** | A formal agreement between Suki and healthcare customers that defines service levels, data retention policies, and compliance requirements. | | **Semantic Versioning** | A versioning scheme (MAJOR.MINOR.PATCH) used for SDKs and APIs where major versions indicate breaking changes, minor versions add features, and patches fix bugs. | | **Session** | A single, time-bound instance of an ambient recording for a specific patient encounter. | | **Session Context** | Metadata provided when creating an ambient session (such as encounter type, patient age, diagnoses) that helps guide note generation and improve output quality. | | **Session ID** | In the Suki Web SDK, the **ambient session** identifier appears as **`ambientId`** on event payloads (`ambient:update`, `ambient:start` through `ambient:submit`; see [Emitter events](/web-sdk/api-reference/types/emitter-events)) and as **`activeAmbientId`** on `SDKClientInstance` (`string` or `null`; see [Classes](/web-sdk/api-reference/classes) and [Hooks](/web-sdk/api-reference/hooks)). After `startAmbient()`, read `sdkClient.activeAmbientId` or the same value from `useSuki()` in React. It is **not** the same as **`encounterId`** on the note submission payload ([Note management](/web-sdk/guides/note-management), [Encounter ID](/Glossary/e)). See [Session status](/web-sdk/guides/ambient-session-status) and [Create session](/web-sdk/guides/ambient-implementation). | | **Session Recovery** | The ability to reconnect and resume an interrupted ambient session, allowing continuation of recording and note generation after a network or device disruption. | | **Session Timeouts** | Automatic disconnection that occurs when no audio data is sent for 25 seconds (active state) or 30 minutes during pause with keep-alive events. | | **SNOMED** | Systematized Nomenclature of Medicine. A comprehensive clinical terminology system used for encoding clinical concepts like diagnoses, procedures, and findings. | | **SOC 2 Type II** | A security compliance certification that evaluates an organization's controls for data security, availability, processing integrity, confidentiality, and privacy over time. | | **Social History** | A clinical note section (LOINC: 29762-2) documenting lifestyle factors such as tobacco use, alcohol consumption, occupation, and living situation. | | **SHA-256** | Secure Hash Algorithm 256-bit. A cryptographic hash function used for data integrity verification and digital signatures in security protocols. | | **SOAP Note** | Subjective, Objective, Assessment, Plan. A traditional clinical documentation format that organizes patient information into these four standardized sections. | | **Speech Recognition** | Technology that converts spoken words into written text, enabling voice-to-text functionality for clinical documentation. | | **Structured Data** | Organized medical information extracted from clinical conversations, such as diagnoses, medications, allergies, and vital signs, formatted for integration with EHR systems. | | **Suki Developer Platform (SDP)** | The official name for the entire suite of Suki's developer tools, including all APIs and SDKs. | | **Suki Token** | The access token returned by Suki's authentication API, used to authorize subsequent API requests to the Suki platform. |
# T Source: https://developer.suki.ai/Glossary/t Glossary terms starting with T

T

| Term | Definition | | :------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Telehealth** | The delivery of healthcare services remotely through technology, including video consultations. Suki's Web SDK supports telehealth by capturing tab audio from virtual visits. | | **Test Mode** | A development feature in the Web SDK that allows developers to simulate ambient sessions without real audio, useful for testing integration and UI flows. | | **TLS 1.2** | Transport Layer Security version 1.2. A cryptographic protocol used to provide secure communication over networks, required by Suki for data transmission. | | **Transcript** | The text version of recorded audio from clinical conversations, generated by automatic speech recognition and used as input for note generation. | | **Transcription Session** | A session specifically for audio dictation, where a provider's spoken monologue is transcribed into text in real-time, as opposed to a full ambient note generation session. |
# U Source: https://developer.suki.ai/Glossary/u Glossary terms starting with U

U

| Term | Definition | | :--------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- | | **Upload Speed** | The rate at which data can be transmitted from a client device to Suki's servers. Suki requires minimum 768kbps upload speed for optimal performance. |
# V Source: https://developer.suki.ai/Glossary/v Glossary terms starting with V

V

| Term | Definition | | :----------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **VARCHAR** | A VARCHAR (Variable Character) data type in SQL accepts variable-length string data, including letters, numbers, and special characters. It is used for storing alphanumeric data where the length of the entries varies significantly, such as names, addresses, or descriptions. | | **varchar(36)** | A **VARCHAR** column with a **36-character** maximum length. Web SDK **`patient.identifier`** and **`encounter.identifier`** must not exceed **36 characters**. For the general **`VARCHAR`** SQL type, see the row above. | | **Verbosity** | A personalization setting that controls the level of detail in generated clinical notes. Options include concise, balanced, and detailed output levels. | | **Visit Type** | A classification of the clinical encounter (e.g., new patient, follow-up, annual wellness), used alongside encounter type to guide note generation behavior. | | **Vitals** | A clinical note section (LOINC: 8716-3) documenting measured vital signs such as blood pressure, heart rate, temperature, and respiratory rate. | | **Voice Commands** | Spoken instructions that trigger specific actions within the Suki platform, enabling hands-free interaction with clinical documentation features. |
# W Source: https://developer.suki.ai/Glossary/w Glossary terms starting with W

W

| Term | Definition | | :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **WAF** | Web Application Firewall. A security service that protects web applications by filtering and monitoring HTTP traffic between applications and the internet. | | **Webhook** | A mechanism that allows Suki to send real-time event notifications (like `session_summary_generated`) to your application's server. | | **Webhook Payload** | The JSON data body sent by Suki to a partner's callback URL when a webhook event is triggered, containing event details and relevant session or note data. | | **WebSocket** | A communication protocol that provides full-duplex communication channels over a single TCP connection, used for real-time audio streaming to Suki's platform. | | **WebSocket Secure (WSS)** | The secure version of WebSocket protocol that uses TLS/SSL encryption for protected data transmission during real-time audio streaming. |
# Suki APIs Overview Source: https://developer.suki.ai/api-overview/overview Overview of REST, WebSocket, and webhook APIs on the Suki Developer Platform, with links to Ambient APIs, Form Filling APIs, and API guidelines.

Suki APIs

Suki provides partner APIs that let you integrate Suki's ambient clinical intelligence into your applications.

Introduction

Suki APIs use REST for API requests, Suki access tokens for authentication, and WebSockets for real-time audio streaming. The APIs return standard HTTP status codes and JSON response bodies. You can explore and test the APIs using the OpenAPI bundle. Access requires partner onboarding.

Use the APIs to capture clinical conversations, stream live audio, retrieve structured output, and receive webhook events while your application owns the UI and downstream integrations.

How it works

  • Use REST endpoints: Create sessions, send context, end sessions, and retrieve results from the API reference.
  • Add streaming when needed: Use WebSocket flows when a workflow needs live audio. Send the correct session context for that workflow.
  • Receive asynchronous notifications: Configure webhooks when you want completion and status events sent to your backend.

Authentication

Suki APIs are available only to approved partners. Complete Partner onboarding before you use them. Authentication has two layers:

  • Partner authentication: Your application sends a JWT from your identity provider (partner token). Suki validates it against your registered keys so traffic is tied to your organization.
  • Provider authentication: Register each clinician once, then sign them in for a Suki access token for REST, WebSocket, and related calls.

Download OpenAPI description

Languages

```bash theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} curl -X POST https://sdp.suki.ai/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{ "partner_id": "your-partner-id", "partner_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "provider_id": "provider-123" }' ```
```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch("https://sdp.suki.ai/api/v1/auth/login", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ partner_id: "your-partner-id", partner_token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", provider_id: "provider-123", // Optional }), }); if (response.ok) { const data = await response.json(); const sukiToken = data.suki_token; console.log(`Authentication successful. Token: ${sukiToken}`); } else { const error = await response.json(); console.error(`Authentication failed: ${response.status}`, error); } ```
```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki.ai/api/v1/auth/login" payload = { "partner_id": "your-partner-id", "partner_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "provider_id": "provider-123" # Optional } response = requests.post(url, json=payload) if response.status_code == 200: data = response.json() suki_token = data["suki_token"] print(f"Authentication successful. Token: {suki_token}") else: print(f"Authentication failed: {response.status_code}") print(response.json()) ```
```ruby theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} require "net/http" require "json" uri = URI("https://sdp.suki.ai/api/v1/auth/login") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true req = Net::HTTP::Post.new(uri) req["Content-Type"] = "application/json" req.body = JSON.generate( "partner_id" => "your-partner-id", "partner_token" => "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "provider_id" => "provider-123" ) res = http.request(req) puts res.body ```
```java theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; public class LoginExample { public static void main(String[] args) throws Exception { String body = "{" + "\"partner_id\":\"your-partner-id\"," + "\"partner_token\":\"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...\"," + "\"provider_id\":\"provider-123\"" + "}"; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://sdp.suki.ai/api/v1/auth/login")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(body)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ```
```php theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} "your-partner-id", "partner_token" => "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "provider_id" => "provider-123", ]) ); $response = curl_exec($ch); curl_close($ch); echo $response; ```

Servers

Production host URL
[https://sdp.suki.ai](https://sdp.suki.ai)
Current API version
[https://sdp.suki.ai/api/v1](https://sdp.suki.ai/api/v1)
Confirm with your Suki partnership team for production URLs, and any host-specific routing before you go live.

Choose your API Workflow

Available APIs

Pick the APIs for your use case and workflow and start building your integration.

REST v1
REST v1
REST v1
Decide Your Workflow

Start building

Ambient APIs illustration Ambient API Introduction Learn more about the Ambient API and how to get started. Ambient APIs illustration Webhooks Introduction Learn more about the Webhooks to receive notifications from Suki. Ambient APIs illustration Ambient API Quickstart Build your first ambient session and stream audio in minutes. Ambient APIs illustration WebSocket APIs Stream visit audio over WebSocket for ambient and form filling sessions. Ambient APIs illustration Form Filling API Introduction Learn more about the Form Filling API and how to get started. Ambient APIs illustration API Guidelines Learn more about the API guidelines to help you build your integration. Ambient APIs illustration Form Filling API Quickstart Build your first form-filling session and retrieve structured data in minutes. Ambient APIs illustration Partner Onboarding Learn more about the partner onboarding process to start using the Suki APIs.

Stay updated

Learn about the latest updates to the Ambient, Form Filling, and Dictation APIs.

New endpoints, deprecations, and behavior notes for Ambient, and Dictation APIs. New endpoints, deprecations, and behavior notes for Form Filling APIs.
# Suki APIs Quickstarts Source: https://developer.suki.ai/api-overview/quickstarts Quickstarts for Suki APIs Get started with the Suki APIs by following the quickstarts below for your workflow of choice. Build your first ambient session, stream audio, and retrieve the note in minutes. Build your first form-filling session and retrieve structured data in minutes. Refer to the Ambient API reference to learn more about the Ambient API. Refer to the Form Filling API reference to learn more about the Form Filling API. Refer to the Dictation API reference to learn more about the Dictation API. # Ambient Content Retrieval API Source: https://developer.suki.ai/api-reference/ambient-content-retrieval Poll session status and retrieve transcripts, recordings, note content, and structured clinical data After you create and run an ambient session, use these endpoints to read processing state and to fetch artifacts: transcripts, audio, generated note text, and structured clinical payloads. Some routes are scoped to the ambient session id; others are scoped to the encounter id when content is shared across sessions for the same encounter. Make sure your session was not skipped. ## Endpoints # Get Ambient Session Content Source: https://developer.suki.ai/api-reference/ambient-content/content GET /api/v1/ambient/session/{ambient_session_id}/content Retrieve generated clinical content from completed ambient session **Updated:** You can now get the structured data blocks in the response of this API, including medication orders details. Use this endpoint to get the summary and structured data associated with the specified ambient session. This endpoint uses the `cumulative` query parameter to get the cumulative summary and structured data for the specified ambient session. If the query parameter is not provided, the default value is `false`. You have two options for the `cumulative` query parameter: Determines whether to retrieve cumulative or snapshot data. Cumulative summary and structured data up to the specified ambient session is retrieved. Snapshot summary and structured data for the specified ambient session is retrieved. **Understanding the SKIPPED Status** If you see a session with a `SKIPPED` status, it means that the clinical note was **not generated** because the conversation transcript was **empty**. This status is an expected outcome if an ambient session is started but contains no audible speech (for example, a silent recording). It does not indicate a system error. Unlike a `FAILED` status, which indicates a processing error, `SKIPPED` is a successful outcome where no action was needed. Typically filter out or ignore sessions with this status in your application's user interface. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests ambient_session_id = "123dfg-456dfg-789dfg-012dfg" url = f"https://sdp.suki-stage.com/api/v1/ambient/session/{ambient_session_id}/content" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } # Get snapshot content (default, cumulative=false) response = requests.get(url, headers=headers, params={"cumulative": False}) if response.status_code == 200: content = response.json() print("Structured data blocks:") for block in content.get("structured_data", []) or []: print(f"\nBlock title: {block.get('title')}") data = block.get("data") or {} for key, value in data.items(): print(f" {key}: {value}") print("\nGenerated note (summary):") for section in content.get("summary", []) or []: print(f"\nTitle: {section.get('title')}") print(f"LOINC Code: {section.get('loinc_code')}") print(f"Content: {section.get('content')}") else: print(f"Failed to get content: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const ambientSessionId = '123dfg-456dfg-789dfg-012dfg'; // Get snapshot content (default, cumulative=false) const response = await fetch( `https://sdp.suki-stage.com/api/v1/ambient/session/${ambientSessionId}/content?cumulative=false`, { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } } ); if (response.ok) { const content = await response.json(); console.log('Structured data blocks:'); (content.structured_data || []).forEach((block: any) => { console.log(`\nBlock title: ${block.title}`); const data = block.data || {}; Object.entries(data).forEach(([key, value]) => { console.log(` ${key}: ${value}`); }); }); console.log('\nGenerated note (summary):'); content.summary?.forEach((section: any) => { console.log(`\nTitle: ${section.title}`); console.log(`LOINC Code: ${section.loinc_code}`); console.log(`Content: ${section.content}`); }); } else { const error = await response.json(); console.error(`Failed to get content: ${response.status}`, error); } ``` # Get Ambient Encounter Content Source: https://developer.suki.ai/api-reference/ambient-content/encounter-content GET /api/v1/ambient/encounter/{encounter_id}/content Retrieve generated clinical content from completed encounter **Updated:** You can now get the medication orders for an encounter from the encounter content response. Use this endpoint to get the cumulative summary and structured data associated with the specified encounter. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests encounter_id = "123dfg-456dfg-789dfg-012dfg" url = f"https://sdp.suki-stage.com/api/v1/ambient/encounter/{encounter_id}/content" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: content = response.json() print("Encounter Summary:") for section in content.get("summary", []): print(f"\nTitle: {section.get('title')}") print(f"LOINC Code: {section.get('loinc_code')}") print(f"Content: {section.get('content')}") print("\nStructured Data:") for structured_block in content.get("structured_data", []): print(f"\n{structured_block.get('title')}:") # data is a key-value object data = structured_block.get('data', {}) for key, value in data.items(): print(f" {key}: {value}") else: print(f"Failed to get encounter content: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const encounterId = '123dfg-456dfg-789dfg-012dfg'; const response = await fetch( `https://sdp.suki-stage.com/api/v1/ambient/encounter/${encounterId}/content`, { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } } ); if (response.ok) { const content = await response.json(); console.log('Encounter Summary:'); content.summary?.forEach((section: any) => { console.log(`\nTitle: ${section.title}`); console.log(`LOINC Code: ${section.loinc_code}`); console.log(`Content: ${section.content}`); }); console.log('\nStructured Data:'); content.structured_data?.forEach((structuredBlock: any) => { console.log(`\n${structuredBlock.title}:`); // data is a key-value object if (structuredBlock.data) { Object.entries(structuredBlock.data).forEach(([key, value]) => { console.log(` ${key}: ${value}`); }); } }); } else { const error = await response.json(); console.error(`Failed to get encounter content: ${response.status}`, error); } ``` # Get Ambient Encounter Structured Data Source: https://developer.suki.ai/api-reference/ambient-content/encounter-structured-data GET /api/v1/ambient/encounter/{encounter_id}/structured-data Retrieve structured clinical data from completed encounter **Updated:** You can now get the medication orders for an encounter from the encounter structured data endpoint. Use this endpoint to get the structured data associated with the specified encounter. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests encounter_id = "123dfg-456dfg-789dfg-012dfg" url = f"https://sdp.suki-stage.com/api/v1/ambient/encounter/{encounter_id}/structured-data" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: structured_data = response.json() print("Encounter Structured Data:") if "structured_data" in structured_data: diagnoses = structured_data["structured_data"].get("diagnoses", {}) if "values" in diagnoses: for diagnosis in diagnoses["values"]: print(f"Diagnosis Note: {diagnosis.get('diagnosis_note')}") # Additional diagnosis fields if diagnosis.get('laterality_indicator') is not None: print(f"Laterality Indicator: {diagnosis.get('laterality_indicator')}") if diagnosis.get('post_coord_lex_flag') is not None: print(f"Post-coordination Lexical Flag: {diagnosis.get('post_coord_lex_flag')}") # Diagnosis codes for code in diagnosis.get("codes", []): print(f" Code: {code.get('code')}") print(f" Description: {code.get('description')}") print(f" Type: {code.get('type')}") print("---") orders = structured_data["structured_data"].get("orders", {}) med_orders = orders.get("medication_orders") or {} for order in med_orders.get("values") or []: print(f"Order (submittable): {order.get('drug_name')} - {order.get('status')}") for order in med_orders.get("partial_values") or []: print(f"Order (partial): {order.get('drug_name')} - {order.get('status')}") else: print(f"Failed to get encounter structured data: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const encounterId = '123dfg-456dfg-789dfg-012dfg'; const response = await fetch( `https://sdp.suki-stage.com/api/v1/ambient/encounter/${encounterId}/structured-data`, { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } } ); if (response.ok) { const structuredData = await response.json(); console.log('Encounter Structured Data:'); if (structuredData.structured_data) { const diagnoses = structuredData.structured_data.diagnoses || {}; if (diagnoses.values) { diagnoses.values.forEach((diagnosis: any) => { console.log(`Diagnosis Note: ${diagnosis.diagnosis_note}`); // Additional diagnosis fields if (diagnosis.laterality_indicator !== undefined && diagnosis.laterality_indicator !== null) { console.log(`Laterality Indicator: ${diagnosis.laterality_indicator}`); } if (diagnosis.post_coord_lex_flag !== undefined && diagnosis.post_coord_lex_flag !== null) { console.log(`Post-coordination Lexical Flag: ${diagnosis.post_coord_lex_flag}`); } // Diagnosis codes diagnosis.codes?.forEach((code: any) => { console.log(` Code: ${code.code}`); console.log(` Description: ${code.description}`); console.log(` Type: ${code.type}`); }); console.log('---'); }); } const orders = structuredData.structured_data.orders || {}; const medOrders = orders.medication_orders || {}; (medOrders.values || []).forEach((order: any) => { console.log(`Order (submittable): ${order.drug_name} - ${order.status}`); }); (medOrders.partial_values || []).forEach((order: any) => { console.log(`Order (partial): ${order.drug_name} - ${order.status}`); }); } } else { const error = await response.json(); console.error(`Failed to get encounter structured data: ${response.status}`, error); } ``` # Get Ambient Session Recording Source: https://developer.suki.ai/api-reference/ambient-content/recording GET /api/v1/ambient/session/{ambient_session_id}/recording Get presigned URLs for ambient session recordings for streaming or download Use this endpoint to get presigned URLs for all recordings for the ambient session. Refer to the [Audio streaming & download](/documentation/audio-streaming-download) guide for more details. Use the `download` query parameter to control the URL type: * If `download=true`, the URL is for downloading the **full** file. * If `download=false` or omitted, the URL supports streaming with **range** requests. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests ambient_session_id = "123dfg-456dfg-789dfg-012dfg" # this will be the ambient session id you get from the create ambient session API url = f"https://sdp.suki-stage.com/api/v1/ambient/session/{ambient_session_id}/recording" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } # For streaming URLs (default) response = requests.get(url, headers=headers) # For download-only URLs # response = requests.get(url, headers=headers, params={"download": True}) if response.status_code == 200: data = response.json() print(f"Streamable: {data.get('is_streamable')}") for rec in data.get("recordings", []): print(f"Recording ID: {rec.get('recording_id')}") print(f"Presigned URL: {rec.get('presigned_url')}") print(f"Expires at: {rec.get('expires_at')}") print(f"Sequence: {rec.get('sequence_number')}") print("---") else: print(f"Failed to get recording URLs: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const ambientSessionId = '123dfg-456dfg-789dfg-012dfg'; // this will be the ambient session id you get from the create ambient session API // For streaming URLs (default) const response = await fetch( `https://sdp.suki-stage.com/api/v1/ambient/session/${ambientSessionId}/recording`, { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } } ); // For download-only URLs, append ?download=true // const response = await fetch( // `https://sdp.suki-stage.com/api/v1/ambient/session/${ambientSessionId}/recording?download=true`, // { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } } // ); if (response.ok) { const data = await response.json(); console.log('Streamable:', data.is_streamable); data.recordings?.forEach((rec: any) => { console.log('Recording ID:', rec.recording_id); console.log('Presigned URL:', rec.presigned_url); console.log('Expires at:', rec.expires_at); console.log('Sequence:', rec.sequence_number); console.log('---'); }); } else { const error = await response.json(); console.error(`Failed to get recording URLs: ${response.status}`, error); } ``` # Get Ambient Session Status Source: https://developer.suki.ai/api-reference/ambient-content/status GET /api/v1/ambient/session/{ambient_session_id}/status Check current status and processing state of ambient session Use this endpoint to get the **current status** of an ambient session. Use it to track the session's progress, for example, to see if it is ready to receive audio, still processing, or has completed. ## Session status values Use the following status values to track the session's progress: * **created**: The ambient session has been created but has not yet started. * **ready**: The ambient session has started and is ready for audio streaming. * **running**: The ambient session is actively processing audio and generating content. * **aborted**: The ambient session has been cancelled by the user or client. * **skipped**: The ambient session was skipped because not enough audio was received or the transcript was empty. * **failed**: The ambient session failed due to an error during processing. * **completed**: The ambient session completed successfully and generated the final content. **paused** status is no longer supported. Upon reaching **completed** state, the session is ready to return the content, transcripts, or other structured data. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests ambient_session_id = "123dfg-456dfg-789dfg-012dfg" url = f"https://sdp.suki-stage.com/api/v1/ambient/session/{ambient_session_id}/status" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: status_data = response.json() status = status_data.get("status") print(f"Session status: {status}") if status == "completed": print("Session completed successfully. Content is ready.") elif status == "failed": print("Session failed during processing.") elif status == "skipped": print("Session was skipped (empty transcript or too short).") else: print(f"Failed to get status: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const ambientSessionId = '123dfg-456dfg-789dfg-012dfg'; const response = await fetch( `https://sdp.suki-stage.com/api/v1/ambient/session/${ambientSessionId}/status`, { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } } ); if (response.ok) { const statusData = await response.json(); const status = statusData.status; console.log(`Session status: ${status}`); if (status === 'completed') { console.log('Session completed successfully. Content is ready.'); } else if (status === 'failed') { console.log('Session failed during processing.'); } else if (status === 'skipped') { console.log('Session was skipped (empty transcript or too short).'); } } else { const error = await response.json(); console.error(`Failed to get status: ${response.status}`, error); } ``` # Get Ambient Session Structured Data Source: https://developer.suki.ai/api-reference/ambient-content/structured-data GET /api/v1/ambient/session/{ambient_session_id}/structured-data Retrieve structured clinical data from completed ambient session **Updated:** You can now get the medication orders for an ambient session from the structured data endpoint. Use this endpoint to get the cumulative structured data associated with the specified ambient session. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests ambient_session_id = "123dfg-456dfg-789dfg-012dfg" url = f"https://sdp.suki-stage.com/api/v1/ambient/session/{ambient_session_id}/structured-data" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: structured_data = response.json() print("Structured Data:") if "structured_data" in structured_data: diagnoses = structured_data["structured_data"].get("diagnoses", {}) if "values" in diagnoses: for diagnosis in diagnoses["values"]: print(f"Diagnosis Note: {diagnosis.get('diagnosis_note')}") # Additional diagnosis fields if diagnosis.get('laterality_indicator') is not None: print(f"Laterality Indicator: {diagnosis.get('laterality_indicator')}") if diagnosis.get('post_coord_lex_flag') is not None: print(f"Post-coordination Lexical Flag: {diagnosis.get('post_coord_lex_flag')}") # Diagnosis codes for code in diagnosis.get("codes", []): print(f" Code: {code.get('code')}") print(f" Description: {code.get('description')}") print(f" Type: {code.get('type')}") print("---") orders = structured_data["structured_data"].get("orders", {}) med_orders = orders.get("medication_orders") or {} for order in med_orders.get("values") or []: med_code = order.get("medication_code") or {} print(f"Order (submittable): {order.get('drug_name')} - {order.get('status')}") print(f" Medication code: {med_code.get('code')} ({med_code.get('type')})") print("---") for order in med_orders.get("partial_values") or []: med_code = order.get("medication_code") or {} print(f"Order (partial): {order.get('drug_name')} - {order.get('status')}") print(f" Medication code: {med_code.get('code')} ({med_code.get('type')})") print("---") else: print(f"Failed to get structured data: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const ambientSessionId = '123dfg-456dfg-789dfg-012dfg'; const response = await fetch( `https://sdp.suki-stage.com/api/v1/ambient/session/${ambientSessionId}/structured-data`, { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } } ); if (response.ok) { const structuredData = await response.json(); console.log('Structured Data:'); if (structuredData.structured_data) { const diagnoses = structuredData.structured_data.diagnoses || {}; if (diagnoses.values) { diagnoses.values.forEach((diagnosis: any) => { console.log(`Diagnosis Note: ${diagnosis.diagnosis_note}`); // Additional diagnosis fields if (diagnosis.laterality_indicator !== undefined && diagnosis.laterality_indicator !== null) { console.log(`Laterality Indicator: ${diagnosis.laterality_indicator}`); } if (diagnosis.post_coord_lex_flag !== undefined && diagnosis.post_coord_lex_flag !== null) { console.log(`Post-coordination Lexical Flag: ${diagnosis.post_coord_lex_flag}`); } // Diagnosis codes diagnosis.codes?.forEach((code: any) => { console.log(` Code: ${code.code}`); console.log(` Description: ${code.description}`); console.log(` Type: ${code.type}`); }); console.log('---'); }); } const orders = structuredData.structured_data.orders || {}; const medOrders = orders.medication_orders || {}; (medOrders.values || []).forEach((order: any) => { const medCode = order.medication_code || {}; console.log(`Order (submittable): ${order.drug_name} - ${order.status}`); console.log(` Medication code: ${medCode.code} (${medCode.type})`); console.log('---'); }); (medOrders.partial_values || []).forEach((order: any) => { const medCode = order.medication_code || {}; console.log(`Order (partial): ${order.drug_name} - ${order.status}`); console.log(` Medication code: ${medCode.code} (${medCode.type})`); console.log('---'); }); } } else { const error = await response.json(); console.error(`Failed to get structured data: ${response.status}`, error); } ``` # Get Session Transcript Source: https://developer.suki.ai/api-reference/ambient-content/transcript GET /api/v1/ambient/session/{ambient_session_id}/transcript Retrieve conversation transcript from completed ambient session Use this endpoint to get the full transcript for a specified ambient session after it has completed. **Updated:** The response will now include the new `lang_id` field within the payload. The `lang_id` field indicates the language in which the transcript was sent. For a full list of language codes and their corresponding languages, refer to the [Language code reference](/api-reference/capabilities/multilingual#language-code-reference) section. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests ambient_session_id = "123dfg-456dfg-789dfg-012dfg" url = f"https://sdp.suki-stage.com/api/v1/ambient/session/{ambient_session_id}/transcript" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: transcript_data = response.json() print("Transcript:") for transcript in transcript_data.get("final_transcript", []): print(f"Transcript ID: {transcript.get('transcript_id')}") print(f"Recording ID: {transcript.get('recording_id')}") print(f"Language: {transcript.get('lang_id')}") print(f"Transcript: {transcript.get('transcript')}") print(f"Start Time: {transcript.get('start_time')}") print(f"End Time: {transcript.get('end_time')}") # Start offset (relative to beginning of audio) start_offset = transcript.get('start_offset', {}) if start_offset: print(f"Start Offset: {start_offset.get('hours')}h {start_offset.get('minutes')}m {start_offset.get('seconds')}s") # End offset (relative to beginning of audio) end_offset = transcript.get('end_offset', {}) if end_offset: print(f"End Offset: {end_offset.get('hours')}h {end_offset.get('minutes')}m {end_offset.get('seconds')}s") print("---") else: print(f"Failed to get transcript: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const ambientSessionId = '123dfg-456dfg-789dfg-012dfg'; const response = await fetch( `https://sdp.suki-stage.com/api/v1/ambient/session/${ambientSessionId}/transcript`, { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } } ); if (response.ok) { const transcriptData = await response.json(); console.log('Transcript:'); transcriptData.final_transcript?.forEach((transcript: any) => { console.log(`Transcript ID: ${transcript.transcript_id}`); console.log(`Recording ID: ${transcript.recording_id}`); console.log(`Language: ${transcript.lang_id}`); console.log(`Transcript: ${transcript.transcript}`); console.log(`Start Time: ${transcript.start_time}`); console.log(`End Time: ${transcript.end_time}`); // Start offset (relative to beginning of audio) if (transcript.start_offset) { const { hours, minutes, seconds } = transcript.start_offset; console.log(`Start Offset: ${hours}h ${minutes}m ${seconds}s`); } // End offset (relative to beginning of audio) if (transcript.end_offset) { const { hours, minutes, seconds } = transcript.end_offset; console.log(`End Offset: ${hours}h ${minutes}m ${seconds}s`); } console.log('---'); }); } else { const error = await response.json(); console.error(`Failed to get transcript: ${response.status}`, error); } ``` # Dictation API Source: https://developer.suki.ai/api-reference/ambient-dictation Create dictation sessions, stream audio for transcription, and end sessions Use the dictation APIs when you need speech-to-text without the full ambient clinical note flow. You create a transcription session, open a WebSocket to stream audio, then end the session when capture is finished so resources can close cleanly. ## Usage scenarios * You need speech-to-text without the full ambient clinical note flow. * You want to create a transcription session, open a WebSocket to stream audio, then end the session when capture is finished so resources can close cleanly. ## How it works The dictation APIs work in four steps: Register the provider and obtain an **`sdp_suki_token`**. Refer to [Provider authentication](/api-reference/provider-authentication) and [Partner authentication](/documentation/partner-authentication). Call [Create dictation session](/api-reference/audio-transcription/create-session) and save **`transcription_session_id`**. Connect to [Stream audio to dictation session](/api-reference/audio-transcription/stream-transcription) when the session is **`READY`** or **`IDLE`**. Refer to [Dictation streaming](/documentation/dictation-streaming) for outbound audio messages and inbound transcript frames. Call [End dictation session](/api-reference/audio-transcription/end-session) when capture is finished. ## Endpoints # Ambient Session Management API Source: https://developer.suki.ai/api-reference/ambient-session-management Create and manage ambient sessions, stream audio, attach metadata, and end sessions These endpoints cover the ambient session lifecycle: create a session, set and update context, attach metadata, stream audio over WebSocket, and end the session when the recording is finished. ## Usage scenarios * Create a new ambient session for your patient encounter during in-person visits or virtual visits * Set and update session context with the patient information, provider details, and diagnosis codes * Stream audio over WebSocket to the Suki backend * End the session when the recording is finished ## Endpoints # Audio Streaming Source: https://developer.suki.ai/api-reference/ambient-sessions/audio-stream GET /ws/stream WebSocket endpoint for real-time audio streaming during ambient sessions Use this API to stream audio to the speech service over a WebSocket connection for ambient and form filling sessions. For more information on how to handle the **handshake**, **wire format**, **message order**, and **error handling**, refer to the [Ambient audio streaming](/documentation/ambient-audio-streaming) guide. ## Prerequisites Complete these steps **before** opening the WebSocket. Opening `/ws/stream` before the session and context are ready often leads to handshake failures or a broken stream. * **Authenticate** and obtain `sdp_suki_token` * **Create an ambient session** with POST [`/api/v1/ambient/session/create`](/api-reference/ambient-sessions/create). A successful create returns **201 Created**; keep the `ambient_session_id` you used or received. * **Seed session context** with POST [`/api/v1/ambient/session/{ambient_session_id}/context`](/api-reference/ambient-sessions/context). Send the JSON body your integration requires (see that endpoint for the full schema). * **Authenticate and open the WebSocket** on `wss://sdp.suki-stage.com/ws/stream`. To stream audio, you must first establish an **authenticated WebSocket connection**. The authentication method you use depends on your client types: browser or non-browser. ## Browser clients When connecting from a browser, include the `Sec-WebSocket-Protocol` header as part of the WebSocket handshake. Set the header value as a single comma-separated string. The order must be: * Subprotocol name * Ambient session ID - Your ambient session ID * Token - Your Suki token Avoid adding spaces between values unless your client library requires it. For example: ```bash theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} Sec-WebSocket-Protocol: SukiAmbientAuth,, ``` The server negotiates this subprotocol to establish the connection. ## Non-browser clients For non-browser clients such as mobile apps, backend services, or testing tools, pass authentication details as separate HTTP headers in the WebSocket upgrade request. Do not use the `Sec-WebSocket-Protocol` header. Include the following headers: * `sdp_suki_token` - Your Suki token. * `sdp_provider_id` - Provider identifier. Optional for standard partners; **Required** for Single Auth Token authentication. * `ambient_session_id` - The ID for the current ambient session. If you push non-JSON payloads where the server expects JSON, you can see parse errors (for example invalid character or null byte errors). ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} # pip install websocket-client import base64 import json from datetime import datetime, timezone import websocket ambient_session_id = "" token = "" sdp_provider_id = "" # Optional; Required for Single Auth Token authentication CHUNK_BYTES = 3200 WAV_HEADER_BYTES = 44 # Non-browser: headers on upgrade. Staging WebSocket URL: ws_url = "wss://sdp.suki-stage.com/ws/stream" ws = websocket.create_connection( ws_url, header=[ f"sdp_suki_token: {token}", f"sdp_provider_id: {sdp_provider_id}", f"ambient_session_id: {ambient_session_id}", ], ) def b64(data: bytes) -> str: return base64.b64encode(data).decode("ascii") try: rfc3339 = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") ws.send(json.dumps({"type": "START_TIME", "data": b64(rfc3339.encode("utf-8"))})) with open("audio.wav", "rb") as f: raw = f.read() if len(raw) >= 12 and raw[:4] == b"RIFF" and raw[8:12] == b"WAVE": pcm = raw[WAV_HEADER_BYTES:] else: pcm = raw for i in range(0, len(pcm), CHUNK_BYTES): chunk = pcm[i : i + CHUNK_BYTES] ws.send(json.dumps({"type": "AUDIO", "data": b64(chunk)})) ws.send(json.dumps({"type": "AUDIO", "data": b64(b"EOF")})) while True: try: print(ws.recv()) except websocket.WebSocketConnectionClosedException: break finally: ws.close() ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} // Browser example: same IDs as Python tab; add in your HTML. const ambientSessionId = ''; const token = ''; const CHUNK_BYTES = 3200; const WAV_HEADER_BYTES = 44; function utf8ToBase64(s: string): string { const bytes = new TextEncoder().encode(s); let binary = ''; for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]!); return btoa(binary); } function bytesToBase64(u8: Uint8Array): string { let binary = ''; for (let i = 0; i < u8.length; i++) binary += String.fromCharCode(u8[i]!); return btoa(binary); } // Staging WebSocket URL const ws = new WebSocket(`wss://sdp.suki-stage.com/ws/stream`, [ `SukiAmbientAuth,${ambientSessionId},${token}`, ]); ws.binaryType = 'arraybuffer'; ws.onopen = () => { const rfc3339 = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z'); ws.send(JSON.stringify({ type: 'START_TIME', data: utf8ToBase64(rfc3339) })); const input = document.getElementById('audioFile') as HTMLInputElement; const file = input.files?.[0]; if (!file) return; const reader = new FileReader(); reader.onload = () => { const buf = new Uint8Array(reader.result as ArrayBuffer); let pcm = buf; if ( buf.length >= 12 && buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 && buf[8] === 0x57 && buf[9] === 0x41 && buf[10] === 0x56 && buf[11] === 0x45 ) { pcm = buf.subarray(WAV_HEADER_BYTES); } for (let i = 0; i < pcm.length; i += CHUNK_BYTES) { const chunk = pcm.subarray(i, i + CHUNK_BYTES); ws.send(JSON.stringify({ type: 'AUDIO', data: bytesToBase64(chunk) })); } ws.send( JSON.stringify({ type: 'AUDIO', data: bytesToBase64(new Uint8Array([0x45, 0x4f, 0x46])), }), ); }; reader.readAsArrayBuffer(file); }; ws.onmessage = (ev) => console.log('Received:', ev.data); ws.onerror = (e) => console.error(e); ws.onclose = () => console.log('closed'); ``` # Seed Ambient Session Context Source: https://developer.suki.ai/api-reference/ambient-sessions/context POST /api/v1/ambient/session/{ambient_session_id}/context Provide clinical context and patient information for ambient session **Updated:** You can now provide **EMR context** and **medication orders** in the ambient session context. Use this endpoint to provide or update the session context for an ambient session. Providing detailed context helps Suki generate a more accurate and relevant clinical note. For example, you can provide: * Provider details (e.g., specialty and role). * Patient and visit information. * A list of LOINC codes for the clinical sections you want to generate. * Existing diagnoses with their associated medical codes. * EMR context, including target EMR, when you need EMR-specific behavior (for example order submission rules). * Orders context (medication orders), including structured medication orders for active medications and related metadata. For more information about the context, refer to the [PBC](/api-reference/capabilities/problem-based-charting) and [Specialty](/documentation/specialties) section. For more information about medication orders, refer to the [Medication orders](/documentation/medication-orders) guide. You can use the `Codes` section to provide additional context for a session, such as **medical codes** for a **diagnosis**. To ensure your requests succeed, follow these validation rules when sending data to the API: ### Field validation and constraints * **Character Limits**: Ensure the **`chief_complaint`** and **`reason_for_visit`** fields do not exceed **255 characters**. * **Enumerated Values**: Use only the predefined string values for **`visit_type`**, **`encounter_type`**, and **`provider_role`**. * **EMR Selection**: You must set **`emr.target_emr`** to one of the following: **`ATHENA`**, **`EPIC`**, or **`CERNER`**. ### Medication order requirements When you send **`orders.medication_orders.values`**, include the following required properties for each object: * **Drug Information**: Provide both the **`drug_name`** and a **`medication_code`**. * **Coding Systems**: For **`medication_code`**, specify the **`code`** and set the **`type`** to **`RXCUI`** or **`NDC`**. * **Order Status**: Set the **`status`** to **`ACTIVE`**, **`DISCONTINUED`**, or **`REFILLED`**. * **Metadata**: Include the **`metadata`** object with a required **`origin`** of **`EMR`** or **`SUKI_AMBIENT`**. If you set **`origin`** to **`EMR`**, you must also set **`metadata.encounter_relation`** to either **`CURRENT_ENCOUNTER`** or **`PRIOR_ENCOUNTER`**. **Diagnosis links**: To link a diagnosis to an order, ensure the codes in **`linked_diagnosis_codes`** match a diagnosis already provided in the **`diagnoses`** section. Use the same coding system for both to allow the service to validate the link. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests ambient_session_id = "123dfg-456dfg-789dfg-012dfg" url = f"https://sdp.suki-stage.com/api/v1/ambient/session/{ambient_session_id}/context" headers = { "sdp_suki_token": "", "sdp_provider_id": "", "Content-Type": "application/json" } payload = { "provider": { "specialty": "CARDIOLOGY", "provider_role": "ATTENDING" }, "patient": { "dob": "2000-01-01", "sex": "male" }, "visit": { "chief_complaint": "Headache", "encounter_type": "AMBULATORY", "reason_for_visit": "Follow-up for migraines", "visit_type": "ESTABLISHED_PATIENT" }, "sections": [ {"loinc": "10164-2"}, {"loinc": "48765-2"} ], "diagnoses": { "values": [ { "codes": [ { "code": "I10", "description": "Essential hypertension", "type": "ICD10" } ], "diagnosis_note": "Hypertension" } ] }, "emr": { "target_emr": "EPIC" }, "orders": { "medication_orders": { "values": [ { "drug_name": "Acetaminophen 500mg Tab", "medication_code": {"code": "860975", "type": "RXCUI"}, "linked_diagnosis_codes": [ {"code": "I10", "type": "ICD10"} ], "metadata": {"origin": "SUKI_AMBIENT"}, "status": "ACTIVE", "instructions": "Take with food" } ] } } } response = requests.post(url, json=payload, headers=headers) if response.status_code == 200: print("Context seeded successfully") else: print(f"Failed to seed context: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const ambientSessionId = '123dfg-456dfg-789dfg-012dfg'; const response = await fetch( `https://sdp.suki-stage.com/api/v1/ambient/session/${ambientSessionId}/context`, { method: 'POST', headers: { 'sdp_suki_token': '', 'sdp_provider_id': '', 'Content-Type': 'application/json' }, body: JSON.stringify({ provider: { specialty: 'CARDIOLOGY', provider_role: 'ATTENDING' }, patient: { dob: '2000-01-01', sex: 'male' }, visit: { chief_complaint: 'Headache', encounter_type: 'AMBULATORY', reason_for_visit: 'Follow-up for migraines', visit_type: 'ESTABLISHED_PATIENT' }, sections: [ { loinc: '10164-2' }, { loinc: '48765-2' } ], diagnoses: { values: [ { codes: [ { code: 'I10', description: 'Essential hypertension', type: 'ICD10' } ], diagnosis_note: 'Hypertension' } ] }, emr: { target_emr: 'EPIC' }, orders: { medication_orders: { values: [ { drug_name: 'Acetaminophen 500mg Tab', medication_code: { code: '860975', type: 'RXCUI' }, linked_diagnosis_codes: [{ code: 'I10', type: 'ICD10' }], metadata: { origin: 'SUKI_AMBIENT' }, status: 'ACTIVE', instructions: 'Take with food' } ] } } }) } ); if (response.ok) { console.log('Context seeded successfully'); } else { const error = await response.json(); console.error(`Failed to seed context: ${response.status}`, error); } ``` # Create Ambient Session Source: https://developer.suki.ai/api-reference/ambient-sessions/create POST /api/v1/ambient/session/create Initialize a new ambient session for patient encounter documentation **Updated** The `multilingual` parameter is deprecated. Multilingual support is now **enabled by default** for all ambient sessions. You no longer need to pass this parameter. The API automatically supports conversations in multiple languages and generates the clinical note in English. Use this endpoint to create an ambient session. Suki will generate an `ambient_session_id` and return it in the response. Use the **`ambient_session_id`** to identify the session in future API calls. Many Suki APIs use this ID to perform operations such as checking session status, generating notes, retrieving transcripts, and other operations. Store the **`ambient_session_id`** after you create a session, as it is required for most session-related operations. ### Request body fields Both fields in the request body are optional. Suki generates any values you omit. | Field | Type | Description | | -------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `ambient_session_id` | string (UUID) | Unique identifier for this ambient session. Must be a string in UUID format. If omitted, Suki generates one and returns it in the response. | | `encounter_id` | string (UUID) | Unique identifier for the patient encounter (visit). Must be a string in UUID format. Use the same `encounter_id` across multiple `session/create` calls to group several ambient sessions under the same visit. If omitted, Suki generates one. | `encounter_id` must be a **string** in UUID format. Numeric IDs from your system must be converted to a string (for example, `String(id)`) before you send them. We recommend that recordings are at least **1 minute** long. Short recordings may not contain enough information for note generation. **Important**: If the recording is too short, note generation may be **skipped**. ## Code examples ```python expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} from typing import Any, Optional, TypedDict, cast import requests BASE_URL = "https://sdp.suki-stage.com" class CreateAmbientSessionRequest(TypedDict, total=False): ambient_session_id: str encounter_id: str class CreateAmbientSessionResponse(TypedDict): ambient_session_id: str class ApiHttpError(RuntimeError): """Wrong HTTP status; OpenAPI errors usually include JSON with message + code.""" def __init__(self, status: int, url: str, detail: str) -> None: super().__init__(f"HTTP {status} {url}: {detail}") self.status = status self.url = url def _post_json_expect(url: str, headers: dict[str, str], payload: dict[str, Any], expect_status: int) -> dict[str, Any]: r = requests.post(url, json=payload, headers=headers, timeout=60) if r.status_code == expect_status: data = r.json() if isinstance(data, dict): return data raise ApiHttpError(expect_status, url, "response JSON was not an object") detail = "" try: err = r.json() if isinstance(err, dict) and isinstance(err.get("message"), str): detail = err["message"] except ValueError: detail = (r.text or "")[:500] raise ApiHttpError(r.status_code, url, detail or "(no body)") def create_ambient_session( suki_token: str, body: Optional[CreateAmbientSessionRequest] = None, ) -> CreateAmbientSessionResponse: """POST /api/v1/ambient/session/create (sdp_suki_token header required). HTTP 201.""" url = f"{BASE_URL}/api/v1/ambient/session/create" headers = {"sdp_suki_token": suki_token, "sdp_provider_id": "", "Content-Type": "application/json"} data = _post_json_expect(url, headers, dict(body or {}), 201) sid = data.get("ambient_session_id") if not isinstance(sid, str) or not sid: raise ValueError(f"{url}: 201 response missing ambient_session_id") return cast(CreateAmbientSessionResponse, {"ambient_session_id": sid}) if __name__ == "__main__": try: session = create_ambient_session( "", { # Optional UUIDs; omit to let Suki generate. "ambient_session_id": "123dfg-456dfg-789dfg-012dfg", "encounter_id": "123dfg-456dfg-789dfg-012dfg", }, ) print(session["ambient_session_id"]) except (ApiHttpError, ValueError) as e: print(e) ``` ```typescript expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const BASE_URL = "https://sdp.suki-stage.com"; type CreateAmbientSessionRequest = { ambient_session_id?: string; encounter_id?: string; }; type CreateAmbientSessionResponse = { ambient_session_id: string }; class ApiHttpError extends Error { status: number; url: string; constructor(status: number, url: string, detail: string) { super(`HTTP ${status} ${url}: ${detail}`); this.status = status; this.url = url; } } async function postJsonExpectObject( url: string, headers: Record, body: Record, expectStatus: number ): Promise> { const res = await fetch(url, { method: "POST", headers, body: JSON.stringify(body) }); const text = await res.text(); const json = text ? JSON.parse(text) : {}; if (res.status !== expectStatus) { const msg = typeof (json as any)?.message === "string" ? (json as any).message : text?.slice(0, 500) || "(no body)"; throw new ApiHttpError(res.status, url, msg); } if (json && typeof json === "object" && !Array.isArray(json)) return json as Record; throw new ApiHttpError(res.status, url, "response JSON was not an object"); } export async function createAmbientSession( sdpSukiToken: string, body: CreateAmbientSessionRequest = {} ): Promise { const url = `${BASE_URL}/api/v1/ambient/session/create`; const data = await postJsonExpectObject( url, { sdp_suki_token: sdpSukiToken, sdp_provider_id: "", "Content-Type": "application/json" }, body as Record, 201 ); const ambientSessionId = data.ambient_session_id; if (typeof ambientSessionId !== "string" || !ambientSessionId) { throw new Error(`${url}: 201 response missing ambient_session_id`); } return { ambient_session_id: ambientSessionId }; } // Example usage const session = await createAmbientSession("", { // Optional UUIDs; omit to let Suki generate. ambient_session_id: "123dfg-456dfg-789dfg-012dfg", encounter_id: "123dfg-456dfg-789dfg-012dfg", }); console.log(session.ambient_session_id); ``` # End Ambient Session Source: https://developer.suki.ai/api-reference/ambient-sessions/end POST /api/v1/ambient/session/{ambient_session_id}/end Complete ambient session and trigger clinical note generation Use this endpoint to end an ambient session and trigger the clinical note generation process. If you get a `skipped` status, it means that the note was not generated because the conversation transcript was empty or the session was too short. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests ambient_session_id = "123dfg-456dfg-789dfg-012dfg" url = f"https://sdp.suki-stage.com/api/v1/ambient/session/{ambient_session_id}/end" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.post(url, headers=headers) if response.status_code == 200: print("Session ended successfully. Clinical note generation triggered.") else: print(f"Failed to end session: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const ambientSessionId = '123dfg-456dfg-789dfg-012dfg'; const response = await fetch( `https://sdp.suki-stage.com/api/v1/ambient/session/${ambientSessionId}/end`, { method: 'POST', headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } } ); if (response.ok) { console.log('Session ended successfully. Clinical note generation triggered.'); } else { const error = await response.json(); console.error(`Failed to end session: ${response.status}`, error); } ``` # Ambient Session Metadata Source: https://developer.suki.ai/api-reference/ambient-sessions/metadata POST /api/v1/ambient/session/{ambient_session_id}/metadata Add metadata to ambient session (deprecated; use context endpoint instead) This endpoint is `deprecated` We no longer support this endpoint. If you are using it, update your code to use the [Context](/api-reference/ambient-sessions/context) endpoint instead. That endpoint lets you set session context for an ambient session. # Update Ambient Session Context Source: https://developer.suki.ai/api-reference/ambient-sessions/update-context PATCH /api/v1/ambient/session/{ambient_session_id}/context Update existing session context with new clinical information **Updated:** You can now update the ambient session context with new **EMR context** and **medication orders**. Use this endpoint to update the session context for an ambient session. The API applies a field mask so you can send only the parts of the context you want to change. This is a **PATCH** operation that allows partial updates to the session context. ## Comparison with POST Context | Feature | POST (Seed) | PATCH (Update) | | :---------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------- | | **Purpose** | Set entire context all at once when available | Incrementally build context as information becomes available | | **Data Approach** | Complete context payload | Partial context updates | | **Timing** | Before EndSession. When you have all context information together. | Before EndSession. As information becomes available progressively | | **Behavior** | Replaces entire context | Updates only specified fields | # API Reference Guidelines Source: https://developer.suki.ai/api-reference/api-guidelines Learn about the tags, indicators, and documentation standards we use in our API documentation This guide explains the **tags**, **indicators**, and **standards** we use in our API documentation. Understanding these conventions will help you navigate the reference materials more effectively and build robust integrations. ## API status tags We use the following tags next to endpoint titles to indicate their status and maturity. ### \[NEW] This tag indicates that an API endpoint has been recently added to Suki for partners. * Use this safely in production; it is fully supported and documented. * The API may receive additional non-breaking features in future updates. ### \[UPDATED] This tag indicates that an API endpoint has received significant, backward-compatible enhancements or modifications. * Look for new parameters, response fields, or behavior changes that you can implement. * Your existing integrations should continue to work without modification. ### \[DEPRECATED] This tag indicates that an API endpoint is scheduled for removal in a future version. * You should plan to migrate any existing integrations to the recommended alternatives. * Check the documentation for the specific migration timeline and replacement APIs. Suki provides migration guides to support your transition. You should avoid using this endpoint in new integrations. ### \[EARLY ACCESS] This tag indicates that an API endpoint is available for testing and feedback but may not be fully stable. * The API's behavior may change based on feedback, and breaking changes are possible before it becomes generally available. * Access to this API may require special configuration. We encourage your feedback to help us improve it. Use early access APIs with caution. The ws and webhook indicators in the API documentation indicate that an API endpoint is a WebSocket or a Webhook endpoint. ## Documentation standards ### Parameters Each parameter in an API request is clearly marked to ensure you know what is required. * **Required**: You must include these parameters in all API requests. Requests will fail without them. * **Optional**: Include these parameters to access enhanced functionality. When applicable, the documentation will note the default value used if you don't provide one. ### Examples All API endpoints include comprehensive examples to guide your implementation. * **Response examples**: You will find examples of success responses with realistic data, as well as common error responses. Each field in the response is described. * **Code examples**: You will find practical code snippets, such as `cURL` commands for direct testing and `JSON` payloads to illustrate the request and response structure. ## Using code examples in your integration Snippets in this reference (Python, TypeScript, cURL, and similar) show real paths, headers, and JSON shapes. To use them in your own systems, do the following: * **Use real credentials**: Replace placeholders (for example ``, ``, or ``) with values from your partner integration. Complete the [Partner onboarding](/documentation/partner-onboarding) flow first, then follow [Provider authentication](/api-reference/provider-authentication) for register, login, and how tokens map to API headers. Form Filling APIs follow the same authentication model; see [Form Filling authentication](/form-filling-api-reference/authentication) for that tab’s layout. * **Use the right base URL**: Examples may use a staging host (for example `https://sdp.suki-stage.com`). Use the base URL Suki gives you for each environment (staging, production, and so on). * **Keep secrets server-side**: Do not put partner tokens, JWTs, or `sdp_suki_token` in untrusted clients, public repos, or browser bundles where they can be extracted. * **Python**: Install any dependency the sample assumes (for example `requests` via `pip install requests`). Run calls from a backend service or trusted script with outbound HTTPS to Suki. * **TypeScript or JavaScript**: Run samples on the **server** using a runtime that provides **`fetch`** (for example **Node.js 18+**, Deno, or Bun). Older Node versions need another HTTP client or a `fetch` polyfill. Calling Suki **directly from a browser** usually hits **CORS** limits unless your integration is explicitly allowed; typical integrations call Suki from **your backend** or **your proxy**. * **cURL**: Use a shell with `curl` installed; pass the same headers and JSON bodies as in the docs, with real tokens and URL. ## Version management ### API versioning Our APIs follow semantic versioning principles to make updates predictable. * **Major versions (`v1`, `v2`)**: Indicate breaking changes that may require you to update your code. * **Minor versions (`v1.1`, `v1.2`)**: Introduce new features in a backward-compatible way. * **Patch versions (`v1.1.1`, `v1.1.2`)**: Include backward-compatible bug fixes and minor improvements. The following table shows which features are available in each version: | Feature | v1 | | ------------------------------- | -- | | Authentication (Login/Register) | ✓ | | Ambient session management | ✓ | | Audio streaming (WebSocket) | ✓ | | Content retrieval | ✓ | | Audio transcription | ✓ | | Multilingual support | ✓ | | Personalization | ✓ | | Problem-Based Charting (PBC) | ✓ | | Webhooks | ✓ | | User preferences | ✓ | | Form filling | ✓ | | Dictation | ✓ | ### Backward compatibility We are committed to making platform updates as smooth as possible. * We communicate breaking changes well in advance and provide migration guidance. * When we add new optional parameters, your existing integrations will not break. * Changes to the format of API responses are additive, meaning we may add new fields, but we will not remove or alter existing ones in a breaking way. ## Best practices ### Choosing the right API * **For production use**: You should use APIs that are unmarked or are tagged as `[NEW]` or `[UPDATED]`. These are stable, fully supported, and have long-term compatibility guarantees. * **For development and testing**: Consider using `[EARLY ACCESS]` APIs to preview upcoming features and provide feedback. This can help you plan for future integrations. ### Migration strategy When an API you are using is marked as `[DEPRECATED]`, we recommend the following process: 1. **Assess impact**: Review your current usage of the deprecated endpoint. 2. **Plan timeline**: Check the deprecation timeline in the documentation and plan your migration. 3. **Test alternatives**: Implement and test the recommended replacement API. 4. **Migrate**: Update your integration in phases to minimize disruption. ### Getting help For questions about API status, migration timelines, or implementation guidance, please contact our **customer success team**. Read the [API changelog](/api-reference/product-updates/changelog) section for the latest updates and changes to the APIs. ## Next steps Use the following API to get started with the Suki Platform: Learn about the Ambient API Learn about the Form Filling API Learn about the Dictation API # Asynchronous Notifications Source: https://developer.suki.ai/api-reference/asynchronous/webhook POST /webhooks/notification Webhook endpoint for receiving asynchronous notifications from Suki platform Use this endpoint specification to implement a webhook endpoint in your application that receives notifications from the Suki platform. This endpoint should be hosted by your application to receive notifications about session completion or failure. Learn more about how webhooks work and how to implement your own webhook endpoint to receive them in the [Notification webhook for partners](/documentation/webhook/overview) documentation. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/webhooks/notification', methods=['POST']) def handle_webhook(): """ Webhook endpoint to receive notifications from Suki platform. This endpoint should be hosted by your application. """ # The payload is received in the request body from Suki data = request.get_json() # This is the payload sent by Suki if not data: return jsonify({"error": "Invalid request"}), 400 status = data.get("status") if status == "success": # Handle success notification session_id = data.get("session_id") encounter_id = data.get("encounter_id") sessions = data.get("sessions", []) additional_info = data.get("additional_info") print(f"Session {session_id} completed successfully") print(f"Encounter ID: {encounter_id}") print(f"Total sessions: {len(sessions)}") if additional_info: print(f"Additional info: {additional_info}") # Access links to retrieve content if "_links" in data: links = data["_links"] print("Available links:") # contents is an array of Link objects if "contents" in links: print(" Session contents:") for link in links["contents"]: print(f" {link.get('method')} {link.get('href')} - {link.get('name')}") # encounter_content is an array of Link objects if "encounter_content" in links: print(" Encounter content:") for link in links["encounter_content"]: print(f" {link.get('method')} {link.get('href')} - {link.get('name')}") # transcripts is an array of Link objects if "transcripts" in links: print(" Transcripts:") for link in links["transcripts"]: print(f" {link.get('method')} {link.get('href')} - {link.get('name')}") # status is an array of Link objects if "status" in links: print(" Status:") for link in links["status"]: print(f" {link.get('method')} {link.get('href')} - {link.get('name')}") return jsonify({"message": "Notification received"}), 200 elif status == "failure": # Handle failure notification session_id = data.get("session_id") encounter_id = data.get("encounter_id") error_code = data.get("error_code") error_detail = data.get("error_detail") print(f"Session {session_id} failed") print(f"Encounter ID: {encounter_id}") print(f"Error Code: {error_code}") print(f"Error Detail: {error_detail}") return jsonify({"message": "Failure notification received"}), 200 else: return jsonify({"error": "Unknown status"}), 400 if __name__ == '__main__': app.run(port=3000) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import express from 'express'; const app = express(); app.use(express.json()); app.post('/webhooks/notification', (req, res) => { /** * Webhook endpoint to receive notifications from Suki platform. * This endpoint should be hosted by your application. */ // The payload is received in the request body from Suki const data = req.body; // This is the payload sent by Suki if (!data) { return res.status(400).json({ error: 'Invalid request' }); } const status = data.status; if (status === 'success') { // Handle success notification const sessionId = data.session_id; const encounterId = data.encounter_id; const sessions = data.sessions || []; const additionalInfo = data.additional_info; console.log(`Session ${sessionId} completed successfully`); console.log(`Encounter ID: ${encounterId}`); console.log(`Total sessions: ${sessions.length}`); if (additionalInfo) { console.log(`Additional info:`, additionalInfo); } // Access links to retrieve content if (data._links) { const links = data._links; console.log('Available links:'); // contents is an array of Link objects if (links.contents) { console.log(' Session contents:'); links.contents.forEach((link: any) => { console.log(` ${link.method} ${link.href} - ${link.name}`); }); } // encounter_content is an array of Link objects if (links.encounter_content) { console.log(' Encounter content:'); links.encounter_content.forEach((link: any) => { console.log(` ${link.method} ${link.href} - ${link.name}`); }); } // transcripts is an array of Link objects if (links.transcripts) { console.log(' Transcripts:'); links.transcripts.forEach((link: any) => { console.log(` ${link.method} ${link.href} - ${link.name}`); }); } // status is an array of Link objects if (links.status) { console.log(' Status:'); links.status.forEach((link: any) => { console.log(` ${link.method} ${link.href} - ${link.name}`); }); } } return res.status(200).json({ message: 'Notification received' }); } else if (status === 'failure') { // Handle failure notification const sessionId = data.session_id; const encounterId = data.encounter_id; const errorCode = data.error_code; const errorDetail = data.error_detail; console.log(`Session ${sessionId} failed`); console.log(`Encounter ID: ${encounterId}`); console.log(`Error Code: ${errorCode}`); console.log(`Error Detail: ${errorDetail}`); return res.status(200).json({ message: 'Failure notification received' }); } else { return res.status(400).json({ error: 'Unknown status' }); } }); app.listen(3000, () => { console.log('Webhook server listening on port 3000'); }); ``` # Create Dictation Session Source: https://developer.suki.ai/api-reference/audio-transcription/create-session POST /api/v1/transcription/session/create Creates a new transcription session for real-time audio transcription Use this endpoint to create a dictation session to transcribe audio from patient-provider conversations into text. Refer to the [Audio dictation guide](/documentation/dictation) for more information. Returns a `201 Created` status with the `transcription_session_id` that is used to identify the session for transcribing audio and ending the session. # End Dictation Session Source: https://developer.suki.ai/api-reference/audio-transcription/end-session POST /api/v1/transcription/session/{transcription_session_id}/end Ends an active transcription session and returns the final transcription results Use this endpoint to end an active dictation session and retrieve the final transcription results. This endpoint stops the audio streaming and returns the complete transcript along with session metadata. Returns a `200 OK` status with success message. # Stream Audio To Dictation Session Source: https://developer.suki.ai/api-reference/audio-transcription/stream-transcription GET /ws/transcribe Establishes a WebSocket connection to the transcription service for real-time audio streaming and transcription. Open only when the dictation session is READY or IDLE. Inbound frames use TranscriptionStreamResponse (partial and final transcripts, then a terminal EOF frame) Use this WebSocket endpoint to stream audio to an active dictation session for **real-time transcription**. For the complete workflow, **usage guidelines**, **wire format**, **message order**, and **error handling**, refer to the [Audio dictation](/documentation/dictation) and [Dictation streaming](/documentation/dictation-streaming) guides. * For a single guide that compares **`/ws/stream`** and **`/ws/transcribe`** (handshake, proxy behavior, and message shapes), refer to [Audio streaming](/documentation/audio-stream) guide. * Stream audio in **chunks** for the best latency and throughput. * For partial and final inbound transcript frames, **`EOF`**, and session state rules, refer to [Dictation streaming](/documentation/dictation-streaming). If the dictation session is **`RUNNING`**, **`COMPLETED`**, or in another state, the WebSocket handshake fails with **`FailedPrecondition`** (for example **transcript session is not accepting new speech sessions**). ## Inbound transcript messages The server sends **JSON text frames** that include `transcript`, `is_final`, and `transcript_id`. Use `is_final` to identify whether the transcript is a partial result or a final result. After the audio stream ends, the server sends `{ "transcript": { "transcript": "EOF" } }` and then closes the WebSocket connection. Refer to [Dictation streaming](/documentation/dictation-streaming) for frame examples, **`words`** and speaker IDs on finals, and client-side filtering rules. ## Authentication Authentication is applied during the WebSocket handshake. The method depends on your client type. Use `Sec-WebSocket-Protocol` header for browser clients, and `sdp_suki_token` and `transcription_session_id` headers for non-browser clients. ### Browser clients If you are connecting from a browser, you must use the `Sec-WebSocket-Protocol` header during the WebSocket handshake. The header must specify the `SukiAmbientAuth` protocol, followed by the **token** and the **transcription session ID** in the following format. ```bash theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} Sec-WebSocket-Protocol: SukiAmbientAuth,, ``` ### Non-browser clients If you are connecting from a non-browser client, such as a mobile or server-side application, you must provide the **token** and **session ID** as separate HTTP headers in the initial WebSocket upgrade request. * `sdp_suki_token`: Your Suki token. * `sdp_provider_id`: Provider identifier. Optional for standard partners; **Required** for Single Auth Token authentication. * `transcription_session_id`: The ID for the current session. Important: * All messages must be sent as **JSON text** frames over the WebSocket connection. * Do not send raw binary data or use HTTP endpoints for streaming audio. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} # pip install websocket-client import base64 import json import websocket # Replace with values from Create dictation session and your authentication flow. transcription_session_id = "" sdp_suki_token = "" sdp_provider_id = "" # Optional; Required for Single Auth Token authentication # Staging WebSocket URL ws_url = "wss://sdp.suki-stage.com/ws/transcribe" ws = websocket.create_connection( ws_url, header=[ f"sdp_suki_token: {sdp_suki_token}", f"sdp_provider_id: {sdp_provider_id}", f"transcription_session_id: {transcription_session_id}", ], ) # If the file is WAV, skip the 44-byte header so payloads are PCM_S16LE only. WAV_HEADER_BYTES = 44 CHUNK_BYTES = 3200 # Example chunk size; size your chunks to your capture pipeline. try: with open("audio.wav", "rb") as audio_file: if WAV_HEADER_BYTES: audio_file.read(WAV_HEADER_BYTES) chunk = audio_file.read(CHUNK_BYTES) while chunk: msg = { "type": "AUDIO", "audioData": base64.b64encode(chunk).decode("ascii"), } ws.send(json.dumps(msg)) chunk = audio_file.read(CHUNK_BYTES) ws.send(json.dumps({"type": "EVENT", "event": "AUDIO_END"})) finally: ws.close() ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} // Browser example: same IDs as Python tab; add in your HTML. const transcriptionSessionId = ''; const sdpSukiToken = ''; // Staging WebSocket URL const ws = new WebSocket('wss://sdp.suki-stage.com/ws/transcribe', [ `SukiAmbientAuth,${sdpSukiToken},${transcriptionSessionId}`, ]); function uint8ToBase64(bytes: Uint8Array): string { let binary = ''; for (let i = 0; i < bytes.byteLength; i += 1) { binary += String.fromCharCode(bytes[i]!); } return btoa(binary); } ws.onopen = () => { const input = document.getElementById('audioFile') as HTMLInputElement | null; const file = input?.files?.[0]; if (!file) { console.error('Select a file for #audioFile'); ws.close(); return; } const reader = new FileReader(); reader.onload = () => { const buffer = reader.result as ArrayBuffer; const wavHeaderBytes = 44; // Set to 0 if the file is already raw PCM. const pcm = new Uint8Array(buffer, wavHeaderBytes); const chunkSize = 3200; for (let offset = 0; offset < pcm.byteLength; offset += chunkSize) { const end = Math.min(offset + chunkSize, pcm.byteLength); const chunk = pcm.subarray(offset, end); ws.send( JSON.stringify({ type: 'AUDIO', audioData: uint8ToBase64(chunk), }), ); } ws.send(JSON.stringify({ type: 'EVENT', event: 'AUDIO_END' })); }; reader.readAsArrayBuffer(file); }; ws.onmessage = (event) => { const payload = JSON.parse(event.data as string); if (payload.transcript?.transcript === 'EOF') { console.log('End of transcription stream'); return; } console.log('Partial:', !payload.is_final, payload.transcript?.transcript); }; ``` # Authentication API Source: https://developer.suki.ai/api-reference/authentication Learn how to register providers, obtain tokens, and retrieve JSON Web Key Set (JWKS) material for the Suki platform The authentication APIs provide the primary endpoints for connecting partners and providers to the Suki Developer Platform. Designed for security and integration, these endpoints allow you to manage user identities and secure your connection to our API gateway. ## Usage scenarios * Onboard a provider with your partner organization * Obtain a **Suki token** for a registered provider also known as a **`sdp_suki_token`** * Fetch the current **JSON Web Key Set** ## What happens when you call the endpoints * **Register** creates a new user and links it to your partner organization * **Login** exchanges your partner credentials for a **Suki token** also known as a **`sdp_suki_token`** * **JWKS** returns the current **JSON Web Key Set** ## Endpoints # JWKS URL Source: https://developer.suki.ai/api-reference/authentication/jwks GET /api/auth/.well-known/jwks-pub.json Public key endpoint for JWT token verification and signature validation Use this public endpoint to get the JWKS (JSON Web Key Set) containing Suki's public keys. Use these keys to verify the signature of any JWT issued by Suki, such as the `suki_token`. This endpoint follows the **RFC 7517** standard. **Authentication** This is a public endpoint and does not require authentication. ## Key use cases * **Verify Tokens**: Confirm the authenticity of the `suki_token` you receive from our authentication API. * **Handle Key Rotation**: Automatically discover new public keys when Suki rotates its signing keys. * **Maintain Security**: Follow industry best practices for JWT validation. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/auth/.well-known/jwks-pub.json" response = requests.get(url) if response.status_code == 200: jwks = response.json() print("Public keys retrieved successfully") print(f"Keys: {jwks}") else: print(f"Failed to retrieve JWKS: {response.status_code}") ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/auth/.well-known/jwks-pub.json'); if (response.ok) { const jwks = await response.json(); console.log('Public keys retrieved successfully'); console.log('Keys:', jwks); } else { console.error(`Failed to retrieve JWKS: ${response.status}`); } ``` # Login Source: https://developer.suki.ai/api-reference/authentication/login POST /api/v1/auth/login Authenticate healthcare provider and obtain access token for API usage Use this endpoint to authenticate a provider. On a successful request, this endpoint returns a Suki Token (`suki_token`/`sdp_suki_token`) that you must use to authorize all subsequent API calls for that user. The `suki_token` is a JWT that is valid for **one hour**. It contains the **user**, **organization**, and Partner information needed to access Suki services. If you are using the JWT Bearer/Assertion authentication method, the response may also include an additional `jwt_bearer` field. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/auth/login" payload = { "partner_id": "your-partner-id", "partner_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "provider_id": "provider-123" # Optional } response = requests.post(url, json=payload) if response.status_code == 200: data = response.json() suki_token = data["suki_token"] print(f"Authentication successful. Token: {suki_token}") else: print(f"Authentication failed: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ partner_id: 'your-partner-id', partner_token: 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...', provider_id: 'provider-123' // Optional }) }); if (response.ok) { const data = await response.json(); const sukiToken = data.suki_token; console.log(`Authentication successful. Token: ${sukiToken}`); } else { const error = await response.json(); console.error(`Authentication failed: ${response.status}`, error); } ``` # Register Source: https://developer.suki.ai/api-reference/authentication/register POST /api/v1/auth/register Register new healthcare provider or link existing provider to partner organization Use this endpoint to register a **new healthcare provider** in the Suki platform or to link an **existing provider** to a new **Partner**-organization relationship. This is a **one-time** setup call for each provider within an organization. ## Registration scenarios This endpoint handles **three** different scenarios depending on the user's status in the Suki system. | Scenario | Condition | Actions Taken | Response | | --------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------ | | **New User** | The provider does not exist in Suki. | • Creates a new organization
• Links your partner account to the organization
• Creates a new user with the provided details | 201 Created | | **Existing User, New Link** | The provider exists but is not yet linked to your partner account. | • Verifies the user and organization details
• Links your partner account to the existing organization | 201 Created | | **Existing User, Already Linked** | The provider and organization are already linked to your partner account. | • Detects the existing link | 409 Conflict | ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/auth/register" payload = { "partner_id": "your-partner-id", "partner_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "provider_name": "Dr. John Smith", "provider_org_id": "org-123", "provider_id": "provider-123", # Optional "provider_specialty": "CARDIOLOGY" # Optional, defaults to FAMILY_MEDICINE } response = requests.post(url, json=payload) if response.status_code == 201: print("Provider registered successfully") elif response.status_code == 409: print("Provider already linked to this partner") else: print(f"Registration failed: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ partner_id: 'your-partner-id', partner_token: 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...', provider_name: 'Dr. John Smith', provider_org_id: 'org-123', provider_id: 'provider-123', // Optional provider_specialty: 'CARDIOLOGY' // Optional, defaults to FAMILY_MEDICINE }) }); if (response.status === 201) { console.log('Provider registered successfully'); } else if (response.status === 409) { console.log('Provider already linked to this partner'); } else { const error = await response.json(); console.error(`Registration failed: ${response.status}`, error); } ``` # Bearer Partner Type Authentication Source: https://developer.suki.ai/api-reference/bearer-partner-authentication Learn how Bearer partner authentication works, when to pass provider_id, and how to integrate with REST APIs Some partners cannot include per-user identity information in the OAuth 2.0 token they send to Suki. During onboarding, Suki configures these organizations as **Bearer partners**. Bearer partners authenticate the same way as other server-to-server partners. Send `partner_token` in the JSON request body for [Login](/api-reference/authentication/login) and [Register](/api-reference/authentication/register). Because the token is shared across providers, Bearer partners must also send `provider_id` in every Login and Register request so Suki can identify the active provider. **Important:** Suki assigns your partner type during onboarding. If you are not sure whether your organization is configured as a Bearer partner, contact your partnership team. This guide applies only to Bearer partners. It does not apply to partners that use a per-user ID token or user-scoped access token as partner\_token. ## Prerequisites Before you implement Bearer partner authentication, confirm the following: * **Bearer partner configuration** - Your Suki partner contact confirms that your organization is configured as a Bearer partner. * **Provider ID format** - You and Suki agree on a stable provider identifier format, such as an email address or external user ID. Use the same format on every login and register call. * **HTTPS required** - Send [Login](/api-reference/authentication/login) and [Register](/api-reference/authentication/register) requests as HTTPS POST requests with a JSON body. Do not send credentials in query parameters. ## Use cases Use Bearer partner authentication when your integration matches one of these scenarios: Your backend uses a single shared `partner_token` for multiple clinicians, and the token does not identify the signed-in provider. Send `provider_id` on every [Login](/api-reference/authentication/login) and [Register](/api-reference/authentication/register) request so Suki can identify the correct provider. Your application already knows the signed-in provider, such as through a session or database record, but you cannot include that identity in the `partner_token`. Instead, send a stable identifier as `provider_id` in the authentication request body. Your identity provider does not issue a per-user ID token for Suki, or you cannot add user claims to the access token. Bearer partner authentication lets you keep your existing token model and identify the provider by using `provider_id`. Diagram: Tenant A, Tenant B, and Tenant C connect through shared partner tokens, then to the Suki platform. Diagram: Tenant A, Tenant B, and Tenant C connect through shared partner tokens, then to the Suki platform. ## How Bearer partners differ from other partners | Topic | Standard partner authentication | Bearer partner authentication | | :--------------------------------- | :------------------------------------- | :------------------------------------------------------ | | User identity source | Derived from `partner_token` | Passed as `provider_id` in the request body | | `partner_token` type | Per-user ID token or user-scoped token | Typically one shared `partner_token` for many providers | | `provider_id` on login or register | Optional and ignored | Required | In Bearer partner authentication, the partner application provides the provider identity on behalf of the signed-in user. This is different from the HTTP `Authorization: Bearer` header format. You still send `partner_token` in the JSON request body for login and register requests. ## Authentication workflow For Bearer partners, Suki validates `partner_id` and `provider_id` on [Login](/api-reference/authentication/login). If the provider is not registered, call [Register](/api-reference/authentication/register), then call Login again. The flow matches standard partners after registration. Learn more about registration scenarios in [Provider authentication](/api-reference/provider-authentication#registration-scenarios). ## Login and Register request fields Bearer partners use the same login and register endpoints as standard partners. You must include `provider_id` on every login and register call. ### Login **Endpoint:** [Login](/api-reference/authentication/login) **Method:** POST | Field | Bearer partners | | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------ | | `partner_id` | Required. Partner ID from Suki. | | `partner_token` | Required. Shared `partner_token` your integration uses for authentication. | | `provider_id` | Required. Stable identifier for the provider in your system. Must match the format agreed with Suki during onboarding. | #### Example request ```bash cURL theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} curl -X POST https://sdp.suki-stage.com/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{ "partner_id": "your-partner-id", "partner_token": "your-shared-partner-token", "provider_id": "provider-123" }' ``` On success, the API returns `suki_token`. Use it as the `sdp_suki_token` header on later Ambient API calls. The token is valid for **1 hour**. To refresh it, call Login again with a valid `partner_token`. ### Register Register a provider once before their first login. Refer to [Provider authentication](/api-reference/provider-authentication#registration-scenarios) for new user, existing user, and conflict responses. **Endpoint:** [Register](/api-reference/authentication/register) **Method:** POST | Field | Bearer partners | | :------------------- | :--------------------------------------------------------------------------------------------------------------------------- | | `partner_id` | Required. Partner ID from Suki. | | `partner_token` | Required. Shared `partner_token` your integration uses for authentication. | | `provider_id` | Required. Stable identifier for the provider in your system. Use this as the user identifier at registration. | | `provider_name` | Required. Display name for the provider. | | `provider_org_id` | Required. Organization the provider belongs to. | | `provider_specialty` | Optional. Defaults to `FAMILY_MEDICINE` if omitted. | #### Example request ```bash cURL theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} curl -X POST https://sdp.suki-stage.com/api/v1/auth/register \ -H "Content-Type: application/json" \ -d '{ "partner_id": "your-partner-id", "partner_token": "your-shared-partner-token", "provider_id": "provider-123", "provider_name": "Dr. Jane Smith", "provider_org_id": "org-123" }' ``` For all Register fields and response codes, refer to the [Register API reference](/api-reference/authentication/register). **Security considerations** If an attacker gets your shared `partner_token` and a valid `provider_id`, they could try to impersonate a provider. To reduce risk: * Allow only trusted systems to call the login and register endpoints. * Monitor for suspicious or unexpected authentication activity. * Rotate shared `partner_token` values regularly when your identity provider allows it. # Multilingual Support Source: https://developer.suki.ai/api-reference/capabilities/multilingual Multi-language support for ambient sessions and clinical documentation
Quick summary
Multilingual support lets patients and providers speak in their preferred language during clinical conversations, while Suki automatically generates the final clinical note in English.
Last updated: June 2026
**Multilingual support is supported by:** Ambient APIs, Mobile SDK, Web SDK (v2.1.1+) Multilingual support lets patients and providers speak in their preferred language during clinical conversations, while Suki automatically generates the final clinical note in English. This removes the need for manual translation and makes healthcare more accessible to diverse patient populations. When you enable multilingual support for an ambient session, you get the following benefits: * **Patient comfort**: Patients can communicate in their native language, leading to more accurate information sharing * **Better care quality**: When patients speak in their preferred language, they provide more detailed and accurate information * **No translation needed**: Clinicians don't need to translate conversations manually, Suki handles it automatically * **EHR compatibility**: All notes are generated in English, ensuring compatibility with standard EHR systems * **Wider accessibility**: Support for 80+ languages makes healthcare more inclusive ## How it works When you enable multilingual support for an ambient session, Suki automatically: 1. **Detects the language** spoken during the conversation 2. **Transcribes the audio** in the detected language 3. **Translates and processes** the conversation content 4. **Generates the clinical note** in English The transcript API returns a `lang_id` field that identifies which language was detected for each segment of the conversation. This helps you understand what language was spoken during different parts of the session. ## How to enable multilingual support Enable multilingual support when creating an ambient session. The exact method depends on whether you're using the Mobile SDK or APIs. **Mobile SDK Example:** ```swift Swift theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} let sessionContext = [ SukiAmbientConstant.kSessionId: encounterId, SukiAmbientConstant.kMultilingual: true // Enable multilingual support ] as [String : AnyHashable] SukiAmbientCoreManager.shared.createSession( with: sessionContext, onCompletion: { result in switch result { case .success(let sessionResponse): let sessionId = sessionResponse.sessionId // Store sessionId for future use case .failure(let error): // Handle error } } ) ``` **API Example:** ```python Python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} payload = { "ambient_session_id": "123dfg-456dfg-789dfg-012dfg", # Optional "encounter_id": "123dfg-456dfg-789dfg-012dfg", # Optional "multilingual": false # [!code --] Deprecated in v1.1.1 } response = requests.post( "https://sdp.suki-stage.com/api/v1/ambient/session/create", json=payload, headers={"sdp_suki_token": "", "sdp_provider_id": ""} ) ``` For complete API documentation, see the [Create ambient session API](/api-reference/ambient-sessions/create). Multilingual support is **enabled by default** for all ambient sessions The `multilingual` parameter is deprecated. You no longer need to pass it when creating a session. Once active, it applies to the entire session and cannot be changed mid-session. ## Supported languages Suki supports over **80 languages** for ambient sessions. The following languages are currently supported: | | | | | | | ------------------- | ------------------ | ----------- | ------------- | --------- | | Spanish | Norwegian | Macedonian | Kazakh | Yoruba | | Italian | Finnish | Hungarian | Icelandic | Telugu | | English | Vietnamese | Tamil | Marathi | Khmer | | Portuguese | Thai | Hindi | Maori | Malayalam | | German | Slovak | Estonian | Swahili | Lao | | Japanese | Greek | Urdu | Armenian | Punjabi | | Polish | Czech | Latvian | Belarusian | Gujarati | | Russian | Croatian | Slovenian | Nepali | Somali | | Dutch | Danish | Azerbaijani | Occitan | Bengali | | Indonesian | Tagalog | Hebrew | Lingala | Georgian | | Catalan | Korean | Lithuanian | Maltese | Assamese | | French | Romanian | Persian | Tajik | Mongolian | | Turkish | Bulgarian | Welsh | Luxembourgish | Myanmar | | Swedish | Galician | Serbian | Hausa | Shona | | Ukrainian | Bosnian | Afrikaans | Uzbek | Amharic | | Malay | Arabic | Kannada | Pashto | Sindhi | | Chinese (Cantonese) | Chinese (Mandarin) | | | | ## Language code reference Pick a **Letter** below to show languages starting with that letter, then use the table to map each `lang_id` to its corresponding language. This helps you interpret the language codes returned by the Transcript API. We regularly update this list as we add support for new languages. If a language is not included in this table, it is not yet supported.
**A** | Language | Language ID (`lang_id`) | | ----------- | ----------------------- | | afrikaans | af | | amharic | am | | arabic | ar | | armenian | hy | | assamese | as | | azerbaijani | az |
**B** | Language | Language ID (`lang_id`) | | ---------- | ----------------------- | | belarusian | be | | bengali | bn | | bosnian | bs | | bulgarian | bg |
**C** | Language | Language ID (`lang_id`) | | ------------------ | ----------------------- | | catalan | ca | | chinese | zh | | chinese\_cantonese | yue | | chinese\_mandarin | cmn | | croatian | hr | | czech | cs |
**D** | Language | Language ID (`lang_id`) | | -------- | ----------------------- | | danish | da | | dutch | nl |
**E** | Language | Language ID (`lang_id`) | | -------- | ----------------------- | | english | en | | estonian | et |
**F** | Language | Language ID (`lang_id`) | | -------- | ----------------------- | | finnish | fi | | french | fr |
**G** | Language | Language ID (`lang_id`) | | -------- | ----------------------- | | galician | gl | | georgian | ka | | german | de | | greek | el | | gujarati | gu |
**H** | Language | Language ID (`lang_id`) | | --------- | ----------------------- | | hausa | ha | | hebrew | he | | hindi | hi | | hungarian | hu |
**I** | Language | Language ID (`lang_id`) | | ---------- | ----------------------- | | icelandic | is | | indonesian | id | | italian | it |
**J** | Language | Language ID (`lang_id`) | | -------- | ----------------------- | | japanese | ja |
**K** | Language | Language ID (`lang_id`) | | -------- | ----------------------- | | kannada | kn | | kazakh | kk | | khmer | km | | korean | ko |
**L** | Language | Language ID (`lang_id`) | | ------------- | ----------------------- | | lao | lo | | latvian | lv | | lingala | ln | | lithuanian | lt | | luxembourgish | lb |
**M** | Language | Language ID (`lang_id`) | | ---------- | ----------------------- | | macedonian | mk | | malay | ms | | malayalam | ml | | maltese | mt | | maori | mi | | marathi | mr | | mongolian | mn | | myanmar | my |
**N** | Language | Language ID (`lang_id`) | | --------- | ----------------------- | | nepali | ne | | norwegian | no |
**O** | Language | Language ID (`lang_id`) | | -------- | ----------------------- | | occitan | oc |
**P** | Language | Language ID (`lang_id`) | | ---------- | ----------------------- | | pashto | ps | | persian | fa | | polish | pl | | portuguese | pt | | punjabi | pa |
**R** | Language | Language ID (`lang_id`) | | -------- | ----------------------- | | romanian | ro | | russian | ru |
**S** | Language | Language ID (`lang_id`) | | --------- | ----------------------- | | serbian | sr | | shona | sn | | sindhi | sd | | slovak | sk | | slovenian | sl | | somali | so | | spanish | es | | swahili | sw | | swedish | sv |
**T** | Language | Language ID (`lang_id`) | | -------- | ----------------------- | | tagalog | tl | | tajik | tg | | tamil | ta | | telugu | te | | thai | th | | turkish | tr |
**U** | Language | Language ID (`lang_id`) | | --------- | ----------------------- | | ukrainian | uk | | urdu | ur | | uzbek | uz |
**V** | Language | Language ID (`lang_id`) | | ---------- | ----------------------- | | vietnamese | vi |
**W** | Language | Language ID (`lang_id`) | | -------- | ----------------------- | | welsh | cy |
**Y** | Language | Language ID (`lang_id`) | | -------- | ----------------------- | | yoruba | yo |
## Best practices * **Enable when needed**: Only enable multilingual support when you expect conversations in multiple languages. This optimizes performance. * **Set patient language preference**: If you know the patient's preferred language, you can display this information in your UI to help providers prepare. * **Monitor language detection**: Use the `lang_id` from transcripts to understand language usage patterns in your application. * **Test with your languages**: Verify multilingual support works correctly with the languages your patients commonly use. * **Note language in UI**: Consider displaying the detected language in your UI so providers know what language was spoken. ## Related APIs Use these APIs to work with multilingual support: Retrieve transcripts with language detection information (`lang_id`) Create ambient sessions with multilingual support enabled # Personalization Source: https://developer.suki.ai/api-reference/capabilities/personalization Customize clinical note generation based on provider preferences and specialty
Quick summary
Personalization allows you to customize how Suki generates clinical notes based on each provider's preferences. Control how much detail (short and concise, balanced, or very detailed) and how it's formatted (continuous paragraphs or bullet points).
Last updated: June 2026
**Personalization is supported by:** APIs, Web SDK, Mobile SDK Personalization allows you to help providers customize how Suki generates their clinical notes. Every provider has different preferences, some want short bullet points, others want detailed paragraphs. Personalization ensures each provider gets notes that match their style. When you use personalization, you can customize two aspects of note generation: * **How much detail**: Short and concise, balanced, or very detailed notes * **How it's formatted**: Continuous paragraphs (narrative) or bullet points Once you set a provider's preferences, Suki automatically applies them to all future notes for that provider. You set it once, and Suki remembers, no need to send preferences with every request. Using personalization, you get the following benefits: * **Provider satisfaction**: Notes match each provider's preferred style and level of detail * **Consistent documentation**: Once set, preferences apply automatically to all future notes * **Efficiency**: Providers don't need to manually adjust notes; they're generated according to their preferences * **Flexibility**: Different providers can have different preferences based on their specialty and workflow * **Better adoption**: When notes match provider preferences, they're more likely to use and trust the system ## How it works Personalization settings are saved at the user level, not per session. Once you set a provider's preferences, Suki automatically applies them to all future note generation for that provider. **The process:** 1. **Set preferences**: Use the Mobile SDK `setPersonalizationPreferences` method or the User Preferences API to configure a provider's preferences 2. **Automatic application**: Suki applies these settings to all future notes for that provider 3. **Update anytime**: Update preferences at any time; the most recent settings always take effect Personalization settings are **persistent** and **user-specific**. Once set, you don't need to send preferences with every session request. Suki automatically uses the saved preferences for each provider. ## How to set personalization preferences Set personalization preferences using the Mobile SDK or APIs. The exact method depends on your integration. **Mobile SDK Example:** ```swift Swift theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} let preferences: [String: AnyHashable] = [ "verbosity": "CONCISE", // Options: CONCISE, BALANCED, DETAILED "section_format": [ [ "loinc": "10164-2", "style": "NARRATIVE" // Options: NARRATIVE, BULLETED ] ] ] SukiAmbientCore.shared.setPersonalizationPreferences(preferences) { result in switch result { case .success: print("Preferences updated successfully") case .failure(let error): print("Error updating preferences: \(error)") } } ``` **API Example:** ```python Python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/user/preferences" payload = { "personalization_preference": { "section_format": [ { "loinc": "10164-2", "style": "NARRATIVE" } ], "verbosity": "CONCISE" } } headers = { "sdp_suki_token": "", "sdp_provider_id": "", "Content-Type": "application/json" } ``` **When to set preferences:** * **After user registration**: Set default preferences when a new provider is added to your system * **When preferences change**: Update preferences whenever a provider requests changes * **Before sessions start**: For best results, set preferences before audio streaming begins The **User Preferences API** is a `PATCH` request, so you only need to send the fields you want to change. Update verbosity and section formats independently. ## Personalization options Customize two aspects of note generation: ### Verbosity Controls how much detail is included in the generated notes. This setting applies to **all note sections**. **Applies to:** All note sections Generates shorter, to-the-point notes with essential information only. Provides a moderate level of detail: comprehensive but not excessive. Generates comprehensive notes with extensive detail and context. ### Section style Controls the formatting style for specific clinical sections. Set different styles for different sections as needed. **Applies to:** * History of Present Illness **(10164-2)** * Assessment and Plan **(51847-2)** * Assessment **(51848-0)** * Plan **(18776-5)** Generates notes in a continuous, story-like format that flows naturally. Generates notes using bullet points for easy scanning and quick reference. **Example:** ```json JSON theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} "section_format": [ { "loinc": "10164-2", "style": "NARRATIVE" }, { "loinc": "51848-0", "style": "BULLETED" } ] ``` ## Best practices * **Set defaults early**: Configure preferences when providers are first registered in your system * **Offer a UI**: Let providers choose their preferences through your application's settings page * **Explain options**: Help providers understand the difference between verbosity levels and style options * **Update when requested**: Make it easy for providers to change their preferences as their needs evolve * **Test with real notes**: Verify that preferences produce notes that match provider expectations ## Related APIs Set and update personalization preferences for providers # Problem-Based Charting Source: https://developer.suki.ai/api-reference/capabilities/problem-based-charting Problem-based clinical documentation approach with diagnosis context integration **Updated** Pass the patient's existing diagnoses when starting a PBC session so the generated note merges them with what's discussed in the visit. Use the Context API for APIs, or `ambientOptions.diagnoses` for the Web SDK (**v2.1.2+**). Optional visit-level fields in `ambientOptions` (`visitType`, `encounterType`, `providerRole`, `reasonForVisit`, `chiefComplaint`) ship in the Web SDK **v2.2.0+** to improve note generation. See [AmbientOptions](/web-sdk/api-reference/types/ambient-options). For how the system reconciles those diagnoses with the conversation (API flow), refer to [Reconciliation](/api-reference/capabilities/problem-based-charting#reconciliation). For Web SDK implementation details, refer to [Existing patient diagnoses](/web-sdk/guides/ambient-problem-based-charting#existing-patient-diagnoses).
Quick summary
Problem-Based Charting (PBC) is a clinical documentation approach that organizes notes by patient problems instead of traditional note sections, and suggests diagnoses for each problem.
Last updated: June 2026
**Problem-Based Charting is supported by:** Ambient APIs, Web SDK, Mobile SDK Problem-Based Charting (PBC) organizes clinical notes by patient problems instead of traditional note sections. When you use PBC, Suki generates two things: 1. **Clinical note**: Organized by each problem or diagnosis 2. **Structured artifacts**: Suggested diagnoses with ICD10 and IMO codes PBC notes are different from traditional notes. In traditional notes, information is organized by sections like "History," "Assessment," and "Plan." In PBC notes, information is organized by each problem, grouping all related information together. When you enable PBC, providers get a note that has the following benefits: * **Easier to read**: See everything about each problem in one place * **Better continuity**: Includes existing problems from previous visits automatically * **Complete picture**: Captures both old and new problems discussed during the visit * **Structured data**: Generates standardized codes (ICD10, IMO) for EHR integration ## How to use PBC for APIs and SDKs You enable PBC by doing three things: * Define which note sections to generate and which one is the PBN * Pass the patient's existing diagnoses into session context * Read structured diagnosis output after the session finishes - **Web SDK:** In `ambientOptions.sections`, set `isPBNSection: true` on **exactly one** section. Rules for defaults, overrides, and errors are in [Configuration rules](/api-reference/capabilities/problem-based-charting#configuration-rules-for-pbc). - **Ambient APIs:** Send the LOINC `sections` array in the [Context API](/api-reference/ambient-sessions/context) body so the Suki backend knows which note sections to generate. PBN defaults (for example, when Assessment & Plan, LOINC `51847-2`, is treated as the PBN) follow the same rules as in [Configuration rules](/api-reference/capabilities/problem-based-charting#configuration-rules-for-pbc). - **Mobile SDK (iOS):** Pass LOINC sections in `kSections` via `setSessionContext`. See the Mobile SDK [Create session](/mobile-sdk/ambient-guides/create-session#provide-clinical-context-optional-but-recommended) guide for field names and examples. * **Ambient APIs:** Include diagnoses when you POST (and, if needed, PATCH) session context. * **Web SDK:** Use `ambientOptions.diagnoses`. Refer to the [AmbientOptions type](/web-sdk/api-reference/types/ambient-options) for more details. * **Mobile SDK (iOS):** Use `SukiAmbientConstant.kDiagnosisInfo` in `setSessionContext`. Refer to the Mobile SDK [Create session](/mobile-sdk/ambient-guides/create-session#provide-clinical-context-optional-but-recommended) guide for more details. * **Ambient APIs:** After the session has finished processing, use the [Structured Data](/api-reference/ambient-content/structured-data) or [Encounter Structured Data](/api-reference/ambient-content/encounter-structured-data) APIs and related endpoints to read suggested diagnoses. * **Mobile SDK (iOS):** After the session completes, call `getStructuredData(for:)`. See [Session status and content retrieval](/mobile-sdk/ambient-guides/session-status-and-content-retrieval#get-structured-data). * **Web SDK:** After the user submits the ambient session and note generation succeeds, read results from the **`onNoteSubmit`** callback (React) or the **`note-submission:success`** event (JavaScript and React). Refer to [Receiving note content](/web-sdk/guides/note-management#receiving-note-content), [Response structure](/web-sdk/guides/note-management#response-structure), [NoteContent](/web-sdk/api-reference/types/note-content), and [Diagnosis](/web-sdk/api-reference/types/diagnosis) for more details. ## Implementation examples Use the `diagnoses` block in `ambientOptions` to provide existing patient diagnoses when starting a session. **Code example:** ```javascript JavaScript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} sdkClient.mount({ rootElement: document.getElementById("suki-root"), encounter: encounterDetails, ambientOptions: { sections: [ { loinc: "51848-0", isPBNSection: true }, // Mark as PBN section { loinc: "11450-4" }, { loinc: "29545-1" }, ], diagnoses: { // [!code ++:14] New in v2.1.2 values: [ { codes: [ { code: "I10", description: "Essential hypertension", type: "ICD10", }, ], diagnosisNote: "Hypertension", }, ], }, }, }); ``` Use `setSessionContext` to pass LOINC sections and structured diagnosis information. After the session ends, call `getStructuredData(for:)` to retrieve diagnoses and other structured output. Refer to the Mobile SDK [Create session](/mobile-sdk/ambient-guides/create-session#provide-clinical-context-optional-but-recommended) guide for more details. **Code example:** ```swift Swift theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} let context = SukiAmbientContext( sections: [ SukiAmbientSection(loinc: "51848-0", isPBNSection: true), // Mark as PBN section SukiAmbientSection(loinc: "11450-4"), SukiAmbientSection(loinc: "29545-1"), ], diagnosisInfo: [ SukiAmbientDiagnosisInfo( codes: [ SukiAmbientCode(code: "I10", description: "Essential hypertension", type: .icd10), ], diagnosisNote: "Hypertension", ), ], ) ``` Use the [Context API](/api-reference/ambient-sessions/context) to provide existing patient diagnoses when starting a session. **Code example:** ```python Python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} payload = { "diagnoses": { "values": [ { "codes": [ { "code": "I10", "description": "Essential hypertension", "type": "ICD10", }, ], "diagnosis_note": "Hypertension", }, ], }, } ``` **APIs to use:** Provide initial diagnoses when starting a session Update or add diagnoses during a session ## Configuration rules for PBC When configuring PBC, follow these rules: Only one section can have `isPBNSection: true`. If multiple sections are marked as PBN, the ambient session will fail to start. If no section includes the `isPBNSection` flag and the Assessment & Plan section (51847-2) is present, that section automatically becomes the PBN. Explicitly set `isPBNSection: false` to prevent automatic PBN assignment. For a given ambient session, **only one section** can have `isPBNSection: true`. If more than one section is marked as PBN, the ambient session will fail to start. ## Core principles Understanding these principles helps you use PBC effectively: The ICD10 code is treated as the **primary identifier** for all clinical problems during processing. **System uses ICD10 for:** * Diagnosis identification and matching * Clinical problem categorization * Cross-session diagnosis continuity * Normalization of other code types (IMO, SNOMED) Non-ICD10 codes are automatically converted to ICD10 equivalents when possible. All diagnosis generation is done on a **best-effort** basis. The system prioritizes returning partial, useful information over failing an entire request due to an issue with a single data point. In reambient scenarios, diagnoses from previous sessions are **not automatically carried forward**. You must provide the full context for each new session. **Your Responsibility**: Include all relevant diagnoses (previous + new + modified) in each session context. ## How PBC works PBC processes diagnoses in three steps: You provide existing diagnoses when starting the session using the Context APIs. Suki's AI analyzes the conversation and identifies new problems or updates to existing diagnoses. Suki generates a clinical note organized by problem and structured artifacts with standardized codes. ```mermaid actions={false} theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#FFE148','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 TD A[Session audio/transcript] --> B[ML processing] B --> C[Suki Backend] C --> D{Valid ICD10?} D -->|Yes| E[Case 1: Enrich with IMO
Add description,
laterality, IMO code] D -->|No| F[Case 2: Enrich with IMO
Add ICD10, description,
laterality, IMO code] E --> G[Final Output
Problems with Code,
Description, Diagnosis Note] F --> G 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:#FFE148,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 style G fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827 ``` Suki backend includes the ML-suggested problem name and returns standardized ICD10 code, description, and IMO equivalent in the final output. ### Validation rules Each diagnosis in your request must follow these rules: * **One code per diagnosis**: Each diagnosis must have exactly one code (ICD10 or IMO) * **No mixed codes**: A single diagnosis cannot contain multiple code types * **Code required**: Every diagnosis must include a code ### Input processing Suki processes diagnoses through normalization and deduplication: Normalization does not preserve the original input code. If a code cannot map to an ICD10 equivalent, **Suki skips the entire diagnosis object** and continues processing the remaining input. ### Reconciliation When you send existing diagnoses via the Context API at session start, Suki **reconciles** them with what is discussed during the session. You get one problem list and no duplicates. This section describes the API flow (Context API to send, Structured Data API to retrieve). For Web SDK, refer to the [Existing patient diagnoses](/web-sdk/guides/ambient-problem-based-charting#existing-patient-diagnoses) section in the ambient guide for more details. **What happens to each diagnosis you send:** * **Discussed in the session** - The diagnosis is updated and returned in the structured data output. * **Not discussed in the session** - The diagnosis is not included in the final output. * **Matches something discussed** - Your diagnosis and the one discussed are merged into a single entry (no duplicate). The Structured Data API returns only diagnoses that were updated or newly generated. ### How diagnoses are generated During the session, Suki's AI analyzes the conversation and takes one of three actions on the diagnoses you provided: 1. **Update existing diagnosis**: Modify the content if it was discussed 2. **Generate new diagnosis**: Create a new diagnosis if a new problem was discussed 3. **Keep unchanged**: Leave a diagnosis untouched if it wasn't significantly discussed Only diagnoses that were **updated or newly generated** are returned in the final output. Untouched diagnoses are not returned. If a diagnosis wasn't discussed, it won't appear in the output. ### Output enrichment For any diagnosis that was updated or newly generated, Suki enriches it with: * **ICD10 code**: Standard diagnosis code * **IMO code**: Intelligent Medical Objects code * **Laterality**: Left/right/bilateral information when applicable * **Post coordination flag**: Indicates if the diagnosis requires additional modifiers The IMO code returned in the output may be different from any IMO code that was sent in the input payload. This is normal: Suki uses the most accurate code based on the conversation content. If enrichment fails, Suki still returns the diagnosis with available information to ensure you don't lose generated content. ### Retrieving generated diagnoses Refer to the [How to use PBC for APIs and SDKs](/api-reference/capabilities/problem-based-charting#how-to-use-pbc-for-apis-and-sdks) section for more details. ## Handling reambient scenarios In reambient scenarios, where a single patient encounter involves multiple recording sessions, understanding how context is managed is critical. Sessions do not **automatically inherit diagnoses** from previous sessions. Each session starts fresh. You must provide all relevant diagnoses for each new session. **What this means:** * When you use APIs in your implementation, only diagnoses passed via the Context APIs for the current session are considered * Diagnoses from previous sessions are **not automatically carried forward** * You must provide the complete and current list of all relevant diagnoses for each new session **Your responsibilities:** Because sessions don't inherit context, you must provide the complete list of all relevant diagnoses for each new session. This includes: * **Modified diagnoses**: Any diagnoses that were changed by the provider in previous sessions * **New diagnoses**: Any newly added diagnoses from previous sessions * **Existing diagnoses**: Diagnoses from previous sessions that should be retained **Recommended workflow:** ```mermaid actions={false} theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#FFE148','primaryTextColor':'#1a1a1a','primaryBorderColor':'#FFE148','lineColor':'#FFE148','secondaryColor':'#FFF394','tertiaryColor':'#FFFADE','mainBkg':'#FFF394','secondBkg':'#FFFADE','border1':'#FFE148','border2':'#FFE148','arrowheadColor':'#FFE148','fontFamily':'Inter, system-ui, sans-serif','fontSize':'14px','nodeBorder':'#FFE148','clusterBkg':'#FFFADE','clusterBorder':'#FFE148','defaultLinkColor':'#FFE148','titleColor':'#1a1a1a','edgeLabelBackground':'#FFE148','nodeTextColor':'#1a1a1a'}}}%% graph TD A[Start session] --> B[Context with
existing diagnoses] B --> C[Conduct encounter] C --> D[End session] D --> E[Get generated
diagnoses] E --> F{Reambient session?} F -->|Yes| G[Include all
relevant diagnoses] F -->|No| H[Complete] G --> B style A fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#1a1a1a style B fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#1a1a1a style C fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#1a1a1a style D fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#1a1a1a style E fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#1a1a1a style F fill:#FFE148,stroke:#FFE148,stroke-width:2px,color:#1a1a1a style G fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#1a1a1a style H fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#1a1a1a ``` After each session, retrieve the generated diagnoses using the Structured Data API, then include all relevant diagnoses (including any modifications) when starting the next session. ## Best practices * **Provide complete context**: Always include all relevant existing diagnoses when starting a session * **Use ICD10 when possible**: ICD10 codes are preferred and processed most reliably * **Handle reambient carefully**: Retrieve diagnoses after each session and include them in the next session * **Validate codes**: Ensure diagnosis codes are valid before sending them * **Monitor output**: Check which diagnoses were updated or generated to understand what was discussed * **Update after user edits**: If providers modify diagnoses, include those modifications in subsequent sessions ## FAQs In reambient scenarios, the system does not automatically carry forward diagnoses from previous sessions. You must provide the complete and current list of all relevant diagnoses for each new session. The system uses [IMO APIs](https://www.imohealth.com/) to find the best possible ICD10 code equivalent for non-ICD10 codes. If a code cannot be mapped, that diagnosis is skipped. The system normalizes all codes to ICD10 before processing. ICD10 is used as the source of truth for all diagnosis operations. The system deduplicates diagnoses based on the ICD10 code. Diagnoses with the same ICD10 code are merged, and their notes are combined. Only diagnoses that were updated or newly generated are returned. Diagnoses that weren't discussed during the session are not included in the output. # Audio Capture & Streaming Source: https://developer.suki.ai/api-reference/faqs/audio-capture-streaming Questions about audio capture, streaming, and WebSocket implementation LINEAR16 (16KHz sampling rate) over the mono channel. Audio should be chunked into 100ms packets for optimal performance. We only support 100ms audio chunks to achieve the right balance between quality, latency, and efficiency. Network connection speed and consistency are important for Suki to perform well. **Suki requires:** * **Upload speed**: 1Mbps * **Bitrate**: 768kbps * **Ping time**: 150ms * **Unloaded latency**: \<50ms * **Loaded latency**: \<150ms Client should set up a WebSocket Secure (wss\://) request with the Suki endpoint. Refer to the [Audio stream API](/api-reference/ambient-sessions/audio-stream) for implementation details. For **Ambient** WebSocket **`/ws/stream`** message format, send **LINEAR16**, **16 kHz**, **mono** audio, in about **100 ms** chunks (see the [Audio streaming](/api-reference/ambient-sessions/audio-stream) reference and [Ambient audio streaming](/documentation/ambient-audio-streaming) guide). ### How messages are sent Each outbound message from the client must be: * **One WebSocket text frame** (UTF-8) with **one JSON object** inside * **One logical send** per frame (do not pack multiple JSON objects in one frame) On **`/ws/stream`**, do **not** send PCM as **binary** WebSocket frames. Do **not** stream raw audio over HTTP with `Content-Type: application/json`. **Field names (proto-style JSON)** * **`START_TIME`** and **`AUDIO`**: use **`type`** and **`data`** * **`data`**: standard Base64 ([RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648)) of the **raw bytes** you mean to send (same idea as Go `encoding/json` for `[]byte`). Do not use hex, URL-safe Base64, or raw binary inside the JSON string. * **`EVENT`**: use **`type`**: `"EVENT"` and the **`event`** field. Do **not** put the action name in **`data`**. ### Message order (each stream segment) 1. Send **`START_TIME`** once: **`data`** is Base64 of a UTF-8 **RFC 3339** timestamp (for example `2026-04-25T12:34:56Z`). 2. Send one or more **`AUDIO`** messages: **`data`** is Base64 of each **raw PCM** chunk. 3. Send a final **`AUDIO`** to end audio: **`data`** is **`RU9G`** (Base64 of ASCII **`EOF`**, bytes `0x45`, `0x4F`, `0x46`). Do not use a separate `end_of_stream` type unless your integration team tells you otherwise. `EVENT` messages can go **anywhere** in the stream when you need control (pause, resume, keep-alive, cancel, abort). ### EVENT values you can send Use **`{"type":"EVENT","event":""}`** with one of: | Value | What it does | | :-------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- | | **PAUSE** | Pause the stream | | **RESUME** | Resume the stream | | **CANCEL** | User cancels the stream | | **ABORT** | Stream is aborted (interruption) | | **KEEP\_ALIVE** | Keep the connection alive during inactivity. While **paused**, send at least once every **five seconds** so the server does not close the connection. | ### Message examples ```json START_TIME theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { "type": "START_TIME", "data": "" } ``` ```json AUDIO (PCM chunk) theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { "type": "AUDIO", "data": "Base64EncodedPcmBytes" } ``` ```json AUDIO (stream end marker) theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { "type": "AUDIO", "data": "RU9G" } ``` ```json PAUSE Event theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { "type": "EVENT", "event": "PAUSE" } ``` ```json RESUME Event theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { "type": "EVENT", "event": "RESUME" } ``` ```json CANCEL Event theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { "type": "EVENT", "event": "CANCEL" } ``` ```json KEEP_ALIVE Event theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { "type": "EVENT", "event": "KEEP_ALIVE" } ``` ```json ABORT Event theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { "type": "EVENT", "event": "ABORT" } ``` The stream end marker is an **`AUDIO`** message whose **`data`** is Base64 of the raw bytes **`EOF`**, not a bare JSON string `"EOF"` and not an **`EVENT`** named EOF, unless your stack documentation says otherwise. # Authentication Source: https://developer.suki.ai/api-reference/faqs/authentication Authentication and authorization questions for API access We support * OAuth 2.0 ID token for public clients such as browsers, mobile devices etc. * Access token for confidential clients such as backend systems. We support [HMAC (Hash-based message authentication code)](https://www.okta.com/identity-101/hmac/) for webhook authentication (Details can be shared) Client systems cannot authenticate with Suki's platform via APIs when a JWT token fails. It's handled with standard HTTPS error codes; refer API reference # Miscellaneous Source: https://developer.suki.ai/api-reference/faqs/miscellaneous General API questions and miscellaneous topics To handle different doctor roles/specialties dynamically, clients use our context API to seed session context with the provider role (e.g. SPECIALTY). # Technical Constraints & Risks Source: https://developer.suki.ai/api-reference/faqs/technical-constraints-risks Technical limitations, constraints, and risk considerations for API integration No we don't have such pre-approved domains. In order to register for our webhook, you just need to give your callback URL so we can notify you there. This step is currently via manual sharing; in the future we plan to upgrade this system. N/A, we can share the IP of our system which calls callback URL if need be A POST call will be made to the webhook hosted by the Partner using the HTTPS protocol. Yes, the Webhook URL should be configured at the Partner level during [partner onboarding](/documentation/partner-onboarding). We currently do not support session-based webhook callbacks or similar configurations; webhook support is only for APIs and not for Web SDK. The client is responsible for creating and managing the `encounter_id`. We support combining sessions and generating the note based on the provided `encounter_id`. An encounter can include multiple ambient sessions. 1. Obtain a developer platform test license (POC: Commercials team).
2. Complete partner onboarding:
* Share required details for partner creation in our system → you will receive a Partner ID (`partner_id`).
* Let us know the unique identifier you will use in the OAuth 2.0 JWT token to identify the user (provider).
Example: user\_id, email\_id, sid, pid, etc. (need not be actual id from your system, can be hash value as well)
* Provide your JWKS endpoint for accessing your public key.
* Test authentication with Suki.
Here's a minimal flow for your reference: `/login → /session/create → /context (optional) → /stream → /end` This flow automatically triggers note generation. Either: 1. Use `/status` to poll the note generation status, then call /content to retrieve the note. 2. Receive a notification through our webhook. As long as the stream is active, there is no upper limit on call duration. The system allows a maximum pause of 30 minutes during the streaming. If you get disconnected and then rejoin, or lose the WebSocket connection, Suki stitches the sessions together using the same session ID. Although there is no strict lower limit, Suki needs a minimum amount of data to generate recommendations. For calls **shorter than 1 minute**, Suki may not have enough meaningful data/information to provide accurate recommendations and returns empty content. The session will be marked as **skipped**. # Ambient Session User Feedback Source: https://developer.suki.ai/api-reference/feedback/feedback POST /api/v1/ambient/session/{session_id}/{entity}/feedback Submit user feedback on generated clinical content for continuous improvement Use the **Feedback API** to collect quantitative (ratings) and qualitative (comments) feedback. Capturing feedback helps drive AI model improvement and increases client confidence. The API supports the following actions: * **Quantitative Feedback**: Rate content using a scale with configurable minimum and maximum values. * **Qualitative Feedback**: Provide optional, free-form comments for detailed insights. * **Entity-Level Tracking**: Tie feedback to specific entities within sessions. ## Supported entity types Provide feedback on the following entity types: | Entity type | Description | | ----------- | -------------------------- | | `content` | Generated clinical content | Within a single ambient session (session\_id), you can provide feedback for each `entity type` only **once**. If you provide feedback for the same `entity type` multiple times, the feedback will not be valid. Also, a single `session_id` can contain **multiple feedbacks**, provided each entry corresponds to a **different** entity type. ## Rating system The `ratingFeedback` object provides quantitative feedback. It includes the following fields: * `min_rating`: The minimum rating value (e.g., 0). * `max_rating`: The maximum rating value. * `rating`: The actual rating you provide within the min-max range. Configure the rating scale by setting the `min_rating` and `max_rating` values. The range is **inclusive**, so both the `min_rating` and `max_rating` values are valid ratings. For example: * To create a rating scale of 0 to 5, set `min_rating` to 0 and `max_rating` to 5. A user can provide any integer rating from 0 to 5. * To create a binary scale, set `min_rating` to 0 and `max_rating` to 1. A user can provide a rating of either 0 or 1. * Suki suggests using a scale of 1 to 5 for the rating. ## Character limits * `qualitative_comments`: Maximum **2000** characters. Your feedback helps Suki to improve the AI-generated content. All feedback is reviewed and used to enhance quality. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests session_id = "session_abc_123" entity = "content" url = f"https://sdp.suki-stage.com/api/v1/ambient/session/{session_id}/{entity}/feedback" headers = { "sdp_suki_token": "", "sdp_provider_id": "", "Content-Type": "application/json" } payload = { "ratingFeedback": { "min_rating": 0, "max_rating": 5, "rating": 4 }, "qualitative_comments": "The generated content was accurate and helpful. Great job!" # Optional, max 2000 chars } response = requests.post(url, json=payload, headers=headers) if response.status_code == 201: data = response.json() feedback_id = data.get("feedback_id") print(f"Feedback submitted successfully. Feedback ID: {feedback_id}") else: print(f"Failed to submit feedback: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const sessionId = 'session_abc_123'; const entity = 'content'; const response = await fetch( `https://sdp.suki-stage.com/api/v1/ambient/session/${sessionId}/${entity}/feedback`, { method: 'POST', headers: { 'sdp_suki_token': '', 'sdp_provider_id': '', 'Content-Type': 'application/json' }, body: JSON.stringify({ ratingFeedback: { min_rating: 0, max_rating: 5, rating: 4 }, qualitative_comments: 'The generated content was accurate and helpful. Great job!' // Optional, max 2000 chars }) } ); if (response.status === 201) { const data = await response.json(); const feedbackId = data.feedback_id; console.log(`Feedback submitted successfully. Feedback ID: ${feedbackId}`); } else { const error = await response.json(); console.error(`Failed to submit feedback: ${response.status}`, error); } ``` # HTTPS Guidelines Source: https://developer.suki.ai/api-reference/https-guidelines Learn about the standard HTTPS guidelines for APIs that Suki uses Suki uses **standard HTTP status codes** to indicate the outcome of an API request. * **`2xx` codes** indicate success. * **`4xx` codes** indicate a client-side error (e.g., you omitted a required parameter or provided an invalid configuration). * **`5xx` codes** indicate a server-side error on Suki's end. These are rare. The following table lists the most common HTTP status codes you may receive. | Code | Title | Description | | :----------------------- | :---------------- | :---------------------------------------------------------------------------------------------------------------------------------------- | | **`200`** | OK | The request was successful. | | **`201`** | Created | The resource was created successfully. The URL for the new resource is in the `Location` header. | | **`204`** | No Content | The request was successful, and there is no content to return. | | **`400`** | Bad Request | The request was unacceptable, often due to malformed syntax or a missing parameter. | | **`401`** | Unauthorized | The request was not authenticated. This could be due to missing, invalid, or insufficient credentials. | | **`402`** | Over Quota | The request was valid, but you have exceeded your plan's quota or rate limits. | | **`403`** | Forbidden | The request was not authenticated. This could be due to missing, invalid, or insufficient credentials. | | **`404`** | Not Found | The requested resource does not exist. | | **`409`** | Conflict | The request conflicts with the current state of the resource (e.g., the resource already exists, or the request was based on stale data). | | **`422`** | Validation Failed | The request was parsed correctly but failed a validation rule. | | **`429`** | Too Many Requests | You have sent too many requests in a short period. We recommend using an exponential backoff strategy for your requests. | | **`500, 502, 503, 504`** | Server Errors | An unexpected error occurred on Suki's servers. | # Info API Source: https://developer.suki.ai/api-reference/info Reference data for specialties, diagnoses, encounter types, visit types, LOINC codes, and provider roles These read-only endpoints return catalogs and coded lists for building requests, forms, and client-side validation. Response bodies are stable reference data you can cache on a schedule that fits your release process. ## Endpoints # Supported Diagnosis Codes Source: https://developer.suki.ai/api-reference/info/diagnosis GET /api/v1/info/diagnosis Get list of supported diagnosis codes and medical conditions Use this endpoint to get the list of supported diagnosis codes. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/diagnosis" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: diagnosis_data = response.json() print("Supported Diagnosis Code Types:") for code_type in diagnosis_data.get("diagnosis_code_types", []): print(f" {code_type.get('code_type')}") else: print(f"Failed to get diagnosis codes: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/diagnosis', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const diagnosisData = await response.json(); console.log('Supported Diagnosis Code Types:'); diagnosisData.diagnosis_code_types?.forEach((codeType: any) => { console.log(` ${codeType.code_type}`); }); } else { const error = await response.json(); console.error(`Failed to get diagnosis codes: ${response.status}`, error); } ``` # Encounter Types Source: https://developer.suki.ai/api-reference/info/encounter-types GET /api/v1/info/encounter-types Get list of supported clinical encounter types Use this endpoint to get the list of supported encounter types. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/encounter-types" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: encounter_types_data = response.json() print("Supported Encounter Types:") for encounter_type in encounter_types_data.get("encounter_types", []): print(f" {encounter_type.get('code')}") else: print(f"Failed to get encounter types: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/encounter-types', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const encounterTypesData = await response.json(); console.log('Supported Encounter Types:'); encounterTypesData.encounter_types?.forEach((encounterType: any) => { console.log(` ${encounterType.code}`); }); } else { const error = await response.json(); console.error(`Failed to get encounter types: ${response.status}`, error); } ``` # System Information Source: https://developer.suki.ai/api-reference/info/information GET /api/v1/info Get system information and supported configuration values Use this endpoint to get the list of supported LOINC codes, specialties, encounter types, visit types, provider roles, diagnosis code types, and medication order metadata (coding systems, dosage units, frequency types, timings, order statuses, encounter relations, and origins). You can also fetch each category with dedicated `GET /api/v1/info/...` routes listed under **Info** in the API reference. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: info = response.json() print("System Information:") print(f"LOINCs: {len(info.get('loincs', []))} codes") print(f"Specialties: {len(info.get('specialties', []))} specialties") print(f"Encounter Types: {len(info.get('encounter_types', []))} types") print(f"Visit Types: {len(info.get('visit_types', []))} types") print(f"Provider Roles: {len(info.get('provider_roles', []))} roles") print(f"Diagnosis Code Types: {len(info.get('diagnosis_code_types', []))} types") print(f"Medication coding systems: {len(info.get('medication_coding_systems', []))}") print(f"Medication dosage units: {len(info.get('medication_dosage_units', []))}") print(f"Medication frequency types: {len(info.get('medication_frequency_types', []))}") print(f"Medication timings: {len(info.get('medication_timings', []))}") print(f"Medication order statuses: {len(info.get('medication_order_statuses', []))}") print(f"Order encounter relations: {len(info.get('order_encounter_relations', []))}") print(f"Order origins: {len(info.get('order_origins', []))}") else: print(f"Failed to get system information: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const info = await response.json(); console.log('System Information:'); console.log(`LOINCs: ${info.loincs?.length || 0} codes`); console.log(`Specialties: ${info.specialties?.length || 0} specialties`); console.log(`Encounter Types: ${info.encounter_types?.length || 0} types`); console.log(`Visit Types: ${info.visit_types?.length || 0} types`); console.log(`Provider Roles: ${info.provider_roles?.length || 0} roles`); console.log(`Diagnosis Code Types: ${info.diagnosis_code_types?.length || 0} types`); console.log(`Medication coding systems: ${info.medication_coding_systems?.length ?? 0}`); console.log(`Medication dosage units: ${info.medication_dosage_units?.length ?? 0}`); console.log(`Medication frequency types: ${info.medication_frequency_types?.length ?? 0}`); console.log(`Medication timings: ${info.medication_timings?.length ?? 0}`); console.log(`Medication order statuses: ${info.medication_order_statuses?.length ?? 0}`); console.log(`Order encounter relations: ${info.order_encounter_relations?.length ?? 0}`); console.log(`Order origins: ${info.order_origins?.length ?? 0}`); } else { const error = await response.json(); console.error(`Failed to get system information: ${response.status}`, error); } ``` # Supported LOINCs Source: https://developer.suki.ai/api-reference/info/loincs GET /api/v1/info/loincs Get list of supported LOINC codes for clinical note sections Use this endpoint to get the list of supported LOINC codes. For more information about the LOINC codes, refer to the [Note sections](/documentation/note-sections). ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/loincs" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: loincs_data = response.json() print("Supported LOINC Codes:") for loinc in loincs_data.get("loincs", []): print(f" {loinc.get('code')}: {loinc.get('common_name')}") else: print(f"Failed to get LOINC codes: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/loincs', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const loincsData = await response.json(); console.log('Supported LOINC Codes:'); loincsData.loincs?.forEach((loinc: any) => { console.log(` ${loinc.code}: ${loinc.common_name}`); }); } else { const error = await response.json(); console.error(`Failed to get LOINC codes: ${response.status}`, error); } ``` # Medication Order Metadata Source: https://developer.suki.ai/api-reference/info/orders GET /api/v1/info/orders Get all supported medication order metadata in one response Use this endpoint to get supported metadata for medication orders in one response, including coding systems, dosage units, frequency types, timings, statuses, origins, and encounter relations. For more information about medication orders, refer to the [Medication orders](/documentation/medication-orders). ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/orders" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: order_info = response.json() print("Medication order metadata:") print(f" Coding systems: {len(order_info.get('coding_systems', []))}") print(f" Dosage units: {len(order_info.get('dosage_units', []))}") print(f" Encounter relations: {len(order_info.get('encounter_relations', []))}") print(f" Frequency types: {len(order_info.get('frequency_types', []))}") print(f" Origins: {len(order_info.get('origins', []))}") print(f" Statuses: {len(order_info.get('statuses', []))}") print(f" Timings: {len(order_info.get('timings', []))}") else: print(f"Failed to get medication order metadata: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/orders', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const orderInfo = await response.json(); console.log('Medication order metadata:'); console.log(` Coding systems: ${orderInfo.coding_systems?.length ?? 0}`); console.log(` Dosage units: ${orderInfo.dosage_units?.length ?? 0}`); console.log(` Encounter relations: ${orderInfo.encounter_relations?.length ?? 0}`); console.log(` Frequency types: ${orderInfo.frequency_types?.length ?? 0}`); console.log(` Origins: ${orderInfo.origins?.length ?? 0}`); console.log(` Statuses: ${orderInfo.statuses?.length ?? 0}`); console.log(` Timings: ${orderInfo.timings?.length ?? 0}`); } else { const error = await response.json(); console.error(`Failed to get medication order metadata: ${response.status}`, error); } ``` # Medication Coding Systems Source: https://developer.suki.ai/api-reference/info/orders-coding-systems GET /api/v1/info/orders/coding-systems Get supported medication coding systems Use this endpoint to get the list of supported medication coding systems. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/orders/coding-systems" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: coding_systems_data = response.json() print("Supported Medication Coding Systems:") for item in coding_systems_data.get("coding_systems", []): print(f" {item.get('code')}") else: print(f"Failed to get medication coding systems: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/orders/coding-systems', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const codingSystemsData = await response.json(); console.log('Supported Medication Coding Systems:'); codingSystemsData.coding_systems?.forEach((item: any) => { console.log(` ${item.code}`); }); } else { const error = await response.json(); console.error(`Failed to get medication coding systems: ${response.status}`, error); } ``` # Medication Dosage Units Source: https://developer.suki.ai/api-reference/info/orders-dosage-units GET /api/v1/info/orders/dosage-units Get supported medication dosage units Use this endpoint to get the list of supported medication dosage units. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/orders/dosage-units" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: dosage_units_data = response.json() print("Supported Medication Dosage Units:") for item in dosage_units_data.get("dosage_units", []): print(f" {item.get('code')}") else: print(f"Failed to get medication dosage units: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/orders/dosage-units', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const dosageUnitsData = await response.json(); console.log('Supported Medication Dosage Units:'); dosageUnitsData.dosage_units?.forEach((item: any) => { console.log(` ${item.code}`); }); } else { const error = await response.json(); console.error(`Failed to get medication dosage units: ${response.status}`, error); } ``` # Order Encounter Relations Source: https://developer.suki.ai/api-reference/info/orders-encounter-relations GET /api/v1/info/orders/encounter-relations Get supported order encounter relations Use this endpoint to get the list of supported order encounter relations. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/orders/encounter-relations" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: encounter_relations_data = response.json() print("Supported Order Encounter Relations:") for item in encounter_relations_data.get("encounter_relations", []): print(f" {item.get('code')}") else: print(f"Failed to get order encounter relations: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/orders/encounter-relations', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const encounterRelationsData = await response.json(); console.log('Supported Order Encounter Relations:'); encounterRelationsData.encounter_relations?.forEach((item: any) => { console.log(` ${item.code}`); }); } else { const error = await response.json(); console.error(`Failed to get order encounter relations: ${response.status}`, error); } ``` # Medication Frequency Types Source: https://developer.suki.ai/api-reference/info/orders-frequencies GET /api/v1/info/orders/frequencies Get supported medication frequency types Use this endpoint to get the list of supported medication frequency types. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/orders/frequencies" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: frequency_types_data = response.json() print("Supported Medication Frequency Types:") for item in frequency_types_data.get("frequency_types", []): print(f" {item.get('code')}") else: print(f"Failed to get medication frequency types: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/orders/frequencies', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const frequencyTypesData = await response.json(); console.log('Supported Medication Frequency Types:'); frequencyTypesData.frequency_types?.forEach((item: any) => { console.log(` ${item.code}`); }); } else { const error = await response.json(); console.error(`Failed to get medication frequency types: ${response.status}`, error); } ``` # Medication Timings Source: https://developer.suki.ai/api-reference/info/orders-medication-timings GET /api/v1/info/orders/medication-timings Get supported medication timings Use this endpoint to get the list of supported medication timings. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/orders/medication-timings" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: timings_data = response.json() print("Supported Medication Timings:") for item in timings_data.get("timings", []): print(f" {item.get('code')}") else: print(f"Failed to get medication timings: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/orders/medication-timings', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const timingsData = await response.json(); console.log('Supported Medication Timings:'); timingsData.timings?.forEach((item: any) => { console.log(` ${item.code}`); }); } else { const error = await response.json(); console.error(`Failed to get medication timings: ${response.status}`, error); } ``` # Order Origins Source: https://developer.suki.ai/api-reference/info/orders-origins GET /api/v1/info/orders/origins Get supported order origins Use this endpoint to get the list of supported order origins. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/orders/origins" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: origins_data = response.json() print("Supported Order Origins:") for item in origins_data.get("origins", []): print(f" {item.get('code')}") else: print(f"Failed to get order origins: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/orders/origins', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const originsData = await response.json(); console.log('Supported Order Origins:'); originsData.origins?.forEach((item: any) => { console.log(` ${item.code}`); }); } else { const error = await response.json(); console.error(`Failed to get order origins: ${response.status}`, error); } ``` # Medication Order Statuses Source: https://developer.suki.ai/api-reference/info/orders-statuses GET /api/v1/info/orders/statuses Get supported medication order statuses Use this endpoint to get the list of supported medication order statuses. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/orders/statuses" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: statuses_data = response.json() print("Supported Medication Order Statuses:") for item in statuses_data.get("statuses", []): print(f" {item.get('code')}") else: print(f"Failed to get medication order statuses: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/orders/statuses', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const statusesData = await response.json(); console.log('Supported Medication Order Statuses:'); statusesData.statuses?.forEach((item: any) => { console.log(` ${item.code}`); }); } else { const error = await response.json(); console.error(`Failed to get medication order statuses: ${response.status}`, error); } ``` # Provider Roles Source: https://developer.suki.ai/api-reference/info/provider-roles GET /api/v1/info/provider-roles Get list of supported healthcare provider roles Use this endpoint to get the list of supported provider roles. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/provider-roles" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: provider_roles_data = response.json() print("Supported Provider Roles:") for provider_role in provider_roles_data.get("provider_roles", []): print(f" {provider_role.get('code')}") else: print(f"Failed to get provider roles: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/provider-roles', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const providerRolesData = await response.json(); console.log('Supported Provider Roles:'); providerRolesData.provider_roles?.forEach((providerRole: any) => { console.log(` ${providerRole.code}`); }); } else { const error = await response.json(); console.error(`Failed to get provider roles: ${response.status}`, error); } ``` # Supported Medical Specialties Source: https://developer.suki.ai/api-reference/info/specialties GET /api/v1/info/specialties Get list of supported medical specialties and their identifiers Use this endpoint to get the list of supported medical specialties. This list is used to validate the specialty field in the session context when creating or updating an ambient session. For more information about the specialties, refer to the [Medical specialties section](/documentation/specialties). ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/specialties" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: specialties_data = response.json() print("Supported Medical Specialties:") for specialty in specialties_data.get("specialties", []): print(f" {specialty.get('code')}") else: print(f"Failed to get specialties: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/specialties', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const specialtiesData = await response.json(); console.log('Supported Medical Specialties:'); specialtiesData.specialties?.forEach((specialty: any) => { console.log(` ${specialty.code}`); }); } else { const error = await response.json(); console.error(`Failed to get specialties: ${response.status}`, error); } ``` # Visit Types Source: https://developer.suki.ai/api-reference/info/visit-types GET /api/v1/info/visit-types Get list of supported clinical visit types Use this endpoint to get the list of supported visit types. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/info/visit-types" headers = { "sdp_suki_token": "", "sdp_provider_id": "" } response = requests.get(url, headers=headers) if response.status_code == 200: visit_types_data = response.json() print("Supported Visit Types:") for visit_type in visit_types_data.get("visit_types", []): print(f" {visit_type.get('code')}") else: print(f"Failed to get visit types: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/info/visit-types', { headers: { 'sdp_suki_token': '', 'sdp_provider_id': '' } }); if (response.ok) { const visitTypesData = await response.json(); console.log('Supported Visit Types:'); visitTypesData.visit_types?.forEach((visitType: any) => { console.log(` ${visitType.code}`); }); } else { const error = await response.json(); console.error(`Failed to get visit types: ${response.status}`, error); } ``` # Medication Orders Info API Source: https://developer.suki.ai/api-reference/medication-orders-info Get supported medication order metadata in one response Use this endpoint to get supported metadata for medication orders in one response, including coding systems, dosage units, frequency types, timings, statuses, origins, and encounter relations. ## Endpoints # Ambient APIs Overview Source: https://developer.suki.ai/api-reference/overview Introduction to the Suki Ambient APIs: REST, Partner WebSocket audio, webhooks, sessions, clinical notes, and structured clinical output Suki provides **REST APIs** that let you add **Ambient Clinical Documentation workflows** to your application. The APIs give you full control over your application workflows and user experience while enabling you to capture visit conversations and generate clinical notes. The Suki Ambient APIs support **ambient sessions** where providers and patients have real-time conversations. During a session, Suki processes encounter audio and produces **clinical notes** for your product to retrieve. Most operations use REST endpoints and return standard [HTTP status codes](/api-reference/https-guidelines). You stream visit audio over the Partner WebSocket (`GET /ws/stream`) using your ambient session ID. Webhooks notify your application when processing is complete, which removes the need for continuous polling. ## Key capabilities The Ambient APIs expose the capabilities below so you can control capture, note quality, and how generated outputs reach your product and downstream systems. Create ambient sessions, stream encounter audio over the Partner WebSocket, and pause, resume, or end capture when the visit is complete. Turn provider-patient conversations into structured clinical notes and full transcripts, then retrieve draft content and metadata after processing finishes. Let patients speak in 80+ languages while Suki generates English notes and transcripts that fit standard EHR workflows. Set provider-level verbosity and section formats through the User Preferences API so generated notes match how each clinician documents care. Organize documentation by patient problems, merge existing diagnoses from context, and retrieve ICD10 and IMO structured output for EHR integration. Extract diagnoses, medications, and other encounter-level artifacts from the conversation for charting, orders, and analytics in your application. Configure which LOINC-based sections appear in generated notes so output aligns with your specialty templates and compliance requirements. Run speech-to-text sessions when you need transcription without the full ambient clinical note workflow. Receive webhook callbacks when processing completes, and submit feedback on transcripts or generated content to track quality over time. ## Requirements Before you can use the Ambient APIs, you need to meet the following requirements: * You must be a Suki partner. Learn more about how to become a Suki partner in the [Partner onboarding](/documentation/partner-onboarding) documentation. * HTTP/2.0 compliant authentication system (e.g. OAuth 2.0, JWT, etc.). * JWT tokens with consistent user identifiers (e.g. `sub`, `email`, `userId`, etc.). * Publicly accessible JWKS endpoint for token verification. ## What you can build Use the Ambient APIs to build custom ambient clinical documentation workflows. Control how sessions are created, how audio is captured and streamed, and how notes and outputs are presented in your product. You can configure note generation based on: * Visit types * Specialties * Compliance requirements * Existing clinical processes etc. Implement your own logic for session state management, note review, editing, and downstream handoff workflows and connect to your EHR, telehealth platform, or internal systems using REST APIs, WebSockets, and optional webhooks. ### Common use cases Create your own ambient session workflow with full control over the user experience, from session creation to note retrieval. Build custom UI and workflow logic for pausing, resuming, and canceling ambient sessions within your application. Integrate ambient session creation, audio streaming, and structured output retrieval directly into your EHR or telehealth platform. ## API versioning All endpoints use the `/api/v1/` prefix. **v1** is the stable version. Non-breaking changes may ship without a major version jump. For policies and migration, refer to [API guidelines](/api-reference/api-guidelines#version-management). These APIs may include Early Access features. If you are unsure what is enabled for your account, contact your Suki representative. ## Available APIs The following set of APIs are available for the ambient and dictation workflows. View each card below to learn more about the endpoints that are available and how to use them. Endpoints for authentication and authorization. Endpoints for ambient session management. Endpoints for dictation. Endpoints for content retrieval after the session is completed. Endpoints for managing the user preferences. Endpoints for managing user feedback. Endpoints for managing notifications to your service. Endpoints for retrieving information about the encounter type, visit type, and provider role. Endpoints for retrieving information about the medication orders. ## Suki Ambient APIs workflow To integrate with the Suki Ambient API, you follow a session-based workflow. ```mermaid actions={false} theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} flowchart TD Start([Start Session]) --> Auth[Authentication] Auth --> Check{User registered?} Check -->|No| Register[Register new user] Register --> Auth Check -->|Yes| Token[Get sdp_suki_token] Token --> Create[Create session] Create --> SessionID[Get session_id] SessionID --> Context{Seed Context?} Context -->|Yes| AddContext[Add additional context] Context -->|No| Stream AddContext --> Stream[Stream audio chunks] Stream --> Control[PAUSE/RESUME
/KEEP_ALIVE] Control --> Done{Session Complete?} Done -->|No| Stream Done -->|Yes| End[Generate note] End --> Wait[AI processing] Wait --> Notify{Webhook configured?} Notify -->|Yes| Hook[Receive notification] Notify -->|No| Poll[Poll status] Hook --> Retrieve Poll --> Retrieve[Retrieve note] Retrieve --> Complete([Session Complete]) classDef authStyle fill:#FFE148,stroke:#D4A017,stroke-width:2px,color:#000000 classDef registerStyle fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#000000 classDef highlightStyle fill:#FFD700,stroke:#D4A017,stroke-width:3px,color:#000000 class Auth,Create,Stream,End authStyle class Register registerStyle class Retrieve highlightStyle ``` ### Developer workflow Authenticate with Suki to get a Suki authentication token also called `suki_token`. Create an ambient session to start a new visit. Stream visit audio over WebSocket to the Suki backend. End the session when the visit is complete. Retrieve generated outputs through REST endpoints. If webhooks are enabled for your partner account, your application receives automatic completion notifications instead of relying only on polling. **Best practices** * Store **partner\_id**, **partner\_token**, and issued tokens securely; rotate credentials per your security policy. * Send API traffic over HTTPS and validate webhook signatures when your integration receives callbacks. * Read HTTP status and error bodies from REST responses; handle auth expiry by refreshing **suki\_token** as documented. ## Next steps Refer to the [Ambient APIs quickstart](/api-reference/quickstart) to get started. # API Changelog Source: https://developer.suki.ai/api-reference/product-updates/changelog API product updates and announcements Suki's API versioning policy is based on the semantic versioning standard. For example, in version 1.2.3, 1 is the major version, 2 is the minor version, and 3 is the patch version. When we release a new API version for new features or bug fixes, we increment one of these three version components depending on the type of change introduced. **API version numbering policy** All Suki REST APIs are currently in `v1` version. **Release version** The release version in this changelog page represents the incremental progress. It is not the API version. It tracks new optional fields, performance improvements, new endpoints, and other changes.

No changelog entries match this filter. Choose All or another scope.

### Enhancements * Suki now supports **Single Auth Token authentication**: your backend can use one shared `partner_token` for all clinicians instead of a per-user token. The shared token proves your organization is authorized, but it does not identify who is signed in. If you use this model, you **must** send `sdp_provider_id` on every API call so Suki can route each call to the correct clinician. Learn more in the [Provider authentication](/api-reference/provider-authentication) documentation. ```json JSON theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { "sdp_suki_token": "your-suki-token", // sdp_suki_token required for all API calls // Required with Single Auth Token auth: send sdp_provider_id on Register, Login, and every API call "sdp_provider_id": "doc1234567890" } ``` ### New endpoints * **Info endpoints**: Added new endpoints to get the list of supported medication coding systems, dosage units, encounter relations, frequencies, medication timings, origins, and statuses. * GET [/api/v1/info/orders/coding-systems](/api-reference/info/orders-coding-systems) * GET [/api/v1/info/orders/dosage-units](/api-reference/info/orders-dosage-units) * GET [/api/v1/info/orders/encounter-relations](/api-reference/info/orders-encounter-relations) * GET [/api/v1/info/orders/frequencies](/api-reference/info/orders-frequencies) * GET [/api/v1/info/orders/medication-timings](/api-reference/info/orders-medication-timings) * GET [/api/v1/info/orders/origins](/api-reference/info/orders-origins) * GET [/api/v1/info/orders/statuses](/api-reference/info/orders-statuses) ### Enhancements * **Medication orders**: You can now send and retrieve medication orders for an ambient session and encounter using the following endpoints. **Structured data endpoints**: These endpoints return the structured data for an ambient session and encounter. * GET [/api/v1/ambient/session//structured-data](/api-reference/ambient-content/structured-data) * GET [/api/v1/ambient/session//encounter-structured-data](/api-reference/ambient-content/encounter-structured-data) **Context API**: This endpoint allows you to update the ambient session context with new EMR context and medication orders. * POST [/api/v1/ambient/session//context](/api-reference/ambient-sessions/update-context) **Content API**: This endpoint returns the content for an ambient session and encounter. * GET [/api/v1/ambient/session//content](/api-reference/ambient-content/content) * GET [/api/v1/ambient/session//encounter-content](/api-reference/ambient-content/encounter-content) **Payload structure**: ```json JSON theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { "structured_data": { "orders": { "medication_orders": { "values": [ { "drug_name": "Drug Name", "status": "Status", "medication_code": "Medication Code", "medication_code_type": "Medication Code Type" } ] } } } } ``` When you send medication orders to the context API, the medication orders are validated against the EMR context. If the medication orders are not valid, the context API will return an error. Learn more in the [Medication orders](/documentation/medication-orders) documentation.
### New endpoints * **Audio streaming and download**: We've added a new endpoint for audio streaming and download from ambient sessions. Stream or download the audio recording from an ambient session. * GET [/api/v1/ambient/session//recording](/api-reference/ambient-content/recording) Learn more in the [Audio streaming and download](/documentation/audio-streaming-download) documentation.
### Deprecated * **Multilingual support**: The `multilingual` parameter is deprecated in the `Create Ambient Session` endpoint. When you call create ambient session API, the multilingual support is now **set to true by default**.
### New endpoints * **Audio Dictation API**: Added support for real-time audio transcription/dictation. Create dictation sessions, stream audio data, and end sessions to get final transcripts. This enables use cases like dictation, real-time captioning, and transcript generation. * POST [/api/v1/transcription/session/create](/api-reference/audio-transcription/create-session) * POST [/api/v1/transcription/session//end](/api-reference/audio-transcription/end-session) * GET [/ws/transcribe](/api-reference/audio-transcription/stream-transcription)
### Enhancements * **Code examples**: Added code examples in Python and TypeScript for all APIs, making it easier to integrate with the platform regardless of your preferred programming language.
### New endpoints * **Info endpoints**: Introduced three new info endpoints to provide supported enum values, helping you validate context data before submission and ensuring data consistency. * GET [/api/v1/info/encounter-types](/api-reference/info/encounter-types) * GET [/api/v1/info/visit-types](/api-reference/info/visit-types) * GET [/api/v1/info/provider-roles](/api-reference/info/provider-roles) * **API reference guidelines**: Added a new [API reference guidelines](/api-reference/api-guidelines) page to help you understand API status tags, versioning, and documentation standards. ### Enhancements * **Enhanced API documentation**: Significantly restructured and enhanced API reference documentation for better developer experience, clearer organization, and improved discoverability. * **Problem-based charting guide**: Completely rewritten the Problem-Based Charting (PBC) guide with a clearer structure and more detailed explanations of the processing pipeline. * **Audio streaming authentication**: Added detailed authentication guidance for both browser and non-browser clients in the Audio streaming API reference documentation. * **Enhanced context support**: Updated the [Ambient session context APIs](/api-reference/ambient-sessions/context) to support a new `VisitContext` schema, including fields like `chief_complaint` and `visit_type`. The provider context has also been enhanced to support `provider_role`. ### Removed support * **SNOMED codes**: SNOMED codes are no longer supported for the diagnosis context * **Paused state**: Paused state is no longer supported for ambient sessions
# Provider Authentication Source: https://developer.suki.ai/api-reference/provider-authentication Learn how to authenticate providers and users to use the Suki ambient APIs **Not a Suki Partner yet?** To use the Suki APIs, you must first register your organization as a partner. To begin, follow the [Partner onboarding](/documentation/partner-onboarding) guide to learn more or schedule a call with Suki using the **Ask AI** chat assistant. After you register, you use a Partner Token (`partner_token`) to authenticate your API requests. The `partner_token` is a JWT that **you** provide, and it is a **required parameter** when registering a provider. Find more details on how to get a `partner_token` in the [Partner authentication](/documentation/partner-authentication) guide. All Suki Partner APIs require partner authentication. To authenticate, exchange your Partner Token (`partner_token`) to get a Suki access token. Use the Suki access token to call the [Register](/api-reference/authentication/register) and [Login](/api-reference/authentication/login) APIs and authenticate clinicians with Suki. Suki access tokens are valid for **1 hour**. This guide explains the **two main endpoints** for the authentication workflow: * **Register user**: A **one-time** call to register a **new provider** in the Suki system. * **Authenticate user**: Call this endpoint to get a **suki\_token** (`sdp_suki_token`) for a registered provider. ## Authentication methods Suki supports the following authentication methods. Suki configures your method during [Partner onboarding](/documentation/partner-onboarding). ### Standard partner authentication Each clinician authenticates with their own `partner_token`. Suki derives provider identity from that token, so you do not need to send `provider_id` on Register or Login. **Best for** * Enterprise deployments where each clinician has their own account in your identity provider * Integrations where your IdP issues a per-user ID token or user-scoped JWT as `partner_token` * Flows where the token already identifies the signed-in provider without a separate `provider_id` ### Single Auth Token authentication Your backend uses one shared `partner_token` for multiple clinicians. The token proves your organization is authorized, but it does not identify who is signed in. Send `provider_id` on every Register, Login, and API request. **Best for** * Server backends that authenticate to Suki with one organization-level token for many clinicians * Applications that already know the active provider from your session, EHR, or user directory * Identity setups that cannot include per-user claims in the `partner_token` * Bearer partner configurations (refer to [Bearer partner authentication](/api-reference/bearer-partner-authentication)) If you plan to use Single Auth Token authentication, see [Authentication with a Single Auth Token](/api-reference/provider-authentication#authentication-with-a-single-auth-token) for more details. * To refresh a Suki access token, send another **POST** request to [Login](/api-reference/authentication/login) with a valid `partner_token`. * You need the Suki access token to call all Suki REST and WebSocket APIs. If you are a Bearer partner, you must send `sdp_provider_id` on every REST API and WebSocket API call. Refer to [Bearer partner authentication](/api-reference/bearer-partner-authentication) for more details. ## Register provider/user account Use the below endpoint to **register** a new **provider/user** in the Suki platform. You only need to do this **once** for each new provider. **Endpoint**: [Register](/api-reference/authentication/register) **Method:** POST ### Registration scenarios Flowchart: POST register leads to User Exists; if No, New User Registration, Create User and Link, then Response 201; if Yes, Linked to this Partner; if No, Existing User New Partner Link, Link User to Partner, then Response 201; if Yes, Existing User Already Linked, then Response 409 Conflict. Flowchart: POST register leads to User Exists; if No, New User Registration, Create User and Link, then Response 201; if Yes, Linked to this Partner; if No, Existing User New Partner Link, Link User to Partner, then Response 201; if Yes, Existing User Already Linked, then Response 409 Conflict. The `Register` endpoint handles three main scenarios: * **New user registration**: If the provider **does not exist** in the Suki system, this call **creates a new user** and links them to your partner account and organization. * **Existing user, new partner link**: If the provider **already exists** but is not linked to your partner account, this call **links them to your partner** and their existing organization. * **Existing user, already linked**: If the provider is already registered and linked to your partner account, the API returns a `409` Conflict error. ## Authenticate provider/user session After a provider is registered, call [Login](/api-reference/authentication/login) endpoint to get a Suki access token (`sdp_suki_token`). If you are a Bearer partner, you must send `provider_id` on every API call, including [Login](/api-reference/authentication/login). Refer to [Bearer partner authentication](/api-reference/bearer-partner-authentication) for more details. ### JWKS endpoint Suki provides a public **JWKS (JSON Web Key Set)** endpoint that you can use to verify the signature of the `sdp_suki_token` that our API returns. **Endpoint:** [JWKS URL](/api-reference/authentication/jwks) **Method:** GET **Authentication:** None (Public) ### Use cases Diagram: Fetch Public Keys leads to JWKS Endpoint; from JWKS, three branches to Token Verification, Signature Validation, and Key Rotation. Diagram: Fetch Public Keys leads to JWKS Endpoint; from JWKS, three branches to Token Verification, Signature Validation, and Key Rotation. * **Token verification**: Fetch public keys to verify JWTs issued by Suki. * **Signature validation**: Validate the signature of the `sdp_suki_token`. * **Key rotation**: Automatically discover new public keys when Suki rotates our signing keys. ## Authentication with a Single Auth Token Some partners use **one shared `partner_token`** for all providers instead of a per-user token from their identity provider. Suki configures this during [Partner onboarding](/documentation/partner-onboarding). Because the shared token does not identify which clinician is signed in, your backend must send **`provider_id`** in the body of Register and Login requests and **`sdp_provider_id`** as a header on every subsequent request so Suki knows who each request is for. ### Typical flow **Register** each clinician once with [Register](/api-reference/authentication/register). Use a stable **`provider_id`** for that person. **Login** with [Login](/api-reference/authentication/login). Send your `partner_id`, shared `partner_token`, and the active clinician's **`provider_id`**. **Call Suki APIs** with the **`sdp_suki_token`** returned from Login. Include the **`sdp_provider_id`** header on every REST and WebSocket request. **Refresh** the token before it expires (**1 hour**). Call Login again with the same `partner_token` and `provider_id`. ### Send sdp\_provider\_id with all API requests When you use **Single Auth Token authentication method** for all clinicians, include the `sdp_provider_id` header on **every** Suki API request after Login. The token proves your organization is authorized; it does not identify which clinician is acting. You pass `sdp_provider_id` to tell Suki that. * **Register and Login:** Your app already knows which clinician is signing in. Send that person's identifier as `provider_id` so Suki can register or authenticate them. * **All other APIs:** After Login, send `sdp_provider_id` on every REST and WebSocket request along with `sdp_suki_token`. Suki uses it to route the request to the correct clinician. Register each provider with a stable `provider_id` before their first Login. If Login fails because the provider is not registered, call Register, then call Login again. For request fields, security guidance, and examples, refer to [Bearer partner authentication](/api-reference/bearer-partner-authentication). # Ambient API Quickstart Source: https://developer.suki.ai/api-reference/quickstart Step-by-step guide to authenticate, create a session, stream audio, and retrieve the clinical note This guide walks you through the steps to use the Suki Ambient APIs to create an ambient session, stream audio, and retrieve the clinical note. **What you will do** 1. **Authenticate** to get a Suki token (and **register** the user if needed). 2. **Create** an ambient session and optionally **seed context** for better notes. 3. **Stream audio** over the WebSocket, send control events, and **end** the session when the visit is done. 4. **Retrieve** the clinical note and transcript, or rely on a **webhook** when processing finishes. **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). 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). ## Access and credentials You need partner credentials to use the Suki Ambient API. Contact our [Partnership team](https://www.suki.ai/suki-partners/) to get your credentials. They will guide you through the [Onboarding process](/documentation/partner-onboarding) and provide what you need to get started. ### Prerequisites To use the Suki Ambient APIs, you must have the following: * An OAuth-compliant authentication system * JWT tokens with consistent user identifiers * A publicly accessible JWKS endpoint (or Okta authorization server) for token validation Refer to the [Partner onboarding](/documentation/partner-onboarding) and [Partner authentication](/documentation/partner-authentication) guides for more details. ### Environments to use for development and testing This guide uses **`https://sdp.suki-stage.com`** and **`wss://sdp.suki-stage.com`** for API and WebSocket examples (staging). **Important**: * The production environment is **`https://sdp.suki.ai`** and **`wss://sdp.suki.ai`**. * The staging environment is **`https://sdp.suki-stage.com`** and **`wss://sdp.suki-stage.com`**. * Your partnership team will confirm which environment, base URL, and credentials apply for your integration. ## Step 1: Authenticate and get token To begin, you must authenticate to get your access token. Send a **POST** request to the [/api/v1/auth/login](/api-reference/authentication/login) endpoint with the following parameters in the request body: 1. **partner\_id**: Your unique Partner ID, which we provide to you securely offline. 2. **partner\_token**: The user's OAuth 2.0 ID token (Partner Token) from your identity provider. 3. **provider\_id** (Optional): Unique identifier for the provider. Required for Bearer type partners only. Suki verifies the `partner_token` using your publicly exposed **JWKS endpoint** (or your Okta authorization server URL if you use Okta). On a successful request, the API returns a Suki Token (`suki_token`) that you must include as the `sdp_suki_token` header for all subsequent API calls. **Handling an unregistered user**: * If the user is not yet registered in our system, the `/login` request will fail. * In this case, you must first call the [/api/v1/auth/register](/api-reference/authentication/register) endpoint to create the user, then call `/login` again. * You only need to call the register endpoint once for each new user. * Refer to the [Register API reference](/api-reference/authentication/register) for the full specification. ```bash cURL theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} curl -X POST https://sdp.suki-stage.com/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{ "partner_id": "your-partner-id", "partner_token": "your-jwt-token", "provider_id": "provider-123" }' ``` Save the `suki_token` from the response. This token is valid for **1 hour**. When it is about to expire, you can get a new one by making the same **POST** request to `/login` with a valid `partner_token`. ## Step 2: Create ambient session To start an ambient session, send a **POST** request to the [/api/v1/ambient/session/create](/api-reference/ambient-sessions/create) endpoint with the following parameters in the request body: This guide uses `encounter_id`. In older versions of the API, this parameter was named `session_group_id`. The old name will be deprecated in a future release. The `multilingual` parameter is deprecated. Multilingual support is now **true** by default for all Suki for Partner users. 1. **encounter\_id** (Optional): A unique identifier for the patient encounter (also called a visit). This can be any alphanumeric string up to **255 characters** long. 2. **ambient\_session\_id** (Optional): A UUID v4 to identify the session. If you do not provide one, Suki will generate it and include it in the response. ```bash cURL theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} curl -X POST https://sdp.suki-stage.com/api/v1/ambient/session/create \ -H "sdp_suki_token: YOUR_SUKI_TOKEN" \ -H "sdp_provider_id: " \ -H "Content-Type: application/json" \ -d '{ "ambient_session_id": "123dfg-456dfg-789dfg-012dfg", "encounter_id": "123dfg-456dfg-789dfg-012dfg" }' ``` Save the `ambient_session_id` from the response. You will need it to stream audio and retrieve content. ## Step 3: Seed context After creating the session, you can send a **POST** request to the [/api/v1/ambient/session//context](/api-reference/ambient-sessions/context) endpoint to provide additional metadata. Providing **context** significantly improves the accuracy of the generated clinical note. Include the following parameters in the request body: * **provider\_specialty** (Optional): The specialty of the provider (e.g., "cardiology"). * **sections** (Optional): A list of the clinical sections you want summarized, such as "Assessment and Plan" or "Chief Complaint". If you do not provide this, a default set of sections will be used. * **patient\_info** (Optional): An object containing `date_of_birth` (for accurate age calculation) and `sex` (**MALE**, **FEMALE**, **OTHER**, or **UNKNOWN**; defaults to **UNKNOWN**). Refer to the [Context API reference](/api-reference/ambient-sessions/context) for the full request structure. ## Step 4: Stream audio via WebSocket After you **create** the ambient session and **seed context** (previous steps), open a **WebSocket** to `wss://sdp.suki-stage.com/ws/stream`. Upgrading before the session exists or before context is ready often fails. For authentication, use the `Sec-WebSocket-Protocol` header (browser clients) with the comma-separated value `SukiAmbientAuth,,`, or send `sdp_suki_token` and `ambient_session_id` as separate HTTP headers on the upgrade (non-browser clients). See the [Audio streaming API reference](/api-reference/ambient-sessions/audio-stream) for the full wire format and code samples. **Audio format**: You must stream **raw PCM** in each `AUDIO` message (after Base64 encoding) with: * **encoding**: LINEAR16 * **sample\_rate**: 16KHz * **channel**: Mono `.wav` files are containers; strip the usual **44-byte** WAV header (or decode to PCM) before chunking. Sending RIFF headers as PCM hurts recognition. For optimal performance, we recommend chunking the audio into **100ms packets**. **Outbound WebSocket messages** must each be **one JSON text frame** (one object per send). Use proto JSON field names: **`type`** and **`data`** for `START_TIME` and `AUDIO`. The **`data`** field is always **standard Base64** (RFC 4648) of **raw bytes**. Do not send PCM as binary WebSocket frames on this endpoint. **Required send order** for a stream segment: 1. **`START_TIME`**: `data` is Base64 of the UTF-8 RFC 3339 timestamp string. 2. **`AUDIO`**: one or more messages with `data` set to Base64 of each PCM chunk. 3. **End marker**: an **`AUDIO`** message whose `data` is Base64 of the three bytes **`EOF`** (ASCII), value **`RU9G`**. Do not use `{"type":"end_of_stream"}` for this protocol. **`EVENT` messages** use **`{"type":"EVENT","event":""}`** (not `data` for the action). Supported values include: * **PAUSE**: Pauses the stream. * **RESUME**: Resumes a paused audio stream. * **CANCEL**: Immediately mark an ambient session as CANCELLED in our system, it closes the WebSocket. The session cannot be resumed again; create a new session if you want to record again. * Deprecated **ABORT**: Aborts the stream due to an interruption. A note will be generated from the audio received so far. The session remains active and can be resumed. * **KEEP\_ALIVE**: Pings the server to keep the connection alive during periods of inactivity (e.g., when paused). When you are done sending audio, **close the WebSocket**, then call the **end session** endpoint (next step) and **poll status and REST content endpoints** for the final note and transcript. Final results are not guaranteed from the WebSocket alone. **Keep the connection alive**: You must send a **KEEP\_ALIVE** event at least once every **five seconds** when the stream is paused to prevent the connection from closing. **Stream behavior and timeouts**: 1. **Session Timeouts**: If no audio data is sent for **25 seconds**, Suki will disconnect the stream. 2. **Paused Stream**: If the stream is paused and receiving KEEP\_ALIVE events, Suki will disconnect the stream after **30 minutes** of inactivity. **CANCEL vs. ABORT**: Sending **CANCEL** terminates the session completely. No note will be generated. Sending **ABORT** ends the current stream, but the session remains **active**. Suki will generate a note from the audio received before the interruption. Resume streaming to the same `ambient_session_id` later. ## Step 5: End session To complete the session and begin the note generation process, send a **POST** request to the [/api/v1/ambient/session//end](/api-reference/ambient-sessions/end) endpoint. This signals that no more audio will be sent for this session. ```bash cURL theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} curl -X POST "https://sdp.suki-stage.com/api/v1/ambient/session/YOUR_SESSION_ID/end" \ -H "sdp_suki_token: YOUR_SUKI_TOKEN" \ -H "sdp_provider_id: " ``` ## Step 6: Retrieve generated content Once the note is ready, Suki notifies your application. The recommended way to know when a note is ready is to use a **webhook**. Suki will send a `session_summary_generated` event to a webhook endpoint that you provide. Details on configuring your webhook and its authentication will be provided during the onboarding process. **Retrieving content manually**: Alternatively, you can use the following endpoints to check the status and retrieve the session's content: 1. [GET /api/v1/ambient/session//status](/api-reference/ambient-content/status): Check the processing status of a session. 2. [GET /api/v1/ambient/session//content](/api-reference/ambient-content/content): Retrieve the final, structured clinical note. 3. [GET /api/v1/ambient/session//transcript](/api-reference/ambient-content/transcript): Get the full conversation transcript, including **timestamps** for each part of the dialogue. ```bash cURL theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} # Get clinical note curl -X GET "https://sdp.suki-stage.com/api/v1/ambient/session/YOUR_SESSION_ID/content?cumulative=false" \ -H "sdp_suki_token: YOUR_SUKI_TOKEN" \ -H "sdp_provider_id: " # Get transcript curl -X GET "https://sdp.suki-stage.com/api/v1/ambient/session/YOUR_SESSION_ID/transcript" \ -H "sdp_suki_token: YOUR_SUKI_TOKEN" \ -H "sdp_provider_id: " ``` **Session Duration Requirement** Your ambient session must be **at least 1 minute long** for note generation to occur. Sessions shorter than 1 minute will receive a `SKIPPED` status, meaning no clinical note was generated. For complete technical specifications, please refer to the relevant API Reference pages. ## Next steps After completing your first session, explore these resources to deepen your integration: [Authentication API](/api-reference/authentication/login) - Login, register, and JWKS configuration. [Context API](/api-reference/ambient-sessions/context) - Seed specialty, sections, and patient info for better note accuracy. [Audio Streaming API](/api-reference/ambient-sessions/audio-stream) - WebSocket connection details and message formats. [Webhook](/api-reference/asynchronous/webhook) - Configure webhooks to receive notifications when notes are ready. # Security & Best Practices Source: https://developer.suki.ai/api-reference/security-best-practices Learn about the best practices for securing your Suki APIs This section provides best practices for securing your Suki APIs and SDKs. ## Security best practices All API requests must use **HTTPS** (TLS 1.2 or higher) to ensure data encryption in transit. Never send requests over unencrypted HTTP connections. ### Token management Following are the best practices for token management: Never expose `sdp_suki_token` in client-side code, logs, or version control. Store tokens securely on your backend server. Implement token refresh logic to automatically obtain a new `sdp_suki_token` when the current one expires. Call the `/login` endpoint with a valid partner token to refresh. When receiving `sdp_suki_token` from Suki, verify its signature using the public keys from the JWKS endpoint ([Authentication JWKS](/api-reference/authentication/jwks)) (`/api/auth/.well-known/jwks-pub.json`). Your partner token must be a standards-compliant JWT signed with RS256 (RSA Signature with SHA-256) algorithm. Ensure your JWKS endpoint is publicly accessible and properly configured. ### Webhook security Following are the best practices for webhook security: Suki signs webhook POSTs with **HMAC-SHA-256**. A **secret key** on your **partner record** is provided by Suki. Each request sends **`generated-at`** (Unix ms) and **`X-API-Key`** (hex HMAC of `generated-at`, a colon, and the raw JSON body). Verify before you process the body. For the exact steps, refer to [Notification webhook for Partners](/documentation/webhook/signature-verification) for more details. Your webhook callback URL must use HTTPS protocol. Never use HTTP endpoints for webhooks. Always validate the webhook payload structure and verify the HMAC signature before processing notifications. ### Data protection Following are the best practices for data protection: All data transmitted to and from Suki is encrypted using TLS 1.2. Ensure your application maintains encryption standards for data at rest. Ensure your integration complies with HIPAA requirements. Obtain patient consent before sending personal data to the platform. Only send the minimum required data for each API call. Avoid including unnecessary patient or provider information. ### Error handling Following are the best practices for error handling: If you receive a `401 Unauthorized` or `403 Forbidden` response, verify your `sdp_suki_token` is valid and not expired. Re-authenticate if necessary. For transient errors (5xx status codes), implement exponential backoff retry logic. Do not retry on 4xx client errors. When logging API errors, never include tokens, passwords, or sensitive patient data in logs. For more details on security and compliance, see the [Security FAQs](/documentation/faqs/security). # Send Notifications API Source: https://developer.suki.ai/api-reference/send-notifications Receive asynchronous notifications from Suki using your notification endpoint Configure your application to expose an HTTPS URL that accepts inbound requests when asynchronous work completes. Suki calls that URL with a signed or documented payload so your backend can pull results or update job state without polling. Learn more about how to configure your application to receive notifications from Suki in the [Notification webhook for partners](/documentation/webhook/overview) documentation. ## Usage scenarios * Receive asynchronous notifications from Suki using your notification endpoint * Receive notifications when a session is completed or failed * Receive notifications when a session is timed out or cancelled * Receive notifications when a session is created or updated * Receive notifications when a session is deleted * Receive notifications when a session is started or stopped * Receive notifications when a session is paused or resumed ## Endpoints # User Feedback API Source: https://developer.suki.ai/api-reference/user-feedback Submit feedback on ambient session entities such as transcripts or generated content Send structured feedback tied to a session and a specific entity so Suki can track quality issues, regressions, or user-reported problems against concrete artifacts. ## Usage scenarios * Submit feedback on ambient session entities such as transcripts or generated content ## Endpoints # User Preferences API Source: https://developer.suki.ai/api-reference/user-preferences Read and update end-user preferences for the Suki platform Use this endpoint to read or change preferences for the authenticated user so your client stays aligned with Suki defaults for language, layout, or other user-scoped settings exposed by the API. ## Endpoints # User Preferences Source: https://developer.suki.ai/api-reference/user-preferences/preferences PATCH /api/v1/user/preferences Update user personalization preferences for clinical note generation Use this endpoint to update and save a user's personalization preferences. These settings are saved at the user level, not per session, and will be applied to all of the user's future interactions. For details, see [Personalization](/api-reference/capabilities/personalization). Section format preferences use LOINC codes to identify note sections. This is a `PATCH` request, you only need to send the fields you want to change. For the best results, we recommend that you call this endpoint before the **main interaction begins** (for example, before audio streaming starts or before you call the `/end` endpoint). This ensures the user's preferences are applied before content is generated. However, you can call this endpoint at any time to update the settings. ## Code examples ```python theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import requests url = "https://sdp.suki-stage.com/api/v1/user/preferences" headers = { "sdp_suki_token": "", "sdp_provider_id": "", "Content-Type": "application/json" } payload = { "personalization_preference": { "verbosity": "CONCISE", # Options: CONCISE, BALANCED, DETAILED "section_format": [ { "loinc": "10164-2", "style": "NARRATIVE" # Options: NARRATIVE, BULLETED } ] } } response = requests.patch(url, json=payload, headers=headers) if response.status_code == 200: data = response.json() print("Preferences updated successfully") print(f"Updated preferences: {data}") else: print(f"Failed to update preferences: {response.status_code}") print(response.json()) ``` ```typescript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} const response = await fetch('https://sdp.suki-stage.com/api/v1/user/preferences', { method: 'PATCH', headers: { 'sdp_suki_token': '', 'sdp_provider_id': '', 'Content-Type': 'application/json' }, body: JSON.stringify({ personalization_preference: { verbosity: 'CONCISE', // Options: CONCISE, BALANCED, DETAILED section_format: [ { loinc: '10164-2', style: 'NARRATIVE' // Options: NARRATIVE, BULLETED } ] } }) }); if (response.ok) { const data = await response.json(); console.log('Preferences updated successfully'); console.log('Updated preferences:', data); } else { const error = await response.json(); console.error(`Failed to update preferences: ${response.status}`, error); } ``` # Dictation SDK Changelog Source: https://developer.suki.ai/dictation-sdk/changelog Dictation SDK product updates and announcements Suki's Dictation SDK versioning policy is based on the semantic versioning standard. For example, in version 1.2.3, 1 is the major version, 2 is the minor version, and 3 is the patch version. When we release a new Dictation SDK version for new features or bug fixes, we increment one of these three version components depending on the type of change introduced. ### New features * **Initial beta release**: First release of the Suki Dictation SDK. Build custom speech-to-text integrations with complete control over your user interface. Currently in **beta** stage for you to try out and provide feedback. # General Source: https://developer.suki.ai/dictation-sdk/faqs/general General questions about the Suki Dictation SDK The Suki Dictation SDK is a JavaScript and React library for dictation in the browser. It lets you add speech-to-text to your web application using Suki's hosted dictation experience, authentication helpers, and callbacks. Read the [Dictation SDK Overview](/dictation-sdk/introduction) for supported packages, In-field and Scratchpad modes, and how a typical session flows. You can build dictation in two ways: * **In-field:** Dictation overlays a target field. This pattern fits notes, forms, and similar workflows. * **Scratchpad:** Dictation uses a floating panel that is not tied to a single input. Read [In-field mode](/dictation-sdk/guides/in-field-mode) and [Scratchpad mode](/dictation-sdk/guides/scratchpad-mode). The [Introduction](/dictation-sdk/introduction) page also summarizes both. **Dictation SDK:** Your app embeds dictation in the browser. The SDK handles platform authentication with **`SukiAuthManager`**, the iframe lifecycle, and callbacks such as **`onSubmit`**. **Dictation APIs:** You call Suki's REST and WebSocket dictation APIs from your own code without using this iframe SDK. That path is documented under [Audio dictation](/documentation/dictation) and the [Dictation API](/api-reference/ambient-dictation) reference. The [Introduction](/dictation-sdk/introduction) page includes a short note that compares the two approaches. Every setup uses **`@suki-sdk/core`** for **`SukiAuthManager`**. You then add one surface package: * **JavaScript (vanilla or non-React frameworks):** **`@suki-sdk/dictation`** plus **`@suki-sdk/core`**. * **React:** **`@suki-sdk/dictation-react`** plus **`@suki-sdk/core`**. You still import **`DictationClient`** from **`@suki-sdk/dictation`** in examples when you construct the client in code. Copy-paste install commands are in [Installation](/dictation-sdk/installation). Package names also appear on the [Introduction](/dictation-sdk/introduction) page. No. The product is meant for **browser** embedding. Your page needs a real **`HTMLIFrameElement`**, **`postMessage`**, and layout so the hosted UI can mount and size correctly. **Not supported:** Using Node.js as the runtime that hosts **`DictationClient`** or the dictation iframe, or relying on **SSR alone** to render dictation instead of initializing on the client after the DOM (and your container, when you use one) exists. Read the runtime section in [Error handling](/dictation-sdk/guides/error-handling) and [Prerequisites](/dictation-sdk/prerequisites). # Integration Source: https://developer.suki.ai/dictation-sdk/faqs/integration Integration questions about the Suki Dictation SDK **JavaScript:** Use **`DictationClient`** from **`@suki-sdk/dictation`** and call **`await dictationClient.show({ ... })`** when the user should dictate. Walk through [Dictation SDK JavaScript integration](/dictation-sdk/javaScript-integration/javaScript). **React:** Use **`DictationProvider`** and **`Dictation`** from **`@suki-sdk/dictation-react`**, with the same **`DictationClient`** instance passed into the provider. Walk through [Dictation SDK React integration](/dictation-sdk/react-integration/react). Pick the guide that matches your stack. The [Quickstart](/dictation-sdk/quickstart) shows both patterns in one place if you want a shorter comparison. The documentation treats **`SukiAuthManager`** and **`DictationClient`** as **long-lived** for a page or session. If you create a new **`DictationClient`** on every render or for every textarea, the iframe and session tend to tear down and start again, which feels unstable. That guidance is spelled out in the [Quickstart](/dictation-sdk/quickstart) (recommended integration pattern) and in the best-practices sections of the [JavaScript](/dictation-sdk/javaScript-integration/javaScript) and [React](/dictation-sdk/react-integration/react) integration guides. Call **`show()`** again with the next field's options. A new **`show()`** call **replaces** the active session. You do **not** need to call **`hide()`** manually just to move from one field to another for that pattern. See [JavaScript integration](/dictation-sdk/javaScript-integration/javaScript) and [Configuration](/dictation-sdk/guides/configuration) for examples and option details. Keep a **single** **`client`** and **`DictationProvider`**. Use state (for example **`activeFieldId`** or a boolean) so **only one** **`Dictation`** is mounted at a time, or change **`fieldId`** / **`initialText`** when you remount. You do **not** need to call **`hide()`** yourself for that kind of switch. Full pattern: [React integration](/dictation-sdk/react-integration/react). When **`Dictation`** unmounts, the SDK **automatically** calls **`hide()`**. For normal React flows you do **not** call **`hide()`** yourself. Details: [React integration](/dictation-sdk/react-integration/react). # Technical Source: https://developer.suki.ai/dictation-sdk/faqs/technical Technical questions about the Suki Dictation SDK **Required** * **`partnerId`** * **`partnerToken`** **Optional** (when your integration needs them) * **`environment`** (for example **`"staging"`** or **`"production"`**) * **`autoRegister`** * **`loginOnInitialize`** Field descriptions and **AuthConfig** details are in [Configuration](/dictation-sdk/guides/configuration) and [Authentication](/dictation-sdk/guides/authentication). Invalid **`partnerId`** or **`partnerToken`** block iframe initialization, as noted on those pages and in [Prerequisites](/dictation-sdk/prerequisites). **`fieldId`** is a **stable, unique** string that names one dictation session. Every callback returns it together with **`text`** so you know which field the result belongs to. It does **not** have to match a DOM **`id`**, but using the same string as your input's **`id`** is a simple pattern. Naming examples and guidance: [Configuration](/dictation-sdk/guides/configuration) (Field IDs in practice) and [Callbacks](/dictation-sdk/guides/callbacks). **`onSubmit`** runs when the user **commits** the transcript. If you omit it, dictation often **closes immediately** after the user acts, so production integrations should always implement it. Read [Configuration](/dictation-sdk/guides/configuration) and [Callbacks](/dictation-sdk/guides/callbacks) for the full callback contract. **`rootElement`** is the **DOM node** where the SDK mounts the dictation iframe. The iframe **sizes to that container**, so the node should have real width and height. **Layout:** Wrapper markup and CSS patterns are described under **Wrapper layout** on the [Configuration](/dictation-sdk/guides/configuration) page. [In-field mode](/dictation-sdk/guides/in-field-mode) and [Error handling](/dictation-sdk/guides/error-handling) cover related layout issues. **React:** Some examples omit **`rootElement`**; the [React integration](/dictation-sdk/react-integration/react) guide explains when the minimal pattern skips it and when to pass it (including refs in real apps). [Configuration examples](/dictation-sdk/guides/examples/configuration-examples) includes sample wiring. Work through checks in this order: 1. **Runtime:** Browser-only use, correct timing (call after the DOM and container exist and have size). 2. **Layout:** **`rootElement`** (when used), height, and CSS. 3. **Auth and CSP:** Valid partner credentials and any CSP rules that affect iframes. 4. **Configuration and callbacks:** **AuthConfig**, **ShowOptions**, and a working **`onSubmit`**. That order is documented on [Error handling](/dictation-sdk/guides/error-handling). Use [Configuration](/dictation-sdk/guides/configuration) for every option field. # Dictation SDK Architecture Source: https://developer.suki.ai/dictation-sdk/guides/architecture Learn how your application, the Dictation SDK, sign-in, and Suki-hosted dictation fit together
Quick summary
Learn about the architecture of the Suki Dictation SDK and how your application, the Dictation SDK, sign-in, and Suki-hosted dictation fit together.
Last updated: June 2026
This guide explains the responsibilities for embedding dictation in your application. You maintain control of your user interface and determine when you turn dictation on or off. The Suki Dictation SDK hosts the microphone experience and transcription to ensure a consistent look and behavior across every integration. ## Architecture of the Suki Dictation SDK There are four main components in the Suki Dictation SDK: * Your application * The Suki Auth Manager * The Dictation SDK * The Suki hosted dictation iframe The following diagram illustrates the architecture of the Suki Dictation SDK and how each component fits together: Diagram: your web application contains application code, Dictation SDK, and layout with callbacks; Suki provides sign-in and hosted dictation; arrows show authenticate and tokens, hosted dictation session, and transcript back to your app. Diagram: your web application contains application code, Dictation SDK, and layout with callbacks; Suki provides sign-in and hosted dictation; arrows show authenticate and tokens, hosted dictation session, and transcript back to your app. Your app never has to build the dictation screen itself. The SDK opens that experience in the place you choose and passes results back to your code. ### What each layer does | Layer | What it does | | :------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Your application** | You decide when dictation should appear, where it mounts on the page, and what to do with text when the user is done (and optional live updates if you use them). | | **Dictation SDK** | The client you install talks to Suki, shows or hides the hosted dictation experience, and wires your callbacks so you receive transcripts. | | **Sign-in** | You configure this once with your partner details. It checks your setup, signs in with Suki, refreshes access when needed, and gives the hosted experience what it needs to run securely. | | **Hosted dictation** | The surface users speak into lives on Suki's side. It stays separate from your page's styles and layout so the experience stays consistent.

The iframe is isolated from host CSS and DOM to ensure consistent rendering across integrations. | If you need step-by-step setup, start with [Authentication](./authentication), then the [Quickstart](../quickstart). ## Lifecycle of a dictation session Diagram: four steps from configure SukiAuthManager, create DictationClient, open dictation, to close dictation. Diagram: four steps from configure SukiAuthManager, create DictationClient, open dictation, to close dictation. Create and configure [SukiAuthManager](/dictation-sdk/guides/authentication#use-sukiauthmanager-for-authentication) with your partner credentials. Sign-in may run when you initialize, depending on your settings. Create [DictationClient](/dictation-sdk/javaScript-integration/javaScript), or use the React provider and component, tied to that auth. When the user should dictate, **open** dictation (in-field or scratchpad). A session is active while they work. When they finish or you no longer need dictation, **close** it. In React, unmounting the dictation UI usually closes the session for you. For full implementation details for these APIs, refer to [JavaScript integration](../javaScript-integration/javaScript) for JavaScript, and [React integration](../react-integration/react) for React. ## Next steps Refer to the [Callbacks guide](/dictation-sdk/guides/callbacks) for more details on how to use the callbacks. # Dictation SDK Authentication Source: https://developer.suki.ai/dictation-sdk/guides/authentication Sign in to Suki before dictation opens: use SukiAuthManager with the partner ID and token Suki gives you The Dictation SDK uses a helper called **`SukiAuthManager`** from the **`@suki-sdk/core`** package. You give it the **partner ID** and **partner token** Suki assigned to your app. You create this helper **once**, then hand it to **`DictationClient`** in JavaScript or to **`DictationProvider`** in React. After sign-in works, Suki can show the dictation experience (the screen users talk to) inside your page. The helper also renews access when it expires. If the ID or token is wrong, or sign-in never finishes, that dictation screen will not appear. ## Prerequisites Before you set up **`SukiAuthManager`**, you must have: * **Partner ID** (the **`partnerId`** value): Suki gives you this when you complete [Partner onboarding](/documentation/partner-onboarding). * **Partner token** (the **`partnerToken`** value): The access value your program uses for this SDK. Your Suki contact explains how you get it and what it looks like. ## Use SukiAuthManager for authentication Create the helper when your app already knows **`partnerId`** and **`partnerToken`** by running the following code: ```javascript JavaScript expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import { SukiAuthManager } from "@suki-sdk/core"; const authManager = new SukiAuthManager({ partnerId: "YOUR_PARTNER_ID", // required partnerToken: "YOUR_PARTNER_TOKEN", // required environment: "staging", // optional: "staging" or "production" (default "production") loginOnInitialize: true, // optional (default false) autoRegister: false, // optional (default false); when true, provider fields below are often required providerId: "YOUR_PROVIDER_ID", // optional; provider identifier in your system providerName: "YOUR_PROVIDER_NAME", // optional; full name, often required if autoRegister is true providerOrgId: "YOUR_PROVIDER_ORG_ID", // optional; org in your system, often required if autoRegister is true providerSpecialty: "FAMILY_MEDICINE", // optional; often required if autoRegister is true }); ``` For values you can pass as **`providerSpecialty`**, see [Specialties](/documentation/specialties). ## What SukiAuthManager does * **Checks** your settings before dictation tries to open. * **Signs in** to Suki's platform with your partner details. * **Renews access** when the SDK needs a fresh session. * **Lets** Suki's hosted dictation UI run with the right permissions. A bad **`partnerId`** or **`partnerToken`** stops dictation from loading. Users will not see the dictation UI until sign-in succeeds. Refer to [AuthConfig](/dictation-sdk/guides/configuration#authconfig) section in [Configuration](/dictation-sdk/guides/configuration) guide for more details on the available options and how to use them. If **`autoRegister`** is on, you may need extra **provider metadata**. Check your package README or ask your Suki contact. ## Sign in later instead of on create You can create **`SukiAuthManager`** first and call **`login()`** when your app is ready, instead of **`loginOnInitialize: true`**. Use whatever pattern your installed SDK version supports. ## Next steps Refer to [Quickstart](/dictation-sdk/quickstart) guide to get started with the Dictation SDK. # Callbacks Source: https://developer.suki.ai/dictation-sdk/guides/callbacks Learn about Callback contract payload shape, and JavaScript vs React usage for onSubmit, onCancel, and onDraft in the Dictation SDK
Quick summary
The Suki Dictation SDK supports three callbacks: `onSubmit`, `onCancel`, and `onDraft`. These callbacks are called when the user commits, cancels, or drafts the dictation respectively. You can use these callbacks to handle the dictation result, cancel the session, or receive intermediate updates while the user is dictating.
Last updated: June 2026
**Callbacks** allow your application to run your own code when the user commits, cancels, or moves on without committing during dictation. You supply functions; the Suki Dictation SDK calls them when those events occur. You do **not** poll on a timer or in a loop for new text. **Registering callbacks** When you start a session, register them in **JavaScript** as properties on the object you pass to `DictationClient.show()`, or in **React** as props on ``. **Callback execution** It calls **`onSubmit`** after the user commits, and **`onCancel`** if they leave without committing. If you supply **`onDraft`**, the SDK may call it when the user does **not** submit and switches to another field (or otherwise moves on without committing). **`onDraft`** is **not** invoked on every live transcript change while dictation stays on one field. The SDK does **not** persist draft text to your systems; only your **`onDraft`** handler decides whether to store or send it to your partner backend. **Payload** Every callback receives the same argument: one object, `{ fieldId, text }`. The `fieldId` value is whatever you passed into `show()` or ``. A common pattern is to set it to the **same value as the target control's `id`**, so `onSubmit` can use `document.getElementById(fieldId)` and write `text` into that element. ## Supported callbacks Dictation SDK supports the following callbacks: Runs when the user commits the dictation result. **Optional**: Runs when the user discards the session without committing. **Optional**. May run when the user leaves dictation **without** submitting and switches context (for example, to another field). Use it if you want to capture unstaged transcript text; the SDK does not save or forward it unless you do. **Mode** controls how dictation is shown. Set it to **`in-field`** when the UI is tied to a container on your page, or **`scratchpad`** for a standalone surface. Refer to [In-field mode](/dictation-sdk/guides/in-field-mode) and [Scratchpad mode](/dictation-sdk/guides/scratchpad-mode) guides for behavior and layout. For every other option you pass to `DictationClient.show()` or to `` as props, including **`rootElement`**, **`initialText`**, and these callbacks, use the [Configuration](/dictation-sdk/guides/configuration) reference. ## Callback contract payload shape All callbacks receive a **single** argument: an object with these fields: This is the string you invent to name this dictation session. The SDK includes it in every callback so you know which field the `text` is for. Using the same text as your input’s `id` (for example `clinical-notes`) is a simple way to tie them together. The transcript string for this callback (committed result, state at cancel, or interim draft, depending on which handler ran). **Example:** ```javascript JavaScript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} // After the user commits, your onSubmit might receive: { fieldId: "clinical-notes", text: "The user said hello.", } ``` For structured notes, use **stable**, **unique** ids per section, for example **`soap.subjective`**, **`soap.objective`**, **`soap.assessment`**, **`soap.plan`**, or **`scratchpad`** for a floating session. See [Field IDs](/dictation-sdk/guides/configuration#field-ids-in-practice). If **`onSubmit`** is missing, dictation often **closes immediately** after the user acts. Always implement `onSubmit`. ## Code examples Use callbacks as properties on the object you pass to **`await dictationClient.show({ ... })`**. They sit alongside `mode`, `fieldId`, `rootElement`, `initialText`, and other options from [Configuration](/dictation-sdk/guides/configuration). The iframe **resizes to the container** you pass as `rootElement` when you use `in-field` mode. ```javascript JavaScript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import { SukiAuthManager } from "@suki-sdk/core"; import { DictationClient } from "@suki-sdk/dictation"; const authManager = new SukiAuthManager({ partnerId: "YOUR_PARTNER_ID", // Required partnerToken: "YOUR_PARTNER_TOKEN", // Required environment: "staging", // Optional loginOnInitialize: true, autoRegister: false, // Optional - default is false providerId: "YOUR_PROVIDER_ID", // Optional - required if autoRegister is true providerName: "YOUR_PROVIDER_NAME", // Optional - required if autoRegister is true providerOrgId: "YOUR_PROVIDER_ORG_ID", // Optional - required if autoRegister is true providerSpecialty: "YOUR_PROVIDER_SPECIALTY", // Optional - required if autoRegister is true }); const dictationClient = new DictationClient({ authManager }); // Example markup for in-field: //
// await dictationClient.show({ mode: "in-field", fieldId: "clinical-notes", // same string as id="clinical-notes" on your textarea rootElement: document.getElementById("clinical-notes-dictation-root"), initialText: document.getElementById("clinical-notes")?.value ?? "", onSubmit: ({ fieldId, text }) => { const el = document.getElementById(fieldId); if (el) el.value = text; }, onCancel: ({ fieldId, text }) => { // Optional: user cancelled without committing }, onDraft: ({ fieldId, text }) => { // Optional: e.g. user switched fields without submit; persist draft in your app if needed }, }); ``` Calling **`show()`** again **replaces** the active session; you do not need to call **`hide()`** between fields for that pattern. Wrap `show()` in `try` / `catch` if you want to log configuration or auth failures. Refer to the [Error handling](/dictation-sdk/guides/error-handling) guide for more details. For more on imperative `show()` and one client per page scope, refer to the [JavaScript integration](/dictation-sdk/javaScript-integration/javaScript) guide for more details.
Pass the same three handlers as **props** on **``**. Build **`DictationClient`** once (with `SukiAuthManager`), wrap your tree with **``**, then render `Dictation` where dictation should be active. When `Dictation` **unmounts**, the SDK calls **`hide()`** for you. ```jsx React theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import { useMemo, useState } from "react"; import { SukiAuthManager } from "@suki-sdk/core"; import { DictationClient } from "@suki-sdk/dictation"; import { DictationProvider, Dictation } from "@suki-sdk/dictation-react"; function NotesApp() { const client = useMemo(() => { const authManager = new SukiAuthManager({ partnerId: "YOUR_PARTNER_ID", // Required partnerToken: "YOUR_PARTNER_TOKEN", // Required environment: "staging", // Optional loginOnInitialize: true, autoRegister: false, // Optional - default is false providerId: "YOUR_PROVIDER_ID", // Optional - required if autoRegister is true providerName: "YOUR_PROVIDER_NAME", // Optional - required if autoRegister is true providerOrgId: "YOUR_PROVIDER_ORG_ID", // Optional - required if autoRegister is true providerSpecialty: "YOUR_PROVIDER_SPECIALTY", // Optional - required if autoRegister is true }); return new DictationClient({ authManager }); }, []); const [notes, setNotes] = useState(""); // Drive from your UI: e.g. setActiveField("clinical-notes") when this field owns dictation. const [activeField, setActiveField] = useState(null); const handleSubmit = ({ fieldId, text }) => { // fieldId matches id="clinical-notes" below if you use that pattern setNotes(text); }; const handleCancel = ({ fieldId, text }) => { // Optional }; const handleDraft = ({ fieldId, text }) => { // Optional: e.g. save unstaged text when user leaves without submit }; return (
``` ```css theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} .wrapper { position: relative; height: 100%; } ``` For mode usage, you should use the `in-field` mode when dictation is tied to a specific text field or editor, and the `scratchpad` mode when dictation is not tied to a specific text field or editor. ```javascript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} mode: "in-field", ``` ```javascript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} mode: "scratchpad", ``` ## Next steps Refer to the [Error handling](/dictation-sdk/guides/error-handling) guide for more details on common issues and how to troubleshoot them. # Dictation SDK Error Handling Source: https://developer.suki.ai/dictation-sdk/guides/error-handling Learn to fix common Dictation SDK issues: auth, CSP, layout, missing callbacks, and client-only runtime requirements The Dictation SDK does not return one consistent error code for every problem. Instead, several systems have to work together: the **Suki platform** handles **authentication**, the hosted UI runs inside an **iframe**, and your app passes **`rootElement`** and **callbacks**. When one piece is wrong, you often only see a vague symptom, such as **no UI**, **dictation closing immediately**, or **broken layout**. Work through this page in this order: **runtime** (browser and timing), **layout** (**`rootElement`** and CSS), **auth and CSP**, then **configuration and callbacks**. That order usually finds the cause fastest. For every field on **`AuthConfig`** and **`ShowOptions`**, use [Configuration](/dictation-sdk/guides/configuration). The **wrapper** pattern for **`rootElement`** (stable height, **`position: relative`**) is documented on [Configuration guide wrapper layout](/dictation-sdk/guides/configuration#wrapper-layout). Refer to that page if you are not sure how to structure your DOM. ## Runtime requirements The Dictation SDK is built for **in-browser** embedding. It is **not** a Node-only or server-rendered iframe product. Browser environments where you can create an `HTMLIFrameElement`, use `postMessage`, and measure a DOM container Using Node.js as the environment that hosts `DictationClient` or the dictation iframe Relying on **SSR** alone to render dictation; initialize and call `show()` on the client after the document (and your `rootElement`) exist * A real `HTMLIFrameElement` (the SDK creates and manages it inside your container) * `postMessage` between your page and the hosted UI * Layout information so the iframe can size to `rootElement` Dictation runs in the **browser** only. The iframe is not created during **SSR** or on the server. Call **`show()`** only after **`rootElement`** points at an element that **already exists** in the DOM and has been laid out (so it has a real size). If you call too early, **`rootElement`** may be **`null`** or zero height. * [React integration](/dictation-sdk/react-integration/react) for **`DictationProvider`** and **`Dictation`** * [Configuration examples](/dictation-sdk/guides/examples/configuration-examples) for sample **`rootElement`** wiring ## Layout and root element related issues The iframe **fills the layout box** of the element you pass as **`rootElement`**. Common mistakes are as follows: * A **zero-height** parent * A flex or grid child that **shrinks to zero** * **`overflow: hidden`** on a parent that clips the overlay ### Recommended approach * Use a dedicated **wrapper** around the dictation region, not the raw **` ``` The wrapper and textarea can be structured however your layout needs; the important part is that **`rootElement`** points at the **element that should host the iframe**, not at the textarea node. | Do this | So that | | :------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | Give the host element a **visible height and width** | The iframe fills its parent. A parent with no height often produces a blank area where dictation should be. | | Set **`position: relative`** on the host when you use overlays or stacking | The dictation layer stays aligned with the field region in typical layouts. | Refer to [Configuration](/dictation-sdk/guides/configuration) for every `ShowOptions` field and matching React props. ### Field ID `fieldId` is a **string you invent** to name this dictation session. Every callback sends it back with `text`, so you know **which field** the result belongs to if you have several on the page. It does not have to match a DOM `id`, but using the same value as your input's `id` is a simple pattern. Each open dictation instance should use a **stable**, **unique** `fieldId`. Examples for SOAP-style sections: **`soap.subjective`**, **`soap.objective`**, **`soap.assessment`**, **`soap.plan`**. Refer to [Callback contract payload shape](/dictation-sdk/guides/callbacks#callback-contract-payload-shape) for more details. ## How to use in-field mode **You** build how users **start** dictation: a **Dictation** button, a link, an icon, or any control that calls `show()` or mounts ``. After they start, **Suki** draws the dictation UI inside the iframe: **microphone**, **submit**, **cancel**, and the rest. You do not rebuild those controls yourself. You receive text and events through **`onSubmit`**, **`onCancel`**, and optionally **`onDraft`**. ## Quick reference | Item | In-field behavior | | :--------------- | :------------------------------------------------------------------------ | | **Layout** | Dictation sits over the **input container** you target with `rootElement` | | **Mode** | `"in-field"` | | **Root element** | Recommended: element that wraps the field | ## Next steps Refer to [Scratchpad mode](/dictation-sdk/guides/scratchpad-mode) for floating dictation off a single field. # Scratchpad Mode Source: https://developer.suki.ai/dictation-sdk/guides/scratchpad-mode Learn about when to use scratchpad mode for the Suki Dictation SDK and how to configure it
Quick summary
Scratchpad mode opens dictation in a floating surface that is not tied to a single text field. You choose how users open it, and you still receive committed (and optional draft) text through callbacks.
Last updated: May 2026
**Scratchpad mode** allows you to run the Suki Dictation SDK in a standalone area of your web application. Dictation does not attach to one specific input the way [In-field mode](/dictation-sdk/guides/in-field-mode) does. **Launching dictation** The entry point is entirely part of your UI. You can use a toolbar action, header button, floating launcher, menu item, keyboard shortcut, or any pattern you prefer. To launch scratchpad dictation, your code must call `show()` with **mode: "scratchpad"** in **JavaScript** or mount the **Dictation** component in **React** with **mode: "scratchpad"**. **Managing the dictation interface** Once the session is open, the Suki Dictation SDK provides the dictation surface. This includes the **microphone**, **Close**, **copy-to-clipboard**, and related controls. The interface appears as a hosted iframe in the layout you configure. Keep the following requirements in mind to ensure the interface displays correctly: * **Layout**: You control where the scratchpad appears (for example, a floating panel anchored to a launcher). * **Mode**: You must pass **scratchpad** in `show()` or on `` so the SDK uses the floating surface. * **Data handling**: You receive transcript text through defined callbacks. The diagram below is a **clinical-style form** (for example, SOAP note sections) with a **floating Open dictation** launcher in the corner. After the user opens it, the **scratchpad** appears **above** that launcher as a tall panel on the right, with the transcript area and **Mic**, **Close**, and **Copy**. You can place the launcher anywhere in your application that fits your design. Your real layout might use a portal, column, or different spacing. These screens are only examples.
New SOAP Note interface with Subjective, Objective, and Assessment sections and a patient sidebar; floating Suki Dictate button in the bottom-right corner with an arrow and label reading Floating Scratchpad for dictation.
## When to choose scratchpad mode Use **scratchpad mode** when: * Dictation should live in its **own** area (side panel, overlay region, or similar), not overlaid on one field’s container. * Users need to **capture speech first** and then paste or apply text elsewhere, or you want **quick dictation** without binding the session to a single `textarea`. When dictation should stay tied to **one** text field and your **Dictate** control sits with that field, use [In-field mode](/dictation-sdk/guides/in-field-mode) instead. ## How to configure scratchpad mode For scratchpad dictation you set **`mode`**, **`fieldId`**, and usually consider **`rootElement`** (and other [`ShowOptions`](/dictation-sdk/guides/configuration)) so the SDK knows **which layout to use**, **where the iframe mounts**, and **how to label the session** in callbacks. ### Mode Set `mode` to the string **`"scratchpad"`** so the SDK uses the **floating standalone** dictation UI instead of in-field overlay. * **JavaScript:** include `mode: "scratchpad"` in the object you pass to `DictationClient.show()`. * **React:** set `mode="scratchpad"` on ``. ```javascript Mode configuration theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} mode: "scratchpad", ``` ### Root element For scratchpad, **`rootElement`** is still the DOM node where the SDK **mounts** the dictation iframe. It is usually a **dedicated region** of your layout (panel, column, or modal body), **not** a wrapper around a single clinical line item. The hosted UI still **measures the same layout box** as in-field mode: **`rootElement`** should be an element with **real width and height** so the floating surface has room to render. If the host **collapses** (for example **zero height** in a flex or grid row, a hidden parent, or no **`min-height`**), you will usually see a **blank** or **clipped** area even though scratchpad is “floating.” When the scratchpad region **sits on top of** or **beside** other UI, set **`position: relative`** on that host (unless you already have another positioning context) so stacking and alignment stay predictable. For wrapper sizing patterns and CSS, refer to [Wrapper layout best practices](/dictation-sdk/guides/configuration#wrapper-layout) on [Configuration](/dictation-sdk/guides/configuration). ### Field ID **`fieldId`** is a **string you invent** to name this scratchpad session. Every callback sends it back with `text`, which helps if you run **multiple** scratchpads or mix scratchpad with in-field flows. It does not have to match a DOM `id`. Use a **stable**, **unique** id per scratchpad instance; a common choice is **`scratchpad`**, or a namespaced value such as **`scratchpad.draft`** if you run more than one. ## How to use scratchpad mode **You** build how users **open** scratchpad dictation. After they start, **Suki** draws the dictation UI in the iframe: **microphone**, **close**, **copy**, and the rest. You do not recreate those controls yourself. You receive text and events through **`onSubmit`**, **`onCancel`**, and optionally **`onDraft`**. ## Quick reference | Item | Scratchpad behavior | | :--------------- | :-------------------------------------------------------------------- | | **Layout** | **Floating** standalone dictation UI, not tied to one input container | | **Mode** | `"scratchpad"` | | **Root element** | Host region for the iframe | ## Next steps Refer to [In-field mode](/dictation-sdk/guides/in-field-mode) when dictation should attach to a specific field. Read [Callbacks](/dictation-sdk/guides/callbacks) for handlers and payload shape, and the [Configuration](/dictation-sdk/guides/configuration) reference for all options. # Dictation SDK Installation Source: https://developer.suki.ai/dictation-sdk/installation Install Suki Dictation SDK in your JavaScript or React application We have modularized the Suki Dictation SDK into **framework-specific packages** plus shared **`@suki-sdk/core`** for **`SukiAuthManager`**, so you install **`core`** in every setup and add either **`@suki-sdk/dictation`** or **`@suki-sdk/dictation-react`** depending on your environment. The Dictation SDK is built for browser applications and requires **`HTMLIFrameElement`** and **`postMessage`** (refer to [Prerequisites](/dictation-sdk/prerequisites) guide for more details). ## Prerequisites For the rest of this documentation, we will assume you have completed the [Partner onboarding](/documentation/partner-onboarding) process. Refer to the [Prerequisites](/dictation-sdk/prerequisites) guide for more information. ## Install the package ### For vanilla JavaScript Use **`@suki-sdk/dictation`** with **`@suki-sdk/core`** for plain JavaScript or frameworks other than React. To install the packages, run one of the following commands: ```shell pnpm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} pnpm add @suki-sdk/core @suki-sdk/dictation ``` ```shell npm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} npm install @suki-sdk/core @suki-sdk/dictation ``` ```shell yarn theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} yarn add @suki-sdk/core @suki-sdk/dictation ``` ### For React For React applications, use **`@suki-sdk/dictation-react`** with **`@suki-sdk/core`**. It includes **`DictationProvider`** and **`Dictation`** so you can wire dictation declaratively. To install the packages, run one of the following commands: ```shell pnpm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} pnpm add @suki-sdk/core @suki-sdk/dictation-react @suki-sdk/dictation ``` ```shell npm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} npm install @suki-sdk/core @suki-sdk/dictation-react @suki-sdk/dictation ``` ```shell yarn theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} yarn add @suki-sdk/core @suki-sdk/dictation-react @suki-sdk/dictation ``` ## Next steps Read the [Authentication](/dictation-sdk/guides/authentication) guide to learn how to authenticate yourself to use the Dictation SDK. # Dictation SDK Overview Source: https://developer.suki.ai/dictation-sdk/introduction Overview of the Suki Dictation SDK and how it works The Suki Dictation SDK is a JavaScript and React library for dictation in the browser. Use Dictation SDK to add speech-to-text capabilities to your web application. If you use our **Headed Web SDK** `v3.X.X+`, you can use audio dictation capabilities out of the box. Refer to the [Web SDK for audio dictation](/web-sdk/dictation-overview) guide for more details. You can implement the Suki Dictation SDK in two modes: **In-field** and **Scratchpad**. Use this mode for dictation over a target field. Commonly used for notes and forms. Use this mode for a floating dictation panel, not tied to one input. Commonly used for dictation in a separate area of the page. When the user starts the dictation session: 1. Recording begins automatically 2. Transcription appears inside the text field and the scratchpad UI 3. When the user finishes dictation and confirms, the SDK calls the handler functions you registered and passes the final transcript into your app so you can update fields, save data, or run your own logic The Dictation SDK is different from integrating directly with the [Dictation APIs](/api-reference/audio-transcription/create-session). The SDK manages authentication through `SukiAuthManager`, iframe lifecycle, and transcript callbacks for you. If you need a custom or server-side integration without the hosted iframe experience, use the APIs described in [Dictation basic usage](/documentation/dictation-basic-usage). ## Supported packages The Dictation SDK is available in the following packages: Use `@suki-sdk/dictation-react` for React web applications. Install the Dictation SDK for React:
Use `@suki-sdk/dictation` for vanilla JavaScript applications. Install the Dictation SDK for JavaScript:
Both require shared authentication through **`@suki-sdk/core`** (Refer to the [Dictation SDK Quickstart](/dictation-sdk/quickstart) for more information). ## When to use Dictation SDK Choose the Dictation SDK when: * You want **real-time speech-to-text** in the browser with Suki's hosted iframe experience * You need **in-field** overlays on inputs or a **scratchpad** workflow for dictation mechanics * You prefer **callback-driven** commit of the transcription result over owning REST and WebSocket dictation calls yourself ## Recommended integration pattern Follow the below pattern to integrate the Dictation SDK into your application: ```mermaid actions={false} theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#FFE148','primaryTextColor':'#111827','lineColor':'#6B7280','fontSize':'14px','edgeLabelBackground':'#FFFFFF','tertiaryColor':'#F9FAFB','tertiaryTextColor':'#111827','tertiaryBorderColor':'#D1D5DB'}}}%% graph TB SM["SukiAuthManager
@suki-sdk/core
Once, after partner token is available"] DC["DictationClient
new DictationClient({ authManager })
One instance per page · reuse for every target"] DP["DictationProvider
@suki-sdk/dictation-react
React only · wrap your tree"] F1["In-field · field A
show() or Dictation when this field is active"] F2["In-field · field B
Same pattern · switch active field"] SP["Scratchpad
mode: scratchpad · still one client"] SM -->|auth| DC DC -.->|optional · pass same client| DP DC --> F1 DC --> F2 DC --> SP ``` ## How it works The following diagram illustrates the Dictation SDK architecture and workflow: ```mermaid actions={false} theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#FFE148','primaryTextColor':'#111827','lineColor':'#6B7280','fontSize':'14px','edgeLabelBackground':'#FFFFFF','tertiaryColor':'#F9FAFB','tertiaryTextColor':'#111827','tertiaryBorderColor':'#D1D5DB'}}}%% graph TB subgraph client["Your web application"] direction TB A["Application code
React / JavaScript / Other frameworks"] B["Dictation SDK
@suki-sdk/dictation or dictation-react + core"] C["Your layout + callbacks
Container • onSubmit • optional onDraft"] A --> B B --> C end subgraph platform["Suki"] direction TB D["Authentication
SukiAuthManager"] E["Dictation iframe
Speech UI + transcription"] end B -->|Authenticate / tokens| D B -->|Hosted dictation session| E E -->|Transcript / draft to your app| C style client fill:#FFFADE,stroke:#D1D5DB,stroke-width:2px,color:#111827 style platform fill:#FFF394,stroke:#FFE148,stroke-width:2px,color:#111827 style A fill:#ffffff,stroke:#9CA3AF,stroke-width:2px,color:#111827 style B fill:#FFE148,stroke:#111827,stroke-width:3px,color:#111827 style C fill:#ffffff,stroke:#9CA3AF,stroke-width:2px,color:#111827 style D fill:#ffffff,stroke:#9CA3AF,stroke-width:2px,color:#111827 style E fill:#ffffff,stroke:#9CA3AF,stroke-width:2px,color:#111827 ``` ### Architecture workflow * **You** choose when dictation should open and where it should appear on the page (for example over one input, or as a separate floating area). * **Your code** starts dictation and listens for results from the SDK. When the user finishes, you receive the final text. * **Your UI** decides what to do with that text (fill a field, save a draft, discard, and so on). * **Sign-in:** Suki checks your configuration, signs in with the partner account details you provide, keeps access fresh, and hands the hosted dictation experience what it needs to run securely. * **Hosted dictation:** The microphone experience and transcription run in an embedded view that Suki hosts. That way the dictation screen looks and behaves the same in every app, and it does not inherit your site’s fonts, colors, or layout. 1. Set up sign-in once using the partner details Suki gives you. 2. Add the dictation SDK to your app and connect it to that sign-in. 3. When the user asks to dictate, open dictation in the place you picked (over a field or as a scratchpad-style area). 4. The user speaks and confirms. Your app receives the text so you can put it where it belongs in your workflow. 5. When dictation should stop, close it from your app so the session ends. Refer to the [Architecture guide](/dictation-sdk/guides/architecture) for more details. ## Next steps Get started by following these steps: Refer to the [Installation guide](/dictation-sdk/installation) to add the packages to your project Refer to the [Prerequisites](/dictation-sdk/prerequisites) guide to confirm browser, CSP, and layout requirements Refer to the [Quickstart](/dictation-sdk/quickstart) for JavaScript and React examples through your first `show()` call # Dictation SDK JavaScript Integration Source: https://developer.suki.ai/dictation-sdk/javaScript-integration/javaScript Learn how to integrate the Dictation SDK in a JavaScript application (browser-based) using the JavaScript package provided by Suki This guide walks you through the process of integrating the Dictation SDK in a JavaScript application (browser-based) using the JavaScript package provided by Suki. You will create **Auth Manager** and **Dictation Client**, then start dictation by calling **`await dictationClient.show({ ... })`** from your own code when the user is ready. Let's get started! ## Prerequisites Before you begin, you must have the following requirements met: * **Packages:** Install `@suki-sdk/dictation` and `@suki-sdk/core` packages. * **Partner credentials:** Obtain `partnerId` and `partnerToken` from Suki after [Partner onboarding](/documentation/partner-onboarding). * **Browser and layout:** Your app runs in a **browser**, with a real DOM and a dictation **container** that has height. Refer to [Prerequisites](/dictation-sdk/prerequisites) guide for more details. ## Install the packages Add both packages to the same project you load in the browser: ```shell pnpm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} pnpm add @suki-sdk/core @suki-sdk/dictation ``` ```shell npm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} npm install @suki-sdk/core @suki-sdk/dictation ``` ```shell yarn theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} yarn add @suki-sdk/core @suki-sdk/dictation ``` After you install, pull the SDK into your files with **`import`**, the same way as in the examples below. Use whatever approach your project already uses for other npm libraries. ## Step 1: Add container and field HTML For this example we will assume you are using **`in-field`** mode as your preferred mode. In **`in-field`** mode you need **two** nodes in the page: a **`div`** (or similar) that you pass as **`rootElement`**, where the dictation controls show up, and a **textarea** (or input) that **`onSubmit`** will update when the user finishes. The dictation layer **matches the size of** **`rootElement`**, so that node should have a **height** you control. Refer to [Wrapper layout](/dictation-sdk/guides/configuration#wrapper-layout) guide for recommended markup and CSS. ```html HTML theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}
``` ## Step 2: Create auth manager Now you need to create the **Auth Manager** for your application. In order to create the Auth Manager, you must have the `partnerId` and `partnerToken` credentials from Suki. Refer to [Partner onboarding](/documentation/partner-onboarding) guide to learn how to get these credentials. Once you have all the required credentials, create **one** auth manager for the page (or app shell). **Code example for creating auth manager** ```js JavaScript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import { SukiAuthManager } from "@suki-sdk/core"; 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: "staging" | "production" loginOnInitialize: true, // optional: sign in as soon as this runs autoRegister: false, // optional: enable provider auto-registration providerId: "YOUR_PROVIDER_ID", // optional: provider identifier in your system providerName: "YOUR_PROVIDER_NAME", // optional: full provider display name providerOrgId: "YOUR_PROVIDER_ORG_ID", // optional: organization identifier for the provider in your system providerSpecialty: "YOUR_PROVIDER_SPECIALTY", // optional: clinical specialty }); ``` ## Step 3: Create dictation client After you have created the auth manager, you can create the **dictation client** for your application. The Dictation Client is the object that will be used to start the dictation session. Create **one** dictation client and reuse it for every **`show()`** call on that page. **Code example for creating dictation client** ```js JavaScript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import { DictationClient } from "@suki-sdk/dictation"; const dictationClient = new DictationClient({ authManager }); ``` ## Step 4: Call show() to start dictation Now you can start the dictation session by calling the **`show()`** method on the dictation client. Call **`await dictationClient.show({ ... })`** from a click handler (or similar) when the DOM is ready. Pass **`mode`**, **`fieldId`**, **`rootElement`**, **`onSubmit`**, and any optional fields you need. Refer to [Configuration](/dictation-sdk/guides/configuration) guide for more details on the available options and how to use them. **Code example for starting dictation** ```javascript JavaScript expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} async function startDictation() { const root = document.getElementById("dictation-root"); const notes = document.getElementById("clinical-notes"); if (!root || !notes) { console.error("Missing dictation-root or clinical-notes in the DOM"); return; } try { await dictationClient.show({ mode: "in-field", // replace with your preferred mode - required fieldId: "clinical-notes", // often the same string as the textarea id rootElement: root, // replace with the DOM element where the dictation controls will be shown - required initialText: notes.value ?? "", // replace with the initial text for the dictation session - optional onSubmit: ({ fieldId, text }) => { const el = document.getElementById(fieldId); if (el) el.value = text; }, onCancel: ({ fieldId }) => { console.log("Dictation cancelled", fieldId); }, onDraft: ({ fieldId, text }) => { const el = document.getElementById(fieldId); if (el) el.value = text; // optional live preview while dictating }, }); } catch (err) { console.error("Dictation show() failed", err); } } document.getElementById("start-dictation")?.addEventListener("click", () => { void startDictation(); }); ``` **`onSubmit`** is required for a good user experience. If you omit it, dictation often **closes immediately** after the user acts. ## Callbacks Every callback receives the same shape as shown in the code example below: ```javascript JavaScript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { fieldId: string, text: string } ``` Refer to [Callbacks](/dictation-sdk/guides/callbacks) guide for more details on the available callbacks and how to use them. ## Switching fields Calling **`show()`** again **replaces** the active session. You do **not** need to call **`hide()`** manually just to move from one field to another: ```js JavaScript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} await dictationClient.show({ /* field A options */ }); await dictationClient.show({ /* field B options */ }); ``` ## Complete code example Below is a complete code example in JavaScript for in-field mode with a single field. ```js JavaScript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import { SukiAuthManager } from "@suki-sdk/core"; import { DictationClient } from "@suki-sdk/dictation"; 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: "staging" | "production" loginOnInitialize: true, // optional: sign in as soon as this runs autoRegister: false, // optional: enable provider auto-registration providerId: "YOUR_PROVIDER_ID", // optional: provider identifier in your system providerName: "YOUR_PROVIDER_NAME", // optional: full provider display name providerOrgId: "YOUR_PROVIDER_ORG_ID", // optional: organization identifier for the provider in your system providerSpecialty: "YOUR_PROVIDER_SPECIALTY", // optional: clinical specialty }); const dictationClient = new DictationClient({ authManager }); async function startClinicalNotesDictation() { const root = document.getElementById("dictation-root"); const notes = document.getElementById("clinical-notes"); if (!root || !notes) return; try { await dictationClient.show({ mode: "in-field", fieldId: "clinical-notes", rootElement: root, initialText: notes.value ?? "", onSubmit: ({ fieldId, text }) => { const el = document.getElementById(fieldId); if (el) el.value = text; }, onCancel: ({ fieldId }) => { console.log("Cancelled", fieldId); }, }); } catch (e) { console.error(e); } } document.addEventListener("DOMContentLoaded", () => { document .getElementById("start-dictation") ?.addEventListener("click", () => void startClinicalNotesDictation()); }); ``` This page focuses on **`in-field`** dictation next to a specific input. If you want a **floating dictation panel** instead, set **`mode`** to **`"scratchpad"`** and follow [Scratchpad mode](/dictation-sdk/guides/scratchpad-mode) guide. ## Best practices * **Reuse one dictation client.** Build a single **DictationClient** for the page or shell and call it again for each dictation session. Creating a new client on every click or for every field often resets the hosted UI and feels flaky. * **Reuse one auth manager.** Create **SukiAuthManager** once and pass that same instance into the client, the same pattern as in the steps above. * **Handle when the user commits.** You must supply a submit handler so the SDK can deliver the final text. Without it, dictation often closes right after the user tries to finish. * **Pick a clear field label.** Each session needs a stable, unique **fieldId** in callbacks. Using the same value as the target input's **id** is a simple way to know which element to update. Refer to [Field IDs](/dictation-sdk/guides/configuration#field-ids-in-practice) guide for more details. * **Open dictation only when the host is ready.** The DOM node you use as the dictation host should exist and have real height before you open. Otherwise the dictation area can look blank. Refer to [Error handling](/dictation-sdk/guides/error-handling) and [In-field mode](/dictation-sdk/guides/in-field-mode) guides for more details. * **Catch failures when opening dictation.** Wrap the open call so auth or setup errors show up in your logs instead of disappearing. * **Move to another field by opening again.** A new open call replaces the active session. You usually do not need a separate hide step when you are only switching which field is dictating. ## Next steps Refer to the following guides for more information. [Configuration](/dictation-sdk/guides/configuration) to learn about the available options and how to use them. [React integration](/dictation-sdk/react-integration/react) to learn how to integrate the Dictation SDK with React. # Dictation SDK Prerequisites Source: https://developer.suki.ai/dictation-sdk/prerequisites Browser, layout, authentication, and partner setup required before you integrate the Suki Dictation SDK This guide outlines technical requirements you need to meet before you integrate the Dictation SDK. ## Technical requirements The following is required before you integrate the Dictation SDK: ### Browser and runtime * Your app runs in a **browser**. Dictation SDK does not support **Node.js** or **SSR** for iframe rendering. * The hosted dictation iframe is not something **SSR** alone covers; you still need **`HTMLIFrameElement`**, **`postMessage`**, and **DOM layout** on the client so the SDK can mount and size the iframe. ### Layout * Give dictation a **container** (**`rootElement`**) with **real height** and a stable layout box. ### Authentication requirements * The Dictation SDK needs `partnerId` and `partnerToken`. Refer to [Partner onboarding](/documentation/partner-onboarding) guide to learn how to get these credentials. Invalid credentials **block iframe initialization** . ## Information you will receive from Suki After you complete [Partner onboarding](/documentation/partner-onboarding), your Suki contact will provide you with `partnerId` and `partnerToken`. ## Next steps Refer to [Quickstart](/dictation-sdk/quickstart) guide to get started with the Dictation SDK. # Dictation SDK Quickstart Source: https://developer.suki.ai/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 partner token 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. **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). 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). ## 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. Initialize **once per session** and reuse: Create **`SukiAuthManager`** from **`@suki-sdk/core`** after the **partner token** is available. Create **`DictationClient`** with that **`authManager`**. **Reuse** this client **across** dictation fields. In React, wrap components with **`DictationProvider`** from **`@suki-sdk/dictation-react`**. Show the dictation UI **per field** or **scratchpad**. Avoid recreating **`DictationClient`** on every render or **per field**. The **JavaScript** and **React** tabs under **Your first dictation session** below mirror this pattern: one auth manager, one client, then **`show()`** or **``** for the active target only. ## 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 ```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 ``` More detail: [Installation](/dictation-sdk/installation). ```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 ``` More detail: [Installation](/dictation-sdk/installation). ## 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"}}
``` 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`**. 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. Create **`DictationClient`** once (**`useMemo`**), wrap the tree with **`DictationProvider`**, and render **``** only when that field should own the session. Unmounting **``** 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 ( ``` ## Step 2: Create auth manager Now you need to create the **Auth Manager** for your application. In order to create the Auth Manager, you must have the `partnerId` and `partnerToken` credentials from Suki. Refer to [Partner onboarding](/documentation/partner-onboarding) guide to learn how to get these credentials. Once you have all the required credentials, create **one** auth manager for the page (or app shell). **Code example for creating auth manager** ```javascript JavaScript expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import { SukiAuthManager } from "@suki-sdk/core"; 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: "staging" | "production" loginOnInitialize: true, // optional: sign in as soon as this runs autoRegister: false, // optional: enable provider auto-registration providerId: "YOUR_PROVIDER_ID", // optional: provider identifier in your system providerName: "YOUR_PROVIDER_NAME", // optional: full provider display name providerOrgId: "YOUR_PROVIDER_ORG_ID", // optional: organization identifier for the provider in your system providerSpecialty: "YOUR_PROVIDER_SPECIALTY", // optional: clinical specialty }); ``` ## Step 3: Create dictation client After you have created the auth manager, you can create the **dictation client** for your application. The Dictation Client is the object that will be used to start the dictation session. Create **one** dictation client and reuse it for every **`show()`** call on that page. **Code example for creating dictation client** ```javascript JavaScript expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import { DictationClient } from "@suki-sdk/js"; const dictationClient = new DictationClient({ authManager }); ``` ## Step 4: Call show() to start dictation Now you can start the dictation session by calling the **`show()`** method on the dictation client. Call **`await dictationClient.show({ ... })`** from a click handler (or similar) when the DOM is ready. Pass **`mode`**, **`fieldId`**, **`rootElement`**, **`onSubmit`**, and any optional fields you need. Refer to [Configuration](/dictation-sdk/guides/configuration) guide for more details on the available options and how to use them. **Code example for starting dictation** ```javascript JavaScript expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} async function startDictation() { const root = document.getElementById("dictation-root"); const notes = document.getElementById("clinical-notes"); if (!root || !notes) { console.error("Missing dictation-root or clinical-notes in the DOM"); return; } try { await dictationClient.show({ mode: "in-field", // replace with your preferred mode - required fieldId: "clinical-notes", // often the same string as the textarea id rootElement: root, // replace with the DOM element where the dictation controls will be shown - required initialText: notes.value ?? "", // replace with the initial text for the dictation session - optional onSubmit: ({ fieldId, text }) => { const el = document.getElementById(fieldId); if (el) el.value = text; }, onCancel: ({ fieldId }) => { console.log("Dictation cancelled", fieldId); }, onDraft: ({ fieldId, text }) => { const el = document.getElementById(fieldId); if (el) el.value = text; }, }); } catch (err) { console.error("Dictation show() failed", err); } } document.getElementById("start-dictation")?.addEventListener("click", () => { void startDictation(); }); ``` **`onSubmit`** is required for a good user experience. If you omit it, dictation often **closes immediately** after the user acts. ## Callbacks Every callback receives the same shape as shown in the code example below: ```javascript JavaScript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} { fieldId: string, text: string } ``` Refer to [Callbacks](/dictation-sdk/guides/callbacks) guide for more details on the available callbacks and how to use them. ## Switching fields Calling **`show()`** again **replaces** the active session. You do **not** need to call **`hide()`** manually just to move from one field to another: ```javascript JavaScript theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} await dictationClient.show({ /* field A options */ }); await dictationClient.show({ /* field B options */ }); ``` ## Complete code example Below is a complete code example in JavaScript for in-field mode with a single field. ```javascript JavaScript expandable theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} import { SukiAuthManager } from "@suki-sdk/core"; import { DictationClient } from "@suki-sdk/js"; 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: "staging" | "production" loginOnInitialize: true, // optional: sign in as soon as this runs autoRegister: false, // optional: enable provider auto-registration providerId: "YOUR_PROVIDER_ID", // optional: provider identifier in your system providerName: "YOUR_PROVIDER_NAME", // optional: full provider display name providerOrgId: "YOUR_PROVIDER_ORG_ID", // optional: organization identifier for the provider in your system providerSpecialty: "YOUR_PROVIDER_SPECIALTY", // optional: clinical specialty }); const dictationClient = new DictationClient({ authManager }); async function startClinicalNotesDictation() { const root = document.getElementById("dictation-root"); const notes = document.getElementById("clinical-notes"); if (!root || !notes) return; try { await dictationClient.show({ mode: "in-field", fieldId: "clinical-notes", rootElement: root, initialText: notes.value ?? "", onSubmit: ({ fieldId, text }) => { const el = document.getElementById(fieldId); if (el) el.value = text; }, onCancel: ({ fieldId }) => { console.log("Cancelled", fieldId); }, }); } catch (e) { console.error(e); } } document.addEventListener("DOMContentLoaded", () => { document .getElementById("start-dictation") ?.addEventListener("click", () => void startClinicalNotesDictation()); }); ``` This page focuses on **`in-field`** dictation next to a specific input. If you want a **floating dictation panel** instead, set **`mode`** to **`"scratchpad"`** and follow [Scratchpad mode](/dictation-sdk/guides/scratchpad-mode) guide. ## Best practices * **Reuse one dictation client.** Build a single **DictationClient** for the page or shell and call it again for each dictation session. Creating a new client on every click or for every field often resets the hosted UI and feels flaky. * **Reuse one auth manager.** Create **SukiAuthManager** once and pass that same instance into the client, the same pattern as in the steps above. * **Handle when the user commits.** You must supply a submit handler so the SDK can deliver the final text. Without it, dictation often closes right after the user tries to finish. * **Pick a clear field label.** Each session needs a stable, unique **fieldId** in callbacks. Using the same value as the target input's **id** is a simple way to know which element to update. Refer to [Field IDs](/dictation-sdk/guides/configuration#field-ids-in-practice) guide for more details. * **Open dictation only when the host is ready.** The DOM node you use as the dictation host should exist and have real height before you open. Otherwise the dictation area can look blank. Refer to [Error handling](/dictation-sdk/guides/error-handling) and [In-field mode](/dictation-sdk/guides/in-field-mode) guides for more details. * **Catch failures when opening dictation.** Wrap the open call so auth or setup errors show up in your logs instead of disappearing. * **Move to another field by opening again.** A new open call replaces the active session. You usually do not need a separate hide step when you are only switching which field is dictating. ## Next steps Refer to the following guides for more information. [Configuration](/dictation-sdk/guides/configuration) to learn about the available options and how to use them. [React integration](/web-sdk/guides/dictation-react) to learn how to integrate audio dictation in a React application using the Suki Web SDK. # Audio Dictation In Web SDK For React Source: https://developer.suki.ai/web-sdk/guides/dictation-react Learn how to use dictation in the Suki Web SDK for React applications This guide walks you through the process of integrating the Suki Web SDK for audio dictation in a React application (browser-based) using the React package provided by Suki. You will create **Auth Manager** and **Dictation Client** (typically inside **`useMemo`** so they are not recreated every render), wrap your tree with **Dictation Provider**, and render **Dictation** when the user should dictate. Let's get started! ## Prerequisites Before you begin, you must have the following requirements met: * **Packages:** Install **`@suki-sdk/react`**, **`@suki-sdk/core`**. * **Partner credentials:** Obtain **`partnerId`** and **`partnerToken`** from Suki after [Partner onboarding](/documentation/partner-onboarding). * **Browser and layout:** Your app runs in a **browser**, with a real DOM and enough layout for the dictation UI. Refer to [Prerequisites](/web-sdk/prerequisites) guide for more details. ## Install the packages Add the following packages to the same project you load in the browser: ```shell pnpm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} pnpm add @suki-sdk/core @suki-sdk/react ``` ```shell yarn theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} yarn add @suki-sdk/core @suki-sdk/react ``` ```shell npm theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}} npm install @suki-sdk/core @suki-sdk/react ``` After you install, pull the SDK into your files with **`import`**, the same way as in the examples below. Use whatever approach your project already uses for other npm libraries. ## Step 1: Add container and field layout For this example we will assume you are using **`in-field`** mode as your preferred mode. In **`in-field`** mode you need **two** parts in the UI: a **`div`** (or similar) that you can pass as **`rootElement`**, where the dictation controls show up, and a **textarea** (or input) that **`onSubmit`** will update when the user finishes. The dictation layer **matches the size of** **`rootElement`** when you set it, so that node should have a **height** you control. Refer to [Wrapper layout](/dictation-sdk/guides/configuration#wrapper-layout) guide for recommended markup and CSS. **Code example for container and field layout** ```jsx React theme={"theme":{"light":"github-dark","dark":"material-theme-darker"}}