Skip to main content
The @corti/sdk package exports four main APIs:
ExportImportPurpose
CortiClientimport { CortiClient } from "@corti/sdk"Full API client with all resource groups, authentication, and WebSockets
CortiAuthimport { CortiAuth } from "@corti/sdk"Standalone authentication client for token management and OAuth flows
CortiWebSocketProxyClientimport { CortiWebSocketProxyClient } from "@corti/sdk"WebSocket-only proxy client for stream and transcribe
Utilitiesimport { ... } from "@corti/sdk/utils"Token decoding, environment resolution, and PKCE helpers

CortiClient

The main client for all Corti API operations.

Constructor options

JavaScript
import { CortiClient } from "@corti/sdk";

const client = new CortiClient({
    environment: "YOUR_ENVIRONMENT_ID",
    tenantName: "YOUR_TENANT_NAME",
    auth: { ... },                     // see Authentication Guide

    // Optional
    headers: { "X-Custom": "value" },  // headers sent with every request
    timeoutInSeconds: 60,              // default request timeout
    maxRetries: 2,                     // default retry count
    fetcher: customFetchFn,            // custom fetch implementation
    logging: { ... },                  // logging configuration
    withCredentials: false,            // include cookies in CORS requests
    encodeHeadersAsWsProtocols: false, // encode auth headers as WS subprotocols
});
OptionTypeDefaultDescription
environmentCortiEnvironment | CortiEnvironmentUrls | stringRequiredAPI region or custom URLs
tenantNamestringRequiredYour Corti tenant name
authCortiClient.AuthRequiredAuthentication configuration (all flows)
headersRecord<string, string>undefinedHeaders sent with every request
timeoutInSecondsnumber60Default request timeout
maxRetriesnumber2Default retry count
fetcher(url, init) => Promise<Response>undefinedCustom fetch implementation
logging{ level, logger, silent }{ silent: true }Logging config
withCredentialsbooleanfalseInclude cookies in CORS requests
encodeHeadersAsWsProtocolsbooleanfalseEncode auth as WS subprotocols (for restrictive gateways)
baseUrlstringundefinedRoute all traffic through a proxy

Request options

Every HTTP method accepts an optional request options object as the last argument:
JavaScript
const response = await client.interactions.create(
    { encounter: { identifier: "id", status: "planned", type: "first_consultation" } },
    {
        timeoutInSeconds: 30,
        maxRetries: 3,
        abortSignal: controller.signal,
        headers: { "X-Custom-Header": "value" },
        queryParams: { customKey: "customValue" },
    },
);
OptionTypeDescription
timeoutInSecondsnumberOverride the default 60s timeout
maxRetriesnumberOverride the default 2 retries
abortSignalAbortSignalCancel the request
headersRecord<string, string>Additional HTTP headers
queryParamsRecord<string, string>Additional query string parameters

Resource groups

The client exposes the following resource groups as properties:
GroupDescriptionAPI endpoints
client.interactionsManage patient encounters and interaction sessionsInteractions API
client.recordingsUpload and retrieve audio recordings for interactionsRecordings API
client.transcriptsCreate and retrieve transcriptions of recordingsTranscripts API
client.documentsGenerate and manage AI-produced clinical documentsDocuments API
client.factsExtract and manage structured clinical factsFacts API
client.templatesList and retrieve document generation templatesTemplates API
client.codesPredict medical codes from clinical dataCodes API
client.agentsCreate and interact with AI agentsAgents API
client.streamReal-time WebSocket streaming (transcription + facts)Stream API
client.transcribeReal-time WebSocket speech-to-text (standalone)Transcribe API
client.authOAuth token management and authorization URLsAuth API

Interactions

Manage interaction sessions that group recordings, transcripts, documents, and facts together.
// List interactions (paginated)
const page = await client.interactions.list({ limit: 10 });
for await (const interaction of page) {
    console.log(interaction.interactionId);
}

// Create a new interaction
const { interactionId } = await client.interactions.create({
    encounter: {
        identifier: "my-encounter-id",
        status: "planned",
        type: "first_consultation",
    },
});

// Get a specific interaction
const interaction = await client.interactions.get(interactionId);

// Update an interaction
await client.interactions.update(interactionId, {
    encounter: { status: "in-progress" },
});

// Delete an interaction
await client.interactions.delete(interactionId);
MethodParametersReturns
list(request?)Filter and pagination optionsPaginated list of interactions
create(request)Interaction definitionCreated interaction
get(id)Interaction UUIDSingle interaction
update(id, request?)Interaction UUID + update fieldsUpdated interaction
delete(id)Interaction UUIDvoid

Recordings

Upload and manage audio recordings within an interaction.
JavaScript
import { createReadStream } from "fs";

// Upload a recording
const { recordingId } = await client.recordings.upload(
    createReadStream("audio.mp3"),
    interactionId,
);

// List recordings for an interaction
const recordings = await client.recordings.list(interactionId);

// Download a recording (returns binary)
const binary = await client.recordings.get(interactionId, recordingId);
const stream = binary.stream();

// Delete a recording
await client.recordings.delete(interactionId, recordingId);
MethodParametersReturns
upload(file, interactionId)Uploadable file + interaction UUIDCreated recording
list(interactionId)Interaction UUIDList of recordings
get(interactionId, recordingId)Interaction UUID + recording UUIDBinary audio data
delete(interactionId, recordingId)Interaction UUID + recording UUIDvoid
See File uploads for all supported file input types.

Transcripts

Create transcriptions from uploaded recordings and retrieve results.
JavaScript
// Create a transcript from a recording
const { id: transcriptId } = await client.transcripts.create(interactionId, {
    recordingId,
    primaryLanguage: "en",
});

// Check transcription status
const status = await client.transcripts.getStatus(interactionId, transcriptId);

// List transcripts for an interaction
const transcripts = await client.transcripts.list(interactionId);

// Get a specific transcript
const result = await client.transcripts.get(interactionId, transcriptId);

// Delete a transcript
await client.transcripts.delete(interactionId, transcriptId);
MethodParametersReturns
create(interactionId, request)Interaction UUID + transcript definitionCreated transcript
getStatus(interactionId, transcriptId)Interaction UUID + transcript UUIDTranscription status
list(interactionId, request?)Interaction UUID + optional filtersList of transcripts
get(interactionId, transcriptId)Interaction UUID + transcript UUIDSingle transcript
delete(interactionId, transcriptId)Interaction UUID + transcript UUIDvoid

Documents

Generate AI-produced clinical documents (e.g. SOAP notes) from interaction data.
// Generate a document
const { id: documentId } = await client.documents.create(interactionId, {
    context: [{
        type: "string",
        data: "Patient presents with chest pain...",
    }],
    templateKey: "corti-soap",
    outputLanguage: "en",
});

// List documents for an interaction
const documents = await client.documents.list(interactionId);

// Get a specific document
const doc = await client.documents.get(interactionId, documentId);

// Update a document
await client.documents.update(interactionId, documentId, {
    name: "Updated note",
});

// Delete a document
await client.documents.delete(interactionId, documentId);
MethodParametersReturns
create(interactionId, request)Interaction UUID + document generation optionsGenerated document
list(interactionId)Interaction UUIDList of documents
get(interactionId, documentId)Interaction UUID + document UUIDSingle document
update(interactionId, documentId, request?)Interaction UUID + document UUID + update fieldsUpdated document
delete(interactionId, documentId)Interaction UUID + document UUIDvoid

Facts

Extract structured clinical facts from text or manage facts on an interaction.
// Extract facts from text (standalone, no interaction needed)
const extracted = await client.facts.extract({
    context: [{ type: "text", text: "Patient has a temperature of 38.5°C and reports headache." }],
    outputLanguage: "en",
});

// List facts for an interaction
const facts = await client.facts.list(interactionId);

// Create facts on an interaction
const { id: factId } = await client.facts.create(interactionId, {
    facts: [{ text: "Temperature 38.5°C", group: "vitals" }],
});

// Batch update facts
await client.facts.batchUpdate(interactionId, {
    facts: [{ factId, text: "Temperature 39.0°C" }],
});

// Update a single fact
await client.facts.update(interactionId, factId, { text: "Temperature 39.0°C" });
// List available fact groups
const groups = await client.facts.factGroupsList();
MethodParametersReturns
extract(request)Extraction options (context, output language)Extracted facts
list(interactionId)Interaction UUIDList of facts
create(interactionId, request)Interaction UUID + fact definitionsCreated facts
batchUpdate(interactionId, request)Interaction UUID + fact updatesUpdated facts
update(interactionId, factId, request?)Interaction UUID + fact ID + update fieldsUpdated fact
factGroupsList()NoneAvailable fact group definitions

Templates

List and inspect document generation templates available to your tenant.
JavaScript
// List all templates
const templates = await client.templates.list();

// Get a specific template by key
const template = await client.templates.get("corti-soap");

// List template sections
const sections = await client.templates.sectionList();
MethodParametersReturns
list(request?)Optional filtersList of templates
get(key)Template key stringSingle template
sectionList(request?)Optional filtersList of template sections

Codes

Predict medical codes from clinical data.
JavaScript
const response = await client.codes.predict({
  system: ["icd10cm-inpatient"],
  context: [
    {
      type: "text",
      text: "Progress Note — Day 3: Patient continues on IV vancomycin for MRSA bacteremia. Blood cultures from yesterday still pending. Acute kidney injury improving — creatinine down to 1.8 from 2.4. Patient also has history of CHF, currently euvolemic on home dose of furosemide. Diabetes managed with insulin sliding scale, glucose well controlled.",
    },
  ],
});
MethodParametersReturns
predict(request)Prediction options (text, code system)Code predictions

Agents

Create and interact with AI agents (Agentic Framework).
// List agents
const agents = await client.agents.list();

// Create an agent
const agent = await client.agents.create({
    name: "My Agent",
    description: "A helpful assistant",
});

// Get agent details
const details = await client.agents.get(agent.id);

// Get agent card (A2A)
const card = await client.agents.getCard(agent.id);

// Send a message to an agent
const response = await client.agents.messageSend(agent.id, {
    message: { role: "user", parts: [{ kind: "text", text: "Hello" }] },
});

// Get a task
const task = await client.agents.getTask(agent.id, taskId);

// Get context
const context = await client.agents.getContext(agent.id, contextId);

// List registry experts
const experts = await client.agents.getRegistryExperts();

// Update an agent
await client.agents.update(agent.id, { description: "Updated" });

// Delete an agent
await client.agents.delete(agent.id);
MethodParametersReturns
list(request?)Optional filtersList of agents
create(request)Agent definitionCreated agent
get(id)Agent IDAgent details
getCard(id)Agent IDAgent card (A2A format)
messageSend(id, request)Agent ID + message payloadAgent response
getTask(id, taskId, request?)Agent ID + task IDTask details
getContext(id, contextId, request?)Agent ID + context IDContext details
getRegistryExperts(request?)Optional filtersRegistry experts
update(id, request?)Agent ID + update fieldsUpdated agent
delete(id)Agent IDvoid

Stream

Real-time WebSocket connection for combined transcription, fact extraction, and more — tied to an interaction.
const socket = await client.stream.connect({
    id: interactionId,
    configuration: {
        transcription: {
            primaryLanguage: "en",
            participants: [{ channel: 0, role: "doctor" }],
        },
        mode: { type: "facts", outputLocale: "en" },
    },
});

socket.on("message", (msg) => {
    console.log(msg.type, msg.data);
});

socket.sendAudio(audioBuffer);

connect parameters

ParameterTypeRequiredDescription
idstringYesInteraction UUID to attach the stream to
configurationCorti.StreamConfigNoStream configuration (transcription language, participants, mode). When provided, the SDK automatically sends the config message once the socket opens. If omitted, you must call sendConfiguration() yourself
awaitConfigurationbooleanNoWhen true (default), connect() waits for CONFIG_ACCEPTED before resolving. When false, returns the socket immediately and dispatches config errors as events
proxyProxyOptionsNoRoute through a proxy instead of connecting directly. Connects to the provided URL exactly as-is (no endpoint path is appended)
debugbooleanNoEnable debug logging
reconnectAttemptsnumberNoNumber of reconnection attempts on disconnect
The SDK injects tenantName and token automatically. If configuration is provided and awaitConfiguration is true, the promise rejects on CONFIG_DENIED or timeout.

Socket methods

MethodDescription
on(event, handler)Subscribe to events: "open", "message", "close", "error"
off(event, handler?)Remove an event handler
sendAudio(data)Send binary audio data (ArrayBuffer, Blob, or ArrayBufferView)
sendFlush(message)Request the server to flush buffered audio and return results
sendEnd(message)Signal end of audio stream
sendConfiguration(message)Send a configuration message (used internally by connect)
send(data)Send raw data directly on the underlying WebSocket
close()Close the connection and unregister event handlers. You should call sendEnd() first and wait for the ended message before closing — see Flush the Audio Buffer
waitForOpen()Returns a promise that resolves when the socket is open
readyStateCurrent connection state (property, not method)

Transcribe

Real-time WebSocket speech-to-text without an interaction context.
JavaScript
const socket = await client.transcribe.connect({
  configuration: {
    primaryLanguage: "en",
    automaticPunctuation: true,
  },
});

socket.on("message", (message) => {
  if (message.type === "transcript") {
    console.log("Transcript:", message.data.text);
  }
});

// Send audio data (e.g. from a microphone stream)
socket.sendAudio(audioBuffer);

connect parameters

ParameterTypeRequiredDescription
configurationCorti.TranscribeConfigNoTranscribe configuration (language, punctuation, commands). When provided, the SDK automatically sends the config message once the socket opens. If omitted, you must call sendConfiguration() yourself
awaitConfigurationbooleanNoWhen true (default), connect() waits for CONFIG_ACCEPTED before resolving. When false, returns the socket immediately and dispatches config errors as events
proxyProxyOptionsNoRoute through a proxy instead of connecting directly. Connects to the provided URL exactly as-is (no endpoint path is appended)
debugbooleanNoEnable debug logging
reconnectAttemptsnumberNoNumber of reconnection attempts on disconnect
The socket methods are the same as Stream (sendAudio, sendFlush, sendEnd, close, etc.). The key differences are:
  • No interaction ID — Transcribe operates standalone
  • Different message types — Transcribe delivers transcript, command, flushed, ended, usage, and error messages, while Stream delivers transcript, facts, flushed, ended, usage, and error

Auth

OAuth token management. In most cases you won’t call these directly — the SDK handles tokens automatically based on the auth option you pass to the constructor. These methods are useful for advanced scenarios like generating authorization URLs for browser-based flows.
MethodDescription
getToken(request)Get a token via client credentials
getRopcFlowToken(request)Get a token via ROPC flow
getCodeFlowToken(request)Exchange an authorization code for a token
getPkceFlowToken(request)Exchange a PKCE authorization code for a token
refreshToken(request)Refresh an expired token
authorizeURL(options)Generate an authorization code flow URL and redirect to it
authorizePkceUrl(options)Generate a PKCE flow redirect URL
For detailed usage and end-to-end examples, see the Authentication Guide. For standalone use without CortiClient, see CortiAuth below.

CortiAuth

A standalone authentication client for when you need OAuth token management without the full CortiClient. Useful for proxy servers, custom backends, or applications that handle tokens separately from API calls.
JavaScript
import { CortiAuth } from "@corti/sdk";

const auth = new CortiAuth({
    environment: "YOUR_ENVIRONMENT_ID",
    tenantName: "YOUR_TENANT_NAME",
});

Constructor options

OptionTypeRequiredDescription
environmentCortiEnvironment | CortiEnvironmentUrls | stringYesAPI region or custom URLs
tenantNamestringYesYour Corti tenant name
headersRecord<string, string>NoAdditional headers
timeoutInSecondsnumberNoRequest timeout
maxRetriesnumberNoRetry count

Methods

All token methods accept an optional scopes array. openid and profile are added automatically — pass additional scopes like "streams" or "transcribe" to get a scoped token.
MethodDescriptionReturns
getToken(request)Get a token via client credentialsAuthTokenResponse
getRopcFlowToken(request)Get a token via ROPC flowAuthTokenResponse
getCodeFlowToken(request)Exchange an authorization code for a tokenAuthTokenResponse
getPkceFlowToken(request)Exchange a PKCE authorization code for a tokenAuthTokenResponse
refreshToken(request)Refresh an expired tokenAuthTokenResponse
authorizeURL(options)Generate an authorization code flow URL and redirect to itstring
authorizePkceUrl(options)Generate a PKCE flow redirect URLstring
CortiAuth.getCodeVerifier()Get the PKCE code verifier from the last authorizePkceUrl call (static)string | null
For end-to-end examples and detailed usage of each method, see the Authentication Guide.

CortiWebSocketProxyClient

A lightweight client for WebSocket-only proxy scenarios. Unlike CortiClient, it requires no environment, tenant, or authentication configuration — all routing is handled by the proxy option you pass at connect time.
JavaScript
import { CortiWebSocketProxyClient } from "@corti/sdk";

Static properties

PropertyTypeDescription
streamCustomProxyStreamStream proxy client (transcription + facts, tied to an interaction)
transcribeCustomProxyTranscribeTranscribe proxy client (standalone speech-to-text)

stream.connect

const socket = await CortiWebSocketProxyClient.stream.connect({
    proxy: {
        url: "wss://your-proxy.com/corti/stream",
        protocols: ["custom-protocol"],
        queryParameters: { interactionId: "id" },
    },
    configuration: {
        transcription: {
            primaryLanguage: "en",
            participants: [{ channel: 0, role: "doctor" }],
        },
        mode: { type: "facts", outputLocale: "en" },
    },
    awaitConfiguration: true, // default: true
    debug: false,
    reconnectAttempts: 3,
});

socket.on("message", (msg) => console.log(msg.type, msg.data));
socket.sendAudio(audioBuffer);
ParameterTypeRequiredDescription
proxyProxyOptionsYesProxy URL, subprotocols, and query parameters. Connects to the provided URL exactly as-is (no endpoint path is appended)
configurationCorti.StreamConfigNoStream configuration (language, punctuation, etc.)
awaitConfigurationbooleanNoWait for CONFIG_ACCEPTED before resolving (default true)
debugbooleanNoEnable debug logging
reconnectAttemptsnumberNoNumber of reconnection attempts
Returns Promise<CustomStreamSocket> — same socket API as client.stream.connect.

transcribe.connect

const socket = await CortiWebSocketProxyClient.transcribe.connect({
    proxy: {
        url: "wss://your-proxy.com/corti/transcribe",
    },
    configuration: {
        primaryLanguage: "en",
        automaticPunctuation: true,
    },
});

socket.on("message", (msg) => {
    if (msg.type === "transcript") {
        console.log(msg.data.text);
    }
});
socket.sendAudio(audioBuffer);
ParameterTypeRequiredDescription
proxyProxyOptionsYesProxy URL, subprotocols, and query parameters. Connects to the provided URL exactly as-is (no endpoint path is appended)
configurationCorti.TranscribeConfigNoTranscribe configuration (language, punctuation, etc.)
awaitConfigurationbooleanNoWait for CONFIG_ACCEPTED before resolving (default true)
debugbooleanNoEnable debug logging
reconnectAttemptsnumberNoNumber of reconnection attempts
Returns Promise<CustomTranscribeSocket> — same socket API as client.transcribe.connect.

ProxyOptions

The ProxyOptions type is also exported from @corti/sdk for use when typing proxy arguments in your own code.
JavaScript
import type { ProxyOptions } from "@corti/sdk";
PropertyTypeRequiredDescription
urlstringYesWebSocket URL of your proxy server
protocolsstring[] | Record<string, string>NoWebSocket subprotocols. Arrays are passed as-is; objects are encoded as [name, encodeURIComponent(value), ...] pairs
queryParametersRecord<string, string>NoQuery parameters appended to the WebSocket URL
For a full walkthrough of proxy patterns (including baseUrl, custom environments, encodeHeadersAsWsProtocols, and scoped tokens), see the Proxy Guide.

Utilities

The @corti/sdk/utils sub-package exports helper functions for token inspection, environment resolution, and PKCE. These are useful in proxy servers, middleware, and custom authentication flows.
JavaScript
import {
    decodeToken,
    getEnvironment,
    generateCodeVerifier,
    generateCodeChallenge
} from "@corti/sdk/utils";
ExportDescription
decodeToken(token)Decode a Corti JWT to extract environment, tenantName, accessToken, and expiresAt. Returns null if the token is invalid or the issuer doesn’t match
getEnvironment(env)Normalize an environment string (e.g. "eu") or CortiEnvironment object into the internal URL format the SDK uses
generateCodeVerifier()Generate a PKCE code verifier (32 random bytes, base64url-encoded)
generateCodeChallenge(verifier)Compute the PKCE code challenge from a verifier (SHA-256, base64url-encoded). Returns a Promise
DecodedTokenTypeScript type for the return value of decodeToken