Manage tasks (also called "steps") within projects and phases. Tasks represent individual work items that can be assigned, tracked, and completed.
{
"id": 123,
"title": "Design homepage wireframe",
"completed": false,
"published": true,
"is_approval": false,
"approval_status": null,
"due_date": "2023-02-15T00:00:00.000000Z",
"created_at": "2023-01-01T12:00:00.000000Z",
"updated_at": "2023-01-01T12:00:00.000000Z",
"phase": { "id": 456, "title": "Design Phase", "is_internal": false },
"project": { "id": 789, "title": "Website Redesign" },
"client": { "id": 101, "title": "Acme Corporation" },
"company": { "id": 202, "title": "Design Studio Inc" },
"tags": [ { "id": 12, "name": "Round 1 of 2", "color": "mint" } ],
"assignees": [ { "id": 3, "name": "Dave Prince" } ]
}
due_date is returned as an empty string ("") when the task has no due date.
assignees is included in list responses; single-task responses (get / create / update)
omit it — read or change assignees via the Task Assignees endpoints.
A task's audience comes from its phase. A task has no visibility flag of its own
— it is internal (team-only) or client-facing purely according to its
phase's is_internal
value (surfaced on the task as phase.is_internal). To change a task's audience, move
it to a phase on the other side. Separately, published controls whether a
client-facing task is visible to the client yet or still a draft.
| Attribute | Type | Description |
|---|---|---|
| id | integer | Unique identifier for the task |
| title | string | The task's name |
| completed | boolean | Whether the task has been completed |
| due_date | string | Task due date (ISO 8601), or "" when not set |
| published | boolean | Whether the task is published (visible) within its phase |
| is_approval | boolean | Whether the task is an approval (sign-off) gate |
| approval_status | string or null | Verdict recorded when an approval task is completed: approved or not_approved. null while the task is open, or for non-approval tasks |
| content | string | Task body as Markdown. Only returned when requested via ?include=content (see below) |
| tags | object[] | Tags applied to the task (id, name, color). Only returned when requested via ?include=tags (see below); an empty array when the task has no tags. Change them via the Task Tags endpoints below — tags is read-only on create and update |
| phase | object | The phase the task belongs to (id, title, is_internal) |
| project | object | The project the task belongs to (id, title) |
| client | object | The client the task belongs to (id, title) |
| company | object | The agency company that owns the task (id, title) |
| assignees | object[] | Users assigned to the task (id, name). Managed via the Task Assignees endpoints |
Including task content: The Markdown content field is opt-in for
performance. Append ?include=content to a list or single-task request to have it
returned. Without it, content is omitted from the response.
Including tags: Tags are opt-in in the same way — append
?include=tags to a list or single-task request. Combine includes with a comma, e.g.
?include=content,tags. Each tag is an object with an id, a
name, and a color (one of mandarin, coral,
pink, orchid, mint, aqua,
mustard, steel). Tasks with no tags return [].
Retrieves a list of tasks the authenticated user has access to. Tasks belonging to template projects are always excluded.
/api/v1/steps
| Parameter | Type | Description |
|---|---|---|
| company_id | integer | Filter tasks by specific company ID |
| completed | boolean | Filter by completion status |
| has_due_date | boolean | Filter tasks that have or don't have due dates |
| exclude_templates | boolean | Deprecated and no longer necessary — template tasks are always excluded. Accepted but has no effect |
| include | string | Comma-separated extra fields to include. Use content to return each task's Markdown body, and tags to return each task's tags. |
| per_page | integer | Number of results per page (max 1000) |
GET /api/v1/steps?completed=false&company_id=202&include=content&per_page=25
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json
[
{
"id": 123,
"title": "Design homepage wireframe",
"completed": false,
"published": true,
"due_date": "2023-02-15T00:00:00.000000Z",
"created_at": "2023-01-01T12:00:00.000000Z",
"updated_at": "2023-01-01T12:00:00.000000Z",
"phase": { "id": 456, "title": "Design Phase", "is_internal": false },
"project": { "id": 789, "title": "Website Redesign" },
"client": { "id": 101, "title": "Acme Corporation" },
"company": { "id": 202, "title": "Design Studio Inc" },
"assignees": [ { "id": 3, "name": "Dave Prince" } ]
}
]
Retrieves a specific task by ID.
/api/v1/steps/{id}
GET /api/v1/steps/123
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json
{
"id": 123,
"title": "Design homepage wireframe",
"completed": false,
"published": true,
"due_date": "2023-02-15T00:00:00.000000Z",
"created_at": "2023-01-01T12:00:00.000000Z",
"updated_at": "2023-01-01T12:00:00.000000Z",
"phase": { "id": 456, "title": "Design Phase", "is_internal": false },
"project": { "id": 789, "title": "Website Redesign" },
"client": { "id": 101, "title": "Acme Corporation" },
"company": { "id": 202, "title": "Design Studio Inc" }
}
Creates a new task within a phase.
/api/v1/steps
| Parameter | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | The task's name |
| phase_id | integer | Yes | ID of the phase this task belongs to |
| content | string | No | Task content that will appear in the task details. Plain text is automatically converted to rich text format. |
| due_date | string | No | Task due date (YYYY-MM-DD) |
| completed | boolean | No | Whether the task is completed (defaults to false) |
| published | boolean | No | Whether the task is published (visible) within its phase |
| is_approval | boolean | No | Create the task as an approval (sign-off) gate (defaults to false) |
POST /api/v1/steps
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Accept: application/json
{
"title": "Create user flow diagram",
"phase_id": 456,
"content": "Design user flow for the new checkout process.\n\nInclude all edge cases and error states.",
"due_date": "2023-02-20"
}
{
"id": 124,
"title": "Create user flow diagram",
"completed": false,
"published": true,
"due_date": "2023-02-20T00:00:00.000000Z",
"created_at": "2023-01-15T10:00:00.000000Z",
"updated_at": "2023-01-15T10:00:00.000000Z",
"phase": { "id": 456, "title": "Design Phase", "is_internal": false },
"project": { "id": 789, "title": "Website Redesign" },
"client": { "id": 101, "title": "Acme Corporation" },
"company": { "id": 202, "title": "Design Studio Inc" }
}
Updates an existing task's information, including marking it as completed.
Attachments, form fields, and embeds are preserved on content updates. Markdown cannot express these elements, so when content replaces the body, any such elements in the existing content are kept in place even if your markdown omits them (elements retained as plain links are upgraded back to their original form). To remove them deliberately, pass allow_removing_attachments: true.
/api/v1/steps/{id}
| Parameter | Type | Description |
|---|---|---|
| title | string | The task's name |
| content | string | Task content/description. Plain text is automatically converted to rich text format. |
| completed | boolean | Whether the task is completed |
| published | boolean | Whether the task is published (visible) within its phase |
| is_approval | boolean | Turn the approval (sign-off) requirement on or off for the task |
| approval_status | string | Verdict for an approval task: approved or not_approved. Only valid together with completed: true (or on an already-completed approval task). Completing an approval task without it records approved; reopening the task clears the verdict |
| due_date | string|null | Task due date (YYYY-MM-DD). Send null to clear it |
| phase_id | integer | Move the task to a different phase. The phase must belong to a project in one of your companies — it can be in another project, and it can be an internal phase |
Moving a task between phases: Setting phase_id moves the task, which
also changes its visibility — moving a task into an internal phase hides it from the client,
and moving it into a client-facing phase exposes it. Check the target phase's
is_internal flag before you move.
PUT /api/v1/steps/123
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Accept: application/json
{
"title": "Design homepage wireframe (Updated)",
"content": "Updated requirements based on client feedback.",
"completed": true,
"due_date": "2023-02-18"
}
{
"id": 123,
"title": "Design homepage wireframe (Updated)",
"completed": true,
"published": true,
"due_date": "2023-02-18T00:00:00.000000Z",
"created_at": "2023-01-01T12:00:00.000000Z",
"updated_at": "2023-01-15T14:30:00.000000Z",
"phase": { "id": 456, "title": "Design Phase", "is_internal": false },
"project": { "id": 789, "title": "Website Redesign" },
"client": { "id": 101, "title": "Acme Corporation" },
"company": { "id": 202, "title": "Design Studio Inc" }
}
Repositions a task within its phase. Pass either position
("first" or "last") or after_step_id to place the task
directly after another task in the same phase — the same result as drag-and-drop in the app.
/api/v1/steps/{id}/reorder
| Parameter | Type | Description |
|---|---|---|
| position | string | "first" or "last". Required unless after_step_id is given. |
| after_step_id | integer | Place the task directly after this task. Must be a task in the same phase; returns 422 otherwise. |
POST /api/v1/steps/123/reorder
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
{
"position": "first"
}
Returns the updated task object, including its new order.
Permanently deletes a task. Only company members can delete tasks.
/api/v1/steps/{id}
Warning: Deleting a task will permanently remove it and cannot be undone. Consider marking tasks as completed instead of deleting them to maintain project history.
DELETE /api/v1/steps/123
Authorization: Bearer YOUR_ACCESS_TOKEN
Accept: application/json
204 No Content