Skip to main content

TypeScript SDK

@4players/odin-cortex is the official TypeScript SDK for ODIN Cortex. It wraps the entire REST API in a typed, ergonomic client — and adds live objects and Firestore-style real-time subscriptions on top.

It’s the same SDK the Cortex dashboard is built on, and the same one your serverless functions get pre-authenticated as ctx.cortex.

Installation

npm install @4players/odin-cortex

Requires Node.js 18+ (it uses the global fetch for streaming). It also works in modern browsers — but keep API keys server-side.

Creating a client

Authenticate with an API key for server-to-server use:

import { CortexClient } from "@4players/odin-cortex";

const client = new CortexClient({
baseUrl: "https://ots.odin.4players.io",
apiKey: process.env.CORTEX_API_KEY, // ots_live_...
});

For a browser/dashboard session where a user has logged in, pass a JWT instead:

const client = new CortexClient({
baseUrl: "https://ots.odin.4players.io",
accessToken: jwt,
});

See Authentication for when to use each.

Project scope

Project-scoped resources are reached through client.project(projectId):

const project = client.project("your-project-id");

await project.sessions.list();
await project.gatherings.create({ name: "Standup" });
await project.participants.create({ externalUserId: "u1", displayName: "Alice" });

Available resource managers on a project scope include sessions, gatherings, participants, sanctions, plugins, webhooks, functions, voice and settings. A few resources hang off the client directly: client.auth, client.apiKeys and client.pluginCatalog.

Live objects

Methods like create() and get() return live objects. Every field from the API response is available directly on the object (e.g. session.title), and the object also exposes action methods and knows its own identity — no need to thread ids back through every call:

const session = await project.sessions.create({
title: "Team Meeting",
externalRoomId: "room-42",
idleTimeout: 120,
});

// Fields are on the object directly:
console.log(session.title, session.status);

// ...and so are the action methods:
await session.start();
const messages = await session.getMessages();
await session.regenerateSummary();
await session.stop();

A live object is also plain data: JSON.stringify(session) returns exactly the API payload (no client internals), and a Session is assignable to SessionResponse. The older session.data.title form still works but is deprecated — prefer session.title.

Real-time watch()

Every list() / get() returns a one-shot snapshot. To receive live updates instead, call watch() — it loads the initial state over REST and keeps it in sync over Server-Sent Events:

const sub = project.sessions.watch();

sub.onSnapshot((sessions, changes) => {
for (const c of changes) console.log(c.type, c.id); // added | modified | removed
});
sub.onError((err) => console.error(err));

console.log(sub.current); // latest array, readable synchronously
sub.unsubscribe(); // stop listening

Watch a single object by id, a session’s transcript, or a gathering’s members and invitations:

project.sessions.watch(sessionId);          // one session

const session = await project.sessions.get(sessionId);
session.watchMessages(); // transcript streams in live

const gathering = await project.gatherings.get(gatheringId);
gathering.watchMembers();
gathering.watchInvitations();

All watchers for a project share one auto-reconnecting SSE connection, and every reconnect re-syncs state — so a dropped connection never leaves you stale. Full walkthrough: Real-time updates.

Typed errors

The SDK throws typed errors keyed to HTTP status codes:

import {
CortexAuthError, // 401, 403
CortexNotFoundError, // 404
CortexValidationError, // 422
CortexRateLimitError, // 429
CortexApiError, // other HTTP errors
CortexError, // base class
} from "@4players/odin-cortex";

try {
await project.sessions.get("nope");
} catch (err) {
if (err instanceof CortexNotFoundError) {
// handle missing session
}
}

Debug logging

Set debug: true to log every request and response (method, URL, status, body) to console.debug:

const client = new CortexClient({ baseUrl, apiKey, debug: true });

API reference

Every class, method and type is documented in the generated reference:

Browse the SDK API reference