On this page

Event management endpoints

20 endpoints.

MethodPathSummary
GET/api/eventsList events
POST/api/eventsCreate an event
DELETE/api/events/{id}Delete an event
GET/api/events/{id}One event
PUT/api/events/{id}Edit an event
DELETE/api/events/{id}/attendWithdraw your RSVP
POST/api/events/{id}/attendRSVP for yourself
PATCH/api/events/{id}/attendanceSet a member's RSVP (moderators)
GET/api/events/{id}/attendance/statsAttendance counts (moderators)
GET/api/events/{id}/attendeesAttendees of an event
GET/api/events/{id}/attendees/export.csvDownload the attendee list (organisers — calendar:manage / calendar:moderate)
GET/api/events/{id}/confirmedMembers who confirmed they are going
POST/api/events/{id}/interestToggle your interest bookmark
GET/api/events/{id}/interestedMembers who marked the event as interesting
DELETE/api/events/{id}/waitlistLeave the waitlist
GET/api/events/{id}/waitlistThe waitlist in order (organisers — calendar:manage / calendar:moderate)
POST/api/events/{id}/waitlistJoin the waitlist of a FULL event (first come, first served)
GET/api/events/{id}/waitlist/meMy place in the waitlist (null when not waiting)
GET/api/events/user/{userId}Events a member responded to (moderators)
GET/api/events/user/{userId}/attendanceA member's attendance history (moderators)

optionalAuth. What comes back depends on who is asking in THIS community:

  • A moderator sees every event.
  • An APPROVED member sees every event except other people's drafts.
  • A guest, or a signed-in non-member, gets only PUBLISHED events opted into guest preview, and only in a PUBLIC community whose plan includes it.
  • Anyone else gets an empty page. Guests receive a reduced event: no meeting link or passcode, no attendee list, no attachments. Attendee emails go to moderators only. All event routes sit behind the router-level feature gate requireFeature(events): a plan without it gets 403 FEATURE_NOT_AVAILABLE on every route, reads included.

Auth: optional — a token changes what you can see (see "Who may read what").

Parameters

NameInRequiredTypeDescription
communityIdquerynostring (uuid)Defaults to the community the request resolved to (custom domain / X-Tenant-Id).
statusquerynostringComma-separated DRAFT,PUBLISHED,CANCELLED,COMPLETED (still filtered by visibility).
includePastquerynobooleanPast events are excluded unless true.
onlyAvailablequerynobooleanOnly events with free seats.
isOnlinequerynoboolean—
searchquerynostring—
tagsquerynostringComma-separated.
categoryIdquerynostring (uuid)—
fromDatequerynostring (date-time)Events still running at or after this instant (an event overlapping the period is included, not only one that starts inside it).
toDatequerynostring (date-time)—
pagequerynointeger—
pageSizequerynointeger—

Responses

StatusDescriptionBody
200success, data: [event], page, pageSize, total, hasNext. Each event carries attendeeStats going, maybe (= interested), notGoing, capacity, availableSpots and creator (the community name, or isFormerMember).—
403FEATURE_NOT_AVAILABLE — the plan lacks events.—

Needs an APPROVED member holding calendar:manage or calendar:create, who is not suspended or blocked from events. The community is the one the guards checked (?communityId= or X-Tenant-Id). A body communityId that disagrees is refused with 400 COMMUNITY_MISMATCH. Uploads count against the plan's storage and are refused over the cap. Rate limit: 10 per burst, 1 per 5 seconds. All event routes sit behind the router-level feature gate requireFeature(events): a plan without it gets 403 FEATURE_NOT_AVAILABLE on every route, reads included.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).

Request body (required) — multipart/form-data

FieldTypeRequiredDescription
communityIdstring (uuid)noOptional; must equal the checked community when sent.
titlestringyes—
titleArabicstringyes—
descriptionstringnoRich text; sanitized server-side.
startDatestring (date-time)yes—
endDatestring (date-time)yesMust not be before startDate.
statusenum: DRAFT, PUBLISHED, CANCELLED, COMPLETEDnoOnly PUBLISHED notifies members and fires the event.created webhook. A DRAFT is visible to its creator and to moderators only.
locationstringno—
isOnlinebooleanno—
meetingUrlstringnoAbsolute http:// or https:// only (400 INVALID_URL otherwise). Never sent to guests or in home-feed cards.
meetingPasscodestringnoNever sent to guests.
meetingLinkVisibilityenum: BEFORE_BOOKING, AFTER_BOOKINGnoWhen members see meetingUrl + meetingPasscode. AFTER_BOOKING = only after «going» (free) or a PAID ticket (paid); moderators and the creator always. Optional — absent or empty leaves it unchanged (NULL on create = paid → after, free → before). Any other value → 400 EVENT_LINK_VISIBILITY_INVALID.
registrationUrlstringnoAbsolute http:// or https:// only (400 INVALID_URL otherwise).
timezonestringno—
capacityintegernoGOING seats. Empty or 0 means unlimited.
feenumberno—
currencystringno—
hasCertificatebooleanno—
allowGuestsbooleanno—
allowCommentsbooleanno—
isGuestVisiblebooleannoShow to guests of a PUBLIC community. Requires the community and its events section to be opted into guest preview; 400 otherwise.
tagsstringnoJSON array or comma-separated list.
categoryIdsstringnoJSON array of existing event-category ids (see /api/event-categories). At most 3 together with newCategories. A malformed array is a 400.
newCategoriesstringnoJSON array of name, description to find-or-create before linking. At most 3 together with categoryIds.
eventCoverstring (binary)no—
eventDocumentsstring (binary)[]no—

Responses

StatusDescriptionBody
201success, data: event—
400A validation error: a missing title or date, endDate before startDate, INVALID_URL, more than 3 categories, a malformed JSON field, or COMMUNITY_MISMATCH.—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—
429Rate limited.—

Same access rules as PUT. Nobody is notified. To tell attendees, set status=CANCELLED with PUT instead.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring (uuid)—
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).

Responses

StatusDescriptionBody
200success: true—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—
404No such event.—

optionalAuth, with the same visibility as the list: another member's draft, or any event a guest may not preview, answers 404 exactly as a missing id does. Guests get the reduced event. Attendee emails go to moderators only. The creator's email is visible to members (intended). All event routes sit behind the router-level feature gate requireFeature(events): a plan without it gets 403 FEATURE_NOT_AVAILABLE on every route, reads included.

Auth: optional — a token changes what you can see (see "Who may read what").

Parameters

NameInRequiredTypeDescription
idpathyesstring (uuid)—
communityIdquerynostring (uuid)—

Responses

StatusDescriptionBody
200success, data: event—
404No such event, or not visible to this caller.—

The event's creator, or a holder of calendar:manage or calendar:moderate. Either way the caller must be an APPROVED member who is not suspended or blocked from events. calendar:create alone does not let you edit other people's events. Only the fields you send change.

  • A link is checked only when you change it, so an old link stays savable.
  • existingAttachments selects which current attachments to keep, by id or url; the server's copy is kept, never yours.
  • removeAttachments (or removeAttachmentIds) removes attachments by id.
  • removeCover=true clears the cover. Bytes are recorded, but an edit is never refused over the storage cap. Setting status=CANCELLED, or moving the start date, notifies the attendees who are still members.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring (uuid)—
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).

Request body — multipart/form-data

FieldTypeRequiredDescription
titlestringno—
titleArabicstringno—
descriptionstringnoRich text; sanitized server-side.
startDatestring (date-time)no—
endDatestring (date-time)noMust not be before startDate.
statusenum: DRAFT, PUBLISHED, CANCELLED, COMPLETEDnoOnly PUBLISHED notifies members and fires the event.created webhook. A DRAFT is visible to its creator and to moderators only.
locationstringno—
isOnlinebooleanno—
meetingUrlstringnoAbsolute http:// or https:// only (400 INVALID_URL otherwise). Never sent to guests or in home-feed cards.
meetingPasscodestringnoNever sent to guests.
meetingLinkVisibilityenum: BEFORE_BOOKING, AFTER_BOOKINGnoWhen members see meetingUrl + meetingPasscode. AFTER_BOOKING = only after «going» (free) or a PAID ticket (paid); moderators and the creator always. Optional — absent or empty leaves it unchanged (NULL on create = paid → after, free → before). Any other value → 400 EVENT_LINK_VISIBILITY_INVALID.
registrationUrlstringnoAbsolute http:// or https:// only (400 INVALID_URL otherwise).
timezonestringno—
capacityintegernoGOING seats. Empty or 0 means unlimited.
feenumberno—
currencystringno—
hasCertificatebooleanno—
allowGuestsbooleanno—
allowCommentsbooleanno—
isGuestVisiblebooleannoShow to guests of a PUBLIC community. Requires the community and its events section to be opted into guest preview; 400 otherwise.
tagsstringnoJSON array or comma-separated list.
categoryIdsstringnoJSON array of existing event-category ids (see /api/event-categories). At most 3 together with newCategories. A malformed array is a 400.
newCategoriesstringnoJSON array of name, description to find-or-create before linking. At most 3 together with categoryIds.
eventCoverstring (binary)no—
eventDocumentsstring (binary)[]no—
existingAttachmentsstringnoJSON array of id or url. Malformed → 400.
removeAttachmentsstringnoJSON array or comma-separated attachment ids.
removeAttachmentIdsstringnoSame as removeAttachments (the Flutter app's name for it).
removeCoverenum: trueno—

Responses

StatusDescriptionBody
200success, data: event—
400Validation error (dates, INVALID_URL, categories, malformed JSON).—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—
404No such event.—
429Rate limited.—

Same access rules as POST. Keeps your interest bookmark. Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring (uuid)—
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).

Responses

StatusDescriptionBody
200success, data: event—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—
404No such event, the caller cannot open it, or there is no RSVP to withdraw.—

Any APPROVED member who is not suspended or blocked from RSVPs, on an event they can open (another member's draft answers 404 and nothing is written). GOING is refused with 400 "Event capacity reached" when the seats are taken. Re-confirming a seat you already hold always succeeds. The event comes back at the caller's own visibility.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring (uuid)—
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).

Request body — application/json

FieldTypeRequiredDescription
statusenum: GOING, MAYBE, NOT_GOINGno—

Responses

StatusDescriptionBody
201success, data: event—
400Event capacity reached.—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—
404No such event, or the caller cannot open it.—

Needs an APPROVED member holding calendar:manage or calendar:moderate. A moderator decision, so it is not held to capacity. The member must already have a response row.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring (uuid)—
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).

Request body (required) — application/json

FieldTypeRequiredDescription
userIdstring (uuid)yesA User.id.
statusenum: GOING, MAYBE, NOT_GOINGyes—

Responses

StatusDescriptionBody
200success, data: event—
400userId or status missing or invalid.—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—
404That member has no response row for this event.—

Needs an APPROVED member holding calendar:manage or calendar:moderate. maybe is the interested count. notGoing excludes interest-only bookmarks.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring (uuid)—
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).

Responses

StatusDescriptionBody
200success, data: { total, going, maybe, notGoing, capacity, availableSpots }—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—
404No such event.—

Everyone with a response row, optionally filtered by ?status=GOING,MAYBE,NOT_GOING. Any APPROVED member may call it, but the caller must be able to open the event, so another member's draft answers 404. Lists current APPROVED members only. The email field is filled for moderator-tier callers only and is null for everyone else.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring (uuid)—
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).
statusquerynostringComma-separated GOING,MAYBE,NOT_GOING.

Responses

StatusDescriptionBody
200success, data: [attendee], count—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—
404No such event, or the caller cannot open it.—

CSV (UTF-8 with BOM): name, status (going / maybe / not going / interested / waitlisted), waitlist position, registration time (UTC), and email for the moderator tier (the in-app roster's rule). Current members only. Every export is recorded.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring—

Responses

StatusDescriptionBody
200text/csv—

The GOING list. Any APPROVED member may call it, but the caller must be able to open the event, so another member's draft answers 404. Lists current APPROVED members only. The email field is filled for moderator-tier callers only and is null for everyone else.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring (uuid)—
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).

Responses

StatusDescriptionBody
200success, data: [attendee], count—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—
404No such event, or the caller cannot open it.—

Independent of the RSVP, and the same access rules as POST /attend. The creator is notified when interest is added, as long as the creator is still a member.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring (uuid)—
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).

Responses

StatusDescriptionBody
200success, data: event, isInterested—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—
404No such event, or the caller cannot open it.—

The heart / bookmark list. Any APPROVED member may call it, but the caller must be able to open the event, so another member's draft answers 404. Lists current APPROVED members only. The email field is filled for moderator-tier callers only and is null for everyone else.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring (uuid)—
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).

Responses

StatusDescriptionBody
200success, data: [attendee], count—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—
404No such event, or the caller cannot open it.—

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring—

Responses

StatusDescriptionBody
200success—

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring—

Responses

StatusDescriptionBody
200success, data: [{ userId, position, joinedAt, name, avatar }] — current, unblocked members only, numbered in seat order; name + photo as this community knows them, never contact fields—

Only when the event is published, not over, free, has a seat limit and every seat is taken. When a seat frees up the first person in line is moved to GOING automatically and notified. 409 codes: EVENT_HAS_SEATS, ALREADY_GOING, EVENT_NOT_OPEN, NO_CAPACITY, EVENT_NOT_FREE.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring—

Responses

StatusDescriptionBody
201success, data: { position }—
409Not possible now — see the code—

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
idpathyesstring—

Responses

StatusDescriptionBody
200success, data: { position, length }—

Needs an APPROVED member holding calendar:manage or calendar:moderate. Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
userIdpathyesstring (uuid)A User.id.
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).
statusquerynostringComma-separated GOING,MAYBE,NOT_GOING.
fromDatequerynostring (date-time)—
toDatequerynostring (date-time)—
pagequerynointeger—
pageSizequerynointeger—

Responses

StatusDescriptionBody
200success, data: [event], page, pageSize, total—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—

Needs an APPROVED member holding calendar:manage or calendar:moderate. Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
userIdpathyesstring (uuid)A User.id (not a CommunityMember.id).
communityIdqueryyesstring (uuid)The community the event belongs to (also accepted as X-Tenant-Id).
statusquerynostringComma-separated GOING,MAYBE,NOT_GOING.

Responses

StatusDescriptionBody
200success, data: [attendance]—
401No or invalid token.—
403Read the body's error to tell which guard refused (CLAUDE.md §14). NOT_A_COMMUNITY_MEMBER or a membership message means you are not an APPROVED member of this community. FEATURE_NOT_AVAILABLE means the plan lacks events. error:'Forbidden', message:'Missing permission: …' means a permission is missing. RESTRICTION_BLOCKED means the member is suspended or blocked from events.—