---
title: "Tasks API reference"
canonical_url: https://zentrik.ai/docs/api/tasks
markdown_url: https://zentrik.ai/docs/api/tasks.md
last_reviewed: 2026-09-10
---

# Tasks API reference

Find sprint work, edit tasks and attach pull requests with workspace-scoped API access. Request tasks:read for reads and tasks:write for mutations.

- Human reference: https://zentrik.ai/docs/api/tasks
- Complete Markdown index: https://zentrik.ai/docs/api/index.md
- Base URL: `https://zentrik.ai/api`
- Authentication: `Authorization: Bearer YOUR_API_KEY`
- Shared pagination and rate limits: https://zentrik.ai/docs/api/index.md#shared-conventions

## GET /external/v1/tasks — Find pending tasks

Operation ID: `list-execution-tasks`

Find tasks owned by one team, including tasks inherited from its Initiatives. status defaults to pending, which means every status except done. sprintId=current selects the explicitly active sprint; when none is active the result is empty. Omitting sprintId includes backlog and other sprints. Results sort by executionPosition and then UUID. List responses are arrays with X-Total-Count, X-Limit, X-Offset and X-Has-More headers. Continue until X-Has-More is false; concurrent edits can shift offset pages.

Required API key scopes: `tasks:read`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `teamId` | uuid | Yes | Required query parameter. Resolve it with GET /external/v1/teams (initiatives:read). |
| `limit` | integer | No | Page size, 1–100. Default 20. |
| `offset` | integer | No | Matching rows to skip. Default 0. |
| `sprintId` | uuid \| current | No | Filter to a sprint, or use current. |
| `status` | enum | No | pending (default), all, or triage, ready, in_progress, in_review, blocked, done. |
| `ownerUserId` | uuid | No | Filter by owner. |
| `projectId` | uuid | No | Filter by Initiative. |
| `sourceIdeaId` | uuid | No | Filter by linked Idea. |
| `q` | string | No | Literal search in task title and description; up to 200 characters. |

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | The requested data is returned. | — |
| 400 | Invalid request | Invalid ID, unsupported field, empty patch, or invalid value. | — |
| 403 | Missing scope | The key does not grant the required resource scope. | — |
| 404 | Not found | The addressed record or assignment is outside this workspace or team. | — |

### Example response

```json
[
  {
    "id": "22222222-2222-4222-8222-222222222222",
    "summary": "Fix duplicate exports",
    "executionStatus": "in_review",
    "sourceIdeaId": null,
    "sourceEvidenceId": "33333333-3333-4333-8333-333333333333",
    "sprintId": null,
    "ownerUserId": null
  }
]
```

---

## GET /external/v1/tasks/:id — Get task context

Operation ID: `get-execution-task`

Read task instructions, dependencies, owner, sprint, sourceIdeaId and sourceEvidenceId. readOnly identifies completed-sprint tasks; sourceManaged identifies provider-owned tasks. Follow sourceIdeaId with the Ideas API, sourceEvidenceId with the Signal evidence API, and list PR attachments separately. The response includes safe provider metadata and linked user-story context.

Required API key scopes: `tasks:read`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | Yes | Record UUID in the path. |
| `teamId` | uuid | Yes | Required query parameter. Resolve it with GET /external/v1/teams (initiatives:read). |

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | The requested data is returned. | — |
| 400 | Invalid request | Invalid ID, unsupported field, empty patch, or invalid value. | — |
| 403 | Missing scope | The key does not grant the required resource scope. | — |
| 404 | Not found | The addressed record or assignment is outside this workspace or team. | — |

### Example response

```json
{
  "id": "22222222-2222-4222-8222-222222222222",
  "summary": "Fix duplicate exports",
  "executionStatus": "in_review",
  "sourceIdeaId": null,
  "sourceEvidenceId": "33333333-3333-4333-8333-333333333333",
  "sprintId": null,
  "ownerUserId": null,
  "description": "Make retries reuse the export.",
  "dependencies": [],
  "readOnly": false,
  "sourceManaged": false
}
```

---

## POST /external/v1/tasks — Create a task

Operation ID: `create-execution-task`

Create a native team task. Omitted values use ready status, medium priority and the planned lane. sourceIdeaId can link product context without requiring an Initiative. Reuse clientRequestId after a timeout; use a new UUID for a different task.

Required API key scopes: `tasks:write`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `teamId` | uuid | Yes | Required query parameter. Resolve it with GET /external/v1/teams (initiatives:read). |

### JSON request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `summary` | string | Yes | Task title, 3–500 characters after trimming. |
| `description` | string | No | Task instructions, up to 12,000 characters. |
| `role` | string | No | Delivery role, up to 120 characters. |
| `kind` | enum | No | task, bug, request, or design. |
| `executionStatus` | enum | No | triage, ready, in_progress, in_review, blocked, done. |
| `executionPriority` | enum | No | urgent, high, medium, or low. |
| `executionLane` | enum | No | planned or fast. |
| `projectId` | uuid \| null | No | Initiative in this team; null makes the task standalone. |
| `sprintId` | uuid \| null | No | Non-completed sprint in this team; null removes sprint assignment. |
| `ownerUserId` | uuid \| null | No | Workspace user who belongs to this team; null clears ownership. |
| `sourceIdeaId` | uuid | No | Optional source Idea in this workspace. |
| `triageNote` | string \| null | No | Up to 4,000 characters; null clears the note. |
| `clientRequestId` | uuid | Yes | Required stable UUID for this creation attempt. Reuse on retries to avoid duplicate tasks. |

### Example request

```json
{
  "summary": "Fix duplicate exports",
  "clientRequestId": "22222222-2222-4222-8222-222222222222",
  "sourceIdeaId": "33333333-3333-4333-8333-333333333333"
}
```

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 201 | Success | The saved record is returned. | — |
| 400 | Invalid request | Invalid ID, unsupported field, empty patch, or invalid value. | — |
| 403 | Missing scope | The key does not grant the required resource scope. | — |
| 404 | Not found | The addressed record or assignment is outside this workspace or team. | — |
| 409 | Conflict | The observed status changed, the sprint is completed, or a source-managed field must be edited in Linear. | — |

### Example response

```json
{
  "id": "22222222-2222-4222-8222-222222222222",
  "summary": "Fix duplicate exports",
  "executionStatus": "in_review",
  "sourceIdeaId": null,
  "sourceEvidenceId": "33333333-3333-4333-8333-333333333333",
  "sprintId": null,
  "ownerUserId": null
}
```

---

## PATCH /external/v1/tasks/:id — Update a task

Operation ID: `update-execution-task`

Send at least one supported field. Omitted fields remain unchanged; nullable fields can be cleared. Arrays replace the full saved relation. Completed-sprint tasks are read-only. Linear-owned source fields (title, instructions, effort, kind, status, priority, lane, sprint, owner and dependencies) must be edited in Linear. Updating a task never changes an Idea status or evidence resolution.

Required API key scopes: `tasks:write`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | Yes | Record UUID in the path. |
| `teamId` | uuid | Yes | Required query parameter. Resolve it with GET /external/v1/teams (initiatives:read). |

### JSON request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `summary` | string | No | Task title, 3–500 characters after trimming. |
| `description` | string | No | Task instructions, up to 12,000 characters. |
| `role` | string | No | Delivery role, up to 120 characters. |
| `kind` | enum | No | task, bug, request, or design. |
| `executionStatus` | enum | No | triage, ready, in_progress, in_review, blocked, done. |
| `executionPriority` | enum | No | urgent, high, medium, or low. |
| `executionLane` | enum | No | planned or fast. |
| `projectId` | uuid \| null | No | Initiative in this team; null makes the task standalone. |
| `sprintId` | uuid \| null | No | Non-completed sprint in this team; null removes sprint assignment. |
| `ownerUserId` | uuid \| null | No | Workspace user who belongs to this team; null clears ownership. |
| `sourceIdeaId` | uuid \| null | No | Source Idea in this workspace; null clears the link. |
| `triageNote` | string \| null | No | Up to 4,000 characters; null clears the note. |
| `storyPoints` | integer \| null | No | Effort from 0 to 1,000; null clears the estimate. |
| `dependencies` | uuid[] | No | Complete dependency task list, up to 100 unique IDs accessible in this team. |
| `userStoryIds` | uuid[] | No | Complete user-story list, up to 100 unique IDs in this team. |
| `expectedCurrentStatus` | enum | No | Optional observed task status; a mismatch returns 409. triage, ready, in_progress, in_review, blocked, done. |

### Example request

```json
{
  "description": "Reuse the existing export on retry.",
  "expectedCurrentStatus": "ready"
}
```

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | The saved record is returned. | — |
| 400 | Invalid request | Invalid ID, unsupported field, empty patch, or invalid value. | — |
| 403 | Missing scope | The key does not grant the required resource scope. | — |
| 404 | Not found | The addressed record or assignment is outside this workspace or team. | — |
| 409 | Conflict | The observed status changed, the sprint is completed, or a source-managed field must be edited in Linear. | — |

### Example response

```json
{
  "id": "22222222-2222-4222-8222-222222222222",
  "summary": "Fix duplicate exports",
  "executionStatus": "in_review",
  "sourceIdeaId": null,
  "sourceEvidenceId": "33333333-3333-4333-8333-333333333333",
  "sprintId": null,
  "ownerUserId": null
}
```

---

## PATCH /external/v1/tasks/:id/status — Change task status

Operation ID: `set-execution-task-status`

Set one task status. expectedCurrentStatus rejects a stale update. A done task does not automatically ship its Idea or resolve supporting evidence.

Required API key scopes: `tasks:write`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | Yes | Record UUID in the path. |
| `teamId` | uuid | Yes | Required query parameter. Resolve it with GET /external/v1/teams (initiatives:read). |

### JSON request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `status` | enum | Yes | triage, ready, in_progress, in_review, blocked, done. |
| `expectedCurrentStatus` | enum | No | Previously observed status; mismatch returns 409. |

### Example request

```json
{
  "status": "in_review",
  "expectedCurrentStatus": "in_progress"
}
```

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | The saved record is returned. | — |
| 400 | Invalid request | Invalid ID, unsupported field, empty patch, or invalid value. | — |
| 403 | Missing scope | The key does not grant the required resource scope. | — |
| 404 | Not found | The addressed record or assignment is outside this workspace or team. | — |
| 409 | Conflict | The observed status changed, the sprint is completed, or a source-managed field must be edited in Linear. | — |

### Example response

```json
{
  "id": "22222222-2222-4222-8222-222222222222",
  "summary": "Fix duplicate exports",
  "executionStatus": "in_review",
  "sourceIdeaId": null,
  "sourceEvidenceId": "33333333-3333-4333-8333-333333333333",
  "sprintId": null,
  "ownerUserId": null
}
```

---

## GET /external/v1/tasks/:id/pull-requests — List task PR attachments

Operation ID: `list-task-pull-requests`

Read task attachments and stored GitHub status from the same workspace when available. Missing synced fields are null. No provider request is made; mergedAt is not proof of production shipment. List responses are arrays with X-Total-Count, X-Limit, X-Offset and X-Has-More headers. Continue until X-Has-More is false; concurrent edits can shift offset pages.

Required API key scopes: `tasks:read`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | Yes | Record UUID in the path. |
| `teamId` | uuid | Yes | Required query parameter. Resolve it with GET /external/v1/teams (initiatives:read). |
| `limit` | integer | No | Page size, 1–100. Default 20. |
| `offset` | integer | No | Matching rows to skip. Default 0. |

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | The requested data is returned. | — |
| 400 | Invalid request | Invalid ID, unsupported field, empty patch, or invalid value. | — |
| 403 | Missing scope | The key does not grant the required resource scope. | — |
| 404 | Not found | The addressed record or assignment is outside this workspace or team. | — |

### Example response

```json
[
  {
    "id": "33333333-3333-4333-8333-333333333333",
    "url": "https://github.com/example/app/pull/42",
    "repositoryFullName": "example/app",
    "number": 42,
    "pullRequestId": null,
    "title": null,
    "state": null,
    "checksState": null,
    "mergedAt": null,
    "lastSyncedAt": null
  }
]
```

---

## POST /external/v1/tasks/:id/pull-requests — Attach a PR to a task

Operation ID: `attach-task-pull-request`

Attach an HTTPS github.com pull request URL, including before the integration has synced it. The URL is recorded without fetching or verifying it. Repository and PR number determine identity; retrying returns the existing attachment. This does not create an Idea/Initiative delivery link, publish a PR, or change any status. Use the existing Zentrik trailer contract separately for product delivery links.

Required API key scopes: `tasks:write`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | Yes | Record UUID in the path. |
| `teamId` | uuid | Yes | Required query parameter. Resolve it with GET /external/v1/teams (initiatives:read). |

### JSON request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `url` | url | Yes | https://github.com/owner/repository/pull/number. Query and fragment are removed; repository case is normalized. GitHub Enterprise hosts are not supported. |

### Example request

```json
{
  "url": "https://github.com/example/app/pull/42"
}
```

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 201 | Success | The saved record is returned. | — |
| 400 | Invalid request | Invalid ID, unsupported field, empty patch, or invalid value. | — |
| 403 | Missing scope | The key does not grant the required resource scope. | — |
| 404 | Not found | The addressed record or assignment is outside this workspace or team. | — |
| 409 | Conflict | The observed status changed, the sprint is completed, or a source-managed field must be edited in Linear. | — |

### Example response

```json
{
  "id": "33333333-3333-4333-8333-333333333333",
  "workspaceId": "33333333-3333-4333-8333-333333333333",
  "taskId": "22222222-2222-4222-8222-222222222222",
  "repositoryFullName": "example/app",
  "number": 42,
  "url": "https://github.com/example/app/pull/42",
  "createdAt": "2026-09-10T10:00:00Z",
  "updatedAt": "2026-09-10T10:00:00Z"
}
```

---

## DELETE /external/v1/tasks/:id/pull-requests/:linkId — Detach a task PR

Operation ID: `detach-task-pull-request`

Remove only this task attachment. Repeated removal returns changed:false. The PR and Idea/Initiative delivery links remain available. Completed-sprint tasks are read-only.

Required API key scopes: `tasks:write`

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | uuid | Yes | Record UUID in the path. |
| `teamId` | uuid | Yes | Required query parameter. Resolve it with GET /external/v1/teams (initiatives:read). |
| `linkId` | uuid | Yes | Attachment ID returned by attach/list, not the GitHub PR ID. |

### Responses

| Status | Meaning | Description | Schema |
| --- | --- | --- | --- |
| 200 | Success | The saved record is returned. | — |
| 400 | Invalid request | Invalid ID, unsupported field, empty patch, or invalid value. | — |
| 403 | Missing scope | The key does not grant the required resource scope. | — |
| 404 | Not found | The addressed record or assignment is outside this workspace or team. | — |
| 409 | Conflict | The observed status changed, the sprint is completed, or a source-managed field must be edited in Linear. | — |

### Example response

```json
{
  "id": "22222222-2222-4222-8222-222222222222",
  "linkId": "33333333-3333-4333-8333-333333333333",
  "changed": true
}
```
