Issue tracker with projects, labels, comments, relations, and agent execution.
Issues are crew-scoped tracker items: each carries a human-readable identifier (e.g. ENG-42), a status flow, and lifecycle operations for agent execution. Beyond CRUD, the API covers comments, relations, an activity log, workspace labels, and projects that group issues with tracking metadata. Under the hood, issues are stored in the missions table with mission_type = 'issue' — they share infrastructure with missions but keep their own status flow, identifiers, and lifecycle.
All issue endpoints require authentication and workspace context.
Create, read, update, and delete issues. Most write operations require OWNER, ADMIN, or MANAGER role and emit a WebSocket event on workspace:{workspaceId}.
Who created the issue: {type, id, name} where type is "user" (created via the API/UI) or "agent" (created by an agent tool call). name is resolved at read time like assignee_name. Omitted on issues that predate creator attribution
authored_via
string?
Creation channel: "user_api" (human via API/UI/slash command) or "agent_tool_call" (agent via sidecar). Omitted on legacy issues
due_date
string?
Due date
sort_order
number
Manual sort order for board views
mission_type
string
Always "issue" for issues
lead_agent_id
string
Crew’s lead agent ID
labels
array
Array of label objects
project_id
string?
Parent project ID
estimate
integer?
Effort/points estimate
parent_issue_id
string?
Parent issue ID for sub-issues
milestone_id
string?
Associated milestone ID
sub_issues_count
integer
Count of child issues with parent_issue_id = this issue
routine_id
string?
Bound pipeline ID for /run-routine (omitted if unbound)
GET /api/v1/issues/{identifier}?workspace_id={workspaceId}
Get an issue by its identifier (e.g., ENG-42) across the entire workspace. No crew ID needed.Response:200 OK — full issue object with labels and comment count.
POST /api/v1/crews/{crewId}/issues?workspace_id={workspaceId}
Auth:OWNER, ADMIN, or MANAGER roleThe crew must have a LEAD agent. The issue identifier is auto-generated from the crew’s issue_prefix (or first 3 characters of the slug) and an auto-incrementing counter.Request Body:
Field
Type
Required
Default
Description
title
string
Yes
—
Issue title
description
string
No
null
Issue description
priority
string
No
"none"
Priority: none, low, medium, high, urgent
assignee_type
string
No
null
"user" or "agent"
assignee_id
string
No
null
Assignee ID
due_date
string
No
null
Due date (YYYY-MM-DD)
project_id
string
No
null
Parent project ID
estimate
integer
No
null
Effort/points estimate
parent_issue_id
string
No
null
Parent issue ID for sub-issues (validated against current workspace)
milestone_id
string
No
null
Associated milestone ID
labels
string[]
No
[]
Array of label IDs to attach
routine_id
string
No
null
Pipeline ID to bind for /run-routine (must exist in workspace)
routine_inputs
object
No
{}
JSON object of routine input values; rejected with 400 if set without routine_id
{ "title": "Fix authentication token refresh", "description": "Tokens are not being refreshed before expiry", "priority": "high", "assignee_type": "agent", "assignee_id": "agent_789", "labels": ["label_bug"]}
Response:201 Created — issue object with generated number and identifier.
Status
Condition
400
Missing title, crew has no lead agent, routine_inputs set without routine_id, routine_id/parent_issue_id not in workspace, or routine_inputs not valid JSON
403
Insufficient role
404
Crew not found
WebSocket event:issue.created on workspace:{workspaceId}
Pipeline ID to bind; empty string clears binding (also resets routine_inputs)
routine_inputs
object
Full-replacement JSON object for routine inputs
Status Transitions:
From
Allowed To
BACKLOG
TODO, IN_PROGRESS, CANCELLED
TODO
IN_PROGRESS, BACKLOG, CANCELLED
IN_PROGRESS
REVIEW, DONE, FAILED, CANCELLED, TODO
REVIEW
DONE, TODO, IN_PROGRESS, FAILED, CANCELLED
DONE
BACKLOG
FAILED
BACKLOG, TODO, IN_PROGRESS
CANCELLED
BACKLOG, TODO
When status changes to DONE or CANCELLED, completed_at is automatically set.Significant changes (status, assignee, priority) are logged as activity entries.Response:200 OK — updated issue object.
Status
Condition
400
Invalid status transition, no fields to update, parent_issue_id equals issue itself, parent_issue_id/routine_id not in workspace, or routine_inputs not valid JSON
404
Issue not found
WebSocket event:issue.updated on workspace:{workspaceId}
Apply a single set of field updates to up to 100 issues at once. Used by the board/list views’ multi-select toolbar. Each issue is processed in its own statement — partial success is possible: a request touching 50 ids where 3 have invalid status transitions returns {"updated": 47} rather than rolling back.Auth:OWNER, ADMIN, or MANAGER role (create permission).Request Body:
Field
Type
Required
Description
ids
string[]
Yes
1-100 mission ids. Ids outside the caller’s workspace are skipped silently.
updates.status
string
No
New status. Invalid transitions are skipped per-issue (not 400). When DONE or CANCELLED, completed_at is set automatically.
updates.priority
string
No
Priority level.
updates.assignee_type
string
No
"user" or "agent".
updates.assignee_id
string
No
Assignee id.
updates.project_id
string
No
Project id; empty string unlinks.
updates.labels
string[]
No
Replace all labels on each issue with this set of label ids.
Count of issues that successfully applied at least one field. Issues whose updates resolved to a no-op are excluded.
Status
Condition
400
Invalid JSON, missing ids, or ids length > 100.
403
Caller lacks the create permission for the workspace.
When updated > 0, an issues.bulk_updated WebSocket event is broadcast on workspace:{workspaceId} with the count. Per-issue status changes additionally produce activity entries (status_changed, details suffixed with (bulk)).
GET /api/v1/crews/{crewId}/issues/{identifier}/subtasks
Returns the children of one parent issue — rows where parent_issue_id equals the resolved parent id. Ordered by sort_order ASC, created_at ASC so the response matches the order operators see in the UI’s nested list.Path parameters:
Param
Description
crewId
Crew id (used to disambiguate identifiers across crews).
identifier
Human-readable identifier (e.g. ENG-42) or raw mission id of the parent.
Response:200 OK — array of full issue objects matching the GET /api/v1/issues shape. Empty array (never null) when the parent has no sub-issues.
Status
Condition
404
Parent issue not found in the supplied crew + workspace.