Responses are JSON. One thing comes back as { "data": { … } }; lists as { "data": [ … ] }. Every object has an id and an object type, and a url to open it in Formation where there is one.
Pages. Long lists come a page at a time (limit, up to 100) with "pagination": { "nextCursor": "…", "hasMore": true }. Pass cursor=nextCursor for the next page until hasMore is false.
Times come back in UTC (ISO 8601) with the event's own timezone alongside. When you send one, include an offset (2026-10-24T19:00:00-05:00) for an exact moment, or leave it off (2026-10-24T19:00) to mean that time in the organization's timezone.
Filters that take several values accept them comma-separated (teamId=a,b). Use updatedSince to sync only what changed.
Writes. POST creates, PATCH changes only the fields you send (send null to clear one), PUT sets a result or attendance, DELETE removes. Scheduling, results and announcements notify people and post to Discord just as they do in Formation; add "notify": false when creating to skip that.
Safe retries. Send an Idempotency-Key header on a POST (any string unique to that request — a UUID works well) and a retry with the same key, within 24 hours, returns the first response instead of doing it twice. The response comes back with Idempotent-Replayed: true. Reusing a key with a different body is a 422; a new attempt needs a new key.
Event details — the maps, lobby codes and other fields from Settings → Event Details — come back as details. Set them with an object keyed by field label or id: { "details": { "Maps": ["Ascent", "Bind"] } }.
Limits. Each key can make 120 requests a minute. Every response carries X-RateLimit-Remaining and X-RateLimit-Reset.
Errors look like { "error": { "code", "message", "details", "requestId" } }:
| 400 | invalid_request | A query parameter or the body isn't valid JSON or isn't allowed. |
| 401 | unauthorized / key_expired | No key, a wrong or revoked key, or an expired one. |
| 403 | missing_scope | The key doesn't have the scope this needs — details.scope names it. |
| 404 | not_found | No such thing in your organization. |
| 422 | validation_failed | The body was understood but a value isn't allowed — details lists each field. |
| 429 | rate_limited | Too many requests; wait for Retry-After seconds. |