> ## Documentation Index
> Fetch the complete documentation index at: https://docs.corti.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK - API Reference

> Complete reference for CortiClient, CortiAuth, and SDK utilities

The `@corti/sdk` package exports four main APIs:

| Export                                                    | Import                                                   | Purpose                                                                  |
| :-------------------------------------------------------- | :------------------------------------------------------- | :----------------------------------------------------------------------- |
| [`CortiClient`](#corticlient)                             | `import { CortiClient } from "@corti/sdk"`               | Full API client with all resource groups, authentication, and WebSockets |
| [`CortiAuth`](#cortiauth)                                 | `import { CortiAuth } from "@corti/sdk"`                 | Standalone authentication client for token management and OAuth flows    |
| [`CortiWebSocketProxyClient`](#cortiwebsocketproxyclient) | `import { CortiWebSocketProxyClient } from "@corti/sdk"` | WebSocket-only proxy client for stream and transcribe                    |
| [Utilities](#utilities)                                   | `import { ... } from "@corti/sdk/utils"`                 | Token decoding, environment resolution, and PKCE helpers                 |

***

## CortiClient

The main client for all Corti API operations.

### Constructor options

```ts title="JavaScript" theme={null}
import { CortiClient } from "@corti/sdk";

const client = new CortiClient({
    environment: "<eu-or-us>",
    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
});
```

| Option                       | Type                                                 | Default            | Description                                                        |
| :--------------------------- | :--------------------------------------------------- | :----------------- | :----------------------------------------------------------------- |
| `environment`                | `CortiEnvironment \| CortiEnvironmentUrls \| string` | Required           | API region or custom URLs                                          |
| `tenantName`                 | `string`                                             | Required           | Your Corti tenant name                                             |
| `auth`                       | `CortiClient.Auth`                                   | Required           | Authentication configuration ([all flows](/sdk/js/authentication)) |
| `headers`                    | `Record<string, string>`                             | `undefined`        | Headers sent with every request                                    |
| `timeoutInSeconds`           | `number`                                             | `60`               | Default request timeout                                            |
| `maxRetries`                 | `number`                                             | `2`                | Default retry count                                                |
| `fetcher`                    | `(url, init) => Promise<Response>`                   | `undefined`        | Custom fetch implementation                                        |
| `logging`                    | `{ level, logger, silent }`                          | `{ silent: true }` | [Logging config](/sdk/js/overview#logging)                         |
| `withCredentials`            | `boolean`                                            | `false`            | Include cookies in CORS requests                                   |
| `encodeHeadersAsWsProtocols` | `boolean`                                            | `false`            | Encode auth as WS subprotocols (for restrictive gateways)          |
| `baseUrl`                    | `string`                                             | `undefined`        | Route all traffic through a [proxy](/sdk/js/proxy)                 |

***

### Request options

Every HTTP method accepts an optional request options object as the last argument:

```ts title="JavaScript" theme={null}
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" },
    },
);
```

| Option             | Type                     | Description                        |
| :----------------- | :----------------------- | :--------------------------------- |
| `timeoutInSeconds` | `number`                 | Override the default 60s timeout   |
| `maxRetries`       | `number`                 | Override the default 2 retries     |
| `abortSignal`      | `AbortSignal`            | Cancel the request                 |
| `headers`          | `Record<string, string>` | Additional HTTP headers            |
| `queryParams`      | `Record<string, string>` | Additional query string parameters |

***

### Resource groups

The client exposes the following resource groups as properties:

| Group                                  | Description                                           | API endpoints                                                                |
| :------------------------------------- | :---------------------------------------------------- | :--------------------------------------------------------------------------- |
| [`client.interactions`](#interactions) | Manage patient encounters and interaction sessions    | [Interactions API](/api-reference/interactions/list-all-interactions)        |
| [`client.recordings`](#recordings)     | Upload and retrieve audio recordings for interactions | [Recordings API](/api-reference/recordings/list-recordings)                  |
| [`client.transcripts`](#transcripts)   | Create and retrieve transcriptions of recordings      | [Transcripts API](/api-reference/transcripts/list-transcripts)               |
| [`client.documents`](#documents)       | Generate and manage AI-produced clinical documents    | [Documents API](/api-reference/documents/list-documents)                     |
| [`client.facts`](#facts)               | Extract and manage structured clinical facts          | [Facts API](/api-reference/facts/list-facts)                                 |
| [`client.templates`](#templates)       | List and retrieve document generation templates       | [Templates API](/api-reference/templates/list-templates)                     |
| [`client.codes`](#codes)               | Predict medical codes from clinical data              | [Codes API](/api-reference/codes/predict-codes)                              |
| [`client.agents`](#agents)             | Create and interact with AI agents                    | [Agents API](/agentic/agents/list-agents)                                    |
| [`client.stream`](#stream)             | Real-time WebSocket streaming (transcription + facts) | [Stream API](/api-reference/streams)                                         |
| [`client.transcribe`](#transcribe)     | Real-time WebSocket speech-to-text (standalone)       | [Transcribe API](/api-reference/transcribe)                                  |
| [`client.auth`](#auth)                 | OAuth token management and authorization URLs         | [Auth API](/api-reference/admin/auth/authenticate-user-and-get-access-token) |

***

### Interactions

Manage interaction sessions that group recordings, transcripts, documents, and facts together.

```ts expandable theme={null}
// 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);
```

| Method                 | Parameters                       | Returns                        |
| :--------------------- | :------------------------------- | :----------------------------- |
| `list(request?)`       | Filter and pagination options    | Paginated list of interactions |
| `create(request)`      | Interaction definition           | Created interaction            |
| `get(id)`              | Interaction UUID                 | Single interaction             |
| `update(id, request?)` | Interaction UUID + update fields | Updated interaction            |
| `delete(id)`           | Interaction UUID                 | `void`                         |

***

### Recordings

Upload and manage audio recordings within an interaction.

```ts title="JavaScript" theme={null}
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);
```

| Method                               | Parameters                         | Returns            |
| :----------------------------------- | :--------------------------------- | :----------------- |
| `upload(file, interactionId)`        | Uploadable file + interaction UUID | Created recording  |
| `list(interactionId)`                | Interaction UUID                   | List of recordings |
| `get(interactionId, recordingId)`    | Interaction UUID + recording UUID  | Binary audio data  |
| `delete(interactionId, recordingId)` | Interaction UUID + recording UUID  | `void`             |

<Tip>See [File uploads](/sdk/js/overview#file-uploads) for all supported file input types.</Tip>

***

### Transcripts

Create transcriptions from uploaded recordings and retrieve results.

```ts title="JavaScript" theme={null}
// 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);
```

| Method                                   | Parameters                               | Returns              |
| :--------------------------------------- | :--------------------------------------- | :------------------- |
| `create(interactionId, request)`         | Interaction UUID + transcript definition | Created transcript   |
| `getStatus(interactionId, transcriptId)` | Interaction UUID + transcript UUID       | Transcription status |
| `list(interactionId, request?)`          | Interaction UUID + optional filters      | List of transcripts  |
| `get(interactionId, transcriptId)`       | Interaction UUID + transcript UUID       | Single transcript    |
| `delete(interactionId, transcriptId)`    | Interaction UUID + transcript UUID       | `void`               |

***

### Documents

Generate AI-produced clinical documents (e.g. SOAP notes) from interaction data.

```ts expandable theme={null}
// 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);
```

| Method                                        | Parameters                                       | Returns            |
| :-------------------------------------------- | :----------------------------------------------- | :----------------- |
| `create(interactionId, request)`              | Interaction UUID + document generation options   | Generated document |
| `list(interactionId)`                         | Interaction UUID                                 | List of documents  |
| `get(interactionId, documentId)`              | Interaction UUID + document UUID                 | Single document    |
| `update(interactionId, documentId, request?)` | Interaction UUID + document UUID + update fields | Updated document   |
| `delete(interactionId, documentId)`           | Interaction UUID + document UUID                 | `void`             |

***

### Facts

Extract structured clinical facts from text or manage facts on an interaction.

```ts expandable theme={null}
// 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();
```

| Method                                    | Parameters                                    | Returns                          |
| :---------------------------------------- | :-------------------------------------------- | :------------------------------- |
| `extract(request)`                        | Extraction options (context, output language) | Extracted facts                  |
| `list(interactionId)`                     | Interaction UUID                              | List of facts                    |
| `create(interactionId, request)`          | Interaction UUID + fact definitions           | Created facts                    |
| `batchUpdate(interactionId, request)`     | Interaction UUID + fact updates               | Updated facts                    |
| `update(interactionId, factId, request?)` | Interaction UUID + fact ID + update fields    | Updated fact                     |
| `factGroupsList()`                        | None                                          | Available fact group definitions |

***

### Templates

List and inspect document generation templates available to your tenant.

```ts title="JavaScript" theme={null}
// 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();
```

| Method                  | Parameters          | Returns                   |
| :---------------------- | :------------------ | :------------------------ |
| `list(request?)`        | Optional filters    | List of templates         |
| `get(key)`              | Template key string | Single template           |
| `sectionList(request?)` | Optional filters    | List of template sections |

***

### Codes

Predict medical codes from clinical data.

```ts title="JavaScript" theme={null}
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.",
    },
  ],
});
```

| Method             | Parameters                             | Returns          |
| :----------------- | :------------------------------------- | :--------------- |
| `predict(request)` | Prediction options (text, code system) | Code predictions |

***

### Agents

Create and interact with AI agents (Agentic Framework).

```ts title="JavaScript" expandable theme={null}
// Replace these with your values
const TASK_ID = "<your-task-id>";
const CONTEXT_ID = "<your-context-id>";

// 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" }],
        messageId: crypto.randomUUID(),
        kind: "message",
    },
});

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

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

// 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);
```

| Method                                | Parameters                 | Returns                 |
| :------------------------------------ | :------------------------- | :---------------------- |
| `list(request?)`                      | Optional filters           | List of agents          |
| `create(request)`                     | Agent definition           | Created agent           |
| `get(id)`                             | Agent ID                   | Agent details           |
| `getCard(id)`                         | Agent ID                   | Agent card (A2A format) |
| `messageSend(id, request)`            | Agent ID + message payload | Agent response          |
| `getTask(id, taskId, request?)`       | Agent ID + task ID         | Task details            |
| `getContext(id, contextId, request?)` | Agent ID + context ID      | Context details         |
| `getRegistryExperts(request?)`        | Optional filters           | Registry experts        |
| `update(id, request?)`                | Agent ID + update fields   | Updated agent           |
| `delete(id)`                          | Agent ID                   | `void`                  |

***

### Stream

Real-time WebSocket connection for combined transcription, fact extraction, and more -- tied to an interaction.

```ts expandable theme={null}
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

| Parameter            | Type                 | Required | Description                                                                                                                                                                                                      |
| :------------------- | :------------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                 | `string`             | Yes      | Interaction UUID to attach the stream to                                                                                                                                                                         |
| `configuration`      | `Corti.StreamConfig` | No       | Stream 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 |
| `awaitConfiguration` | `boolean`            | No       | When `true` (default), `connect()` waits for `CONFIG_ACCEPTED` before resolving. When `false`, returns the socket immediately and dispatches config errors as events                                             |
| `proxy`              | `ProxyOptions`       | No       | Route through a [proxy](/sdk/js/proxy) instead of connecting directly. Connects to the provided URL exactly as-is (no endpoint path is appended)                                                                 |
| `debug`              | `boolean`            | No       | Enable debug logging                                                                                                                                                                                             |
| `reconnectAttempts`  | `number`             | No       | Number of reconnection attempts on disconnect                                                                                                                                                                    |

The SDK injects `tenantName` and `token` automatically. If `configuration` is provided and `awaitConfiguration` is `true`, the promise rejects when the stream configuration is denied (`CONFIG_DENIED`, `CONFIG_MISSING`, `CONFIG_NOT_PROVIDED`).

#### Socket methods

| Method                       | Description                                                                                                                                                                                                             |
| :--------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `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](/api-reference/transcribe#flush-the-audio-buffer) |
| `waitForOpen()`              | Returns a promise that resolves when the socket is open                                                                                                                                                                 |
| `readyState`                 | Current connection state (property, not method)                                                                                                                                                                         |

***

### Transcribe

Real-time WebSocket speech-to-text without an interaction context.

```ts title="JavaScript" theme={null}
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

| Parameter            | Type                     | Required | Description                                                                                                                                                                                               |
| :------------------- | :----------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `configuration`      | `Corti.TranscribeConfig` | No       | Transcribe configuration (language, punctuation, commands). When provided, the SDK automatically sends the config message once the socket opens. If omitted, you must call `sendConfiguration()` yourself |
| `awaitConfiguration` | `boolean`                | No       | When `true` (default), `connect()` waits for `CONFIG_ACCEPTED` before resolving. When `false`, returns the socket immediately and dispatches config errors as events                                      |
| `proxy`              | `ProxyOptions`           | No       | Route through a [proxy](/sdk/js/proxy) instead of connecting directly. Connects to the provided URL exactly as-is (no endpoint path is appended)                                                          |
| `debug`              | `boolean`                | No       | Enable debug logging                                                                                                                                                                                      |
| `reconnectAttempts`  | `number`                 | No       | Number of reconnection attempts on disconnect                                                                                                                                                             |

The socket methods are the same as [Stream](#socket-methods) (`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`, `delta_usage`, and `error` messages, while Stream delivers `transcript`, `facts`, `flushed`, `ended`, `usage`, `delta_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.

| Method                      | Description                                                |
| :-------------------------- | :--------------------------------------------------------- |
| `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                          |

<Tip>For detailed usage and end-to-end examples, see the [Authentication Guide](/sdk/js/authentication). For standalone use without `CortiClient`, see [CortiAuth](#cortiauth) below.</Tip>

***

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

```ts title="JavaScript" theme={null}
import { CortiAuth } from "@corti/sdk";

const auth = new CortiAuth({
    environment: "<eu-or-us>",
    tenantName: "<your-tenant-name>",
});
```

### Constructor options

| Option             | Type                                                 | Required | Description               |
| :----------------- | :--------------------------------------------------- | :------- | :------------------------ |
| `environment`      | `CortiEnvironment \| CortiEnvironmentUrls \| string` | Yes      | API region or custom URLs |
| `tenantName`       | `string`                                             | Yes      | Your Corti tenant name    |
| `headers`          | `Record<string, string>`                             | No       | Additional headers        |
| `timeoutInSeconds` | `number`                                             | No       | Request timeout           |
| `maxRetries`       | `number`                                             | No       | Retry 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.

| Method                        | Description                                                               | Returns             |
| :---------------------------- | :------------------------------------------------------------------------ | :------------------ |
| `getToken(request)`           | Get a token via client credentials                                        | `AuthTokenResponse` |
| `getRopcFlowToken(request)`   | Get a token via ROPC flow                                                 | `AuthTokenResponse` |
| `getCodeFlowToken(request)`   | Exchange an authorization code for a token                                | `AuthTokenResponse` |
| `getPkceFlowToken(request)`   | Exchange a PKCE authorization code for a token                            | `AuthTokenResponse` |
| `refreshToken(request)`       | Refresh an expired token                                                  | `AuthTokenResponse` |
| `authorizeURL(options)`       | Generate an authorization code flow URL and redirect to it                | `string`            |
| `authorizePkceUrl(options)`   | Generate a PKCE flow redirect URL                                         | `string`            |
| `CortiAuth.getCodeVerifier()` | Get the PKCE code verifier from the last `authorizePkceUrl` call (static) | `string \| null`    |

<Tip>For end-to-end examples and detailed usage of each method, see the [Authentication Guide](/sdk/js/authentication).</Tip>

***

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

```ts title="JavaScript" theme={null}
import { CortiWebSocketProxyClient } from "@corti/sdk";
```

### Static properties

| Property     | Type                    | Description                                                         |
| :----------- | :---------------------- | :------------------------------------------------------------------ |
| `stream`     | `CustomProxyStream`     | Stream proxy client (transcription + facts, tied to an interaction) |
| `transcribe` | `CustomProxyTranscribe` | Transcribe proxy client (standalone speech-to-text)                 |

### `stream.connect`

```ts expandable theme={null}
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);
```

| Parameter            | Type                            | Required | Description                                                                                                              |
| :------------------- | :------------------------------ | :------- | :----------------------------------------------------------------------------------------------------------------------- |
| `proxy`              | [`ProxyOptions`](#proxyoptions) | Yes      | Proxy URL, subprotocols, and query parameters. Connects to the provided URL exactly as-is (no endpoint path is appended) |
| `configuration`      | `Corti.StreamConfig`            | No       | Stream configuration (language, punctuation, etc.)                                                                       |
| `awaitConfiguration` | `boolean`                       | No       | Wait for `CONFIG_ACCEPTED` before resolving (default `true`)                                                             |
| `debug`              | `boolean`                       | No       | Enable debug logging                                                                                                     |
| `reconnectAttempts`  | `number`                        | No       | Number of reconnection attempts                                                                                          |

Returns `Promise<CustomStreamSocket>` -- same socket API as [`client.stream.connect`](#stream).

### `transcribe.connect`

```ts expandable theme={null}
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);
```

| Parameter            | Type                            | Required | Description                                                                                                              |
| :------------------- | :------------------------------ | :------- | :----------------------------------------------------------------------------------------------------------------------- |
| `proxy`              | [`ProxyOptions`](#proxyoptions) | Yes      | Proxy URL, subprotocols, and query parameters. Connects to the provided URL exactly as-is (no endpoint path is appended) |
| `configuration`      | `Corti.TranscribeConfig`        | No       | Transcribe configuration (language, punctuation, etc.)                                                                   |
| `awaitConfiguration` | `boolean`                       | No       | Wait for `CONFIG_ACCEPTED` before resolving (default `true`)                                                             |
| `debug`              | `boolean`                       | No       | Enable debug logging                                                                                                     |
| `reconnectAttempts`  | `number`                        | No       | Number of reconnection attempts                                                                                          |

Returns `Promise<CustomTranscribeSocket>` -- same socket API as [`client.transcribe.connect`](#transcribe).

### `ProxyOptions`

The `ProxyOptions` type is also exported from `@corti/sdk` for use when typing proxy arguments in your own code.

```ts title="JavaScript" theme={null}
import type { ProxyOptions } from "@corti/sdk";
```

| Property          | Type                                 | Required | Description                                                                                                            |
| :---------------- | :----------------------------------- | :------- | :--------------------------------------------------------------------------------------------------------------------- |
| `url`             | `string`                             | Yes      | WebSocket URL of your proxy server                                                                                     |
| `protocols`       | `string[] \| Record<string, string>` | No       | WebSocket subprotocols. Arrays are passed as-is; objects are encoded as `[name, encodeURIComponent(value), ...]` pairs |
| `queryParameters` | `Record<string, string>`             | No       | Query parameters appended to the WebSocket URL                                                                         |

<Tip>For a full walkthrough of proxy patterns (including `baseUrl`, custom environments, `encodeHeadersAsWsProtocols`, and scoped tokens), see the [Proxy Guide](/sdk/js/proxy).</Tip>

***

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

```ts title="JavaScript" theme={null}
import {
    decodeToken,
    getEnvironment,
    generateCodeVerifier,
    generateCodeChallenge
} from "@corti/sdk/utils";
```

| Export                            | Description                                                                                                                                                   |
| :-------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `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`                                                             |
| `DecodedToken`                    | TypeScript type for the return value of `decodeToken`                                                                                                         |
