API Reference
Projects
List, view, create, and update epics and stories. Uses the secret key or a personal access token for authentication. Requires the Projects module to be enabled — requests return 403 when it is off.
A personal access token carries its user's Projects permission: view is needed to read and edit to create or update, and requests return 403 otherwise. Secret key requests are trusted at the account level and are not subject to per-user permissions.
Pagination
Both list endpoints accept limit and offset, and return a meta object with the unpaginated total so you can page through everything.
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | integer | No | Number of results, 1–100 (default 50) |
| offset | integer | No | Number of results to skip (default 0) |
"meta": { "total": 137, "limit": 50, "offset": 0 }
List Epics
/api/v1/epics
Secret Key / PAT
30 req/min
Returns the account's epics ordered by position. Filterable by priority bucket and owner.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| priority_bucket | string | No | One of: ongoing, now, next, future, done |
| owner_id | integer | No | Filter to epics owned by a user (see the Members endpoint for IDs) |
Response
{
"epics": [
{
"id": 1,
"title": "Authentication",
"priority_bucket": "now",
"theme": "Feature",
"position": 0,
"owner": { "id": 5, "name": "Jane Smith" },
"start_date": "2025-01-01",
"end_date": "2025-03-31",
"stories_count": 8,
"created_at": "2025-01-01T09:00:00Z",
"updated_at": "2025-01-15T14:30:00Z"
}
],
"meta": { "total": 12, "limit": 50, "offset": 0 }
}
Get Epic Details
/api/v1/epics/:id
Secret Key / PAT
30 req/min
Returns a single epic with its description, notes, and all of its stories in board order.
Response
{
"epic": {
"id": 1,
"title": "Authentication",
"priority_bucket": "now",
"theme": "Feature",
"position": 0,
"owner": { "id": 5, "name": "Jane Smith" },
"start_date": "2025-01-01",
"end_date": "2025-03-31",
"stories_count": 2,
"created_at": "2025-01-01T09:00:00Z",
"updated_at": "2025-01-15T14:30:00Z",
"description": "Sign in, sign up and password reset.",
"actual_start_date": "2025-01-04",
"actual_end_date": null,
"stories": [
{
"id": 10,
"title": "Login page",
"status": "doing",
"story_points": 1.0,
"position": 0,
"epic": { "id": 1, "title": "Authentication" },
"owner": { "id": 5, "name": "Jane Smith" },
"started_at": "2025-01-12T09:00:00Z",
"done_at": null,
"created_at": "2025-01-02T09:00:00Z",
"updated_at": "2025-01-12T09:00:00Z"
}
],
"notes": [
{ "id": 3, "body": "Blocked on the SSO spike", "user": "Jane Smith", "created_at": "2025-01-14T10:00:00Z" }
]
}
}
start_date and end_date are the planned dates. actual_start_date and actual_end_date are derived from when the epic's stories actually started and finished, and are null until then.
Create Epic
/api/v1/epics
Secret Key / PAT
30 req/min
Creates an epic. Only the title is required; the other attributes take the same values as an update.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | Epic title |
| description | string | No | Longer description |
| priority_bucket | string | No | One of: ongoing, next, future, done (default future). A new epic can't start in now because it has no stories yet |
| theme | string | No | Theme label |
| owner_id | integer | No | User ID to own the epic |
| start_date | date | No | Planned start, ISO 8601 (e.g. "2025-01-01") |
| end_date | date | No | Planned end, must be after the start date |
| position | integer | No | Sort position within its bucket (default 0) |
Success Response (201)
{
"epic": {
"id": 13,
"title": "Billing",
"priority_bucket": "next",
"theme": "Feature",
"position": 0,
"owner": { "id": 5, "name": "Jane Smith" },
"start_date": null,
"end_date": null,
"stories_count": 0,
"created_at": "2025-02-01T09:00:00Z",
"updated_at": "2025-02-01T09:00:00Z"
}
}
Error Response (422)
{ "errors": ["Title can't be blank"] }
{ "errors": ["Priority bucket can't be Now without stories"] }
{ "errors": ["End date must be after start date"] }
{ "errors": ["Owner must belong to the same account"] }
A new epic has no stories yet, so it can't be created straight into now. Create it in next or future, add stories, then move it with an update.
Update Epic
/api/v1/epics/:id
Secret Key / PAT
30 req/min
Updates an epic. Only the attributes you send are changed.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| title | string | No | Epic title |
| description | string | No | Longer description |
| priority_bucket | string | No | One of: ongoing, now, next, future, done |
| theme | string | No | Theme label |
| owner_id | integer | No | User ID to own the epic (or null to unassign) |
| start_date | date | No | Planned start, ISO 8601 (e.g. "2025-01-01") |
| end_date | date | No | Planned end, must be after the start date |
| position | integer | No | Sort position within its bucket |
Success Response
{
"epic": {
"id": 1,
"title": "Authentication",
"priority_bucket": "done",
"theme": "Feature",
"position": 0,
"owner": { "id": 5, "name": "Jane Smith" },
"start_date": "2025-01-01",
"end_date": "2025-03-31",
"stories_count": 8,
"created_at": "2025-01-01T09:00:00Z",
"updated_at": "2025-01-20T11:00:00Z"
}
}
Error Response (422)
{ "errors": ["Priority bucket can't be Now without stories"] }
{ "errors": ["Priority bucket can't be Done while there are incomplete stories"] }
{ "errors": ["End date must be after start date"] }
{ "errors": ["Owner must belong to the same account"] }
Epics enforce their own rules: an epic can't move to now until it has stories, and can't move to done while any of its stories are incomplete.
List Stories
/api/v1/stories
Secret Key / PAT
30 req/min
Returns the account's stories ordered by position. Filterable by status, epic, and owner.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | No | One of: backlog, ready, doing, review, done. All statuses by default. |
| epic_id | integer | No | Filter to stories in one epic |
| owner_id | integer | No | Filter to stories owned by a user |
Response
{
"stories": [
{
"id": 10,
"title": "Login page",
"status": "doing",
"story_points": 1.0,
"position": 0,
"epic": { "id": 1, "title": "Authentication" },
"owner": { "id": 5, "name": "Jane Smith" },
"started_at": "2025-01-12T09:00:00Z",
"done_at": null,
"created_at": "2025-01-02T09:00:00Z",
"updated_at": "2025-01-12T09:00:00Z"
}
],
"meta": { "total": 43, "limit": 50, "offset": 0 }
}
Get Story Details
/api/v1/stories/:id
Secret Key / PAT
30 req/min
Returns a single story with its description, checklist tasks, and notes.
Response
{
"story": {
"id": 10,
"title": "Login page",
"status": "doing",
"story_points": 1.0,
"position": 0,
"epic": { "id": 1, "title": "Authentication" },
"owner": { "id": 5, "name": "Jane Smith" },
"started_at": "2025-01-12T09:00:00Z",
"done_at": null,
"created_at": "2025-01-02T09:00:00Z",
"updated_at": "2025-01-12T09:00:00Z",
"description": "Email and password sign in.",
"cycle_time": null,
"tasks_progress": { "completed": 1, "total": 3 },
"tasks": [
{ "id": 1, "body": "Build the form", "description": null, "completed": true, "position": 0 }
],
"notes": [
{ "id": 7, "body": "Design signed off", "user": "Jane Smith", "created_at": "2025-01-13T10:00:00Z" }
]
}
}
cycle_time is the number of seconds between the story starting and finishing, and is null until it is done. tasks_progress is null when the story has no tasks.
Create Story
/api/v1/stories
Secret Key / PAT
30 req/min
Creates a story in an epic. Title and epic_id are required; the other attributes take the same values as an update.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | Story title |
| epic_id | integer | Yes | Epic the story belongs to (must be in this account) |
| description | string | No | Longer description |
| status | string | No | One of: backlog, ready, doing, review, done (default backlog) |
| story_points | number | No | One of: 0.5, 1, 2, 4, 8 (default 1) |
| owner_id | integer | No | User ID to own the story |
| position | integer | No | Sort position within its status column (default 0) |
Success Response (201)
{
"story": {
"id": 42,
"title": "Wire up search",
"status": "backlog",
"story_points": 2.0,
"position": 0,
"epic": { "id": 13, "title": "Billing" },
"owner": null,
"started_at": null,
"done_at": null,
"created_at": "2025-02-01T09:05:00Z",
"updated_at": "2025-02-01T09:05:00Z"
}
}
Error Response (422)
{ "errors": ["Title can't be blank"] }
{ "errors": ["Epic must exist"] }
{ "errors": ["Epic must belong to the same account"] }
{ "errors": ["Story points is not included in the list"] }
Creating a story with status doing stamps started_at, and done stamps done_at, the same as moving it later.
Update Story
/api/v1/stories/:id
Secret Key / PAT
30 req/min
Updates a story — most commonly to move it across the board. Only the attributes you send are changed.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| title | string | No | Story title |
| description | string | No | Longer description |
| status | string | No | One of: backlog, ready, doing, review, done |
| story_points | decimal | No | One of: 0.5, 1, 2, 4, 8 |
| owner_id | integer | No | User ID to own the story (or null to unassign) |
| epic_id | integer | No | Move the story to a different epic in the same account |
| position | integer | No | Sort position within its status column |
Success Response
{
"story": {
"id": 10,
"title": "Login page",
"status": "done",
"story_points": 1.0,
"position": 0,
"epic": { "id": 1, "title": "Authentication" },
"owner": { "id": 5, "name": "Jane Smith" },
"started_at": "2025-01-12T09:00:00Z",
"done_at": "2025-01-20T16:45:00Z",
"created_at": "2025-01-02T09:00:00Z",
"updated_at": "2025-01-20T16:45:00Z"
}
}
Error Response (422)
{ "errors": ["Status can't be Done while there are incomplete tasks"] }
{ "errors": ["Status can't be changed because the epic is done"] }
{ "errors": ["Story points is not included in the list"] }
{ "errors": ["Epic must belong to the same account"] }
Moving a story to doing stamps started_at, and moving it to done stamps done_at — you don't set these yourself. Moving a story out of done clears done_at.