Join a private intercom
Intercom audio is private crew communication. Joining does not add a program source or broadcast a microphone, camera, or screen. Availability depends on the studio's intercom capability. A successful control request confirms membership; it does not prove that another participant can hear audio.
Use intercom:read to read GET /v1/studios/{studioId}/intercom/rooms and receive
room status over the studio event stream. Use intercom:join for membership
operations. Microphone enablement additionally requires intercom:publish and
studio edit permission; listening requires studio view permission. These scopes
are explicit and are not added to existing API keys automatically.
Join listening
Send POST /v1/studios/{studioId}/intercom/memberships:
{"channel":"crew","idempotencyKey":"client-generated-unique-attempt-key"}
Retain the key for retries of this same join attempt. A new deliberate join after
leaving uses a new key. Retrying an old or retired attempt cannot replace a newer
membership. The response contains an opaque membershipId, a room snapshot,
media endpoints, a private token, and separate membership and credential expiry
times. Treat the token and TURN credentials as secrets; do not log them or send
them through the event stream.
Subscribe to the other publishing participants' audioPath values using the
returned media base and credentials. Exclude your own publish path. A microphone
grant does not mean the publisher has started sending media: watch its reported
microphoneState, and handle a bounded initial stream-readiness delay. Keep
playback blocked/pending/error visible; browsers may require an explicit user
gesture to enable audio.
Request a microphone explicitly
Only after an explicit local user gesture, send
POST /v1/studios/{studioId}/intercom/memberships/{membershipId}/microphone with:
{"publish":true}
The client must independently request microphone permission and publish only
that audio track using the returned grant. Never capture a device merely because
a roster or refreshed grant says canPublish:true. Keep the microphone muted
until the publisher connects and the operator explicitly chooses to talk.
Send {"publish":false} to withdraw microphone permission while retaining
listening. Stop the client's owned publisher and microphone tracks immediately.
This control operation cannot instantly revoke a previously issued media token
or an already accepted media session; do not rely on it as remote media teardown.
Refresh, leave, and report local state
Refresh the current membership before either expiry with bodyless
POST /v1/studios/{studioId}/intercom/memberships/{membershipId}/refresh.
Refresh never upgrades a listener to a publisher. A key without
intercom:publish cannot retrieve a publishing credential after another client
has upgraded that membership; request a deliberate downgrade or use an
appropriately authorized key. Stop owned media when access expires or refresh
fails. An expired membership requires a new deliberate join.
Use PATCH /v1/studios/{studioId}/intercom/memberships/{membershipId} for partial
listen/talk state and bounded local transport reports:
{"listenState":"connected","microphoneState":"idle","mediaErrorCode":""}
Media states are idle, connecting, connected, or failed. Safe error codes
are listed in the API reference; never submit raw device errors, tokens, SDP, or
private URLs. The server stamps mediaObservedAt. These are client reports,
not independent server measurements of audible audio. A failed talk update must
leave the local microphone muted.
Leave with DELETE /v1/studios/{studioId}/intercom/memberships/{membershipId} and
stop all owned tracks/readers. Delayed responses must be discarded when their
studio, connection, or membership no longer matches the current client state.
A stale leave must never target the client's newer membership.
Reconcile room events
GET /v1/studios/{studioId}/events carries whole-room intercom events and
snapshot intercomRooms when the key has intercom:read in addition to the
normal event-stream scopes. Grant tokens and TURN credentials are excluded.
Replace that room's roster, including when it becomes empty. Preserve the
studio/room boundary, and show reported progress and failure separately from
control membership.
After a disconnect, use the fresh snapshot or the room read endpoint to recover
missed state. Last-Event-ID participates in the existing stream contract; it is
not a promise of durable replay of every intermediate audio status change.