Skip to content

REST API: Tasks

Task lifecycle management with workflow state machine and notes support.

Overview

The tasks endpoint provides:

  • Task CRUD operations
  • Workflow state transitions (start, block, review, complete)
  • Task notes for collaboration
  • Proper state machine validation

Base URL: /api/tasks

Authentication

All endpoints require authentication via:

  • JWT access token (cookie or Authorization header)
  • API key with api:write scope

Role Requirements

All task operations require: Owner, Admin, or Member role.

Task Model

typescript
interface Task {
  id: string;
  title: string;
  description: string;
  status: TaskStatus;
  priority: TaskPriority;
  complexity: TaskComplexity;
  project_id: string;
  epic_id?: string;
  assignees: string[];
  feature?: string;
  tags: string[];
  technologies: string[];
  branch_name?: string;
  pr_url?: string;
  created_at: string;
  updated_at: string;
}

Status Values

StatusDescription
backlogNot yet prioritized
todoReady to work on
doingCurrently in progress
blockedWaiting on dependency
reviewIn code review
doneCompleted
archivedArchived (terminal)

Priority Values

PriorityDescription
criticalImmediate attention
highImportant, do soon
mediumNormal priority (default)
lowNice to have
somedayBacklog item

Complexity Values

ComplexityDescription
trivialMinutes of work
simpleLess than an hour
mediumFew hours (default)
complexMultiple days
epicNeeds breakdown

Endpoints

Create Task

http
POST /api/tasks

Request Body:

json
{
  "title": "Implement OAuth callback handler",
  "description": "Handle OAuth callback from GitHub with PKCE validation",
  "project_id": "proj_abc123",
  "priority": "high",
  "complexity": "medium",
  "status": "todo",
  "assignees": ["alice"],
  "epic_id": "epic_oauth",
  "feature": "authentication",
  "tags": ["backend", "security"],
  "technologies": ["python", "fastapi"],
  "depends_on": ["task_oauth_setup"]
}

Request Schema:

FieldTypeRequiredDefaultDescription
titlestringYes-Task title
descriptionstringNo""Task description
project_idstringYes-Parent project ID
prioritystringNomediumTask priority
complexitystringNomediumTask complexity
statusstringNotodoInitial status
assigneesstring[]No[]Assignee names
epic_idstringNo-Parent epic ID
featurestringNo-Feature area
tagsstring[]No[]Tags
technologiesstring[]No[]Technologies
depends_onstring[]No[]Task dependencies

Response:

json
{
  "success": true,
  "action": "create",
  "task_id": "task_xyz789",
  "message": "Task created successfully",
  "data": {
    "project_id": "proj_abc123"
  }
}

Start Task

http
POST /api/tasks/{task_id}/start

Moves task from todo to doing status.

Request Body (optional):

json
{
  "assignee": "alice"
}

Response:

json
{
  "success": true,
  "action": "start_task",
  "task_id": "task_xyz789",
  "message": "Task started",
  "data": {
    "status": "doing",
    "branch_name": "task/xyz789-implement-oauth"
  }
}

Block Task

http
POST /api/tasks/{task_id}/block

Marks task as blocked with a reason.

Request Body:

json
{
  "reason": "Waiting on API credentials from vendor"
}

Response:

json
{
  "success": true,
  "action": "block_task",
  "task_id": "task_xyz789",
  "message": "Task blocked: Waiting on API credentials from vendor",
  "data": {
    "status": "blocked",
    "reason": "Waiting on API credentials from vendor"
  }
}

Unblock Task

http
POST /api/tasks/{task_id}/unblock

Resumes a blocked task (moves to doing).

Response:

json
{
  "success": true,
  "action": "unblock_task",
  "task_id": "task_xyz789",
  "message": "Task unblocked, resuming work",
  "data": {
    "status": "doing"
  }
}

Submit for Review

http
POST /api/tasks/{task_id}/review

Submits task for code review.

Request Body (optional):

json
{
  "pr_url": "https://github.com/org/repo/pull/42",
  "commit_shas": ["abc123", "def456"]
}

Response:

json
{
  "success": true,
  "action": "submit_review",
  "task_id": "task_xyz789",
  "message": "Task submitted for review",
  "data": {
    "status": "review",
    "pr_url": "https://github.com/org/repo/pull/42"
  }
}

Complete Task

http
POST /api/tasks/{task_id}/complete

Marks task as done with optional learnings.

Request Body (optional):

json
{
  "actual_hours": 4.5,
  "learnings": "OAuth state parameter must be cryptographically random. Used secrets.token_urlsafe(32) for 256-bit entropy."
}

Response:

json
{
  "success": true,
  "action": "complete_task",
  "task_id": "task_xyz789",
  "message": "Task completed with learnings captured",
  "data": {
    "status": "done",
    "learnings": "OAuth state parameter must be..."
  }
}

When learnings are provided, Sibyl automatically creates an episode entity and enqueues it for processing in the background.

Archive Task

http
POST /api/tasks/{task_id}/archive

Archives task without completing.

Request Body (optional):

json
{
  "reason": "Requirement changed, no longer needed"
}

Response:

json
{
  "success": true,
  "action": "archive_task",
  "task_id": "task_xyz789",
  "message": "Task archived",
  "data": {
    "status": "archived"
  }
}

Update Task

http
PATCH /api/tasks/{task_id}

Updates task fields directly. Bypasses workflow state machine.

Request Body:

json
{
  "status": "todo",
  "priority": "critical",
  "complexity": "complex",
  "title": "Updated task title",
  "description": "Updated description",
  "assignees": ["alice", "bob"],
  "epic_id": "epic_new",
  "feature": "new-feature",
  "tags": ["urgent"],
  "technologies": ["python", "redis"]
}

Request Schema (all fields optional):

FieldTypeDescription
statusstringNew status
prioritystringNew priority
complexitystringNew complexity
titlestringNew title
descriptionstringNew description
assigneesstring[]New assignees
epic_idstringNew epic
featurestringNew feature area
tagsstring[]New tags
technologiesstring[]New technologies

Response:

json
{
  "success": true,
  "action": "update_task",
  "task_id": "task_xyz789",
  "message": "Task updated: priority, assignees",
  "data": {
    "priority": "critical",
    "assignees": ["alice", "bob"]
  }
}

Task Notes

Create Note

http
POST /api/tasks/{task_id}/notes

Adds a note to a task.

Request Body:

json
{
  "content": "Discussed with team, will use PKCE flow instead of implicit",
  "author_type": "user",
  "author_name": "alice"
}

Request Schema:

FieldTypeRequiredDefaultDescription
contentstringYes-Note content
author_typestringNouseruser or agent
author_namestringNo""Author identifier

Response:

json
{
  "id": "note_abc123",
  "task_id": "task_xyz789",
  "content": "Discussed with team, will use PKCE flow instead of implicit",
  "author_type": "user",
  "author_name": "alice",
  "created_at": "2024-12-30T10:30:00Z"
}

List Notes

http
GET /api/tasks/{task_id}/notes

Query Parameters:

ParameterTypeDefaultDescription
limitinteger50Maximum notes to return

Response:

json
{
  "notes": [
    {
      "id": "note_abc123",
      "task_id": "task_xyz789",
      "content": "Discussed with team...",
      "author_type": "user",
      "author_name": "alice",
      "created_at": "2024-12-30T10:30:00Z"
    },
    {
      "id": "note_def456",
      "task_id": "task_xyz789",
      "content": "Found relevant pattern in knowledge base",
      "author_type": "agent",
      "author_name": "claude",
      "created_at": "2024-12-30T11:00:00Z"
    }
  ],
  "count": 2
}

State Machine

Valid Transitions

backlog --> todo --> doing --> blocked
                 |         |
                 v         v
              review --> done --> archived
FromAllowed To
backlogtodo
tododoing, archived
doingblocked, review, done, todo
blockeddoing, archived
reviewdoing, done, archived
donearchived

Invalid transitions return:

json
{
  "detail": "Cannot transition from 'todo' to 'done'. Use workflow actions."
}

Concurrency Control

Update operations acquire a distributed lock:

409 Conflict
{
  "detail": "Task is being updated by another process. Please retry."
}

WebSocket Events

Task operations broadcast real-time events:

EventData
entity_createdTask creation
entity_updatedTask update (includes action field)
note_createdNote added

Error Responses

StatusCause
400Invalid state transition or request
401Missing or invalid authentication
403Insufficient permissions
404Task not found
409Concurrent modification conflict
422Request body validation failed
500Internal server error

Examples

Complete Workflow

bash
# 1. Create task
curl -X POST "/api/tasks" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"title": "Implement feature", "project_id": "proj_123"}'

# 2. Start task
curl -X POST "/api/tasks/task_xyz/start" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"assignee": "alice"}'

# 3. Add note
curl -X POST "/api/tasks/task_xyz/notes" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"content": "Working on this now"}'

# 4. Submit for review
curl -X POST "/api/tasks/task_xyz/review" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"pr_url": "https://github.com/org/repo/pull/42"}'

# 5. Complete with learnings
curl -X POST "/api/tasks/task_xyz/complete" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"learnings": "Key insight from implementation..."}'

Released under the MIT License.