- The player’s device asks your server to talk to a character.
- Your server mints a secret with its API key (
POST /v1/realtime/client_secrets) and sends the device the secret’svalue(orsecret.joinfrom the SDKs). - The device opens the session with it, over WebSocket or WebRTC, straight to EESI.
- Optionally, EESI posts each reply to your server, signed, and your server steers the session over a control channel.
Mint a secret
value is the secret. It opens one session, and expires after
expires_after.seconds (10 to 600) if unused. The session itself lasts as long
as any session, or max_duration_seconds.
With the SDKs, character.clientSecret(...) (TypeScript) and
character.client_secret(...) (Python) compose the session from your character,
its memories and live state, and return secret.join: everything the device
needs, and nothing it must not have.
What the device can and cannot change
eesi_lock names what is fixed; "all" fixes everything. A locked field in the
device’s session.update is dropped, and the rest applies. A locked event is
refused with an error whose code is session_locked.
Even with everything locked, the device can still stream microphone audio, add
the player’s own typed messages (
conversation.item.create with a user
message), ask for a reply (response.create, plain), and send tool results.
eesi_limits, eesi_webhook, eesi_metadata and eesi_data are never part
of the session configuration, so no client event can touch them.
Call length and silence
Microphone audio alone is not activity: a device streams silence
continuously. The player speaking, a typed message, a request for a reply and
the character answering all are. When a limit is reached the device receives
reason is silence or max_duration), and the socket closes normally
(1000). The SDKs end the session with reason hangup.
WebRTC
The same secret opens a WebRTC call, so phones and browsers get the platform’s echo cancellation and Opus. Post the SDP offer to/v1/realtime/calls with the
secret where OpenAI’s clients put their ephemeral key:
application/sdp. Offer exactly one bidirectional Opus audio
track and a data channel; events flow on the data channel as they do on the
WebSocket. The call is the session the secret binds, with every lock, limit,
webhook and data setting. The secret is spent by the first call or socket that
presents it. In secret.join the SDKs include token and callsUrl for this.
Webhooks
Witheesi_webhook, EESI posts the session’s conversation to your URL as it
happens: what the player said or typed (input.completed), each finished reply
(response.completed), and the session’s end with its whole transcript
(session.ended). The URL must be public HTTPS; it is checked when you mint and
resolved again before every post.
"source": "speech") or typed ("text"):
EESI-Signature is v1= and the hex HMAC-SHA256, keyed with your secret, of
{EESI-Webhook-Id}.{EESI-Webhook-Timestamp}.{raw body}. Check it over the raw
body, and refuse a timestamp more than a few minutes old. The SDKs do both:
Remember players across calls
A character can remember each player from one call to the next even though the player’s device holds the session. Your server keeps the memories (in your database, or a file), the SDK puts the player’s into each client secret it mints, and thesession.ended webhook is what it learns from:
rules say what may be kept, in your words. When a
player deletes their account, sage.memory.erase({ playerId }) (Python:
erase(player_id=...)) removes everything about them. This needs no WebSocket on
your server, so it runs on Node 18 and later.
What the session’s audio and words are used for
eesi_data narrows what your organization’s own settings allow; it never
widens them.
"train": false: the session is never used to train, evaluate or improve any model, whatever your organization grants now or later. It is marked when it opens, and every review, dataset and evaluation skips it."record": false: no recording or transcript is kept after the session, and the copy a dropped call would resume from is erased when it ends. The device is told it is not recorded (eesi.recording_disclosure).
"record": false, no recording or transcript is kept after the session ends),
recordings and transcripts are kept for your retention period (one year unless
your organization set another), and none are used to improve Nur unless your
organization turned on Help improve Nur.