Gatherings
A gathering is a coordination space — somewhere people are invited, gather, mark themselves ready, and optionally kick off a transcribed session. It’s pure backend: tables and API endpoints, not a 3D world.
There are three types, each tuned to a different scenario. Working with gatherings through an
API key requires the gatherings scope.
The three types
Lobby
For game matchmaking and parties. Players join, mark themselves ready, and the host starts the gathering — which can auto-create a session so the bot joins the moment play begins.
Appointment
For scheduled meetings. An appointment has startsAt / endsAt, sends email invitations
with .ics calendar attachments, and can autoStartSession so it becomes a live,
transcribed call at the scheduled time.
Open
Always-on, drop-in social spaces. People come and go using a join code; the space can be listed (public) or unlisted.
Lifecycle and the auto-started session
A gathering moves through pending (a scheduled appointment that hasn’t begun) or active
(lobbies and open spaces), then started, and finally ended or cancelled. Appointments
start and end on their own when startsAt / endsAt are reached; any gathering can also be
started, ended or cancelled explicitly. A gathering that has ended or was cancelled can’t be
started again.
With autoStartSession: true, starting the gathering creates a transcription
session for its room (gathering.sessionId). That session
is tied to the gathering: ending or cancelling the gathering — explicitly or because an
appointment reached endsAt — stops the session as well, so the bot leaves the room and no
longer records.
Ownership
A gathering can have an owner (a participant). Calls made by a trusted backend act with full
rights. When your backend acts on behalf of a player — say, the player pressed “Start” in
your game — pass that player as actorParticipantId. Cortex then accepts the change only if
that participant owns the gathering:
Participants may always remove themselves.
Members & invitations
A gathering separates who was invited from who is currently in it:
- Invitations (
gathering_invitations) are the source of truth for reaching people by email — including invitees who never sign in. This is what you’d use to email a summary afterwards. - Members (
gathering_members) track current state with a simple lifecycle:invited→joined→ready→left, plus a role (owner/member).
See Sessions & Gatherings for why invitation, membership and session attendance are tracked separately.
Join codes
Every gathering has a short join code people can use to join — handy for sharing a
lobby or open space. Codes are 8 alphanumeric characters, displayed as XXXX-XXXX and
normalized on input (case-insensitive, hyphens optional), so ABCD-1234 and abcd1234
resolve to the same gathering.
A code only resolves inside the project it belongs to. A code from another project is
answered like an unknown code (404), so the endpoints can’t be used to discover codes
elsewhere. Both the lookup and the join are authenticated like every other gathering route —
there is no public, unauthenticated lookup. Game clients should resolve codes through your own
backend, which is also the right place for game-specific checks such as game mode, capacity or
bans.
Email invitations
When you invite people by email, Cortex sends a branded invitation. For appointments it
includes a standards-compliant .ics attachment so the event lands in the recipient’s
calendar, with a recording notice when autoStartSession is enabled.
You can invite by email right when you create the gathering — invitees without a userId
get an invitation (and the email) but no membership:
Invitation emails are sent fire-and-forget — a delivery problem for one recipient never blocks creating the gathering or inviting others.
Lifecycle events
Gatherings emit a rich set of domain events you can react to over webhooks, SSE or functions — for example:
gathering.created,gathering.started,gathering.ended,gathering.cancelledgathering.member.joined,gathering.member.ready,gathering.member.leftgathering.invitation.sent,gathering.invitation.accepted,gathering.invitation.declined