REST API conventions
The response envelope, error shapes, status codes, rate limits and field-naming rules that apply to every endpoint.
Read this once and every endpoint in the reference becomes predictable.
https://cadence.alen.world/api/v1The response envelope
Every successful response wraps its payload in data:
{
"data": {
"id": "8f1c…",
"name": "Yuzu & Elderflower Sparkling",
"status": "active"
}
}List endpoints return an array in the same place:
{ "data": [ { "id": "8f1c…" }, { "id": "b204…" } ] }Deletes return 204 No Content with an empty body — there is no envelope to parse.
Errors
Errors use a single shape:
{ "error": { "message": "assigneeId must reference a team member", "code": "validation_failed" } }message is written to be shown to a developer, not an end user. code is present only for errors that carry a machine-readable code and is omitted otherwise — it is never null — so always branch on the HTTP status first.
Status codes
| Code | When |
|---|---|
200 | Success |
201 | Resource created |
204 | Deleted; no body |
400 | Invalid request — a required field is missing or malformed |
401 | Missing, invalid, revoked or expired API key |
403 | Valid key, but the plan or role does not permit the action |
404 | Not found, or not in your team |
429 | Rate limit exceeded |
500 | Something broke on our side |
Field naming
Request bodies use camelCase:
{ "phaseId": "…", "title": "Book line trial", "estimatedHours": 6 }Responses use camelCase too — startDate, estimatedHours, assigneeId — with joined relations under readable keys (assignee, phase, projectManager). Dates are ISO 8601 strings.
Partial updates
PATCH endpoints apply only the fields present in the body. Omitting a field leaves it untouched; sending null (or "" for id fields such as assigneeId) clears it.
One exception: projectManagerId cannot be cleared. Every project has a manager — it defaults to whoever created the project — so clearing it returns 400. Assign a different team member instead.
Rate limits
Limits are per team, per minute, counted across REST and MCP together:
| Plan | Requests per minute |
|---|---|
| Pro | 1,000 |
| Enterprise | 5,000 |
Over the limit, every request returns 429 with a message naming your plan's limit, until the current minute window rolls over.
Build for it: back off on 429 rather than retrying immediately, and batch reads where you can — GET /projects/:id returns phases and tasks in one response, so fetching a project and then each of its phases separately is both slower and more expensive than it needs to be.
Dates
All timestamps are ISO 8601 in UTC:
2026-08-19T09:02:11.482ZDate-only fields — start_date, deadline — accept and return YYYY-MM-DD.
Identifiers
Every id is a UUID. Ids are stable for the life of the resource and are never reused after deletion.
A worked example
Create a task on a phase, then mark it in progress:
# Create
curl -X POST https://cadence.alen.world/api/v1/tasks \
-H "Authorization: Bearer $CADENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phaseId": "3f9a2c14-…",
"title": "Book line trial at Rotterdam",
"priority": "high",
"estimatedHours": 6
}'
# Update
curl -X PATCH https://cadence.alen.world/api/v1/tasks/7c1e… \
-H "Authorization: Bearer $CADENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "in-progress" }'