> For the complete documentation index, see [llms.txt](https://docs.unitlab.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.unitlab.ai/api-sdk-cli/apis/annotations-and-workflow-api.md).

# Annotations and workflow API

{% hint style="info" %}
**Outcome:** Operate annotation work through stages and tasks with ownership, actions, overrides, and history.
{% endhint %}

The public route contract exposes annotation automation through Project Workflow tasks. It does not document private browser routes for writing arbitrary annotation payloads.

### Stage and task discovery

| Method | Endpoint                                                           | Purpose                      |
| ------ | ------------------------------------------------------------------ | ---------------------------- |
| GET    | `/api/sdk/projects/{project_id}/workflow/stages/`                  | List stages and task counts  |
| GET    | `/api/sdk/projects/{project_id}/workflow/stages/{stage_id}/tasks/` | List stage tasks             |
| GET    | `/api/sdk/workflow-tasks/{task_id}/`                               | Retrieve complete task state |
| GET    | `/api/sdk/workflow-tasks/{task_id}/timeline/`                      | Retrieve task history        |

```bash
curl --fail-with-body --silent --show-error \
  "$UNITLAB_API_URL/api/sdk/projects/PROJECT_ID/workflow/stages/STAGE_ID/tasks/?include_unavailable=0" \
  -H "Authorization: Api-Key $UNITLAB_API_KEY"
```

### Ownership and actions

| Method | Endpoint                                      | Body                                                     |
| ------ | --------------------------------------------- | -------------------------------------------------------- |
| POST   | `/api/sdk/workflow-tasks/{task_id}/claim/`    | Empty                                                    |
| POST   | `/api/sdk/workflow-tasks/{task_id}/assign/`   | `{"user_id":"USER_ID"}`                                  |
| POST   | `/api/sdk/workflow-tasks/{task_id}/release/`  | Empty                                                    |
| POST   | `/api/sdk/workflow-tasks/{task_id}/priority/` | `{"priority":10}`                                        |
| POST   | `/api/sdk/workflow-tasks/{task_id}/actions/`  | Action, idempotency key, expected stage, reason, comment |
| POST   | `/api/sdk/workflow-tasks/{task_id}/move/`     | Destination stage, reason, idempotency key               |

```bash
curl --fail-with-body --silent --show-error \
  -X POST "$UNITLAB_API_URL/api/sdk/workflow-tasks/TASK_ID/actions/" \
  -H "Authorization: Api-Key $UNITLAB_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "action":"approve",
    "idempotency_key":"YOUR_UUID",
    "expected_stage_id":"REVIEW_STAGE_ID",
    "rejection_reason":"",
    "comment":"QA policy checks passed"
  }'
```

Actions can include `complete`, `approve`, `reject`, and `skip`, only when the current Workflow exposes them. The expected stage protects against stale clients.

### Bulk manager operations

| Method | Endpoint                                                | Purpose                        |
| ------ | ------------------------------------------------------- | ------------------------------ |
| POST   | `/api/sdk/projects/{project_id}/workflow/tasks/assign/` | Assign explicit task IDs       |
| POST   | `/api/sdk/projects/{project_id}/workflow/tasks/move/`   | Dry-run or move explicit tasks |

Use `dry_run:true` before a bulk move. Preserve the reason and compare moved, skipped, and failed counts before treating the action as successful.

### Request operating contract

| Concern           | Required behavior                                                                                     |
| ----------------- | ----------------------------------------------------------------------------------------------------- |
| Execution surface | TLS-verified client using the reviewed current public `/api/sdk/...` route contract.                  |
| Identity          | Least-privilege workspace service identity; secrets remain outside code and logs.                     |
| Request boundary  | URL-encoded stable IDs, explicit deadlines, structured errors, and complete pagination.               |
| Success evidence  | Response identifiers, read-after-write verification, and separate processing status for Batch Queues. |

{% hint style="warning" %}
Do not infer undocumented private routes. After a timeout, inspect remote state before repeating a mutation.
{% endhint %}
