Appearance
Events & phases
An event is the thing you schedule and share — a fireside, meeting, breakout session or speed-networking rotation. Its agenda is a list of phases, each with a modality:
| Modality | What happens |
|---|---|
broadcast | Hosts & speakers on a stage, streamed to a watch-only audience (HLS) |
meeting | One room, everyone joins with camera & mic |
breakout | Parallel small-group rooms, optional timer & extensions |
rotation | Speed networking — attendees shuffle through timed rounds |
Most events have a single phase; multi-phase agendas (e.g. broadcast → breakouts → broadcast) are fully supported.
Create an event
POST /v1/events
sh
curl -X POST https://api.gathercloud.dev/v1/events \
-H "x-api-key: gck_..." \
-H "content-type: application/json" \
-d '{
"type": "fireside",
"title": "Quarterly AMA",
"scheduledAt": "2026-07-01T17:00:00Z",
"visibility": "public",
"allowAnonymousVoting": true,
"metadata": { "description": "Ask the founders anything." },
"phases": [
{ "modality": "broadcast", "featureSet": ["qa", "transcript"] }
]
}'| Field | Type | Notes |
|---|---|---|
type | string, required | Free-form label (fireside, meeting, …) |
title | string, required | |
scheduledAt | ISO timestamp | Planned start |
scheduledEndAt | ISO timestamp | Planned end |
visibility | public | unlisted | private | Default unlisted |
allowAnonymousVoting | boolean | Let signed-out viewers vote on Q&A (public events) |
allowAnonymousQuestions | boolean | Let signed-out viewers submit Q&A questions (public events) |
metadata | object | Your own data; the dashboard uses description |
phases | array | Each: modality (required), config, featureSet |
Phase featureSet values: qa, chat, polls, reactions, transcript, capture. Phase config (per modality): roomSize, durationSeconds, extendable (breakout); rounds, roundSeconds (rotation).
Returns 201 with the new event in draft status.
IMPORTANT
The 201 body is the bare event object — it does not echo back the phases you sent. Your phases are created (this is expected, not a silent failure); they're just not included in the create response. To read them back, follow up with GET /v1/events/:id, which includes the phases array. This matters most for multi-phase agendas, where you'll want to confirm the order and ids of every phase you submitted.
A freshly created event is in draft — not yet on any public surface. The natural next step is to publish it:
sh
curl -X POST https://api.gathercloud.dev/v1/events/{id}/publish \
-H "x-api-key: gck_..."This moves it draft → scheduled and fires the event.published webhook. See Lifecycle below for the full state machine.
Read & list
GET /v1/events— newest first (up to 100).GET /v1/events/:id— includes thephasesarray.
Update
PATCH /v1/events/:id — any of title, scheduledAt (null clears it), visibility, allowAnonymousVoting, metadata (replaced wholesale).
Delete
DELETE /v1/events/:id — permanent; removes phases, Q&A and invites.
Lifecycle
Events move draft → scheduled → live → ended:
| Call | Effect |
|---|---|
POST /v1/events/:id/publish | draft → scheduled; fires event.published |
POST /v1/events/:id/start | Goes live and activates the first phase |
POST /v1/events/:id/advance | Ends the active phase, starts the next (ends the event after the last) |
POST /v1/events/:id/end | Ends the event immediately |
The dashboard displays the
scheduledstate as "Published" — it's on the public surface, awaiting a manual go-live (there is no time-based auto-start atscheduledAt). The API value remainsscheduled.
Phases
POST /v1/events/:id/phases— append a phase (modality,config,featureSet).PATCH /v1/phases/:id— updateconfig/featureSet.POST /v1/phases/:id/extend— add{ "seconds": 300 }(10–3600) to the active phase's timer.
Users & roles
Attendee roles are per event: host, speaker, participant, viewer (plus workspace_admin). When you pre-provision users from your own directory:
GET /v1/users/POST /v1/users— upsert byexternalSub({ externalSub, email, name, picture }).POST /v1/events/:id/memberships—{ "userId": "…", "role": "speaker" }.
Events created from the dashboard automatically make their creator a host.
Which roles an event has
Roles follow the event's phase modalities, because they describe positions in a room topology:
| Phase modality | Assignable roles |
|---|---|
broadcast | host, speaker, viewer |
meeting, breakout, rotation | host, participant |
A broadcast has a stage and a watch-only audience; a call has neither, so speaker there would name the same seat as participant and a viewer would have nothing to watch. An event made of several phases accepts the union of its phases' roles.
Both POST /v1/events/:id/memberships and POST /v1/workspaces/:id/invites reject a role the event has no place for with 400 role_not_on_event, listing the roles it does accept. workspace_admin is exempt — it mirrors workspace membership and is valid on any event.
Roles already stored are narrowed on read rather than rewritten, so an invite or membership that predates a change of modality still resolves to a sensible seat: a speaker in a call becomes a participant, and a participant in a broadcast phase becomes audience (viewer, no media seat). Narrowing never widens access — a viewer stays seatless.
Q&A
GET /v1/events/:id/questions — questions with vote tallies, sorted by votes.