Table of contents

v1.0.0 OpenAPI 3.1.0

MeetAgain API

Programmatic access to public events, member-scoped actions (RSVP, comment, image upload), and platform content, monitoring and log sections. Personal Access Token (PAT) authentication is required for non-public endpoints.

Server: / Download spec: JSON YAML

Authentication

Personal access token

Authenticate against the API with a Personal Access Token - a long-lived bearer token tied to your account.

For your own CLIs, scripts, or ops jobs. Issue a long-lived bearer token at your access tokens page and revoke it any time from the same page.

Header: Authorization: Bearer mapat_...

Acts as: you (the token issuer)

cms

CMS page and block authoring. Reserved for users with ROLE_ADMIN.

GET /api/v1/cms/pages List every CMS page with its owning group and per-locale block counts

List every CMS page with its owning group and per-locale block counts

Responses

Code Description
200 All CMS pages, newest first CmsPageSummaryList
401 Missing or invalid bearer token
403 Insufficient role or scope

Example request

curl '/api/v1/cms/pages' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/cms/block-types Catalogue of block types and the fields each one accepts

Catalogue of block types and the fields each one accepts

Responses

Code Description
200 Field definitions the write endpoints validate against CmsBlockTypeCatalog
401 Missing or invalid bearer token
403 Insufficient role or scope

Example request

curl '/api/v1/cms/block-types' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
DELETE /api/v1/cms/blocks/{blockId} Delete one block

Delete one block

Parameters

Name In Type Description
blockId * path integer

Responses

Code Description
204 Block deleted
401 Missing or invalid bearer token
403 Insufficient role or scope
404 Block not found

Example request

curl -X DELETE '/api/v1/cms/blocks/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
PATCH /api/v1/cms/blocks/{blockId} Overlay fields onto a stored block

Overlay fields onto a stored block

The payload is merged over the stored one, so a partial body only changes the fields it names.

Parameters

Name In Type Description
blockId * path integer

Request body

required

Content type: application/json

Name Type Description
type any Block type name or numeric id; defaults to the stored type
payload object

Responses

Code Description
200 The stored block, after hydration and sanitization CmsBlockSummary
400 Malformed body
401 Missing or invalid bearer token
403 Insufficient role or scope
404 Block not found
422 Unusable block type or a missing required field ValidationErrorResponse

Example request

curl -X PATCH '/api/v1/cms/blocks/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"Text","payload":"value"}'
GET /api/v1/cms/pages/{id}/blocks Ordered blocks of one page in one locale

Ordered blocks of one page in one locale

Parameters

Name In Type Description
id * path integer
locale query string Two-letter language code; defaults to the configured default locale

Responses

Code Description
200 Blocks in priority order CmsBlockList
401 Missing or invalid bearer token
403 Insufficient role or scope
404 Page not found
422 Unknown locale

Example request

curl '/api/v1/cms/pages/1/blocks?locale=en' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/cms/pages/{id}/blocks Append a block to a page in one locale

Append a block to a page in one locale

Parameters

Name In Type Description
id * path integer

Request body

required

Content type: application/json

Name Type Description
locale string
type any Block type name or numeric id from the block-types catalogue
payload object

Responses

Code Description
201 The stored block, after hydration and sanitization CmsBlockSummary
400 Malformed body
401 Missing or invalid bearer token
403 Insufficient role or scope
404 Page not found
422 Unknown locale, unusable block type, or a missing required field ValidationErrorResponse

Example request

curl -X POST '/api/v1/cms/pages/1/blocks' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"locale":"en","type":"Text","payload":"value"}'
POST /api/v1/cms/blocks/{blockId}/move Move a block one position up or down within its page and locale

Move a block one position up or down within its page and locale

Parameters

Name In Type Description
blockId * path integer

Request body

required

Content type: application/json

Name Type Description
direction string

Responses

Code Description
200 The page blocks in their new order CmsBlockList
400 Malformed body
401 Missing or invalid bearer token
403 Insufficient role or scope
404 Block not found
422 Direction other than up or down

Example request

curl -X POST '/api/v1/cms/blocks/1/move' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"direction":"value"}'

images

Per-language image alt text. Reserved for users with ROLE_ADMIN.

PUT /api/v1/images/{id}/alt Store alt text for one image, keyed by locale

Store alt text for one image, keyed by locale

Parameters

Name In Type Description
id * path integer

Request body

required

Content type: application/json

Name Type Description
alt object Locale => alt text; empty string unsets

Responses

Code Description
200 Refreshed item with recomputed required/missing locales MissingAltImageItem
400 Malformed body
401 Missing or invalid bearer token
403 Insufficient role or scope
404 Image not found
422 A locale outside the image's required set

Example request

curl -X PUT '/api/v1/images/1/alt' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"alt":"value"}'
GET /api/v1/images/missing-alt List images missing per-language alt text (keyset-paginated)

List images missing per-language alt text (keyset-paginated)

Parameters

Name In Type Description
after_id query integer Keyset cursor: only scan images with a larger ID
limit query integer Candidates scanned per page (matching items may be fewer)
default: 50

Responses

Code Description
200 Page of images still missing alt text in at least one required locale MissingAltImageList
401 Missing or invalid bearer token
403 Insufficient role or scope

Example request

curl '/api/v1/images/missing-alt?after_id=1&limit=1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/images/{id}/content Stream a downscaled preview of the original image

Stream a downscaled preview of the original image

Parameters

Name In Type Description
id * path integer

Responses

Code Description
200 Preview bytes (usually image/webp; the original media type when conversion fails)
401 Missing or invalid bearer token
403 Insufficient role or scope
404 Image or its original file not found

Example request

curl '/api/v1/images/1/content' \
  -H "Authorization: Bearer $ACCESS_TOKEN"

security

Security incident feed. Read-only, reserved for users with ROLE_ADMIN.

GET /api/v1/security/incidents List recent security incidents

List recent security incidents

Parameters

Name In Type Description
limit query integer
default: 100
since query string (date-time) ISO-8601 datetime lower bound on endedAt

Responses

Code Description
200 Incident list IncidentList
401 Missing or invalid bearer token
403 Insufficient role

Example request

curl '/api/v1/security/incidents?limit=1&since=value' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/security/incidents/{id} Get a single security incident with full provider reports

Get a single security incident with full provider reports

Parameters

Name In Type Description
id * path integer

Responses

Code Description
200 Incident detail IncidentDetail
401 Missing or invalid bearer token
403 Insufficient role
404 Incident not found

Example request

curl '/api/v1/security/incidents/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"

seo

Search-engine monitoring status, issues and actions. Reserved for users with ROLE_ADMIN.

GET /api/v1/seo/status SEO health for one property, with deltas since last pull

SEO health for one property, with deltas since last pull

Parameters

Name In Type Description
property query integer Property id; defaults to the first enabled one

Responses

Code Description
200 Compact current state SeoStatus
401 Missing or invalid bearer token
403 Insufficient role or scope
404 No monitored property

Example request

curl '/api/v1/seo/status?property=1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/seo/issues List detected SEO issues

List detected SEO issues

Parameters

Name In Type Description
property query integer
filter query string
default: open

Responses

Code Description
200 Issue list SeoIssueList
401 Missing or invalid bearer token
403 Insufficient role or scope
404 No monitored property

Example request

curl '/api/v1/seo/issues?property=1&filter=value' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/seo/actions List recently logged SEO actions

List recently logged SEO actions

Parameters

Name In Type Description
limit query integer
default: 100

Responses

Code Description
200 Action list SeoActionList
401 Missing or invalid bearer token
403 Insufficient role or scope

Example request

curl '/api/v1/seo/actions?limit=1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/seo/actions Log an SEO-relevant action for later attribution

Log an SEO-relevant action for later attribution

Request body

required

Content type: application/json

Name Type Description
kind string
title string
detail string | null
git_sha string | null
issue_id integer | null
occurred_at string | null (date-time)

Responses

Code Description
201 The stored action SeoAction
400 Malformed body
401 Missing or invalid bearer token
403 Insufficient role or scope
422 Unknown action kind or unparseable timestamp

Example request

curl -X POST '/api/v1/seo/actions' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"kind":"value","title":"value","detail":"value","git_sha":"value","issue_id":"value","occurred_at":"value"}'

logs

Cron and email send logs. Read-only, reserved for users with ROLE_ADMIN.

GET /api/v1/logs/cron List recent cron run log entries

List recent cron run log entries

Parameters

Name In Type Description
limit query integer
default: 100

Responses

Code Description
200 Paginated cron log list CronLogList
401 Missing or invalid bearer token
403 Insufficient role

Example request

curl '/api/v1/logs/cron?limit=1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/logs/sendlog List email send-log entries

List email send-log entries

Parameters

Name In Type Description
limit query integer
default: 100

Responses

Code Description
200 Paginated sendlog list SendlogList
401 Missing or invalid bearer token
403 Insufficient role

Example request

curl '/api/v1/logs/sendlog?limit=1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/logs/cron/{id} Get a single cron log entry

Get a single cron log entry

Parameters

Name In Type Description
id * path integer

Responses

Code Description
200 Cron log detail CronLogDetail
401 Missing or invalid bearer token
403 Insufficient role
404 Cron log not found

Example request

curl '/api/v1/logs/cron/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/logs/sendlog/{id} Get a single send-log entry

Get a single send-log entry

Parameters

Name In Type Description
id * path integer

Responses

Code Description
200 Sendlog detail SendlogDetail
401 Missing or invalid bearer token
403 Insufficient role
404 Sendlog entry not found

Example request

curl '/api/v1/logs/sendlog/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"

auth

Sign in with email and password to obtain a personal access token

POST /api/v1/auth/login Sign in and receive a personal access token

Sign in and receive a personal access token

Issues a new personal access token for this device and revokes the one an earlier sign-in issued for the same device name. Send it as a Bearer token on every call and sign in again on a 401.

Request body

required

Content type: application/json

Name Type Description
email string (email)
password string (password)
deviceName string Stable name of this installation, shown to the member in their token list

Responses

Code Description
200 Signed in LoginResult
400 Malformed body or invalid device name (bad_request, invalid_device_name) ErrorResponse
401 Wrong email or password (invalid_credentials) ErrorResponse
403 The account cannot sign in yet or any more (account_blocked, email_not_verified, pending_approval); the member fixes it on the website ErrorResponse
429 Too many attempts (too_many_attempts, with Retry-After) or login protection active (login_restricted); sign in on the website ErrorResponse

Example request

curl -X POST '/api/v1/auth/login' \
  -H "Content-Type: application/json" \
  -d '{"email":"value","password":"value","deviceName":"value"}'
POST /api/v1/auth/logout Sign out and revoke the calling token

Sign out and revoke the calling token

Responses

Code Description
204 Token revoked
401 Missing or invalid Bearer token

Example request

curl -X POST '/api/v1/auth/logout' \
  -H "Authorization: Bearer $ACCESS_TOKEN"

community

GET /api/v1/community/blocks List the members the caller has blocked

List the members the caller has blocked

Responses

Code Description
200 Blocked members MemberList
401 Missing or invalid Bearer token

Example request

curl '/api/v1/community/blocks' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/community/members List platform members

List platform members

Members the calling member may see, blocked ones excluded. A member who opted out of the directory is left out here too, exactly as on the website; their profile stays reachable by id.

Parameters

Name In Type Description
limit query integer
default: 20
offset query integer
default: 0

Responses

Code Description
200 Members MemberList
401 Missing or invalid Bearer token

Example request

curl '/api/v1/community/members?limit=1&offset=1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/community/blocks/{id} Block a member

Block a member

Blocking drops any follow in either direction and hides the conversation from both inboxes. Repeating the call is safe.

Parameters

Name In Type Description
id * path integer

Responses

Code Description
204 Blocked
401 Missing or invalid Bearer token
404 No such member (not_found) ErrorResponse
422 Blocking yourself (self_target) ErrorResponse

Example request

curl -X POST '/api/v1/community/blocks/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
DELETE /api/v1/community/blocks/{id} Unblock a member

Unblock a member

Repeating the call is safe. Unblocking does not restore a follow that blocking removed.

Parameters

Name In Type Description
id * path integer

Responses

Code Description
204 Not blocked
401 Missing or invalid Bearer token
404 No such member (not_found) ErrorResponse

Example request

curl -X DELETE '/api/v1/community/blocks/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/community/members/{id} Read one member profile

Read one member profile

Parameters

Name In Type Description
id * path integer

Responses

Code Description
200 The member profile MemberProfile
401 Missing or invalid Bearer token
403 The member has blocked the caller (forbidden) ErrorResponse
404 No such member (not_found) ErrorResponse

Example request

curl '/api/v1/community/members/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/community/conversations List the calling member conversations

List the calling member conversations

One entry per partner, newest first. Partners blocked in either direction are left out.

Parameters

Name In Type Description
limit query integer
default: 20
offset query integer
default: 0

Responses

Code Description
200 Conversations ConversationList
401 Missing or invalid Bearer token
403 Token without the community:read scope (insufficient_scope) ErrorResponse

Example request

curl '/api/v1/community/conversations?limit=1&offset=1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
PATCH /api/v1/community/messages/{id} Edit a message inside the edit window

Edit a message inside the edit window

A message can be edited for ten minutes after it was sent. The website answers 403 here; this surface answers 409, because the window is a state conflict rather than an authorisation failure.

Parameters

Name In Type Description
id * path integer

Request body

required

Content type: application/json

Name Type Description
content string

Responses

Code Description
200 The stored message ThreadMessage
401 Missing or invalid Bearer token
404 No such message, or it was sent by someone else (not_found) ErrorResponse
409 The ten-minute window has passed (edit_window_expired) ErrorResponse
422 content_required or content_too_long ErrorResponse

Example request

curl -X PATCH '/api/v1/community/messages/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"value"}'
POST /api/v1/community/members/{id}/follow Follow a member

Follow a member

Repeating the call is safe: it states the wanted end state rather than toggling.

Parameters

Name In Type Description
id * path integer

Responses

Code Description
204 Following
401 Missing or invalid Bearer token
404 No such member (not_found) ErrorResponse
409 A block in either direction (blocked) ErrorResponse
422 Following yourself (self_target) ErrorResponse

Example request

curl -X POST '/api/v1/community/members/1/follow' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
DELETE /api/v1/community/members/{id}/follow Stop following a member

Stop following a member

Repeating the call is safe.

Parameters

Name In Type Description
id * path integer

Responses

Code Description
204 Not following
401 Missing or invalid Bearer token
404 No such member (not_found) ErrorResponse

Example request

curl -X DELETE '/api/v1/community/members/1/follow' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/community/groups/{slug}/members List the members of one group

List the members of one group

The same list scoped to one group. A group the caller cannot reach answers the same 404 as an unknown slug; reaching a Private or Hidden group needs a token that also carries me:read, because membership is resolved through that scope.

Parameters

Name In Type Description
slug * path string
limit query integer
default: 20
offset query integer
default: 0

Responses

Code Description
200 Members of that group MemberList
401 Missing or invalid Bearer token
404 Group not found or not reachable (not_found) ErrorResponse

Example request

curl '/api/v1/community/groups/slug/members?limit=1&offset=1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/community/conversations/{userId} Read one thread

Read one thread

Oldest first. This read is pure: it does not mark the thread read, unlike opening the page on the website. Call POST /api/v1/community/conversations/{userId}/read for that.

Parameters

Name In Type Description
userId * path integer
limit query integer
default: 20
offset query integer
default: 0

Responses

Code Description
200 The thread MessageThread
401 Missing or invalid Bearer token
404 No such member (not_found) ErrorResponse

Example request

curl '/api/v1/community/conversations/1?limit=1&offset=1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/community/conversations/{userId} Send a direct message

Send a direct message

Parameters

Name In Type Description
userId * path integer

Request body

required

Content type: application/json

Name Type Description
content string

Responses

Code Description
201 The stored message ThreadMessage
401 Missing or invalid Bearer token
404 No such member (not_found) ErrorResponse
409 A block in either direction (blocked) ErrorResponse
422 content_required, content_too_long or self_target ErrorResponse

Example request

curl -X POST '/api/v1/community/conversations/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"value"}'
POST /api/v1/community/conversations/{userId}/read Mark a thread read

Mark a thread read

Parameters

Name In Type Description
userId * path integer

Responses

Code Description
204 Marked read
401 Missing or invalid Bearer token
404 No such member (not_found) ErrorResponse

Example request

curl -X POST '/api/v1/community/conversations/1/read' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/community/groups/{slug}/town-hall/topics List the Town Hall topics of one group

List the Town Hall topics of one group

The whole forum tree of the group, depth first, as the website loads it. Not paged. A group without Town Hall, or one whose Town Hall is closed to the caller, answers 404 - the same answer as an unknown slug.

Parameters

Name In Type Description
slug * path string

Responses

Code Description
200 The topic tree TopicList
401 Missing or invalid Bearer token
404 Group not found, not reachable, or Town Hall closed to the caller (not_found) ErrorResponse

Example request

curl '/api/v1/community/groups/slug/town-hall/topics' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/community/groups/{slug}/town-hall/topics Start a topic or a subtopic

Start a topic or a subtopic

Parameters

Name In Type Description
slug * path string

Request body

required

Content type: application/json

Name Type Description
title string
parentId integer | null Start a subtopic of this topic.

Responses

Code Description
201 Topic created Topic
401 Missing or invalid Bearer token
404 Group or parent topic not found, or Town Hall closed to the caller (not_found) ErrorResponse
422 empty_title, title_too_long or too_deep ErrorResponse

Example request

curl -X POST '/api/v1/community/groups/slug/town-hall/topics' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"value","parentId":"value"}'
GET /api/v1/community/groups/{slug}/town-hall/gallery List the Town Hall gallery of one group

List the Town Hall gallery of one group

The photos uploaded to the group's events, newest first, each with its event. Photos reported by a member are left out, as on the event page.

Parameters

Name In Type Description
slug * path string
limit query integer
default: 20
offset query integer
default: 0
locale query string Language of the event titles

Responses

Code Description
200 A page of photos GalleryList
401 Missing or invalid Bearer token
404 Group not found, not reachable, or Town Hall closed to the caller (not_found) ErrorResponse

Example request

curl '/api/v1/community/groups/slug/town-hall/gallery?limit=1&offset=1&locale=en' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
DELETE /api/v1/community/groups/{slug}/town-hall/topics/{id} Delete a topic

Delete a topic

The author may delete a topic while it has no subtopics and no replies; an admin deletes it with its whole subtree.

Parameters

Name In Type Description
slug * path string
id * path integer

Responses

Code Description
204 Topic deleted
401 Missing or invalid Bearer token
403 Not allowed to delete it (forbidden) ErrorResponse
404 Group or topic not found, or Town Hall closed to the caller (not_found) ErrorResponse

Example request

curl -X DELETE '/api/v1/community/groups/slug/town-hall/topics/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
PATCH /api/v1/community/groups/{slug}/town-hall/topics/{id} Rename a topic (author or admin)

Rename a topic (author or admin)

Parameters

Name In Type Description
slug * path string
id * path integer

Request body

required

Content type: application/json

Name Type Description
title string

Responses

Code Description
200 Topic renamed Topic
401 Missing or invalid Bearer token
403 Not the author and not admin (forbidden) ErrorResponse
404 Group or topic not found, or Town Hall closed to the caller (not_found) ErrorResponse
422 empty_title or title_too_long ErrorResponse

Example request

curl -X PATCH '/api/v1/community/groups/slug/town-hall/topics/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"value"}'
GET /api/v1/community/groups/{slug}/town-hall/topics/{id}/replies List the replies to a topic

List the replies to a topic

Newest first, paged backwards like event comments: pass the previous page's nextBefore.

Parameters

Name In Type Description
slug * path string
id * path integer
before query integer Only replies older than this reply id
limit query integer
default: 20

Responses

Code Description
200 A page of replies CommentList
401 Missing or invalid Bearer token
404 Group or topic not found, or Town Hall closed to the caller (not_found) ErrorResponse

Example request

curl '/api/v1/community/groups/slug/town-hall/topics/1/replies?before=1&limit=1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/community/groups/{slug}/town-hall/topics/{id}/replies Reply to a topic

Reply to a topic

Parameters

Name In Type Description
slug * path string
id * path integer

Request body

required

Content type: application/json

Name Type Description
content string

Responses

Code Description
201 Reply created CommentCreated
401 Missing or invalid Bearer token
404 Group or topic not found, or Town Hall closed to the caller (not_found) ErrorResponse
422 content_required or content_too_long ErrorResponse

Example request

curl -X POST '/api/v1/community/groups/slug/town-hall/topics/1/replies' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"value"}'
DELETE /api/v1/community/groups/{slug}/town-hall/topics/{id}/replies/{replyId} Delete a reply (own or admin)

Delete a reply (own or admin)

Parameters

Name In Type Description
slug * path string
id * path integer
replyId * path integer

Responses

Code Description
204 Reply deleted
401 Missing or invalid Bearer token
403 Not your reply and not admin (forbidden) ErrorResponse
404 Group, topic or reply not found, a reply to another topic, or Town Hall closed to the caller (not_found) ErrorResponse

Example request

curl -X DELETE '/api/v1/community/groups/slug/town-hall/topics/1/replies/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"

event-actions

Authenticated user actions on events: RSVP, comments, image upload

PUT /api/v1/events/{id}/rsvp Set RSVP and guests on an event

Set RSVP and guests on an event

Idempotent: sets the RSVP and the guest count in one call and answers the resulting state.

Parameters

Name In Type Description
id * path integer

Request body

required

Content type: application/json

Name Type Description
going boolean
guests integer Guests the member brings, 0 to 5; ignored when not going

Responses

Code Description
200 Resulting RSVP state RsvpResult
401 Missing or invalid Bearer token
403 Not allowed (not_a_member) ErrorResponse
404 Event not found ErrorResponse
409 Event canceled or already started (event_canceled, event_started) ErrorResponse
400 Body is not an object, or going is not a boolean (bad_request) ErrorResponse
422 Guest count out of range (validation_failed) ErrorResponse

Example request

curl -X PUT '/api/v1/events/1/rsvp' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"going":"value","guests":"value"}'
POST /api/v1/events/{id}/rsvp RSVP yes to an event

RSVP yes to an event

Parameters

Name In Type Description
id * path integer

Responses

Code Description
200 RSVP added (or already present) RsvpResult
401 Missing or invalid Bearer token
403 Not allowed (group membership / blocked) ErrorResponse
404 Event not found ErrorResponse
409 Event canceled or already started ErrorResponse

Example request

curl -X POST '/api/v1/events/1/rsvp' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
DELETE /api/v1/events/{id}/rsvp Remove RSVP from an event

Remove RSVP from an event

Withdrawing is never refused: a canceled event, an event that has started and a lost group membership all still let the member off the attendee list.

Parameters

Name In Type Description
id * path integer

Responses

Code Description
200 RSVP removed (or already absent) RsvpResult
401 Missing or invalid Bearer token
404 Event not found ErrorResponse

Example request

curl -X DELETE '/api/v1/events/1/rsvp' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/events/{id}/images List the photos of an event

List the photos of an event

The photos of the event in every generated size. Photos reported by a member are left out, as on the event page.

Parameters

Name In Type Description
id * path integer

Responses

Code Description
200 The photos of the event ImageList
401 Missing or invalid Bearer token
403 Token without the event-actions:read scope (insufficient_scope) ErrorResponse
404 Event not found or not visible to the caller (not_found) ErrorResponse

Example request

curl '/api/v1/events/1/images' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/events/{id}/images Upload an image to an event

Upload an image to an event

Parameters

Name In Type Description
id * path integer

Request body

required

Content type: multipart/form-data

Name Type Description
file string (binary)

Responses

Code Description
201 Image uploaded ImageUploaded
400 file_required, file_rejected or upload_failed ErrorResponse
401 Missing or invalid Bearer token
403 Not allowed ErrorResponse
404 Event not found ErrorResponse

Example request

curl -X POST '/api/v1/events/1/images' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -F "file=@/path/to/file"
GET /api/v1/events/{id}/comments List the comments on an event

List the comments on an event

Newest first, as on the event page. Page backwards by passing the previous page's nextBefore.

Parameters

Name In Type Description
id * path integer
before query integer Only comments older than this comment id
limit query integer
default: 25

Responses

Code Description
200 A page of comments CommentList
401 Missing or invalid Bearer token
403 Token without the event-actions:read scope (insufficient_scope) ErrorResponse
404 Event not found or not visible to the caller (not_found) ErrorResponse

Example request

curl '/api/v1/events/1/comments?before=1&limit=1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/events/{id}/comments Post a comment on an event

Post a comment on an event

Parameters

Name In Type Description
id * path integer

Request body

required

Content type: application/json

Name Type Description
content string

Responses

Code Description
201 Comment created CommentCreated
400 content_required or content_too_long ErrorResponse
401 Missing or invalid Bearer token
403 Not allowed ErrorResponse
404 Event not found ErrorResponse

Example request

curl -X POST '/api/v1/events/1/comments' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"value"}'
GET /api/v1/events/{id}/attendees List who is coming to an event

List who is coming to an event

Who is coming, as the event page shows it to a signed-in member: the people who RSVPed with their guests, plus the organizer-maintained external count.

Parameters

Name In Type Description
id * path integer

Responses

Code Description
200 The people coming AttendeeList
401 Missing or invalid Bearer token
403 Token without the event-actions:read scope (insufficient_scope) ErrorResponse
404 Event not found or not visible to the caller (not_found) ErrorResponse

Example request

curl '/api/v1/events/1/attendees' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/events/{id}/occurrences List the other dates of a recurring meeting

List the other dates of a recurring meeting

The upcoming visible events of the same recurring series, each with the caller's own RSVP state. An event without a series answers with itself.

Parameters

Name In Type Description
id * path integer

Responses

Code Description
200 Upcoming occurrences of the series EventList
401 Missing or invalid Bearer token
404 Event not found ErrorResponse

Example request

curl '/api/v1/events/1/occurrences' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
DELETE /api/v1/events/{id}/images/{imageId} Delete an event image (own upload or admin)

Delete an event image (own upload or admin)

Parameters

Name In Type Description
id * path integer
imageId * path integer

Responses

Code Description
204 Image deleted
401 Missing or invalid Bearer token
403 Not your image and not admin ErrorResponse
404 Image or event not found ErrorResponse

Example request

curl -X DELETE '/api/v1/events/1/images/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
DELETE /api/v1/events/{id}/comments/{commentId} Delete an event comment (own or admin)

Delete an event comment (own or admin)

Parameters

Name In Type Description
id * path integer
commentId * path integer

Responses

Code Description
204 Comment deleted
401 Missing or invalid Bearer token
403 Not your comment and not admin ErrorResponse
404 Comment or event not found ErrorResponse

Example request

curl -X DELETE '/api/v1/events/1/comments/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"

events

Public event listings and detail

GET /api/v1/events List public upcoming events

List public upcoming events

Parameters

Name In Type Description
locale query string
from query string (date-time) ISO-8601 lower bound (default: now)
to query string (date-time) ISO-8601 upper bound
limit query integer
default: 20
offset query integer
default: 0
group query string Group slug; an unknown slug returns an empty list

Responses

Code Description
200 Paginated event list EventList

Example request

curl '/api/v1/events?locale=en&from=value&to=value&limit=1&offset=1&group=weiqi-club'
GET /api/v1/events/{id} Get a single event by ID

Get a single event by ID

Parameters

Name In Type Description
id * path integer
locale query string

Responses

Code Description
200 Event detail EventDetail
404 Event not found or not visible in current context ErrorResponse

Example request

curl '/api/v1/events/1?locale=value'

group-admin

Group-scoped admin actions. Requires Owner or Organizer role in the named group, or platform ROLE_ADMIN.

GET /api/v1/groups/{groupSlug}/admin/members List members of a group

List members of a group

Parameters

Name In Type Description
groupSlug * path string

Responses

Code Description
200 Members list GroupMemberList
401 Missing or invalid bearer token
403 Caller is not Owner/Organizer of this group
404 Group not found ErrorResponse

Example request

curl '/api/v1/groups/groupSlug/admin/members' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/groups/{groupSlug}/admin/settings Read a group settings

Read a group settings

Parameters

Name In Type Description
groupSlug * path string

Responses

Code Description
200 Group settings GroupSettings
401 Missing or invalid bearer token
403 Caller is not Owner/Organizer of this group
404 Group not found ErrorResponse

Example request

curl '/api/v1/groups/weiqi-club/admin/settings' \
  -H "Authorization: Bearer $ACCESS_TOKEN"

groups

Tenant groups (multisite)

GET /api/v1/groups List active groups

List active groups

Responses

Code Description
200 Array of group summaries GroupList

Example request

curl '/api/v1/groups'
GET /api/v1/groups/{groupSlug} Get a group by slug

Get a group by slug

Parameters

Name In Type Description
groupSlug * path string

Responses

Code Description
200 Group detail GroupDetail
404 Group not found ErrorResponse

Example request

curl '/api/v1/groups/groupSlug'
GET /api/v1/groups/{groupSlug}/cms List a group's CMS pages

List a group's CMS pages

Parameters

Name In Type Description
groupSlug * path string
language query string Two-letter language code. If omitted, each item's first available language is used. If given but the page lacks that language, falls back to 'en' (or the first available).

Responses

Code Description
200 List of CMS pages CmsPageList
404 Group not found ErrorResponse

Example request

curl '/api/v1/groups/weiqi-club/cms?language=en'
GET /api/v1/groups/{groupSlug}/cms/{cmsSlug} Get a CMS page metadata by group and slug

Get a CMS page metadata by group and slug

Parameters

Name In Type Description
groupSlug * path string
cmsSlug * path string
language query string

Responses

Code Description
200 CMS page metadata CmsPage
404 Group not found, or page not found / not visible in this group ErrorResponse

Example request

curl '/api/v1/groups/platform/cms/about?language=value'

me

Authenticated user (token-scoped reads)

GET /api/v1/me Get the authenticated user profile

Get the authenticated user profile

Responses

Code Description
200 User profile MeProfile
401 Missing or invalid Bearer token

Example request

curl '/api/v1/me' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
PATCH /api/v1/me Edit the authenticated member profile

Edit the authenticated member profile

Only the fields present in the body change. The name follows the website rule: a name already stored above the cap keeps working, but a change has to fit it.

Request body

required

Content type: application/json

Name Type Description
name string
bio string | null
locale string One of the languages enabled on this platform
public boolean

Responses

Code Description
200 The saved profile MeProfile
401 Missing or invalid Bearer token
403 Token without the me:write scope (insufficient_scope) ErrorResponse
422 A field was rejected (validation_failed); errors names them: name_required, name_too_long, locale_not_enabled, bio_invalid, public_invalid ValidationErrorResponse

Example request

curl -X PATCH '/api/v1/me' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"value","bio":"value","locale":"value","public":"value"}'
GET /api/v1/me/rsvps List the authenticated user upcoming RSVPs

List the authenticated user upcoming RSVPs

Parameters

Name In Type Description
locale query string Language code; overrides Accept-Language

Responses

Code Description
200 Array of upcoming events the user has RSVPed to MeRsvpList
401 Missing or invalid Bearer token

Example request

curl '/api/v1/me/rsvps?locale=en' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/me/avatar Replace the authenticated member avatar

Replace the authenticated member avatar

Replaces the member avatar. The previous picture stays in the member own gallery, as on the website.

Request body

required

Content type: multipart/form-data

Name Type Description
file string (binary)

Responses

Code Description
200 The profile with its new avatar MeProfile
400 file_required, file_rejected or upload_failed ErrorResponse
401 Missing or invalid Bearer token
403 Token without the me:write scope (insufficient_scope) ErrorResponse

Example request

curl -X POST '/api/v1/me/avatar' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -F "file=@/path/to/file"
GET /api/v1/me/groups List the groups of the authenticated member

List the groups of the authenticated member

Every group the member belongs to or has asked to join, including the ones that blocked them, each with the role and the membership status.

Responses

Code Description
200 The memberships of the authenticated member MembershipList
401 Missing or invalid Bearer token

Example request

curl '/api/v1/me/groups' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/me/events List the upcoming meetings of the authenticated member

List the upcoming meetings of the authenticated member

The upcoming events of the member's groups plus the visible upcoming events they RSVPed to elsewhere, canceled ones included and flagged.

Parameters

Name In Type Description
from query string (date-time) ISO-8601 lower bound (default: now)
limit query integer
default: 20
offset query integer
default: 0
locale query string Language code; overrides Accept-Language

Responses

Code Description
200 Paginated event list EventList
401 Missing or invalid Bearer token

Example request

curl '/api/v1/me/events?from=value&limit=1&offset=1&locale=en' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/me/signal-token Issue the notification signal token for this device

Issue the notification signal token for this device

Issues a second token for the calling app device that can only read GET /api/v1/signal, valid for 90 days. Asking again replaces it, and revoking the device app token revokes it too.

Responses

Code Description
201 The signal token SignalTokenResult
400 The calling token was not issued by the API login (not_an_app_token) ErrorResponse
401 Missing or invalid Bearer token
403 Token without the me:write scope (insufficient_scope) ErrorResponse

Example request

curl -X POST '/api/v1/me/signal-token' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/me/notifications List the authenticated member notifications

List the authenticated member notifications

The website navbar bell, as data. Every item is computed live from the same providers the website uses; nothing is stored, so there is no read state, no history and no cursor. Labels come back in the request locale.

Responses

Code Description
200 The bell NotificationList
401 Missing or invalid Bearer token
403 Token without the me:read scope (insufficient_scope) ErrorResponse

Example request

curl '/api/v1/me/notifications' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
GET /api/v1/me/push-subscriptions List the registered push devices

List the registered push devices

Also carries the VAPID public key a client needs before it can subscribe, and whether push is configured on this platform at all.

Responses

Code Description
200 The registered devices PushSubscriptionList
401 Missing or invalid Bearer token
403 Token without the me:read scope (insufficient_scope) ErrorResponse

Example request

curl '/api/v1/me/push-subscriptions' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/me/push-subscriptions Register a push device

Register a push device

Registers a Web Push endpoint against the calling token, so revoking the device at /profile/access-tokens stops its pings. Re-posting a known endpoint moves it to the calling device and answers 200.

Request body

required

Content type: application/json

Name Type Description
endpoint string
p256dh string
auth string
transport string

Responses

Code Description
200 A known endpoint was updated PushSubscriptionEntry
201 The endpoint was registered PushSubscriptionEntry
401 Missing or invalid Bearer token
403 Token without the me:write scope (insufficient_scope) ErrorResponse
422 validation_failed, endpoint_rejected or too_many_subscriptions ValidationErrorResponse
503 No VAPID key is configured on this platform (push_unavailable) ErrorResponse

Example request

curl -X POST '/api/v1/me/push-subscriptions' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"endpoint":"value","p256dh":"value","auth":"value","transport":"value"}'
GET /api/v1/me/notification-settings Read the authenticated member notification preferences

Read the authenticated member notification preferences

The same master switch and six toggles the member edits at /profile/config.

Responses

Code Description
200 The stored preferences MeNotificationSettings
401 Missing or invalid Bearer token
403 Token without the me:read scope (insufficient_scope) ErrorResponse

Example request

curl '/api/v1/me/notification-settings' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
PATCH /api/v1/me/notification-settings Edit the authenticated member notification preferences

Edit the authenticated member notification preferences

Only the keys present in the body change. Writes through the same service as the website, so a change here shows up at /profile/config.

Request body

required

Content type: application/json

Responses

Code Description
200 The saved preferences MeNotificationSettings
401 Missing or invalid Bearer token
403 Token without the me:write scope (insufficient_scope) ErrorResponse
422 A field was rejected (validation_failed); errors names the offending keys ValidationErrorResponse

Example request

curl -X PATCH '/api/v1/me/notification-settings' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
DELETE /api/v1/me/push-subscriptions/{id} Remove a push device

Remove a push device

Removes one registered device. Another member row answers 404 rather than 403, so the endpoint does not confirm that an id exists.

Parameters

Name In Type Description
id * path integer The subscription id from the list endpoint

Responses

Code Description
204 Removed
401 Missing or invalid Bearer token
403 Token without the me:write scope (insufficient_scope) ErrorResponse
404 No such device for this member
503 No VAPID key is configured on this platform (push_unavailable) ErrorResponse

Example request

curl -X DELETE '/api/v1/me/push-subscriptions/1' \
  -H "Authorization: Bearer $ACCESS_TOKEN"

memberships

The calling member's group memberships: invitations, joining and leaving

GET /api/v1/memberships/invitations List the open group invitations

List the open group invitations

Invitations addressed to the calling member, minus those hidden by a block in either direction.

Responses

Code Description
200 The open invitations InvitationList
401 Missing or invalid Bearer token
403 Token without the memberships:read scope (insufficient_scope) ErrorResponse

Example request

curl '/api/v1/memberships/invitations' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/memberships/groups/{slug} Join a listed group, or ask to

Join a listed group, or ask to

Only a group listed on the groups portal can be joined here. A Hidden group is joined on its own domain and a Private group by invitation, so both answer group_not_joinable. When the group requires approval the membership comes back pending.

Parameters

Name In Type Description
slug * path string

Request body

Content type: application/json

Name Type Description
platformMailConsent boolean Answers the platform crossing: whether the platform may send announcements and event mail

Responses

Code Description
200 The resulting membership, approved or pending Membership
401 Missing or invalid Bearer token
404 No such group (not_found) ErrorResponse
409 group_not_joinable, blocked_in_group or platform_crossing_required ErrorResponse

Example request

curl -X POST '/api/v1/memberships/groups/slug' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"platformMailConsent":"value"}'
DELETE /api/v1/memberships/groups/{slug} Leave a group

Leave a group

The same rules the website applies: the last owner cannot leave, a blocked member cannot, and the platform group can only be left once it is no longer needed for another membership.

Parameters

Name In Type Description
slug * path string

Responses

Code Description
204 Membership ended
401 Missing or invalid Bearer token
404 No such group, or no membership in it (not_found) ErrorResponse
409 last_owner, blocked_in_group or may_not_leave_platform ErrorResponse

Example request

curl -X DELETE '/api/v1/memberships/groups/slug' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
POST /api/v1/memberships/invitations/{id}/accept Accept a group invitation

Accept a group invitation

Accepting settles the membership at the invited role. While the member still has to join the platform group, this answers 409 platform_crossing_required; retry with platformMailConsent to answer that question first.

Parameters

Name In Type Description
id * path integer

Request body

Content type: application/json

Name Type Description
platformMailConsent boolean Answers the platform crossing: whether the platform may send announcements and event mail

Responses

Code Description
200 The resulting membership Membership
401 Missing or invalid Bearer token
404 No such invitation for this member (invitation_not_found) ErrorResponse
409 blocked_in_group, membership_rejected or platform_crossing_required ErrorResponse

Example request

curl -X POST '/api/v1/memberships/invitations/1/accept' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"platformMailConsent":"value"}'
POST /api/v1/memberships/invitations/{id}/decline Decline a group invitation

Decline a group invitation

Parameters

Name In Type Description
id * path integer

Responses

Code Description
204 Invitation declined
401 Missing or invalid Bearer token
404 No such invitation for this member (invitation_not_found) ErrorResponse

Example request

curl -X POST '/api/v1/memberships/invitations/1/decline' \
  -H "Authorization: Bearer $ACCESS_TOKEN"

signal

Whether anything changed for the member, without saying what

GET /api/v1/signal Whether anything changed for the member

Whether anything changed for the member

An opaque value that changes when the bell changes, when an event the member said yes to is cancelled, moved in time or to another place, and when its reminder falls due. It reveals nothing else, so a token that can only read this section is safe to keep where the app cannot protect it.

Responses

Code Description
200 The current value SignalState
401 Missing or invalid Bearer token
403 Token without the signal:read scope (insufficient_scope) ErrorResponse

Example request

curl '/api/v1/signal' \
  -H "Authorization: Bearer $ACCESS_TOKEN"

status

status

GET /api/status Health check endpoint

Health check endpoint

Responses

Code Description
200 Service is healthy HealthStatus

Example request

curl '/api/status'