Skip to main content

Getting Started

This guide takes you from nothing to a working transcript. By the end you will have created a session, attached a transcription bot to an ODIN Voice room, and read back what was said — using the official TypeScript SDK.

It should take about 10 minutes.

Cortex Dashboard

Rather than using code you can also use the dashboard for almost everything. The new unified ODIN dashboard is currently available at https://ots.odin.4players.io/dashboard and will soon replace our current dashboard located at console.4players.io.

What you need

Before you start, make sure you have:

  • A 4Players account and a project. Sign in at console.4players.io; if you don’t have a project yet, create one.
  • ODIN Voice activated on that project, and ODIN Cortex activated as well. Both are activated from the dashboard.
  • An ODIN Voice room with people (or a test client) talking in it. If you are new to Voice, follow the ODIN Voice getting started guide first — Cortex transcribes rooms that Voice creates.
  • Node.js 18+ if you want to follow along with the SDK.
Where Cortex sits

Cortex never creates audio — it listens. You point it at a room that already exists in ODIN Voice (identified by its roomId), and a headless bot joins that room to capture and transcribe audio. See Sessions & Gatherings.

Step 1 — Create an API key

Server-to-server calls to Cortex authenticate with an API key. Create one in the dashboard:

  1. Open your project and go to the Cortex section.
  2. Open API Keys and click Create API Key.
  3. Give it a name (e.g. Backend). Optionally restrict it to specific scopes such as sessions and messages.
  4. Copy the key — it looks like ots_live_... and is shown only once.

Treat the key like a password. Use it from your backend, never from a browser or shipped game client.

Which auth should I use?

Use an API key for any backend or machine client, and a JWT for browser/dashboard sessions. Cortex also has an internal HMAC “project secret” mechanism used by other ODIN platform services — it isn’t the recommended path for your own integrations. Full details in Authentication.

Step 2 — Install the SDK

npm install @4players/odin-cortex

Create a client and scope it to your project:

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

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

// Every Cortex resource is reached through a project scope.
const project = client.project("your-project-id");

Step 3 — Create and start a session

A session is an active transcription instance bound to one ODIN room. Creating a session and starting it makes the bot join the room.

// Create a session bound to an existing ODIN room.
const session = await project.sessions.create({
title: "My First Session",
externalRoomId: "room-1", // the ODIN Voice roomId to transcribe
idleTimeout: 60, // auto-end after 60s of silence (optional)
});

// Start the bot — it joins the room and begins transcribing.
await session.start();

console.log("Session started:", session.id);
externalRoomId

externalRoomId is the ODIN Voice roomId your clients pass when they join the room. That’s how Cortex knows which room to transcribe. See Users & Participants for how speakers are identified.

Step 4 — Read the transcript

Each spoken utterance becomes a message attributed to the participant who said it. Once people have talked for a bit, read them back:

const messages = await session.getMessages();

for (const message of messages) {
console.log(message);
}

When you’re done, stop the session (the bot leaves the room):

await session.stop();

Step 5 — Watch it live (optional)

Polling works, but the real power is live updates. watch() loads the current state over REST and then keeps it in sync over Server-Sent Events — new messages stream in as they’re transcribed, no polling loop required:

const session = await project.sessions.get(sessionId);

const sub = session.watchMessages();
sub.onSnapshot((messages, changes) => {
for (const change of changes) {
if (change.type === "added") {
console.log(`+ ${change.data.senderName}: ${change.data.content}`);
}
}
});

// later: sub.unsubscribe();

See Real-time updates for the full pattern.

Prefer raw HTTP?

You don’t have to use the SDK. The same flow over the REST API:

# Create a session
curl -X POST https://ots.odin.4players.io/api/projects/{projectId}/sessions \
-H "X-API-Key: ots_live_..." \
-H "Content-Type: application/json" \
-d '{ "title": "My First Session", "externalRoomId": "room-1", "idleTimeout": 60 }'

# Start the bot
curl -X POST https://ots.odin.4players.io/api/projects/{projectId}/sessions/{id}/start \
-H "X-API-Key: ots_live_..."

# Read messages
curl https://ots.odin.4players.io/api/projects/{projectId}/sessions/{id}/messages \
-H "X-API-Key: ots_live_..."

Every endpoint is documented in the REST API reference.

Next steps

Core concepts

Sessions vs gatherings, participants, auth and multi-tenancy — the mental model behind the API.

Read concepts
Guides

Runnable, end-to-end walkthroughs: real-time captions, moderation, gatherings and serverless functions.