The room object
Every session carries aroom object describing where FaceMode should
publish:
The room type is locked to the session: a reconnect that passes a
room with
a different type is rejected with ROOM_TYPE_MISMATCH.
How the room name is resolved
Forlivekit rooms the name is resolved in this order:
livekit_room_idon the create request body, if present.room.name, if present.- The
video.roomclaim inside the LiveKit token itself.
ROOM_INVALID - in practice, minting the publish token with a room grant
already satisfies resolution. For daily rooms an omitted name falls back to
a generated identifier, since the Daily room is identified by its URL.
LiveKit rooms
Create the room yourself (LiveKit Cloud dashboard,RoomServiceClient, or
your existing provisioning). Then mint two tokens with different
identities:
- Identity collision - if the publish token shares an identity with your agent or a viewer, LiveKit kicks the older participant. Always give the avatar its own identity.
- Token lifetime - the token must stay valid for the whole session. Mint
it with a TTL that covers the expected call duration; reconnect requests can
carry a replacement
roomobject with a fresh token if needed.
Daily rooms
Fortype: "daily", create the room through the Daily REST API and pass its
URL as room.url. room.token is a Daily meeting token scoped to that room
with permission to join and publish - your backend mints it with
properties.room_name set to the room name. Viewers join with their own
meeting tokens (or the room URL directly for public rooms) and subscribe to
the avatar participant’s tracks.
What FaceMode publishes
Once the session is negotiated, the avatar joins as a single participant and publishes two tracks:- Avatar video - the 1024x1024 stream (VP8 or H264), carrying the idle loop, live lip-synced frames, and the crossfades between them.
- Audio - the rendered speech track, published when speech is active.
Reconnects and credential rotation
POST /api/sessions/:id/reconnect accepts an optional replacement room
object. Use it when the original room token is about to expire or you are
moving the session to a different room instance. Constraints:
room.typemust match the session’s original type.inputProvider, if sent, must equal the value used at creation.- The response mints a fresh one-time
wsTokenfor the new socket.
Credential checklist
1
Create the room in your own account
LiveKit
RoomServiceClient or the Daily REST API. FaceMode never creates
rooms for you.2
Mint the publish token server-side
LiveKit:
room_join + can_publish + can_subscribe on the room name,
under a dedicated identity. Daily: a meeting token scoped to the room.3
Pass it as room.token on session creation
It travels inside the session’s signed credential - keep it off
browsers and out of logs.
4
Mint viewer tokens per user
Subscribe-only grants, one identity each. This is the only room credential
that may reach a browser.
GET /api/sessions/:id echoes room.type back but never the URL or token -
credentials are returned only in the create and reconnect responses.Related pages
- Session lifecycle - where the room object appears in create and reconnect calls.
- Input providers - the audio side of the session.