REST API

Tasks

Create, update, move, and finalize tasks via the REST API.

A task is the core unit of work. Every task belongs to exactly one workspace and one stage, optionally to a project, and may have assignees, tags, subtasks, comments, attachments, and time entries.

Endpoints

MethodPathNotes
GET/api/v1/tasksList with filters. Cursor pagination.
POST/api/v1/tasksCreate. Requires workspaceId. Accepts Idempotency-Key.
GET/api/v1/tasks/{id}Single task with assignees, tags, type, project, stage, subtasks.
PATCH/api/v1/tasks/{id}Update fields, or move by sending workspaceId / stageId / sortOrder.
DELETE/api/v1/tasks/{id}Delete the task.

Subtasks have their own nested resource.

Task model

{
  "id": "t1…",
  "organizationId": "...",
  "workspaceId": "...",
  "stageId": "...",
  "sortOrder": 2,
  "projectId": null,
  "taskTypeId": null,
  "subject": "Wire the OAuth login button",
  "descriptionHtml": "<p>Hook the button up to Better Auth.</p>",
  "priority": "high",
  "expectedStartDate": null,
  "expectedEndDate": null,
  "estimatedHours": 4,
  "finalizedAt": null,
  "finalizationDate": null,
  "assignees": [{ "user": { "id": "...", "name": "Alex" } }],
  "tags": [{ "tag": { "id": "...", "name": "backend" } }],
  "taskType": null,
  "project": null,
  "stage": { "id": "...", "name": "Doing", "isFinalizing": false },
  "subtasks": []
}
FieldTypeNotes
priorityenumlow · normal · high · urgent
descriptionHtmlstringSanitized HTML produced by the Tiptap editor. Inline image URLs must be app-hosted (no base64).
estimatedHoursdecimal | nullHours planned; reported time is computed separately from TimeEntry rows.
finalizedAtISO date | nullSet when the task is closed; auto-set when moved into a finalizing stage.

Listing tasks

GET /api/v1/tasks?workspaceId=...&priority=high&limit=50
ParamTypeNotes
workspaceIdUUIDFilter to one workspace.
stageIdUUIDFilter to one stage.
projectIdUUIDProject filter. Combines with project visibility.
taskTypeIdUUIDTask-type filter.
assigneeIdUUIDTasks assigned to a specific member.
tagIdUUIDTasks carrying a specific tag.
priorityenumOne of the priority values.
querystringCase-insensitive search on subject.
cursorUUIDFrom a previous response.
limitint 1–100Default 50.

Returns { data, pagination: { nextCursor } }. Tasks are ordered by (createdAt DESC, id DESC) so newer work surfaces first.

Creating a task

POST /api/v1/tasks
Content-Type: application/json
Idempotency-Key: ...

{
  "workspaceId": "1f3c…",
  "subject": "Wire the OAuth login button",
  "priority": "high",
  "estimatedHours": 4
}

Required: workspaceId, subject.

The task is placed in the workspace's leftmost stage (lowest sortOrder) — you cannot pass stageId on create. If that stage is the finalizing stage, the task is finalized on creation.

Optional fieldTypeNotes
descriptionHtmlstring≤ 50 000 chars.
projectIdUUID | nullProject access enforced.
taskTypeIdUUID | nullMust belong to the org.
priorityenumDefaults to normal.
expectedStartDate / expectedEndDateISO date | null
estimatedHoursnumber ≥ 0≤ 99 999.99.
assigneeIdsUUID[]Must be org members. Triggers in-app + email notifications.
tagIdsUUID[]Must belong to the org.

Response: 201 Created with the full task.

Updating or moving a task

PATCH /api/v1/tasks/{id}
{ "subject": "OAuth wiring", "priority": "normal" }

All fields are optional. Sending any of workspaceId, stageId, or sortOrder switches the request to move mode:

  • Move within the same stage (sortOrder only) — reorders the task.
  • Move to a new stage — stageId must belong to the same (or target) workspace.
  • Cross-workspace move — pass workspaceId (and optionally stageId). If stageId is omitted, the task lands in the target workspace's leftmost stage.
  • Moving into a finalizing stage auto-sets finalizedAt/finalizationDate to today (in the calling user's timezone).
  • Moving out of a finalizing stage clears them.

A move on a project-restricted task requires project edit access; otherwise the response is 404.

Deleting a task

DELETE /api/v1/tasks/{id}

Returns { "data": { "success": true } }. Cascade-deletes subtasks, comments, attachments, and time entries owned by the task.

Common precondition failures

CodeCause
404Cross-org id, missing workspace, missing task-type, or project access denied.
412Target workspace has no stages — you cannot place a task in it.
400stageId belongs to a different workspace than the target.

On this page