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

# Types & Interfaces

> TypeScript types and interfaces for the Odyssey client.

## Event Handlers

### OdysseyEventHandlers

Event handlers for the Odyssey client class.

```typescript theme={null}
interface OdysseyEventHandlers {
  onConnected?: (mediaStream: MediaStream) => void;
  onDisconnected?: () => void;
  onStreamStarted?: (streamId: string) => void;
  onStreamEnded?: () => void;
  onInteractAcknowledged?: (prompt: string) => void;
  onStreamError?: (reason: string, message: string) => void;
  onError?: (error: Error, fatal: boolean) => void;
  onStatusChange?: (status: ConnectionStatus, message?: string) => void;
  onBroadcastReady?: (info: BroadcastInfo) => void;
}
```

| Handler                  | Parameters                                   | Description                                                                   |
| ------------------------ | -------------------------------------------- | ----------------------------------------------------------------------------- |
| `onConnected`            | `mediaStream: MediaStream`                   | Called when video stream is established                                       |
| `onDisconnected`         | -                                            | Called when video stream is closed                                            |
| `onStreamStarted`        | `streamId: string`                           | Called when interactive stream is ready (streamId can be used for recordings) |
| `onStreamEnded`          | -                                            | Called when interactive stream has ended                                      |
| `onInteractAcknowledged` | `prompt: string`                             | Called when interaction is processed                                          |
| `onStreamError`          | `reason: string, message: string`            | Called on stream error (e.g., model crash)                                    |
| `onError`                | `error: Error, fatal: boolean`               | Called on general error                                                       |
| `onStatusChange`         | `status: ConnectionStatus, message?: string` | Called when connection status changes                                         |
| `onBroadcastReady`       | `info: BroadcastInfo`                        | Called when broadcast is ready (spectators can watch via WHEP or HLS).        |

### UseOdysseyHandlers

Event handlers for the `useOdyssey` React hook. Same interface as `OdysseyEventHandlers`.

```typescript theme={null}
type UseOdysseyHandlers = OdysseyEventHandlers;
```

### UseOdysseyOptions

Configuration for the `useOdyssey` React hook.

```typescript theme={null}
interface UseOdysseyOptions {
  /** API key for authentication (required) */
  apiKey: string;
  /** Event handlers (optional) */
  handlers?: UseOdysseyHandlers;
}
```

| Property   | Type                 | Required | Description          |
| ---------- | -------------------- | -------- | -------------------- |
| `apiKey`   | `string`             | Yes      | Your Odyssey API key |
| `handlers` | `UseOdysseyHandlers` | No       | Event handlers       |

## Configuration

### ClientConfig

Configuration for the Odyssey client constructor.

```typescript theme={null}
interface ClientConfig {
  /** API key for authentication (required) */
  apiKey: string;
}
```

| Property | Type     | Description                |
| -------- | -------- | -------------------------- |
| `apiKey` | `string` | API key for authentication |

## Status Types

### ConnectionStatus

```typescript theme={null}
type ConnectionStatus =
  | 'authenticating'  // Authenticating with Odyssey API
  | 'connecting'      // Connecting to streaming server
  | 'reconnecting'    // Reconnecting after disconnect
  | 'connected'       // Connected and ready
  | 'disconnected'    // Disconnected (clean)
  | 'failed';         // Connection failed (fatal)
```

## Recording Types

<Info>
  Recording types were added in v1.0.0
</Info>

### Recording

Recording data returned from `getRecording()`.

```typescript theme={null}
interface Recording {
  stream_id: string;
  video_url: string | null;
  events_url: string | null;
  thumbnail_url: string | null;
  preview_url: string | null;
  frame_count: number | null;
  duration_seconds: number | null;
}
```

| Property           | Type             | Description                                      |
| ------------------ | ---------------- | ------------------------------------------------ |
| `stream_id`        | `string`         | The stream ID (unique per startStream/endStream) |
| `video_url`        | `string \| null` | Presigned URL for full recording video (MP4)     |
| `events_url`       | `string \| null` | Presigned URL for events log (JSONL)             |
| `thumbnail_url`    | `string \| null` | Presigned URL for thumbnail image (JPEG)         |
| `preview_url`      | `string \| null` | Presigned URL for preview video (MP4)            |
| `frame_count`      | `number \| null` | Total frames in recording                        |
| `duration_seconds` | `number \| null` | Recording duration in seconds                    |

<Note>
  URLs are valid for a limited time (typically 1 hour).
</Note>

### StreamRecordingSummary

Summary of a stream recording returned in `listStreamRecordings()`.

```typescript theme={null}
interface StreamRecordingSummary {
  stream_id: string;
  width: number;
  height: number;
  started_at: string;
  ended_at: string | null;
  duration_seconds: number | null;
}
```

| Property           | Type             | Description                                          |
| ------------------ | ---------------- | ---------------------------------------------------- |
| `stream_id`        | `string`         | Unique stream identifier (per startStream/endStream) |
| `width`            | `number`         | Stream resolution width                              |
| `height`           | `number`         | Stream resolution height                             |
| `started_at`       | `string`         | ISO timestamp when stream started                    |
| `ended_at`         | `string \| null` | ISO timestamp when stream ended                      |
| `duration_seconds` | `number \| null` | Stream duration in seconds                           |

### ListStreamRecordingsOptions

Options for `listStreamRecordings()`.

```typescript theme={null}
interface ListStreamRecordingsOptions {
  limit?: number;
  offset?: number;
}
```

| Property | Type     | Default | Description                               |
| -------- | -------- | ------- | ----------------------------------------- |
| `limit`  | `number` | `50`    | Maximum recordings to return (max 100)    |
| `offset` | `number` | `0`     | Number of recordings to skip (pagination) |

### StreamRecordingsListResponse

Response from `listStreamRecordings()`.

```typescript theme={null}
interface StreamRecordingsListResponse {
  recordings: StreamRecordingSummary[];
  total: number;
  limit: number;
  offset: number;
}
```

| Property     | Type                       | Description                         |
| ------------ | -------------------------- | ----------------------------------- |
| `recordings` | `StreamRecordingSummary[]` | Array of stream recording summaries |
| `total`      | `number`                   | Total recordings available          |
| `limit`      | `number`                   | Limit used in request               |
| `offset`     | `number`                   | Offset used in request              |

## Simulate API Types

<Info>
  Simulate API types were added in v1.0.0
</Info>

### SimulationJobStatus

Status of a simulation job.

```typescript theme={null}
type SimulationJobStatus = 'pending' | 'dispatched' | 'processing' | 'completed' | 'failed' | 'cancelled';
```

| Status       | Description                         |
| ------------ | ----------------------------------- |
| `pending`    | Job is queued and waiting to start  |
| `dispatched` | Job has been dispatched to a worker |
| `processing` | Job is currently being processed    |
| `completed`  | Job finished successfully           |
| `failed`     | Job encountered an error            |
| `cancelled`  | Job was cancelled by user           |

### ScriptEntry

An entry in a simulation script.

```typescript theme={null}
interface ScriptEntry {
  timestamp_ms: number;           // When this action occurs (milliseconds from start)
  start?: {                       // Begin a new stream
    prompt: string;
    image?: File | Blob | string; // Optional image for image-to-video
  };
  interact?: {                    // Send an interaction
    prompt: string;
  };
  end?: Record<string, never>;    // End the stream (empty object)
}
```

| Property       | Type                                                 | Description                                       |
| -------------- | ---------------------------------------------------- | ------------------------------------------------- |
| `timestamp_ms` | `number`                                             | When this action occurs (milliseconds from start) |
| `start`        | `{ prompt: string; image?: File \| Blob \| string }` | Begin a new stream with initial prompt            |
| `interact`     | `{ prompt: string }`                                 | Send an interaction prompt                        |
| `end`          | `{}`                                                 | End the current stream (empty object)             |

### SimulateOptions

Options for `simulate()`.

```typescript theme={null}
interface SimulateOptions {
  /** Single script to run */
  script?: ScriptEntry[];
  /** Batch mode: multiple scripts */
  scripts?: ScriptEntry[][];
  /** URL to script JSON file */
  script_url?: string;
  /** Portrait (true) or landscape (false). Default: true */
  portrait?: boolean;
  /** Skip prompt expansion for this job. Requires the expansion bypass privilege. */
  bypassPromptExpansion?: boolean;
}
```

| Property                | Type              | Description                                                                |
| ----------------------- | ----------------- | -------------------------------------------------------------------------- |
| `script`                | `ScriptEntry[]`   | Single script to run (provide one of `script`, `scripts`, or `script_url`) |
| `scripts`               | `ScriptEntry[][]` | Batch mode: multiple scripts to run in a single job                        |
| `script_url`            | `string`          | URL to a JSON file containing the script                                   |
| `portrait`              | `boolean`         | Portrait mode (default: true)                                              |
| `bypassPromptExpansion` | `boolean`         | Skip prompt expansion (safety-only mode). Requires privilege.              |

### SimulationStream

Output stream from a simulation job, including recording artifact URLs.

```typescript theme={null}
interface SimulationStream {
  stream_id: string;
  video_url: string | null;
  events_url: string | null;
  thumbnail_url: string | null;
  preview_url: string | null;
  frame_count: number | null;
  duration_seconds: number | null;
  script_index: number;
}
```

| Property           | Type             | Description                                             |
| ------------------ | ---------------- | ------------------------------------------------------- |
| `stream_id`        | `string`         | Unique stream identifier                                |
| `video_url`        | `string \| null` | Presigned URL for the video file (MP4)                  |
| `events_url`       | `string \| null` | Presigned URL for the events log (JSONL)                |
| `thumbnail_url`    | `string \| null` | Presigned URL for the thumbnail image (JPEG)            |
| `preview_url`      | `string \| null` | Presigned URL for the preview video (MP4)               |
| `frame_count`      | `number \| null` | Total number of frames in the video                     |
| `duration_seconds` | `number \| null` | Duration of the video in seconds                        |
| `script_index`     | `number`         | Index of the script in batch mode (0 for single script) |

### SimulationJob

Response from `simulate()`.

```typescript theme={null}
interface SimulationJob {
  job_id: string;
  status: SimulationJobStatus;
  priority: string;
  created_at: string;
  estimated_wait_minutes: number | null;
}
```

| Property                 | Type                  | Description                        |
| ------------------------ | --------------------- | ---------------------------------- |
| `job_id`                 | `string`              | Unique identifier for the job      |
| `status`                 | `SimulationJobStatus` | Current job status                 |
| `priority`               | `string`              | Job priority                       |
| `created_at`             | `string`              | ISO timestamp when job was created |
| `estimated_wait_minutes` | `number \| null`      | Estimated wait time in minutes     |

### SimulationJobDetail

Detailed information about a simulation job from `getSimulateStatus()`.

```typescript theme={null}
interface SimulationJobDetail {
  job_id: string;
  status: SimulationJobStatus;
  priority: string;
  created_at: string;
  dispatched_at: string | null;
  started_at: string | null;
  completed_at: string | null;
  error_message: string | null;
  assigned_region: string | null;
  retry_count: number;
  streams: SimulationStream[];
}
```

| Property          | Type                  | Description                                       |
| ----------------- | --------------------- | ------------------------------------------------- |
| `job_id`          | `string`              | Unique identifier for the job                     |
| `status`          | `SimulationJobStatus` | Current job status                                |
| `priority`        | `string`              | Job priority                                      |
| `created_at`      | `string`              | ISO timestamp when job was created                |
| `dispatched_at`   | `string \| null`      | ISO timestamp when job was dispatched to a worker |
| `started_at`      | `string \| null`      | ISO timestamp when processing started             |
| `completed_at`    | `string \| null`      | ISO timestamp when job completed                  |
| `error_message`   | `string \| null`      | Error message if job failed                       |
| `assigned_region` | `string \| null`      | Region where the job is being processed           |
| `retry_count`     | `number`              | Number of times the job has been retried          |
| `streams`         | `SimulationStream[]`  | Output streams from the simulation                |

### SimulationJobInfo

Summary information for a simulation job in a list.

```typescript theme={null}
interface SimulationJobInfo {
  job_id: string;
  status: SimulationJobStatus;
  priority: string;
  created_at: string;
  completed_at: string | null;
  error_message: string | null;
}
```

| Property        | Type                  | Description                        |
| --------------- | --------------------- | ---------------------------------- |
| `job_id`        | `string`              | Unique identifier for the job      |
| `status`        | `SimulationJobStatus` | Current job status                 |
| `priority`      | `string`              | Job priority                       |
| `created_at`    | `string`              | ISO timestamp when job was created |
| `completed_at`  | `string \| null`      | ISO timestamp when job completed   |
| `error_message` | `string \| null`      | Error message if job failed        |

### ListSimulationsOptions

Options for `listSimulations()`.

```typescript theme={null}
interface ListSimulationsOptions {
  status?: SimulationJobStatus;
  active?: boolean;
  limit?: number;
  offset?: number;
}
```

| Property | Type                  | Default | Description                                           |
| -------- | --------------------- | ------- | ----------------------------------------------------- |
| `status` | `SimulationJobStatus` | —       | Filter by job status                                  |
| `active` | `boolean`             | —       | Only show active jobs (pending/dispatched/processing) |
| `limit`  | `number`              | `20`    | Maximum jobs to return (max 100)                      |
| `offset` | `number`              | `0`     | Number of jobs to skip (pagination)                   |

### SimulationJobsList

Response from `listSimulations()`.

```typescript theme={null}
interface SimulationJobsList {
  jobs: SimulationJobInfo[];
  total: number;
  limit: number;
  offset: number;
}
```

| Property | Type                  | Description                       |
| -------- | --------------------- | --------------------------------- |
| `jobs`   | `SimulationJobInfo[]` | Array of simulation job summaries |
| `total`  | `number`              | Total jobs available              |
| `limit`  | `number`              | Limit used in request             |
| `offset` | `number`              | Offset used in request            |

## Client Credentials Types

<Info>
  Client credentials types were added in v1.3.0
</Info>

### StreamerCapabilities

Capabilities advertised by the connected streamer session.

```typescript theme={null}
interface StreamerCapabilities {
  image_to_video: boolean;
}
```

| Property         | Type      | Description                                             |
| ---------------- | --------- | ------------------------------------------------------- |
| `image_to_video` | `boolean` | Whether the streamer supports image-to-video generation |

### ClientCredentials

Pre-minted credentials for client-side connections without an API key.
Created server-side via `createClientCredentials()` and passed to the client application.

```typescript theme={null}
interface ClientCredentials {
  sessionId: string;
  signalingUrl: string;
  sessionToken: string;
  expiresIn: number;
  capabilities?: StreamerCapabilities;
}
```

| Property       | Type                   | Description                                          |
| -------------- | ---------------------- | ---------------------------------------------------- |
| `sessionId`    | `string`               | Unique session ID, derived from the JWT              |
| `signalingUrl` | `string`               | WebSocket URL for the signaling server               |
| `sessionToken` | `string`               | Short-lived JWT for session authentication           |
| `expiresIn`    | `number`               | Token lifetime in seconds                            |
| `capabilities` | `StreamerCapabilities` | Streamer capabilities (e.g., image-to-video support) |

**Serialization helpers:**

```typescript theme={null}
import { credentialsToDict, credentialsFromDict } from '@odysseyml/odyssey';

// Server-side: mint and serialize
const creds = await server.createClientCredentials();
const dict = credentialsToDict(creds);
// Send dict as JSON to the client

// Client-side: deserialize
const creds = credentialsFromDict(dataFromServer);
```

<Note>
  `credentialsFromDict()` re-derives the `sessionId` from the JWT to prevent tampering.
  The `session_id` field in the dict is informational only.
</Note>

## Broadcast Types

### StartStreamOptions

Options for starting a live stream.

```typescript theme={null}
interface StartStreamOptions {
 prompt?: string;
 portrait?: boolean;
 image?: File | Blob;
 bypassPromptExpansion?: boolean;
 broadcast?: boolean;
}
```

| Property                | Type           | Description                                                                        |
| ----------------------- | -------------- | ---------------------------------------------------------------------------------- |
| `prompt`                | `string`       | Initial prompt to generate the stream                                              |
| `portrait`              | `boolean`      | True for portrait (704x1280), false for landscape (1280x704). Default: true        |
| `image`                 | `File \| Blob` | Optional image for image-to-video generation                                       |
| `bypassPromptExpansion` | `boolean`      | Skip prompt expansion (safety-only mode). Requires the expansion bypass privilege. |
| `broadcast`             | `boolean`      | Enable broadcast for spectators (HLS/WebRTC). Default: false                       |

### BroadcastInfo

Represents broadcast playback details delivered via `onBroadcastReady`.

```typescript theme={null}
interface BroadcastInfo {
 webrtcUrl: string;
 spectatorToken: string;
 hlsUrl: string | null;
}
```

| Property         | Type             | Description                                       |
| ---------------- | ---------------- | ------------------------------------------------- |
| `webrtcUrl`      | `string`         | WebRTC (WHEP) endpoint URL for spectator playback |
| `hlsUrl`         | `string \| null` | HLS playlist URL for broad compatibility          |
| `spectatorToken` | `string`         | Authentication token for spectator access         |

### Example: Broadcast Streamer

```typescript theme={null}
import { Odyssey } from "@odysseyml/odyssey";

const client = new Odyssey({ apiKey });

await client.connect({
 onBroadcastReady: ({ webrtcUrl, spectatorToken }) => {
   console.log("Share these with spectators:", webrtcUrl, spectatorToken);
 },
});

await client.startStream({
 prompt: "A floating alien temple",
 broadcast: true,
});
```

### Example: Broadcast Spectator

```typescript theme={null}
const spectator = await Odyssey.connectToStream(
 webrtcUrl,
 spectatorToken
);

videoElement.srcObject = spectator.stream;

spectator.onDisconnect(() => {
 console.log("Broadcast ended");
});
```

## Error Handling

### Fatal vs Non-Fatal Errors

The `onError` handler receives a `fatal` boolean parameter:

| Fatal   | Description                | Action Required             |
| ------- | -------------------------- | --------------------------- |
| `true`  | Connection cannot continue | Return user to connect page |
| `false` | Recoverable error          | May retry or notify user    |

### Common Error Messages

| Error                                                 | Description                                                              |
| ----------------------------------------------------- | ------------------------------------------------------------------------ |
| `Odyssey: config object is required...`               | Constructor called without a config object                               |
| `Odyssey: apiKey is required and must be a string...` | API key is missing, undefined, or not a string                           |
| `Odyssey: apiKey cannot be empty...`                  | API key is an empty string                                               |
| `Invalid API key`                                     | The provided API key is invalid (401)                                    |
| `Invalid API key format...`                           | API key format is malformed (422)                                        |
| `API key access denied`                               | The API key is valid but access is denied (403, e.g., suspended account) |
| `Maximum concurrent sessions (N) reached`             | Concurrent session quota exceeded (429)                                  |
| `No available sessions`                               | No streamers available, try again later                                  |
| `Streamer not available`                              | Assigned streamer is not responding                                      |
| `Streamer disconnected`                               | Streamer disconnected during session                                     |
| `Timed out waiting for a streamer`                    | Queue timeout expired while waiting for a streamer                       |

## TypeScript Exports

```typescript theme={null}
// Main entry point (@odysseyml/odyssey)
export { Odyssey } from './odyssey';
export type { OdysseyEventHandlers, ConnectionStatus, ClientConfig, OdysseyClient } from './types';

// React entry point (@odysseyml/odyssey/react)
export { useOdyssey } from './useOdyssey';
export type { UseOdysseyHandlers, OdysseyClient } from './types';
```

## Browser Compatibility

| Browser     | Minimum Version |
| ----------- | --------------- |
| Chrome/Edge | 90+             |
| Firefox     | 88+             |
| Safari      | 14.1+           |

<Note>
  Requires WebRTC support (`RTCPeerConnection`, `RTCDataChannel`)
</Note>
