> ## Documentation Index
> Fetch the complete documentation index at: https://ago.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Tasks API

> Create, update, move and comment on board tasks through the Public API v1 and MCP

The Tasks API gives your scripts and AI assistants the same board your team uses in **Admin** > **Tasks**: create tasks, link the evidence they came from, move them between statuses and comment on them. See [Tasks](/features/tasks) for the board itself.

## Before you start

* **Tasks must be enabled for your workspace.** It is off by default; contact AGO to enable it. Until then, every call returns `403` with code `tasks_disabled` and the MCP task tools are hidden.
* **Calls run as an active staff user.** For an API key, that is the user who created the key. For OAuth, it is the user who granted access. If that user is not, or is no longer, an active staff user, calls return `403` with code `staff_principal_required`. Changes made through the API are recorded under that user's name.
* **Scopes**: `tasks:read` to read tasks, comments, statuses, labels and assignable staff. `tasks:write` to create, update, move, link, archive, delete and comment. `tasks:write` includes `tasks:read`.

Create the key in **Developer** > **API Keys**. See [API Key Authentication](/security/api-key-authentication).

## REST quickstart

### Create a task

```bash theme={null}
curl -X POST "https://your-tenant-id.api.useago.com/api/v1/tasks" \
  -H "X-API-Key: ago_v1_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: refund-policy-gap-2026-10-14" \
  -d '{
    "title": "Update the refund policy page",
    "description": "Customers ask about refunds after 30 days and the page does not cover it.",
    "priority": "high",
    "deadline": "2026-10-21",
    "links": [
      {"target_type": "conversation", "target_id": "11111111-1111-4111-8111-111111111111"}
    ]
  }'
```

Only `title` is required. Without `status`, the task lands in the first to-do status. Without `owner_id`, it is unowned. You can attach up to 10 links when creating a task. The response is `201` with the task:

```json theme={null}
{
  "id": "22222222-2222-4222-8222-222222222222",
  "identifier": "TASK-12",
  "title": "Update the refund policy page",
  "description": "Customers ask about refunds after 30 days and the page does not cover it.",
  "status": {"key": "TODO", "label": "To do", "category": "todo", "role": null},
  "priority": "high",
  "deadline": "2026-10-21",
  "owner": null,
  "labels": [],
  "links": [
    {
      "id": "33333333-3333-4333-8333-333333333333",
      "target_type": "conversation",
      "target_id": "11111111-1111-4111-8111-111111111111",
      "context": {"conversation_id": "11111111-1111-4111-8111-111111111111", "message_id": null},
      "deleted": false,
      "admin_url": "https://..."
    }
  ],
  "source": "api",
  "created_by": {"id": "...", "name": "Alex Martin", "email": "alex@example.com"},
  "revision": 1,
  "created_at": "2026-10-14T09:12:00Z",
  "updated_at": "2026-10-14T09:12:00Z",
  "finished_at": null,
  "archived_at": null,
  "admin_url": "https://..."
}
```

`identifier` is the task's short ID. Every `{task_id}` in the endpoints below accepts either the UUID or the identifier, so `GET /api/v1/tasks/TASK-12` works.

### List tasks

```bash theme={null}
curl "https://your-tenant-id.api.useago.com/api/v1/tasks?queue=unowned&priority=high,urgent&limit=20" \
  -H "X-API-Key: ago_v1_sk_your_key_here"
```

### Move a task

```bash theme={null}
curl -X POST "https://your-tenant-id.api.useago.com/api/v1/tasks/TASK_ID/move" \
  -H "X-API-Key: ago_v1_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"status": "IN_PROGRESS", "placement": "top"}'
```

Status keys come from `GET /api/v1/task-statuses`. The default keys are `TODO`, `IN_PROGRESS`, `IN_REVIEW`, `DONE` and `CANCELED`.

## Claude and MCP quickstart

The task tools are part of the [MCP server](/api/mcp-tool-api) at `/api/v1/mcp`. Connect your assistant with an API key or OAuth that has `tasks:read` or `tasks:write` (see [Use AGO from AI assistants](/guides/mcp-integration-howto)), then ask in plain language:

> Show me the unowned high-priority tasks and who could take them.

> Create a task to fix the refund policy page, linked to conversation 1111..., due next Tuesday.

> Move TASK-12 to Done and comment that the page is fixed.

To turn recent feedback into tasks, use the `triage_feedback_into_tasks` workflow. See [Triage feedback into tasks](/guides/mcp-integration-howto#triage-feedback-into-tasks).

## Endpoints

Full parameters and schemas are in the **Tasks** section of the **Endpoints** sidebar.

| Method | Endpoint | Scope | Description |
| - | - | - | - |
| GET | `/api/v1/tasks` | `tasks:read` | List tasks |
| POST | `/api/v1/tasks` | `tasks:write` | Create a task |
| GET | `/api/v1/tasks/{task_id}` | `tasks:read` | Get a task |
| PUT | `/api/v1/tasks/{task_id}` | `tasks:write` | Update a task |
| DELETE | `/api/v1/tasks/{task_id}` | `tasks:write` | Delete a task and its comments permanently |
| POST | `/api/v1/tasks/{task_id}/archive` | `tasks:write` | Archive a task (it leaves the board, history is kept) |
| POST | `/api/v1/tasks/{task_id}/restore` | `tasks:write` | Bring an archived task back |
| POST | `/api/v1/tasks/{task_id}/move` | `tasks:write` | Change a task's status and position |
| POST | `/api/v1/tasks/{task_id}/links` | `tasks:write` | Link a conversation, ticket, feedback, message or knowledge update request |
| DELETE | `/api/v1/tasks/{task_id}/links/{link_id}` | `tasks:write` | Remove a link |
| GET | `/api/v1/tasks/{task_id}/comments` | `tasks:read` | List comments, oldest first |
| POST | `/api/v1/tasks/{task_id}/comments` | `tasks:write` | Add a comment |
| GET | `/api/v1/task-statuses` | `tasks:read` | List statuses in board order |
| GET | `/api/v1/task-labels` | `tasks:read` | List labels |
| GET | `/api/v1/task-assignees` | `tasks:read` | List active staff users who can own tasks or be mentioned |

### List filters

| Parameter | Description |
| - | - |
| `queue` | `mine`, `review`, `unowned` or `all` |
| `owner` | `me`, `none`, or a user ID |
| `status` | Status keys, comma-separated |
| `category` | `todo`, `in_progress`, `done`, `canceled`, comma-separated |
| `label_id` | Label IDs or `none`, comma-separated |
| `priority` | `none`, `low`, `normal`, `high`, `urgent`, comma-separated |
| `source` | Where the task came from (see `source` below) |
| `due_before`, `due_after` | Due date bounds (`YYYY-MM-DD`) |
| `overdue` | `true` for open tasks past their due date |
| `q` | Case-insensitive match on the title, or a task ID such as `TASK-12` |
| `include_archived` | `true` to include archived tasks. Default `false` |
| `conversation_id`, `ticket_id`, `feedback_id`, `message_id`, `knowledge_update_request_id` | Tasks linked to that item |
| `sort` | `updated` (default), `created`, `deadline`, `priority` or `manual` (board order) |

An unknown filter value returns `400` with code `invalid_<param>` (for example `invalid_status`). The `message` lists the valid values and `param` names the field.

### Updating a task

`PUT /api/v1/tasks/{task_id}` changes only the fields you send. Send `null` to clear `owner_id`, `deadline` or `description`. `label_ids` replaces all labels on the task. The owner must be an active staff user; use `GET /api/v1/task-assignees` to find valid IDs.

### Moving a task

`POST /api/v1/tasks/{task_id}/move` accepts:

| Field | Description |
| - | - |
| `status` | Target status key. Defaults to the current status |
| `before_task_id` | The card that ends up directly above the task |
| `after_task_id` | The card that ends up directly below the task |
| `placement` | `top` or `bottom` of the column |
| `expected_revision` | Reject the move if the task changed since this revision |

Without neighbors or `placement`, the task goes to the bottom of the column (the top for done and canceled statuses). If the neighbor cards moved in the meantime, the call returns `409` with code `stale_neighbors`: read the board again and retry.

### Links and comments

`POST /api/v1/tasks/{task_id}/links` takes `{"target_type": "...", "target_id": "..."}`, where `target_type` is `conversation`, `ticket`, `feedback`, `message` or `knowledge_update_request`. An ID that does not exist returns `404` with code `link_target_not_found`. When a linked item is later deleted, the link stays with `deleted: true`.

`POST /api/v1/tasks/{task_id}/comments` takes `content` (up to 10,000 characters) and optional `mention_ids` (up to 20 active staff users). Mentioned users are notified.

To read knowledge update requests, use the existing knowledge update request tools in the [MCP Server](/api/mcp-tool-api) reference (`list_knowledge_update_requests`, `get_knowledge_update_request`).

### The task object

| Field | Description |
| - | - |
| `id`, `title`, `description` | The task |
| `status` | `key`, `label`, `category` (`todo`, `in_progress`, `done`, `canceled`) and `role` (`review` for the review column) |
| `priority` | `none`, `low`, `normal`, `high` or `urgent` |
| `deadline` | Due date, or `null` |
| `owner` | `id`, `name` and `email`, or `null` |
| `labels` | `id`, `name` and `color` of each label |
| `links` | Linked items with `id`, `target_type`, `target_id`, `context` (`conversation_id`, `message_id`), `deleted` and `admin_url` |
| `source` | `manual`, `feedback`, `ticket`, `conversation`, `knowledge_update_request`, `agent`, `api` or `mcp` |
| `created_by` | The user who created the task, or `null` for tasks created by an agent |
| `revision` | Increases on every change. Use it with `expected_revision` |
| `created_at`, `updated_at`, `finished_at`, `archived_at` | Timestamps. `finished_at` is set when the task reaches a done or canceled status |
| `admin_url` | Link to the task in AGO |

## Avoiding duplicates with idempotency keys

Send an `Idempotency-Key` header (1 to 255 characters) on `POST /api/v1/tasks` and `POST /api/v1/tasks/{task_id}/comments`. If the request is retried with the same key and body, AGO returns the first response instead of creating a second task or comment. This holds even if the task was deleted afterwards.

Reusing a key with a different body returns `409` with code `idempotency_key_reused`. Keys are kept for 24 hours and are scoped to your API key or user. On MCP, pass the key as the `idempotency_key` argument of `create_task` and `add_task_comment`.

## Handling conflicts

Every task has a `revision` number. To avoid overwriting a teammate's change, send the revision you last read as `expected_revision` on `PUT` or `move`. If the task changed since, the call returns `409` with code `task_revision_conflict`. Read the task again, reapply your change and retry.

## Pagination

`GET /api/v1/tasks` returns up to `limit` tasks (default 50, maximum 100) and uses cursors instead of page numbers:

```json theme={null}
{
  "object": "list",
  "data": [ ... ],
  "has_more": true,
  "next_cursor": "eyJ...",
  "total": 132
}
```

Pass `next_cursor` as the `cursor` parameter to get the next page, keeping the same filters and `sort`. `total` is only included on the first page. A cursor from another sort returns `400` with code `invalid_cursor`.

## Errors

Errors use the standard [error envelope](/api/errors). Task-specific codes:

| Code | Status | Meaning |
| - | - | - |
| `tasks_disabled` | 403 | Tasks is not enabled for your workspace |
| `staff_principal_required` | 403 | The key's creator, OAuth user or session user is not an active staff user |
| `task_not_found` | 404 | No task with this ID |
| `link_target_not_found` | 404 | The conversation, ticket, feedback, message or knowledge update request does not exist |
| `task_revision_conflict` | 409 | The task changed since `expected_revision` |
| `stale_neighbors` | 409 | The cards passed as neighbors moved |
| `idempotency_key_reused` | 409 | The `Idempotency-Key` was already used with a different body |
| `invalid_<param>` | 400 | Unknown value for a filter or field; the message lists valid values |

See [API Errors](/api/errors#tasks) for the full list.

## Related

* [Tasks](/features/tasks)
* [MCP Server](/api/mcp-tool-api#tasks)
* [Public API v1](/api/public-api-v1)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.