# H3 Max Director

> Direct continuous, realtime video streams with live prompts while preserving characters, settings, and story continuity.


## Overview

- **Endpoint**: `https://fal.run/minimax/h3-max/director`
- **Model ID**: `minimax/h3-max/director`
- **Category**: text-to-video
- **Kind**: inference
**Description**: H3 Max Director generates continuous real-time video that can be directed while it streams. Send new prompts during a session to evolve the action while maintaining visual, character, and scene continuity.



## Pricing

Sessions cost **$0.048** per second of video generated.

Note: this is a promotional rate, **40%** off for a limited time. The discount ends **October 15**, after which the price is **$0.08** per second of video. 1080p costs **2×** the standard rate. Each session is billed at a minimum of **60 seconds** of runtime.

For more details, see [fal.ai pricing](https://fal.ai/pricing).

## Realtime API (WMA/WebRTC)

This endpoint publishes a WMA WebRTC contract. Open it with `fal.realtime.open`; do **not** call the session endpoint with `fal.run`, `fal.subscribe`, or the Queue API.

The browser negotiates through fal and then exchanges media with the model over WebRTC.

Client contract for the WebRTC session created by the linked OpenAPI operation.


### Install the experimental client

```bash
npm install @fal-ai/client@alpha @fal-ai/server-proxy@alpha
```

### Authentication and server proxy

Keep `FAL_KEY` on your server. Expose an authenticated proxy route to the browser. In a Next.js App Router application, create `app/api/fal/proxy/route.ts`:

```typescript
import { route } from "@fal-ai/server-proxy/nextjs";

export const { GET, POST, PUT } = route;
```

Protect that route with your application's authentication before deploying it.

### Open a browser session

```typescript
import { createFalClient } from "@fal-ai/client";
import { wma } from "@fal-ai/client/realtime";

const fal = createFalClient({ proxyUrl: "/api/fal/proxy" });

const session = fal.realtime.open(wma("minimax/h3-max/director"), {
  receive: [
    "video",
    "audio"
  ],
  onMedia: (stream) => {
      const element = document.querySelector("video");
      if (element) element.srcObject = stream;
    },
  onData: (raw) => {
      const message = JSON.parse(raw);
      if (message?.type === "configured" && message?.["prompt_version"] === 1) {
        console.log("Session configured. You can now send text updates.");
      }
      console.log(message);
    },
  onState: (state) => console.log("realtime:", state),
  onError: (error) => console.error(error),
});


// Send setup once. The client buffers this until the control channel opens.
// Wait for the matching acknowledgement in onData before sending updates.
session.send({
  "aspect_ratio": "16:9",
  "memory": 3,
  "type": "configure",
  "protocol_version": 1,
  "resolution": "768p",
  "prompt": "A continuous original live-action American sitcom produced in 1994, following the same ensemble of adult roommates, coworkers, neighbors, and rivals. Preserve appearances, apartment and workplace layouts, relationships, jobs, secrets, running jokes, and unresolved storylines. Advance through dialogue, entrances, misunderstandings, escalating attempts to hide mistakes, reversals, and warm character payoffs. Avoid references to existing sitcoms or actors.",
  "prompt_version": 1
});

// Later, release the peer connection and network resources:
// await session.close();
```

## Session flow

Configure once, wait for the model to acknowledge setup, then update the running session. The transport being live does not mean the model is configured.

### 1. Configure the session

Send ` configure ` once with ` /prompt_version ` set to 1. These field paths are JSON Pointers into message payloads. Use the setup message reference below for all configuration fields.

```json
{
  "aspect_ratio": "16:9",
  "memory": 3,
  "type": "configure",
  "protocol_version": 1,
  "resolution": "768p",
  "prompt": "A continuous original live-action American sitcom produced in 1994, following the same ensemble of adult roommates, coworkers, neighbors, and rivals. Preserve appearances, apartment and workplace layouts, relationships, jobs, secrets, running jokes, and unresolved storylines. Advance through dialogue, entrances, misunderstandings, escalating attempts to hide mistakes, reversals, and warm character payoffs. Avoid references to existing sitcoms or actors.",
  "prompt_version": 1
}
```

### 2. Wait for acknowledgement

Wait for ` configured ` whose ` /prompt_version ` matches the version you sent in setup. Only that acknowledgement enables text updates. Pending, applied, or rejected input events do not confirm session readiness.

### 3. Update the running session

Send ` prompt ` with your text at ` /prompt `. Start from ` {"type":"prompt"} `, add the text and the next ` /prompt_version `, and validate the complete payload against the message schema. The first update uses 2; increase by 1 for each subsequent submission.

```json
{
  "type": "prompt",
  "prompt": "They follow a narrow path down to the harbor.",
  "prompt_version": 2
}
```

This action sends only the template, text, and version fields. Other options in the raw message schema are outside this text-update flow. If you use them too, coordinate the same session-wide version sequence.

### Track each update

Match the version in each event to the submission it describes, including the initial setup input. Several updates can have different outcomes while the session stays ready.

- **Pending** (` prompt_pending `): The model is preparing this input. Match the submitted version at ` /prompt_version `.
- **Applied** (` prompt_applied `): Accepted for generation. The result may not be generating or visible yet. Match the submitted version at ` /prompt_version `.
- **Rejected** (` prompt_rejected `): This input was not accepted. An earlier applied input can remain active. Match the submitted version at ` /prompt_version `.

You can send another update while preparation is pending. Newer updates can replace older pending preparation, and the older input may never receive a final event. A missing acknowledgement means the outcome is unknown; it does not prove rejection.

### Handle errors

For ` error `, read the code at ` /code ` and the explanation at ` /error `. Match input failures using ` /prompt_version `.

- **Session failure**: Ends this session attempt, even without a matching version. Codes: ` configuration_timeout `, ` initialization_timeout `, ` invalid_initial_image `, ` invalid_initial_audio `, ` invalid_initial_script `, ` invalid_input `, ` balance_unavailable `, ` content_policy `, ` generation_timeout `, ` generation_failed `.
- **Input failure**: Fails only the submission with a known matching version. An absent or unknown version is diagnostic. Codes: ` stale_prompt_version `.
- **Diagnostic**: Provides information without declaring the session or a submission failed. Codes: ` invalid_message `, ` not_configured `, ` immutable_settings `.

Treat unknown codes as diagnostics. An input failure without a known matching submission is also diagnostic; do not guess which input failed.

### End or reconnect

` stream_exhausted ` ends this session attempt. A closed or failed connection also ends the attempt. Later messages must not reopen it. A session failure does not need to emit a separate end event.

Do not automatically replay setup or updates. Start a new sequence at 1 for a new session. Gaps are allowed; never reuse a version after uncertain delivery, and keep versions within the message schema and JavaScript's safe integer range.


## Media contract

Tracks are described from the browser's perspective.

### Browser sends to the model

None.

### Browser receives from the model

- `video` — optional
  - Settings: `{"frameRate":24}`
- `audio` — optional

## Client-to-model control messages

### Client configure message

- **Wire type**: `configure`
- **Payload**: `object`
- **Correlation field**: `/prompt_version`

- **`prompt`** (`string`, _required_)
  - Constraints: minLength=1, maxLength=50000
- **`resolution`** (`string`, _optional_)
  - Default: `"768p"`
  - Values: `"480p"`, `"768p"`, `"1080p"`
- **`aspect_ratio`** (`string`, _optional_)
  - Default: `"16:9"`
  - Values: `"16:9"`, `"9:16"`, `"1:1"`
- **`image_url`** (`string | null`, _optional_)
  URL of the image to use as the exact first frame. The opening prompt expansion also sees this image, so the first segment's prompt is grounded in it.
  - Default: `null`
  - anyOf alternatives:
    1. `string`
      - Constraints: minLength=1
    2. `null`
- **`end_image_url`** (`string | null`, _optional_)
  One-shot exact final frame for the first chunk. Director jointly plans that arrival and the following checkpoint continuation.
  - Default: `null`
  - anyOf alternatives:
    1. `string`
      - Constraints: minLength=1
    2. `null`
- **`audio_url`** (`string | null`, _optional_)
  Optional startup soundtrack. The stream's audio is pinned to this recording from the first chunk as FL2VA target audio, not a Ref2VA reference: every chunk is conditioned on the next window of it (plus the regenerated seam) until it ends, and the source PCM itself is what plays. Live `prompt` messages can replace or queue more audio at any time.
  - Default: `null`
  - anyOf alternatives:
    1. `string`
      - Constraints: minLength=1
    2. `null`
- **`memory`** (`integer`, _optional_)
  Number of prior segment prompts retained as context for future prompt expansion.
  - Default: `12`
  - Constraints: minimum=1, maximum=50
- **`audio_bitrate`** (`integer | null`, _optional_)
  Session audio target in bits/s: 96000, 128000, or 192000. Explicit values use Opus audio mode on direct WebRTC; LiveKit uses its native mode with the same bitrate target. Null preserves transport defaults (WebRTC: 96000, voip). Immutable; reconnect to compare.
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Values: `96000`, `128000`, `192000`
    2. `null`
- **`seed`** (`integer | null`, _optional_)
  - Default: `null`
- **`type`** (`string`, _required_)
  - Constant: `"configure"`
- **`protocol_version`** (`integer`, _optional_)
  - Constant: `1`
- **`prompt_version`** (`integer`, _required_)
  - Constraints: minimum=1
- **`script`** (`object[] | null`, _optional_)
  Optional upfront script: beats at whole-second offsets from the first generated video. `prompt` stays the series premise; a beat prompt directs from its offset on. Cannot be combined with `end_image_url` or `audio_url` (place them in the script).
  - Default: `null`
  - anyOf alternatives:
    1. `object[]`
      - Constraints: minItems=1, maxItems=64
      - Array items: `object`
        A direction on the associated video's clock, never the stream clock.
        - **`audio_url`** (`string | null`, _optional_)
          Audio that starts playing exactly at this offset as FL2VA target audio; overlapping sources are mixed. The source PCM itself plays.
          - Default: `null`
          - anyOf alternatives:
            1. `string`
              - Constraints: minLength=1
            2. `null`
        - **`end_image_url`** (`string | null`, _optional_)
          Exact final frame of the chunk that ends at this offset. Offsets of successive end images must be at least three seconds apart.
          - Default: `null`
          - anyOf alternatives:
            1. `string`
              - Constraints: minLength=1
            2. `null`
        - **`prompt`** (`string | null`, _optional_)
          Direction that starts at this offset and persists until the next text beat; it also appears as a timed span inside the chunk.
          - Default: `null`
          - anyOf alternatives:
            1. `string`
              - Constraints: minLength=1, maxLength=50000
            2. `null`
        - **`offset`** (`integer`, _required_)
          Whole seconds from the start of the first video generated under this script. Text and audio placed here start at this second; an end image here is the exact final frame at this second.
          - Constraints: minimum=0
        - Additional properties: not allowed
    2. `null`
- Additional properties: not allowed

**Example**

```json
{
  "aspect_ratio": "16:9",
  "memory": 3,
  "type": "configure",
  "protocol_version": 1,
  "resolution": "768p",
  "prompt": "A continuous original live-action American sitcom produced in 1994, following the same ensemble of adult roommates, coworkers, neighbors, and rivals. Preserve appearances, apartment and workplace layouts, relationships, jobs, secrets, running jokes, and unresolved storylines. Advance through dialogue, entrances, misunderstandings, escalating attempts to hide mistakes, reversals, and warm character payoffs. Avoid references to existing sitcoms or actors.",
  "prompt_version": 1
}
```

### Client ping message

- **Wire type**: `ping`
- **Payload**: `object`

- **`type`** (`string`, _required_)
  - Constant: `"ping"`
- **`ts`** (`number`, _required_)
- Additional properties: not allowed

**Example**

```json
{
  "type": "ping",
  "ts": 0
}
```

### Client prompt message

- **Wire type**: `prompt`
- **Payload**: `object`
- **Correlation field**: `/prompt_version`

- **`prompt`** (`string | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `string`
      - Constraints: minLength=1, maxLength=50000
    2. `null`
- **`end_image_url`** (`string | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `string`
      - Constraints: minLength=1
    2. `null`
- **`audio_url`** (`string | null`, _optional_)
  FL2VA target audio for future chunks; this is not a Ref2VA reference. With `audio_behavior` 'replace' (default) it starts at the next undispatched chunk and drops any queued audio; with 'queue' it plays after every previously accepted source ends, sample-exact.
  - Default: `null`
  - anyOf alternatives:
    1. `string`
      - Constraints: minLength=1
    2. `null`
- **`audio_behavior`** (`string`, _optional_)
  'replace' cuts to this audio at the next chunk; 'queue' appends it.
  - Default: `"replace"`
  - Values: `"replace"`, `"queue"`
- **`replan`** (`boolean`, _optional_)
  When a prompt is included: true (default) busts the planned prompt queue so the new direction applies at the next undispatched chunk; false appends the direction after the already-planned chunks.
  - Default: `true`
- **`script_mode`** (`string`, _optional_)
  'replace' cuts to the script at the next chunk; 'append' queues it.
  - Default: `"replace"`
  - Values: `"replace"`, `"append"`
- **`type`** (`string`, _required_)
  - Constant: `"prompt"`
- **`script`** (`object[] | null`, _optional_)
  A new script: beats at whole-second offsets from the first video generated under it. Exclusive with prompt/end_image_url/audio_url. With `script_mode` 'replace' (default) it replaces the pending and current direction at the next undispatched chunk; 'append' starts at the chunk boundary after the running script's last text beat is represented and its audio tails have finished (queued behind earlier appended scripts). Beats without a prompt keep the current text direction.
  - Default: `null`
  - anyOf alternatives:
    1. `object[]`
      - Constraints: minItems=1, maxItems=64
      - Array items: `object`
        A direction on the associated video's clock, never the stream clock.
        - **`audio_url`** (`string | null`, _optional_)
          Audio that starts playing exactly at this offset as FL2VA target audio; overlapping sources are mixed. The source PCM itself plays.
          - Default: `null`
          - anyOf alternatives:
            1. `string`
              - Constraints: minLength=1
            2. `null`
        - **`end_image_url`** (`string | null`, _optional_)
          Exact final frame of the chunk that ends at this offset. Offsets of successive end images must be at least three seconds apart.
          - Default: `null`
          - anyOf alternatives:
            1. `string`
              - Constraints: minLength=1
            2. `null`
        - **`prompt`** (`string | null`, _optional_)
          Direction that starts at this offset and persists until the next text beat; it also appears as a timed span inside the chunk.
          - Default: `null`
          - anyOf alternatives:
            1. `string`
              - Constraints: minLength=1, maxLength=50000
            2. `null`
        - **`offset`** (`integer`, _required_)
          Whole seconds from the start of the first video generated under this script. Text and audio placed here start at this second; an end image here is the exact final frame at this second.
          - Constraints: minimum=0
        - Additional properties: not allowed
    2. `null`
- **`prompt_version`** (`integer`, _required_)
  - Constraints: minimum=1
- Additional properties: not allowed

**Example**

```json
{
  "script_mode": "replace",
  "replan": true,
  "audio_behavior": "replace",
  "type": "prompt",
  "prompt": "They follow a narrow path down to the harbor.",
  "prompt_version": 2
}
```

### Client stop message

- **Wire type**: `stop`
- **Payload**: `object`

- **`type`** (`string`, _required_)
  - Constant: `"stop"`
- Additional properties: not allowed

**Example**

```json
{
  "type": "stop"
}
```

## Model-to-client control messages

### Server audio_applied message

- **Wire type**: `audio_applied`
- **Payload**: `object`

An audio update was accepted; it conditions the next eligible chunk.

``starts_at_chunk_index`` is the first chunk that can carry it (the next
undispatched chunk for ``replace``; for ``queue`` the chunk where the
preceding sources end, if already known).

- **`source`** (`string`, _required_)
- **`remaining_seconds`** (`number`, _required_)
  - Constraints: minimum=0
- **`type`** (`string`, _required_)
  - Constant: `"audio_applied"`
- **`behavior`** (`string`, _required_)
  - Values: `"replace"`, `"queue"`
- **`duration_seconds`** (`number`, _required_)
  - Constraints: exclusiveMinimum=0
- **`prompt_version`** (`integer`, _required_)
  - Constraints: minimum=1
- **`queued_sources`** (`integer`, _required_)
  - Constraints: minimum=0
- **`transcribed`** (`boolean`, _required_)

**Example**

```json
{
  "source": "string",
  "remaining_seconds": 0,
  "type": "audio_applied",
  "behavior": "replace",
  "duration_seconds": 5e-324,
  "prompt_version": 1,
  "queued_sources": 0,
  "transcribed": true
}
```

### Server audio_exhausted message

- **Wire type**: `audio_exhausted`
- **Payload**: `object`

Accepted audio ran out inside this chunk; the rest is silence.

Later chunks continue without audio conditioning (checkpoint continuation
on the same family) until new audio is accepted.

- **`silent_seconds`** (`number`, _required_)
  - Constraints: minimum=0
- **`type`** (`string`, _required_)
  - Constant: `"audio_exhausted"`
- **`chunk_index`** (`integer`, _required_)
  - Constraints: minimum=0
- **`source_version`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Constraints: minimum=0
    2. `null`

**Example**

```json
{
  "silent_seconds": 0,
  "type": "audio_exhausted",
  "chunk_index": 0
}
```

### Server audio_pending message

- **Wire type**: `audio_pending`
- **Payload**: `object`

- **`behavior`** (`string`, _required_)
  - Values: `"replace"`, `"queue"`
- **`type`** (`string`, _required_)
  - Constant: `"audio_pending"`
- **`prompt_version`** (`integer`, _required_)
  - Constraints: minimum=1

**Example**

```json
{
  "behavior": "replace",
  "type": "audio_pending",
  "prompt_version": 1
}
```

### Server audio_rejected message

- **Wire type**: `audio_rejected`
- **Payload**: `object`

- **`type`** (`string`, _required_)
  - Constant: `"audio_rejected"`
- **`error`** (`string`, _required_)
- **`reason`** (`string`, _required_)
  - Values: `"invalid_audio"`, `"content_policy"`, `"preparation_failed"`, `"queue_full"`, `"stale_prompt_version"`
- **`prompt_version`** (`integer`, _required_)
  - Constraints: minimum=1

**Example**

```json
{
  "type": "audio_rejected",
  "error": "string",
  "reason": "invalid_audio",
  "prompt_version": 1
}
```

### Server chunk message

- **Wire type**: `chunk`
- **Payload**: `object`

- **`generation_seconds`** (`number`, _required_)
  - Constraints: minimum=0
- **`native_playable_frame_count`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Constraints: exclusiveMinimum=0
    2. `null`
- **`chunk_index`** (`integer`, _required_)
  - Constraints: minimum=0
- **`generated_frame_count`** (`integer`, _required_)
  - Constraints: exclusiveMinimum=0
- **`buffer_depth_seconds`** (`number`, _required_)
  - Constraints: minimum=0
- **`trimmed_context_frames`** (`integer`, _required_)
  - Constraints: minimum=0
- **`requested_duration_seconds`** (`integer`, _required_)
  - Constraints: minimum=5, maximum=15
- **`prompt_version`** (`integer`, _required_)
  - Constraints: minimum=1
- **`dispatch`** (`object`, _required_)
  - **`phases_ms`** (`object`, _required_)
    - Additional properties: number
  - **`wall_ms`** (`number`, _required_)
    - Constraints: minimum=0
  - **`overhead_ms`** (`number`, _required_)
    - Constraints: minimum=0
  - **`classified_ms`** (`number`, _required_)
    - Constraints: minimum=0
- **`buffer_depth_chunks`** (`integer`, _required_)
  - Constraints: minimum=0
- **`presented_frame_count`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Constraints: exclusiveMinimum=0
    2. `null`
- **`playback_seconds`** (`number`, _required_)
  - Constraints: exclusiveMinimum=0
- **`script_end_keyframe`** (`boolean | null`, _optional_)
  - Default: `null`
- **`scheduling_lead_ms`** (`number`, _required_)
- **`next_generation_estimate_seconds`** (`number`, _required_)
  - Constraints: minimum=0
- **`type`** (`string`, _required_)
  - Constant: `"chunk"`
- **`route`** (`string`, _required_)
  - Values: `"gorgonea"`, `"betelgeuse"`, `"regulus"`, `"unknown"`
- **`script_version`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Constraints: minimum=1
    2. `null`
- **`hard_cut`** (`boolean`, _optional_)
  - Default: `false`
- **`scheduling_slack_ms`** (`number`, _required_)
- **`script_offset_seconds`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Constraints: minimum=0
    2. `null`

**Example**

```json
{
  "generation_seconds": 0,
  "chunk_index": 0,
  "generated_frame_count": 1,
  "buffer_depth_seconds": 0,
  "trimmed_context_frames": 0,
  "requested_duration_seconds": 5,
  "prompt_version": 1,
  "dispatch": {
    "phases_ms": {},
    "wall_ms": 0,
    "overhead_ms": 0,
    "classified_ms": 0
  },
  "buffer_depth_chunks": 0,
  "playback_seconds": 5e-324,
  "scheduling_lead_ms": 0,
  "next_generation_estimate_seconds": 0,
  "type": "chunk",
  "route": "gorgonea",
  "scheduling_slack_ms": 0
}
```

### Server chunk_metrics message

- **Wire type**: `chunk_metrics`
- **Payload**: `object`

- **`chunk_consumable_ready_ms`** (`number | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `number`
      - Constraints: minimum=0
    2. `null`
- **`chunk_consumable_interval_ms`** (`number | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `number`
      - Constraints: minimum=0
    2. `null`
- **`route`** (`string`, _required_)
  - Values: `"gorgonea"`, `"betelgeuse"`, `"regulus"`, `"unknown"`
- **`type`** (`string`, _required_)
  - Constant: `"chunk_metrics"`
- **`chunk_index`** (`integer`, _required_)
  - Constraints: minimum=0
- **`phases_ms`** (`object`, _required_)
  - Additional properties: number
- **`gauges`** (`object`, _required_)
  - Additional properties: number
- **`units`** (`string`, _required_)
  - Constant: `"ms"`

**Example**

```json
{
  "route": "gorgonea",
  "type": "chunk_metrics",
  "chunk_index": 0,
  "phases_ms": {},
  "gauges": {},
  "units": "ms"
}
```

### Server configured message

- **Wire type**: `configured`
- **Payload**: `object`
- **Correlation field**: `/prompt_version`

- **`aspect_ratio`** (`string | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `string`
      - Values: `"16:9"`, `"9:16"`, `"1:1"`
    2. `null`
- **`has_initial_audio`** (`boolean | null`, _optional_)
  - Default: `null`
- **`audio_bitrate`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Values: `96000`, `128000`, `192000`
    2. `null`
- **`type`** (`string`, _required_)
  - Constant: `"configured"`
- **`chunk_duration`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Constraints: minimum=5, maximum=15
    2. `null`
- **`prompt_version`** (`integer`, _required_)
  - Constraints: minimum=1
- **`has_initial_image`** (`boolean | null`, _optional_)
  - Default: `null`
- **`memory`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Constraints: minimum=1, maximum=50
    2. `null`
- **`resolution`** (`string | string | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `string`
      - Values: `"480p"`, `"544p"`, `"640p"`, `"704p"`, `"768p"`
    2. `string`
      - Values: `"480p"`, `"768p"`, `"1080p"`
    3. `null`
- **`acceleration`** (`string | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `string`
      - Values: `"none"`, `"regular"`
    2. `null`
- **`enable_safety_checker`** (`boolean`, _required_)

**Example**

```json
{
  "type": "configured",
  "prompt_version": 1,
  "enable_safety_checker": true
}
```

### Server deadline_missed message

- **Wire type**: `deadline_missed`
- **Payload**: `object`

- **`late_by_seconds`** (`number`, _required_)
  - Constraints: minimum=0
- **`behavior`** (`string`, _required_)
  - Constant: `"freeze_video_and_silence_audio_until_ready"`
- **`type`** (`string`, _required_)
  - Constant: `"deadline_missed"`
- **`chunk_index`** (`integer`, _required_)
  - Constraints: minimum=0

**Example**

```json
{
  "late_by_seconds": 0,
  "behavior": "freeze_video_and_silence_audio_until_ready",
  "type": "deadline_missed",
  "chunk_index": 0
}
```

### Server error message

- **Wire type**: `error`
- **Payload**: `object`
- **Correlation field**: `/prompt_version`

- **`detail`** (`object[] | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `object[]`
      - Array items: `object`
    2. `null`
- **`code`** (`string`, _required_)
  - Values: `"balance_unavailable"`, `"content_policy"`, `"configuration_timeout"`, `"generation_failed"`, `"generation_timeout"`, `"immutable_settings"`, `"initialization_timeout"`, `"invalid_initial_image"`, `"invalid_initial_audio"`, `"invalid_initial_script"`, `"invalid_input"`, `"invalid_message"`, `"not_configured"`, `"stale_prompt_version"`
- **`type`** (`string`, _required_)
  - Constant: `"error"`
- **`error`** (`string`, _required_)
- **`prompt_version`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Constraints: minimum=1
    2. `null`

**Example**

```json
{
  "code": "balance_unavailable",
  "type": "error",
  "error": "string"
}
```

### Server pong message

- **Wire type**: `pong`
- **Payload**: `object`

- **`type`** (`string`, _required_)
  - Constant: `"pong"`
- **`client_ts`** (`number`, _required_)

**Example**

```json
{
  "type": "pong",
  "client_ts": 0
}
```

### Server prompt_applied message

- **Wire type**: `prompt_applied`
- **Payload**: `object`
- **Correlation field**: `/prompt_version`

A direction (or script) is admitted; the script fields report scripts.

``script_origin_chunk_index`` is the first chunk generated under the
script when that is already fixed (a replacement binds to the next
undispatched chunk); an appended script reports ``None`` until it starts.

- **`script_mode`** (`string | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `string`
      - Values: `"replace"`, `"append"`
    2. `null`
- **`type`** (`string`, _required_)
  - Constant: `"prompt_applied"`
- **`script_beats`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Constraints: minimum=1
    2. `null`
- **`script_origin_chunk_index`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Constraints: minimum=0
    2. `null`
- **`script_queued`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Constraints: minimum=0
    2. `null`
- **`prompt_version`** (`integer`, _required_)
  - Constraints: minimum=1

**Example**

```json
{
  "type": "prompt_applied",
  "prompt_version": 1
}
```

### Server prompt_pending message

- **Wire type**: `prompt_pending`
- **Payload**: `object`
- **Correlation field**: `/prompt_version`

- **`type`** (`string`, _required_)
  - Constant: `"prompt_pending"`
- **`prompt_version`** (`integer`, _required_)
  - Constraints: minimum=1

**Example**

```json
{
  "type": "prompt_pending",
  "prompt_version": 1
}
```

### Server prompt_rejected message

- **Wire type**: `prompt_rejected`
- **Payload**: `object`
- **Correlation field**: `/prompt_version`

- **`type`** (`string`, _required_)
  - Constant: `"prompt_rejected"`
- **`error`** (`string | null`, _optional_)
  - Default: `null`
- **`reason`** (`string`, _required_)
  - Values: `"content_policy"`, `"preparation_failed"`, `"stale_prompt_version"`, `"invalid_script"`, `"infeasible_timing"`, `"invalid_audio"`, `"invalid_image"`, `"queue_full"`
- **`prompt_version`** (`integer`, _required_)
  - Constraints: minimum=1

**Example**

```json
{
  "type": "prompt_rejected",
  "reason": "content_policy",
  "prompt_version": 1
}
```

### Server session_info message

- **Wire type**: `session_info`
- **Payload**: `object`

- **`default_acceleration`** (`string`, _optional_)
  - Constant: `"regular"`
- **`script_max_queued`** (`integer`, _optional_)
  - Constant: `4`
- **`script_modes`** (`string[]`, _optional_)
  - Default: `["replace","append"]`
  - Array items: `string`
    - Values: `"replace"`, `"append"`
- **`script_min_end_image_spacing_seconds`** (`integer`, _optional_)
  - Constant: `3`
- **`script_max_beats`** (`integer`, _optional_)
  - Constant: `64`
- **`controller_machine_type`** (`string`, _optional_)
  - Constant: `"XL"`
- **`one_session_per_machine`** (`boolean`, _optional_)
  - Constant: `true`
- **`continuation_playback_seconds`** (`number`, _optional_)
  - Default: `8.5`
- **`script_max_audio_beats`** (`integer`, _optional_)
  - Constant: `8`
- **`script_session_max_decoded_audio_bytes`** (`integer`, _optional_)
  - Default: `335544320`
- **`audio_sample_rate`** (`integer`, _optional_)
  - Constant: `48000`
- **`continuation_context_frames`** (`integer`, _optional_)
  - Constant: `39`
- **`accelerations`** (`string[]`, _optional_)
  - Default: `["none","regular"]`
  - Array items: `string`
    - Values: `"none"`, `"regular"`
- **`type`** (`string`, _required_)
  - Constant: `"session_info"`
- **`default_chunk_duration`** (`integer`, _optional_)
  - Constant: `10`
- **`server_message_types`** (`string[]`, _optional_)
  - Default: `["audio_applied","audio_exhausted","audio_pending","audio_rejected","chunk","chunk_metrics","configured","deadline_missed","error","pong","prompt_applied","prompt_pending","prompt_rejected","session_info","session_metrics","stream_exhausted"]`
  - Array items: `string`
    - Values: `"audio_applied"`, `"audio_exhausted"`, `"audio_pending"`, `"audio_rejected"`, `"chunk"`, `"chunk_metrics"`, `"configured"`, `"deadline_missed"`, `"error"`, `"pong"`, `"prompt_applied"`, `"prompt_pending"`, `"prompt_rejected"`, `"session_info"`, `"session_metrics"`, `"stream_exhausted"`
- **`session_limit_scope`** (`string`, _optional_)
  - Default: `"configured"`
  - Values: `"configured"`, `"effective"`
- **`backend_selection`** (`string`, _optional_)
  - Constant: `"minimax-h3-turbo-balancer"`
- **`scripts`** (`boolean`, _optional_)
  - Constant: `true`
- **`resolutions`** (`string[]`, _optional_)
  - Default: `["480p","768p","1080p"]`
  - Array items: `string`
    - Values: `"480p"`, `"768p"`, `"1080p"`
- **`script_max_decoded_audio_bytes`** (`integer`, _optional_)
  - Default: `67108864`
- **`chunk_seconds`** (`integer`, _optional_)
  - Constant: `10`
- **`opening_reserved`** (`boolean`, _optional_)
  - Default: `false`
- **`audio_bitrates`** (`integer[]`, _optional_)
  - Default: `[96000,128000,192000]`
  - Array items: `integer`
    - Values: `96000`, `128000`, `192000`
- **`max_chunk_duration`** (`integer`, _optional_)
  - Constant: `15`
- **`max_memory`** (`integer`, _optional_)
  - Constant: `50`
- **`conditioning_audio_sample_rate`** (`integer`, _optional_)
  - Constant: `32000`
- **`default_audio_bitrate`** (`integer | null`, _optional_)
  - Default: `null`
  - anyOf alternatives:
    1. `integer`
      - Values: `96000`, `128000`, `192000`
    2. `null`
- **`aspect_ratios`** (`string[]`, _optional_)
  - Default: `["16:9","9:16","1:1"]`
  - Array items: `string`
    - Values: `"16:9"`, `"9:16"`, `"1:1"`
- **`max_session_seconds`** (`number | null`, _optional_)
  - Default: `null`
- **`script_max_pending`** (`integer`, _optional_)
  - Constant: `4`
- **`prompt_deck_size`** (`integer`, _optional_)
  - Constant: `6`
- **`protocol_version`** (`integer`, _optional_)
  - Constant: `1`
- **`audio_conditioning`** (`boolean`, _optional_)
  - Constant: `true`
- **`script_min_opening_chunk_seconds`** (`integer`, _optional_)
  - Constant: `5`
- **`min_memory`** (`integer`, _optional_)
  - Constant: `1`
- **`max_audio_source_seconds`** (`number`, _optional_)
  - Default: `600`
- **`audio_behaviors`** (`string[]`, _optional_)
  - Default: `["replace","queue"]`
  - Array items: `string`
    - Values: `"replace"`, `"queue"`
- **`min_chunk_duration`** (`integer`, _optional_)
  - Constant: `5`
- **`fps`** (`integer`, _optional_)
  - Constant: `24`
- **`prompt_context_segments`** (`integer`, _optional_)
  - Constant: `12`
- **`app`** (`string`, _optional_)
  - Constant: `"minimax-h3-max-director"`
- **`default_memory`** (`integer`, _optional_)
  - Constant: `12`
- **`client_message_types`** (`string[]`, _optional_)
  - Default: `["configure","ping","prompt","stop"]`
  - Array items: `string`
    - Values: `"configure"`, `"ping"`, `"prompt"`, `"stop"`
- **`prompt_expander`** (`string`, _optional_)
  - Constant: `"fast"`
- **`script_max_end_images`** (`integer`, _optional_)
  - Constant: `16`
- **`script_min_chunk_seconds`** (`integer`, _optional_)
  - Constant: `3`

**Example**

```json
{
  "default_acceleration": "regular",
  "script_max_queued": 4,
  "script_min_end_image_spacing_seconds": 3,
  "script_max_beats": 64,
  "controller_machine_type": "XL",
  "one_session_per_machine": true,
  "script_max_audio_beats": 8,
  "audio_sample_rate": 48000,
  "continuation_context_frames": 39,
  "type": "session_info",
  "default_chunk_duration": 10,
  "backend_selection": "minimax-h3-turbo-balancer",
  "scripts": true,
  "chunk_seconds": 10,
  "max_chunk_duration": 15,
  "max_memory": 50,
  "conditioning_audio_sample_rate": 32000,
  "script_max_pending": 4,
  "prompt_deck_size": 6,
  "protocol_version": 1,
  "audio_conditioning": true,
  "script_min_opening_chunk_seconds": 5,
  "min_memory": 1,
  "min_chunk_duration": 5,
  "fps": 24,
  "prompt_context_segments": 12,
  "app": "minimax-h3-max-director",
  "default_memory": 12,
  "prompt_expander": "fast",
  "script_max_end_images": 16,
  "script_min_chunk_seconds": 3
}
```

### Server session_metrics message

- **Wire type**: `session_metrics`
- **Payload**: `object`

- **`history_size`** (`integer`, _required_)
  - Constraints: minimum=0
- **`history_limit`** (`integer`, _required_)
  - Constraints: minimum=1
- **`type`** (`string`, _required_)
  - Constant: `"session_metrics"`
- **`session_wall_ms`** (`number`, _required_)
  - Constraints: minimum=0
- **`final`** (`boolean`, _optional_)
  - Default: `false`
- **`gauges`** (`object`, _required_)
  - Additional properties: number
- **`phases`** (`object`, _required_)
  - Additional properties: object
    - **`count`** (`integer`, _required_)
      - Constraints: minimum=0
    - **`max_ms`** (`number`, _required_)
      - Constraints: minimum=0
    - **`p95_ms`** (`number`, _required_)
      - Constraints: minimum=0
    - **`total_ms`** (`number`, _required_)
      - Constraints: minimum=0
    - **`p50_ms`** (`number`, _required_)
      - Constraints: minimum=0
- **`units`** (`string`, _required_)
  - Constant: `"ms"`

**Example**

```json
{
  "history_size": 0,
  "history_limit": 1,
  "type": "session_metrics",
  "session_wall_ms": 0,
  "gauges": {},
  "phases": {},
  "units": "ms"
}
```

### Server stream_exhausted message

- **Wire type**: `stream_exhausted`
- **Payload**: `object`

- **`type`** (`string`, _required_)
  - Constant: `"stream_exhausted"`
- **`reason`** (`string`, _required_)
  - Values: `"stopped"`, `"session_limit"`
- **`chunks`** (`integer`, _required_)
  - Constraints: minimum=0

**Example**

```json
{
  "type": "stream_exhausted",
  "reason": "stopped",
  "chunks": 0
}
```

## Additional Resources

### Documentation

- [Model Playground](https://fal.ai/models/minimax/h3-max/director)
- [API Documentation](https://fal.ai/models/minimax/h3-max/director/api)
- [OpenAPI Schema](https://fal.ai/api/openapi/queue/openapi.json?endpoint_id=minimax/h3-max/director)
- [AsyncAPI Contract](https://fal.ai/api/apps/fal-ai/minimax-h3-max-director/asyncapi.json)

### fal.ai Platform

- [Platform Documentation](https://fal.ai/docs/documentation)
- [Python Client](https://fal.ai/docs/api-reference/client-libraries/python)
- [JavaScript Client](https://fal.ai/docs/api-reference/client-libraries/javascript)

### Other agent-readable surfaces

This file covers one model. To find anything else:

- [Platform overview](https://fal.ai/llms.txt): Entry points and representative endpoint IDs
- [Documentation index](https://fal.ai/docs/llms.txt): Every documentation page
- [Full documentation text](https://fal.ai/docs/llms-full.txt): The whole documentation inlined
- Any other model: `https://fal.ai/models/<endpoint-id>/llms.txt`
