Browse the docs
API reference
Cycles
Timeboxed sprints of one to four weeks per product. Status is derived from the dates: planned before the start, active until completed. Two open cycles of a product never overlap.
List cycles
GET/v1/projects/{slug}/cycles
Every cycle of a product, oldest first, with done/started/open counts. currentId names the active one, or null. A completed cycle reports what it held when it closed.
Requires work.read
Path parameters
slugstringrequiredThe product's slug.
curl "https://atrix.dev/api/v1/projects/SLUG/cycles" \
-H "Authorization: Bearer $ATRIX_TOKEN"{
"currentId": "cmc1y2c3l40001ab12cd34ef56",
"cycles": [
{
"id": "cmc1y2c3l40001ab12cd34ef56",
"number": 4,
"name": "Cycle 4",
"goal": "Ship retries and the billing page",
"startsOn": "2026-10-26",
"endsOn": "2026-11-08",
"status": "active",
"overdue": false,
"daysLeft": 12,
"completedAt": null,
"progress": {
"total": 9,
"done": 3,
"started": 2,
"open": 6,
"cancelled": 1
}
}
]
}Create a cycle
POST/v1/projects/{slug}/cycles
Starts a cycle. Without startsOn it begins the day after the last open cycle ends, or today. Numbers are sequential per product. An overlap with an open cycle comes back as { error } naming it.
Requires work.write
Path parameters
slugstringrequiredThe product's slug.
Body
weeksintegerLength, 1 to 4. Defaults to 2.
startsOnISO dateFirst day (YYYY-MM-DD).
namestring | nullOptional; shown as "Cycle N" without one.
goalstring | nullWhat the cycle is for.
curl -X POST "https://atrix.dev/api/v1/projects/SLUG/cycles" \
-H "Authorization: Bearer $ATRIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "weeks": 1, "startsOn": "2026-11-02" }'{
"ok": true,
"id": "cmc1y2c3l40001ab12cd34ef56",
"number": 4,
"startsOn": "2026-10-26",
"endsOn": "2026-11-08"
}Get a cycle
GET/v1/projects/{slug}/cycles/{id}
One cycle with its issues, progress, added (issues that joined after the first day) and burndown: one point per day to today, the live scope and what was still open at the end of that day, read from the status history.
Requires work.read
Path parameters
slugstringrequiredThe product's slug.
idstringrequiredThe cycle id.
curl "https://atrix.dev/api/v1/projects/SLUG/cycles/ID" \
-H "Authorization: Bearer $ATRIX_TOKEN"{
"id": "cmc1y2c3l40001ab12cd34ef56",
"number": 4,
"name": "Cycle 4",
"goal": "Ship retries and the billing page",
"startsOn": "2026-10-26",
"endsOn": "2026-11-08",
"status": "active",
"overdue": false,
"daysLeft": 12,
"completedAt": null,
"progress": {
"total": 9,
"done": 3,
"started": 2,
"open": 6,
"cancelled": 1
},
"added": 2,
"burndown": [
{
"day": "2026-10-26",
"scope": 8,
"remaining": 8
},
{
"day": "2026-10-27",
"scope": 9,
"remaining": 6
}
],
"summary": null,
"issues": [
{
"id": "cm9x2k7f40001ab12cd34ef56",
"title": "Retry failed Stripe webhooks",
"status": "IN_PROGRESS",
"type": "TASK",
"priority": "HIGH",
"dueOn": "2026-10-30",
"assignee": {
"id": "cm8q1z0a10003xy98wv76ut54",
"name": "Sara Khan"
}
}
]
}Update a cycle
PATCH/v1/projects/{slug}/cycles/{id}
Renames it, rewrites its goal or moves its dates (at most 4 weeks, never overlapping another open cycle). A completed cycle keeps its dates.
Requires work.write
Path parameters
slugstringrequiredThe product's slug.
idstringrequiredThe cycle id.
Body
namestring | nullNew name, or null for "Cycle N".
goalstring | nullNew goal, or null to clear it.
startsOnISO dateNew first day.
endsOnISO dateNew last day, inclusive.
curl -X PATCH "https://atrix.dev/api/v1/projects/SLUG/cycles/ID" \
-H "Authorization: Bearer $ATRIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "…", "goal": "…" }'{
"ok": true
}Delete a cycle
DELETE/v1/projects/{slug}/cycles/{id}
Removes the cycle. Its issues are kept and simply have no cycle.
Requires work.write
Path parameters
slugstringrequiredThe product's slug.
idstringrequiredThe cycle id.
curl -X DELETE "https://atrix.dev/api/v1/projects/SLUG/cycles/ID" \
-H "Authorization: Bearer $ATRIX_TOKEN"{
"ok": true
}Complete a cycle
POST/v1/projects/{slug}/cycles/{id}/complete
Closes an active cycle and moves its unfinished work. The summary is counted before anything moves. Closing early pulls the end date in to today.
Requires work.write
Path parameters
slugstringrequiredThe product's slug.
idstringrequiredThe cycle id.
Body
rolloverenumrequirednext: into the next open cycle, made (same length) if there is none.backlog: out of any cycle and back to BACKLOG status.nextbacklog
curl -X POST "https://atrix.dev/api/v1/projects/SLUG/cycles/ID/complete" \
-H "Authorization: Bearer $ATRIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "rollover": "next" }'{
"ok": true,
"summary": {
"done": 6,
"open": 2,
"cancelled": 1,
"total": 8,
"added": 2,
"rollover": "next",
"rolledTo": {
"id": "cmc1y2c3l40002ab12cd34ef56",
"number": 5
}
}
}