API Guidelines
General
- RESTful JSON API
- Versioned via URL prefix:
/api/v1/
- Authentication: Bearer token (Zitadel OIDC)
- Tenant scoping: every request is scoped to a tenant (from token)
URL Conventions
- Plural nouns:
/api/v1/groups, /api/v1/members
- Nested resources:
/api/v1/groups/{groupId}/members
- Actions (non-CRUD): POST
/api/v1/groups/{groupId}/join
- kebab-case for multi-word paths:
/api/v1/event-registrations
HTTP Methods
GET — read (list or detail), never changes state
POST — create resource or trigger action
PUT — full replace (rare, prefer PATCH)
PATCH — partial update
DELETE — remove resource
{
"data": { ... },
"meta": {
"page": 1,
"perPage": 25,
"total": 142
}
}
{
"error": {
"code": "MEMBER_NOT_FOUND",
"message": "Member with ID xyz was not found.",
"details": []
}
}
Status Codes
200 — success (GET, PATCH, PUT)
201 — created (POST)
204 — no content (DELETE)
400 — validation error
401 — unauthenticated
403 — unauthorized (missing permission)
404 — resource not found
409 — conflict (duplicate, state violation)
422 — unprocessable entity (business rule violation)
500 — server error (should never happen intentionally)
- Cursor-based for large lists (preferred)
- Offset-based where cursor doesn’t make sense
- Default page size: 25, max: 100
- Query params:
?page=1&perPage=25 or ?cursor=abc123
Filtering & Sorting
- Filter via query params:
?status=active&groupId=123
- Sort:
?sort=createdAt&order=desc
- Search:
?q=searchterm
Timezone Handling
- All timestamps in responses are ISO 8601 with UTC offset:
2026-03-15T14:30:00Z
- Entities with a timezone (events, organizations) include a
timezone field: "timezone": "Europe/Zurich"
- Clients are responsible for converting UTC to the user’s local time or the entity’s timezone
- Accept timestamps in requests as UTC or with explicit offset — reject ambiguous local times
- The
Accept-Timezone header is NOT used — timezone context comes from the entity, not the request
Tenant Scoping
- Every query MUST be scoped to the current tenant
- Tenant ID comes from the authentication token
- Never accept tenant ID as a request parameter
- Cross-tenant access is a critical security violation