The shape of every integration
Whatever you’re building — a web embed, a native app, a character your users talk to — the flow is the same three moves:1
Have a world
Generate one from a premise (
POST /v1/worlds), build one visually in the
Studio, or import one. A world carries its own state graph — states,
choices, endings — that your code can read and react to.2
Mint a session on your server
Your secret key stays server-side. Exchange it for a short-lived session
token bound to a world, a player identity, and your origin:
Pick your path
Characters and simulation are the same primitives wearing different clothes: a
character is a world that talks (
/say, /tts, cross-session memory), and
simulation is a session your code drives instead of a person. If you can mount
a world, you already know how to do both.
Sessions are the metering unit
A live stream reservessession_seconds against your daily budget, fail-closed
— when the budget is gone, new sessions get a 402 instead of a surprise bill.
Concurrency is capped per app and settled when a session ends. Numbers and
knobs: Pricing & billing, Rate limits.
The live embed path currently fires
onReady and onError on the page side;
richer gameplay callbacks (onChoice, onEnding) are delivered on the test
path today and are rolling out to the live player bridge — see
Embedding for the current support matrix before you build page
logic on them. Inside the player, your user’s controls are live either way.Next steps
Quickstart
API key → generated world → playable embed, in one sitting.
Embedding
Mount options, events, theming, token refresh, cross-origin security.
Session handoff & continuity
The drift-refresh double-buffer that keeps long streams clean.
Talk to a character in 5 minutes
The smallest end-to-end interactive integration you can run today.

