Loading API documentation
Start Session
The client provides a convenient way to interact with the model API.
npm install @fal-ai/client@alpha @fal-ai/server-proxy@alphafal.realtime.open is currently available on the alpha release and may change in a minor version.
Keep FAL_KEY on your server and expose an authenticated proxy route to your browser. For a Next.js App Router application, create app/api/fal/proxy/route.ts:
import { route } from "@fal-ai/server-proxy/nextjs";
export const { GET, POST, PUT } = route;Set FAL_KEY in the server environment, and protect this route with your application's authentication before deploying it.
This deployment publishes a WMA WebRTC contract. The example uses fal.realtime.open; its media handlers, capture constraints, and control message are generated from the linked AsyncAPI document.
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("fal-ai/lingbot-world-2"), {
receive: [
"video"
],
onMedia: (stream) => {
const element = document.querySelector("video");
if (element) element.srcObject = stream;
},
onData: (raw) => {
const message = JSON.parse(raw);
console.log(message);
},
onState: (state) => console.log("realtime:", state),
onError: (error) => console.error(error),
});
// Consult the session flow and message reference before sending control messages.
// Later, release the peer connection and network resources:
// await session.close();This world starts automatically. Wait for the first video frame before using the movement controls.
Send commands with held controls in active and newly pressed controls in activated. Send empty arrays when controls are released or focus leaves the world.
configure and wait for configured before sending another world update. Setup is optional and can be used once per session.reset and wait for reset_applied before sending another world update.prompt and wait for prompt_applied before sending another world update.World updates run one at a time and must not be replayed automatically. A error event is diagnostic and does not identify a failed update; read /error for details. The session ends on stream_exhausted.
The browser connects through your server proxy, which reads FAL_KEY from the server environment. Never put that key in browser code.
When running code on the client-side (e.g. in a browser, mobile app or GUI applications), make sure to not expose your FAL_KEY. Instead, use a server-side proxy to make requests to the API. For more information, check out our server-side integration guide.
Client contract for the WebRTC session created by the linked OpenAPI operation.
Tracks are described from the browser's perspective. Send tracks are captured by the browser and sent to the model; receive tracks come back from the model.
No send media tracks.
{
"height": 960,
"frameRate": 48,
"width": 1664
}type: "commands"payload: objectSemantic command-state report.
active contains commands currently held by the user and activated
contains edge-triggered commands since the previous report. A browser may
map a keyboard, gamepad, touch control, or agent action to these names.
activestring[]maxItems: 17
stringValues: "forward", "left", "backward", "right", "look_up", "look_left", "look_down", "look_right", "quick_action_1", "quick_action_2", "quick_action_3", "quick_action_4", "quick_action_5", "quick_action_6", "quick_action_7", "quick_action_8", "quick_action_9"
activatedstring[]maxItems: 17
stringValues: "forward", "left", "backward", "right", "look_up", "look_left", "look_down", "look_right", "quick_action_1", "quick_action_2", "quick_action_3", "quick_action_4", "quick_action_5", "quick_action_6", "quick_action_7", "quick_action_8", "quick_action_9"
typestring* requiredConstant: "commands"
{
"active": [
"forward"
],
"activated": [],
"type": "commands"
}type: "configure"payload: objectOptionally replace the automatic default world, once per connection.
Await configured before submitting more controls. Use reset for
subsequent restarts. Image URL takes precedence over the preset. Safety,
prompt expansion, and the initial quick actions apply to the whole session.
presetstring | nullChoose a built-in world, or provide a starting image below.
Default: null
At most 100 characters when not null
promptstring | nullOptionally replace the starting world's description.
Default: null
At most 2000 characters when not null
image_urlstring | nullUse your own image instead of a built-in world.
Default: null
At most 4096 characters when not null
enable_prompt_expansionbooleanRewrite world descriptions, updates, and quick actions into detailed interactive prompts with an LLM.
Default: true
enable_safety_checkerbooleanScreen prompts and images with standard thresholds. When disabled, only illegal content is blocked.
Default: true
quick_actionsobject[]Up to nine actions, each on its own number key.
maxItems: 9
objectOne action performed while its number key is held.
keyinteger* requiredNumber key (1-9) that performs this action while held.
minimum: 1 · maximum: 9
titlestring* requiredLabel shown next to the action's button.
At least 1 character · At most 40 characters
descriptionstring* requiredWhat happens while the key is held; combined with the world description.
At least 1 character · At most 1000 characters
typestring* requiredConstant: "configure"
A spectacular Mediterranean cliff city above the sea. A broad level stone promenade between terraced gardens leads to an open lookout, with small groups of visitors beside the path, distant boats, warm limestone architecture and immense clear ocean views.
{
"quick_actions": [],
"enable_prompt_expansion": true,
"image_url": "https://v3b.fal.media/files/b/0aad61cc/2Yx7Ey7Pi2QblGQXyf4yY_XdmbNwp8.png",
"type": "configure",
"enable_safety_checker": true,
"prompt": "Photorealistic third-person exploration. Natural sunset light, believable stone and vegetation, true photographic materials. A spectacular Mediterranean cliff city above the sea. A broad level stone promenade between terraced gardens leads to an open lookout, with small groups of visitors beside the path, distant boats, warm limestone architecture and immense clear ocean views. Adult woman with warm brown skin, dark curly ponytail, burnt-orange windbreaker, ivory hiking trousers and dark boots. Third-person follow camera directly behind the character, complete body clearly visible at lower center, facing away along the open route. Keep the avatar visible and recognizable in every future view. Move smoothly forward together with the avatar; stable upright horizon, no cuts, no first-person conversion. Navigation-ready: minimum six-metre-wide unobstructed level route, floor visible to the vanishing point, all obstacles and other characters beside the path, open large turns, no stairs or narrow doorways."
}type: "keys"payload: objectLegacy physical-key report retained for existing WMA clients.
pressedstring[]maxItems: 32
stringactivatedstring[]maxItems: 32
stringtypestring* requiredConstant: "keys"
{
"type": "keys"
}type: "ping"payload: objectLatency probe; the server echoes ts back in a pong payload.
typestring* requiredConstant: "ping"
tsnumber | nullDefault: null
{
"type": "ping"
}type: "prompt"payload: objectpromptstring* requiredChange the scene's description while continuing this world.
At least 1 character · At most 2000 characters
typestring* requiredConstant: "prompt"
{
"type": "prompt",
"prompt": "A serene lakeside scene with a lone tree standing in calm water, surrounded by distant snow-capped mountains under a bright blue sky with drifting white clouds. Gentle ripples reflect the tree and sky."
}type: "quick_actions"payload: objectReplace the whole quick-action mapping; keys left out are un-mapped.
An action changes generation once quick_actions_state reports it ready.
typestring* requiredConstant: "quick_actions"
actionsobject[]* requiredUp to nine actions, each on its own number key.
maxItems: 9
objectOne action performed while its number key is held.
keyinteger* requiredNumber key (1-9) that performs this action while held.
minimum: 1 · maximum: 9
titlestring* requiredLabel shown next to the action's button.
At least 1 character · At most 40 characters
descriptionstring* requiredWhat happens while the key is held; combined with the world description.
At least 1 character · At most 1000 characters
Map dragon-rider actions to keys 1-3.
{
"type": "quick_actions",
"actions": [
{
"title": "Breathe fire",
"description": "The dragon rears its head and breathes a roaring torrent of fire ahead.",
"key": 1
},
{
"title": "Roar",
"description": "The dragon throws its head back and roars, scattering birds from the canopy.",
"key": 2
},
{
"title": "Beat wings",
"description": "The dragon beats its huge wings, whipping up a storm of leaves from the trees below.",
"key": 3
}
]
}type: "reset"payload: objectpresetstring | nullChoose a built-in world, or provide a starting image below.
Default: null
At most 100 characters when not null
promptstring | nullOptionally replace the starting world's description.
Default: null
At most 2000 characters when not null
image_urlstring | nullUse your own image instead of a built-in world.
Default: null
At most 4096 characters when not null
typestring* requiredConstant: "reset"
A spectacular Mediterranean cliff city above the sea. A broad level stone promenade between terraced gardens leads to an open lookout, with small groups of visitors beside the path, distant boats, warm limestone architecture and immense clear ocean views.
{
"type": "reset",
"image_url": "https://v3b.fal.media/files/b/0aad61cc/2Yx7Ey7Pi2QblGQXyf4yY_XdmbNwp8.png",
"prompt": "Photorealistic third-person exploration. Natural sunset light, believable stone and vegetation, true photographic materials. A spectacular Mediterranean cliff city above the sea. A broad level stone promenade between terraced gardens leads to an open lookout, with small groups of visitors beside the path, distant boats, warm limestone architecture and immense clear ocean views. Adult woman with warm brown skin, dark curly ponytail, burnt-orange windbreaker, ivory hiking trousers and dark boots. Third-person follow camera directly behind the character, complete body clearly visible at lower center, facing away along the open route. Keep the avatar visible and recognizable in every future view. Move smoothly forward together with the avatar; stable upright horizon, no cuts, no first-person conversion. Navigation-ready: minimum six-metre-wide unobstructed level route, floor visible to the vanishing point, all obstacles and other characters beside the path, open large turns, no stairs or narrow doorways."
}type: "stop"payload: objectAdditional properties: not allowed
typestring* requiredConstant: "stop"
{
"type": "stop"
}type: "configured"payload: objectenable_prompt_expansionboolean* requiredtypestring* requiredConstant: "configured"
enable_safety_checkerboolean* requiredWhether standard screening is in effect for this session.
promptstring* requiredWorld description now in effect, after any prompt expansion.
{
"enable_prompt_expansion": true,
"type": "configured",
"enable_safety_checker": true,
"prompt": "string"
}type: "error"payload: objecttypestring* requiredConstant: "error"
retryableboolean | nullWhether retrying unchanged input may succeed; absent if unspecified.
Default: null
errorstring* required{
"type": "error",
"error": "string"
}type: "pong"payload: objectReply to a ping, echoing the client's timestamp for RTT measurement.
The echoed timestamp has two wire spellings: apps that handle ping
themselves echo ts; the fallback handler in
:class:registry.wma.sdk.Session replies with client_ts. Clients read
whichever is present. server_ts is the (unsynchronized) runner clock; it
only shows how the round trip divides once the client has an offset estimate.
typestring* requiredConstant: "pong"
server_tsnumber | nullDefault: null
client_tsnumber | nullDefault: null
tsnumber | nullDefault: null
{
"type": "pong"
}type: "prompt_applied"payload: objecttypestring* requiredConstant: "prompt_applied"
promptstring* requiredWorld description now in effect, after any prompt expansion.
{
"type": "prompt_applied",
"prompt": "string"
}type: "quick_actions_state"payload: objectThe quick-action mapping and which actions are ready to use.
typestring* requiredConstant: "quick_actions_state"
actionsobject[]* requiredobjecttitlestring* requiredreadyboolean* requiredHolding the key changes generation.
keyinteger* requiredpromptstring | nullPrompt attended while the key is held.
Default: null
{
"type": "quick_actions_state",
"actions": []
}type: "reset_applied"payload: objecttypestring* requiredConstant: "reset_applied"
promptstring* requiredWorld description now in effect, after any prompt expansion.
{
"type": "reset_applied",
"prompt": "string"
}type: "session_info"payload: objectmodel_variantstringConstant: "14b-causal-fast"
model_revisionstring* requiredmax_blocksinteger* requiredsource_revisionstringDefault: "1895d300d8ac936401689b26389f51cbd36530eb"
pixel_frames_per_blockintegerDefault: 12
model_idstring* requiredmax_quick_actionsintegerDefault: 9
default_promptstring* requiredfirst_block_pixel_framesintegerDefault: 9
presetsobject[]* requiredobjectnamestring* requiredpromptstring* requiredtypestring* requiredConstant: "session_info"
frames_per_secondnumber* requiredquick_action_keysstring[]stringunsupported_featuresstring[]stringresolutionobject* requiredheightinteger* requiredwidthinteger* requiredkey_orderstring[]* requiredstringconflict_groupsstring[][]* requiredstring[]stringsupported_controlsstring[]stringturnboolean* requiredgeneration_speed_verifiedbooleanDefault: false
turn_statusstring* requiredframes_per_blockinteger* required{
"model_variant": "14b-causal-fast",
"model_revision": "string",
"max_blocks": 0,
"model_id": "string",
"default_prompt": "string",
"presets": [],
"type": "session_info",
"frames_per_second": 0,
"resolution": {
"height": 0,
"width": 0
},
"key_order": [],
"conflict_groups": [],
"turn": true,
"turn_status": "string",
"frames_per_block": 0
}type: "stats"payload: objectqueue_age_ms_p50number* requirednative_timingobject | nullDefault: null
Must match at least one of the following:
objectAdditional properties: number | integer
number | integernullqueue_age_ms_maxnumber* requiredgeneration_fpsnumber* requiredtypestring* requiredConstant: "stats"
block_secondsnumber* requiredgpu_wait_fracnumber* requiredpace_sleep_ms_avgnumber* requiredblock_indexinteger* requiredqueue_depthinteger* required{
"queue_age_ms_p50": 0,
"queue_age_ms_max": 0,
"generation_fps": 0,
"type": "stats",
"block_seconds": 0,
"gpu_wait_frac": 0,
"pace_sleep_ms_avg": 0,
"block_index": 0,
"queue_depth": 0
}type: "stream_exhausted"payload: objectThe model has no more frames to send and the current peer is closing. Clients must negotiate a new session to continue.
typestring* requiredConstant: "stream_exhausted"
{
"type": "stream_exhausted"
}