# Tasks

Give a worker a task, list, read and change tasks, take one back, archive or delete it, and read what each run cost.

A task is one piece of work by one worker. You give it, send it a message in plain words, and the worker gets to work. The task says where it stands until it is done.

These routes give, list, read, change, take back, archive and delete tasks, and read what each one cost. A task's events, which let you follow it as it works and send it a message, an answer or a send back, are under `/tasks/{task_id}/events` and get a page of their own next. Until then, the [Quickstart](/get-started/quickstart#follow-the-work) shows both.

> [!NOTE]
> A task is a session in Claude Managed Agents. `status` and `stop_reason` are a session's; `state` says the same in the words the app shows.

## The task object

Every route on this page but delete, take back and receipts answers a task, or a list of them. Times are RFC 3339 in UTC, to the millisecond.

- `type` (string): Always `task`.

- `id` (task id): The task's id: `task_` and 26 letters and digits.

- `worker` (object): The worker doing the task, as the task runs it: the version the task keeps, with any lists the task replaced for itself. Changing the worker later does not change a task already made.

  - `type` (string): Always `worker`.

  - `id` (worker id): The worker.

  - `version` (integer): The worker version the task runs.

  - `name` (string): The worker's name.

  - `description` (string, or null): What the worker is for.

  - `system` (string, or null): The worker's standing instructions, in plain words.

  - `model` (object): The model the task uses: `id`, and its `effort` and `speed`.

  - `apps` (array of objects): The apps the task may call.

  - `skills` (array of objects): The skills the task may use, each at the version it runs.

  - `tools` (array of objects): The task's toolsets, and whether each tool group runs at once, asks first, or is checked.

  - `execution_identity` (object): Always `{ "type": "service_account" }`.

  - `multiagent` (object, or null): The helpers the worker may hand work to. `null` when it works alone.

- `computer_id` (computer id, or null): The computer the task last ran on. `null` when it never used one.

- `routine_id` (routine id, or null): The routine that made the task. `null` for any other task.

- `chat_id` (chat id): The chat with the worker that the task belongs to. A task made without a `chat_id` gets a chat of its own.

- `created_by` (string): Who gave the task: a `person` (in the app or with a key), a `worker` that started it, `need` when a worker's work needed a person and had no task, or a `routine`. One of `person`, `worker`, `need`, `routine`.

- `title` (string, or null): A short name for the task, up to 500 characters. Left out on create, it is the first words of the first message. `null` when the task has none.

- `metadata` (object): Your own labels for the task: up to 16 keys, each with a string value.

- `ask` (string): What was asked: the text of the first message, or the title when there was none.

- `status` (string): Where the task stands, as a Claude session's status. `running` while the worker is on it or it waits its turn, `idle` when the worker stopped (`stop_reason` says why), and `rescheduling` while a plan or spending cap holds it; it goes on by itself when there is room. `terminated` is not used yet. One of `running`, `idle`, `rescheduling`, `terminated`.

- `state` (object): Where the task stands, in the words the app shows.

  - `status` (string): `not_started` waits to start, `working` is under way, `needs_you` waits for a person (see `needs`), and `done` is finished. One of `not_started`, `working`, `needs_you`, `done`.

  - `needs` (string, or null): What a task that `needs_you` asks: `allow` an action, `answer` a question, `help` after a failure or a limit, or `look` at work the worker's own check still found short. `null` for every other status. One of `allow`, `answer`, `help`, `look`.

  - `waiting_reason` (string, or null): Why the task waits: `busy` when the worker is on another task (a worker does one task at a time), `stopped` when its work was stopped, or the cap that holds a `rescheduling` task, such as `five_hour`, `month` or `balance`. `null` otherwise.

- `stop_reason` (object, or null): Why an `idle` task stopped, as its last `task.status_idle` event says. `type` is `end_turn` (its turn is over), `requires_action` (it waits for an Allow, an answer or a step of yours, listed in `event_ids` and `blocking`), `retries_exhausted` (its work failed), `budget_reached`, `refusal`, `turn_limit` or `time_limit`. `null` unless the task is `idle`.

- `result_summary` (string, or null): One line about the result, once there is one. The full answer is the last `worker.message` in the task's events.

- `archived_at` (time, or null): When the task was archived. `null` while it is not.

- `finished_at` (time, or null): When the worker marked the work finished, if it did. A task can be `done` without it, so read `state.status` to know where a task stands.

- `accepted_at` (time, or null): When the task became `done`. Finished work is done by itself; work that needed a look is done when someone accepts it. A send back clears it.

- `sent_back_count` (integer): How many times the result was sent back for more work. A message to a `done` task counts too.

- `budget` (object): The task's spending limit. Every task has one: $5.00 unless you set another.

  - `type` (string): Always `limit`.

  - `max_list_cost` (money): The most the task's work may cost at list price, from 1 cent to $1,000.

    - `amount` (string): Whole US cents, as a string: `"250"` is $2.50.

    - `currency` (string): Always `USD`.

- `outcome_evaluations` (array of objects): Each check round of the outcome the task was given, oldest first. Empty when it was given none.

- `usage` (object): What the task's work used so far, as a Claude session's usage: `input_tokens`, `output_tokens`, `cache_read_input_tokens`, `cache_creation`, `server_tool_use`, `list_cost` (what it cost at list price), and `active_seconds`. Little Worker adds `charged` (what the workspace paid), `included` (what the plan covered) and `own_key_calls`, the sums of the task's receipts. Each amount is money: `{ "amount", "currency" }`.

- `stats` (object): The task's times: `active_seconds`, each run's time at work added up, and `duration_seconds`, from when the task was made until it was done.

- `resources` (array of objects): The files, repositories and memory stores the task was given, in order.

- `password_set_ids` (array of password set ids): The password sets the task signs in with, in order. Unless the task named others, the worker's own set, then the workspace's shared set.

- `created_at` (time): When the task was made.

- `updated_at` (time): When anything about the task last changed.

```json
{
  "type": "task",
  "id": "task_01JA8Z6Q4M3T9V2K7X5R1B0C8D",
  "worker": {
    "type": "worker",
    "id": "worker_8c1f4e2a9b7d4f0e8a6c3b5d1e9f7a20",
    "version": 1,
    "name": "Copywriter",
    "description": null,
    "system": "You write short, clear copy for a small shop. Answer with a numbered list.",
    "model": {
      "id": "grok-4.6",
      "effort": {
        "type": "medium"
      },
      "speed": "standard"
    },
    "apps": [],
    "skills": [],
    "tools": [
      {
        "type": "worker_toolset_20260401",
        "default_config": {
          "enabled": true,
          "permission_policy": {
            "type": "always_allow"
          }
        },
        "configs": []
      }
    ],
    "execution_identity": {
      "type": "service_account"
    },
    "multiagent": null
  },
  "computer_id": null,
  "routine_id": null,
  "chat_id": "chat_3b9d2f6a1c8e4b7d9f0a2c4e6b8d1f3a",
  "created_by": "person",
  "title": "Subject lines",
  "metadata": {},
  "ask": "Write three subject lines for an email that says the shop now opens at 7 am.",
  "status": "idle",
  "state": {
    "status": "done",
    "needs": null,
    "waiting_reason": null
  },
  "stop_reason": {
    "type": "end_turn"
  },
  "result_summary": "1. Open at 7 am, starting Monday",
  "archived_at": null,
  "finished_at": null,
  "accepted_at": "2026-10-25T16:04:31.209Z",
  "sent_back_count": 0,
  "budget": {
    "type": "limit",
    "max_list_cost": {
      "amount": "500",
      "currency": "USD"
    }
  },
  "outcome_evaluations": [],
  "usage": {
    "input_tokens": 1840,
    "output_tokens": 96,
    "cache_read_input_tokens": 0,
    "cache_creation": {
      "ephemeral_1h_input_tokens": 0,
      "ephemeral_5m_input_tokens": 0
    },
    "server_tool_use": {
      "web_fetch_requests": 0,
      "web_search_requests": 0
    },
    "list_cost": {
      "amount": "1",
      "currency": "USD"
    },
    "active_seconds": 4.3,
    "charged": {
      "amount": "1",
      "currency": "USD"
    },
    "included": {
      "amount": "1",
      "currency": "USD"
    },
    "own_key_calls": 0
  },
  "stats": {
    "active_seconds": 4.3,
    "duration_seconds": 18.7
  },
  "resources": [],
  "password_set_ids": [
    "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
    "password_set_37cbbff4bc744ede8217773f8a942448"
  ],
  "created_at": "2026-10-25T16:04:12.512Z",
  "updated_at": "2026-10-25T16:04:31.209Z"
}
```

## Give a task

`POST /tasks`

Give a worker a task. Put what you want in a `user.message` in `initial_events`, written as you would to a person: what to do, and what done looks like. The worker starts at once, or after the task it is on.

With no `initial_events` the task is `idle` and nothing runs until you send it a message. With no `chat_id`, the task gets a new chat with the worker. The task keeps the worker version it was made with, even after the worker changes.

### Headers

- `Idempotency-Key` (UUID): Send one so a retry makes the task once. A second call with the same key answers the task the first call made. The same key with another body is `409` with `error_code` `idempotency_conflict`. Kept for 7 days.

### Body

- `worker` (worker id or object, required): The worker to give the task to: its id, `{ "type": "worker", "id", "version" }` to run one version of it, or `{ "type": "worker_with_overrides", "id", ... }` to give this task its own `apps`, `tools`, `skills`, `model` or `system`. It must be an active worker in the key's workspace.
- `initial_events` (array of events): Up to 50 events sent to the task as it is made, in order, as sending them to its events would. Each is a `user.message` with `content`, a list of blocks such as `{ "type": "text", "text": "..." }`, or a `user.define_outcome`. If one is refused, no task is made.
- `title` (string): A short name for the task, 1 to 500 characters. Left out, it is the first words of the first message.
- `chat_id` (chat id): A chat with the same worker to give the task in, so the worker reads the work done there before.
- `metadata` (object): Your own labels: up to 16 keys, each with a string value.
- `budget` (object): The most the task's work may cost. Left out, it is $5.00. `null` is refused.
  - `type` (string): Always `limit`.
  - `max_list_cost` (money): The most the task's work may cost at list price, from 1 cent to $1,000.
    - `amount` (string): Whole US cents, as a string: `"250"` is $2.50.
    - `currency` (string): Always `USD`.
- `resources` (array of objects): Files, repositories and memory stores the task may use.
- `password_set_ids` (array of password set ids): Up to 20 password sets the task signs in with, in place of the worker's own set and the shared set.
- `computer_id` (computer id): One of the workspace's own active computers. Leave it out to use the workspace's computer.

### Returns

`200` and the task. A task given a message is `running` at once, with `state.status` `not_started` until the worker picks it up and `working` after. While the worker finishes another task first, `state.waiting_reason` is `busy`.

### Example

```bash
curl "https://core.thelittleworker.com/api/v1/tasks" \
  -H "x-api-key: $LITTLE_WORKER_API_KEY" \
  -H "Little-Worker-Version: 2026-10-19" \
  -H "Idempotency-Key: 7b0e4c1a-5d2f-4e8b-9a3c-1f6d8e2b4a90" \
  -H "content-type: application/json" \
  -d '{
  "worker": "worker_8c1f4e2a9b7d4f0e8a6c3b5d1e9f7a20",
  "title": "Subject lines",
  "initial_events": [
    {
      "type": "user.message",
      "content": [
        {
          "type": "text",
          "text": "Write three subject lines for an email that says the shop now opens at 7 am."
        }
      ]
    }
  ]
}'
```

```json
{
  "type": "task",
  "id": "task_01JA8Z6Q4M3T9V2K7X5R1B0C8D",
  "worker": {
    "type": "worker",
    "id": "worker_8c1f4e2a9b7d4f0e8a6c3b5d1e9f7a20",
    "version": 1,
    "name": "Copywriter",
    "description": null,
    "system": "You write short, clear copy for a small shop. Answer with a numbered list.",
    "model": {
      "id": "grok-4.6",
      "effort": {
        "type": "medium"
      },
      "speed": "standard"
    },
    "apps": [],
    "skills": [],
    "tools": [
      {
        "type": "worker_toolset_20260401",
        "default_config": {
          "enabled": true,
          "permission_policy": {
            "type": "always_allow"
          }
        },
        "configs": []
      }
    ],
    "execution_identity": {
      "type": "service_account"
    },
    "multiagent": null
  },
  "computer_id": null,
  "routine_id": null,
  "chat_id": "chat_3b9d2f6a1c8e4b7d9f0a2c4e6b8d1f3a",
  "created_by": "person",
  "title": "Subject lines",
  "metadata": {},
  "ask": "Write three subject lines for an email that says the shop now opens at 7 am.",
  "status": "running",
  "state": {
    "status": "not_started",
    "needs": null,
    "waiting_reason": null
  },
  "stop_reason": null,
  "result_summary": null,
  "archived_at": null,
  "finished_at": null,
  "accepted_at": null,
  "sent_back_count": 0,
  "budget": {
    "type": "limit",
    "max_list_cost": {
      "amount": "500",
      "currency": "USD"
    }
  },
  "outcome_evaluations": [],
  "usage": {
    "input_tokens": 0,
    "output_tokens": 0,
    "cache_read_input_tokens": 0,
    "cache_creation": {
      "ephemeral_1h_input_tokens": 0,
      "ephemeral_5m_input_tokens": 0
    },
    "server_tool_use": {
      "web_fetch_requests": 0,
      "web_search_requests": 0
    },
    "list_cost": {
      "amount": "0",
      "currency": "USD"
    },
    "active_seconds": 0,
    "charged": {
      "amount": "0",
      "currency": "USD"
    },
    "included": {
      "amount": "0",
      "currency": "USD"
    },
    "own_key_calls": 0
  },
  "stats": {
    "active_seconds": 0,
    "duration_seconds": 0.121
  },
  "resources": [],
  "password_set_ids": [
    "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
    "password_set_37cbbff4bc744ede8217773f8a942448"
  ],
  "created_at": "2026-10-25T16:04:12.512Z",
  "updated_at": "2026-10-25T16:04:12.512Z"
}
```

### Errors

- 400 `invalid_request_error`: A field is missing or not valid: an id of the wrong kind, a `title` over 500 characters, a field the route does not take, an event that is refused, or an `Idempotency-Key` that is not a UUID. `message` says which. A `budget` of `null` has `error_code` `budget_required`.
- 401 `authentication_error`: The key is missing, removed, or not a key. Send it in `x-api-key`.
- 404 `not_found_error`: No active worker has this id (`Worker not found.`), or `chat_id` names no chat with this worker (`Chat not found.`).
- 409 `conflict_error`: The `Idempotency-Key` was already used with another body (`error_code` `idempotency_conflict`). Use a new key for a new task.
- 429 `rate_limit_error`: The workspace made too many requests this minute. Wait the seconds in `Retry-After`, then try again.

## List tasks

`GET /tasks`

List the tasks in the key's workspace, newest first. Filter by worker, chat, routine or status. A task that was taken back is not listed, and an archived one only with `include_archived=true`.

### Query parameters

- `worker_id` (worker id): Only this worker's tasks.
- `worker_version` (integer): Only tasks that run this version of the worker. Needs `worker_id`.
- `chat_id` (chat id): Only the tasks in this chat.
- `routine_id` (routine id): Only the tasks this routine made.
- `status` (string): Only tasks whose `state.status` is this, in the words the app shows. One of `not_started`, `working`, `needs_you`, `done`.
- `statuses[]` (string): Only tasks whose `status` is one of these. Repeat it to name more than one. One of `running`, `idle`, `rescheduling`, `terminated`.
- `include_archived` (string): `true` lists archived tasks too. One of `true`, `false`.
- `limit` (integer): How many to answer, 1 to 100. The default is 20.
- `page` (string): The `next_page` of the answer before, to read the next page.
- `order` (string): `desc`, newest first (the default), or `asc`, oldest first. One of `desc`, `asc`.
- `created_at[gt]` (time): Only those made after this time. `created_at[gte]`, `created_at[lt]` and `created_at[lte]` work the same way.

### Returns

A list: `data` holds the tasks, `next_page` is the `page` to send for the next ones (`null` on the last page), and `prev_page` the one before (`null` on the first page).

### Example

```bash
curl "https://core.thelittleworker.com/api/v1/tasks?worker_id=worker_8c1f4e2a9b7d4f0e8a6c3b5d1e9f7a20&status=done&limit=2" \
  -H "x-api-key: $LITTLE_WORKER_API_KEY" \
  -H "Little-Worker-Version: 2026-10-19"
```

```json
{
  "data": [
    {
      "type": "task",
      "id": "task_01JA8Z6Q4M3T9V2K7X5R1B0C8D",
      "worker": {
        "type": "worker",
        "id": "worker_8c1f4e2a9b7d4f0e8a6c3b5d1e9f7a20",
        "version": 1,
        "name": "Copywriter",
        "description": null,
        "system": "You write short, clear copy for a small shop. Answer with a numbered list.",
        "model": {
          "id": "grok-4.6",
          "effort": {
            "type": "medium"
          },
          "speed": "standard"
        },
        "apps": [],
        "skills": [],
        "tools": [
          {
            "type": "worker_toolset_20260401",
            "default_config": {
              "enabled": true,
              "permission_policy": {
                "type": "always_allow"
              }
            },
            "configs": []
          }
        ],
        "execution_identity": {
          "type": "service_account"
        },
        "multiagent": null
      },
      "computer_id": null,
      "routine_id": null,
      "chat_id": "chat_3b9d2f6a1c8e4b7d9f0a2c4e6b8d1f3a",
      "created_by": "person",
      "title": "Subject lines",
      "metadata": {},
      "ask": "Write three subject lines for an email that says the shop now opens at 7 am.",
      "status": "idle",
      "state": {
        "status": "done",
        "needs": null,
        "waiting_reason": null
      },
      "stop_reason": {
        "type": "end_turn"
      },
      "result_summary": "1. Open at 7 am, starting Monday",
      "archived_at": null,
      "finished_at": null,
      "accepted_at": "2026-10-25T16:04:31.209Z",
      "sent_back_count": 0,
      "budget": {
        "type": "limit",
        "max_list_cost": {
          "amount": "500",
          "currency": "USD"
        }
      },
      "outcome_evaluations": [],
      "usage": {
        "input_tokens": 1840,
        "output_tokens": 96,
        "cache_read_input_tokens": 0,
        "cache_creation": {
          "ephemeral_1h_input_tokens": 0,
          "ephemeral_5m_input_tokens": 0
        },
        "server_tool_use": {
          "web_fetch_requests": 0,
          "web_search_requests": 0
        },
        "list_cost": {
          "amount": "1",
          "currency": "USD"
        },
        "active_seconds": 4.3,
        "charged": {
          "amount": "1",
          "currency": "USD"
        },
        "included": {
          "amount": "1",
          "currency": "USD"
        },
        "own_key_calls": 0
      },
      "stats": {
        "active_seconds": 4.3,
        "duration_seconds": 18.7
      },
      "resources": [],
      "password_set_ids": [
        "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
        "password_set_37cbbff4bc744ede8217773f8a942448"
      ],
      "created_at": "2026-10-25T16:04:12.512Z",
      "updated_at": "2026-10-25T16:04:31.209Z"
    }
  ],
  "next_page": null,
  "prev_page": null
}
```

### Errors

- 400 `invalid_request_error`: A filter is not valid, such as a `worker_id` of the wrong kind or a `limit` outside 1 to 100 (`error_code` `validation_error`), or `page` is not a page this list gave with the same `order` and `created_at` filters (`error_code` `invalid_cursor`). Read the first page again.
- 401 `authentication_error`: The key is missing, removed, or not a key. Send it in `x-api-key`.
- 429 `rate_limit_error`: The workspace made too many requests this minute. Wait the seconds in `Retry-After`, then try again.

## Read a task

`GET /tasks/{task_id}`

Read one task as it stands now. Read it again to see it move from `running` to `idle`, or follow its events to hear the moment it changes.

### Path parameters

- `task_id` (task id, required): The task, such as `task_01JA8Z6Q4M3T9V2K7X5R1B0C8D`.

### Returns

The task.

### Example

```bash
curl https://core.thelittleworker.com/api/v1/tasks/task_01JA8Z6Q4M3T9V2K7X5R1B0C8D \
  -H "x-api-key: $LITTLE_WORKER_API_KEY" \
  -H "Little-Worker-Version: 2026-10-19"
```

```json
{
  "type": "task",
  "id": "task_01JA8Z6Q4M3T9V2K7X5R1B0C8D",
  "worker": {
    "type": "worker",
    "id": "worker_8c1f4e2a9b7d4f0e8a6c3b5d1e9f7a20",
    "version": 1,
    "name": "Copywriter",
    "description": null,
    "system": "You write short, clear copy for a small shop. Answer with a numbered list.",
    "model": {
      "id": "grok-4.6",
      "effort": {
        "type": "medium"
      },
      "speed": "standard"
    },
    "apps": [],
    "skills": [],
    "tools": [
      {
        "type": "worker_toolset_20260401",
        "default_config": {
          "enabled": true,
          "permission_policy": {
            "type": "always_allow"
          }
        },
        "configs": []
      }
    ],
    "execution_identity": {
      "type": "service_account"
    },
    "multiagent": null
  },
  "computer_id": null,
  "routine_id": null,
  "chat_id": "chat_3b9d2f6a1c8e4b7d9f0a2c4e6b8d1f3a",
  "created_by": "person",
  "title": "Subject lines",
  "metadata": {},
  "ask": "Write three subject lines for an email that says the shop now opens at 7 am.",
  "status": "idle",
  "state": {
    "status": "done",
    "needs": null,
    "waiting_reason": null
  },
  "stop_reason": {
    "type": "end_turn"
  },
  "result_summary": "1. Open at 7 am, starting Monday",
  "archived_at": null,
  "finished_at": null,
  "accepted_at": "2026-10-25T16:04:31.209Z",
  "sent_back_count": 0,
  "budget": {
    "type": "limit",
    "max_list_cost": {
      "amount": "500",
      "currency": "USD"
    }
  },
  "outcome_evaluations": [],
  "usage": {
    "input_tokens": 1840,
    "output_tokens": 96,
    "cache_read_input_tokens": 0,
    "cache_creation": {
      "ephemeral_1h_input_tokens": 0,
      "ephemeral_5m_input_tokens": 0
    },
    "server_tool_use": {
      "web_fetch_requests": 0,
      "web_search_requests": 0
    },
    "list_cost": {
      "amount": "1",
      "currency": "USD"
    },
    "active_seconds": 4.3,
    "charged": {
      "amount": "1",
      "currency": "USD"
    },
    "included": {
      "amount": "1",
      "currency": "USD"
    },
    "own_key_calls": 0
  },
  "stats": {
    "active_seconds": 4.3,
    "duration_seconds": 18.7
  },
  "resources": [],
  "password_set_ids": [
    "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
    "password_set_37cbbff4bc744ede8217773f8a942448"
  ],
  "created_at": "2026-10-25T16:04:12.512Z",
  "updated_at": "2026-10-25T16:04:31.209Z"
}
```

### Errors

- 400 `invalid_request_error`: `task_id` is not a task id. `error_code` is `validation_error`.
- 401 `authentication_error`: The key is missing, removed, or not a key. Send it in `x-api-key`.
- 404 `not_found_error`: No task in the key's workspace has this id, or it was taken back or deleted (`Task not found.`).
- 429 `rate_limit_error`: The workspace made too many requests this minute. Wait the seconds in `Retry-After`, then try again.

## Change a task

`POST /tasks/{task_id}`

Change a task's title, labels or budget. A field left out stays as it was. The change is refused while the task is at work, so change it when it is `idle`.

### Path parameters

- `task_id` (task id, required): The task, such as `task_01JA8Z6Q4M3T9V2K7X5R1B0C8D`.

### Body

- `title` (string, or null): A new title, 1 to 500 characters. `null` clears it.
- `metadata` (object): Labels to set. A key with a string value is set, a key set to `null` is removed, and keys left out stay.
- `budget` (object): A new budget, more than the task has already spent. Work held at the old budget goes on at once.
  - `type` (string): Always `limit`.
  - `max_list_cost` (money): The most the task's work may cost at list price, from 1 cent to $1,000.
    - `amount` (string): Whole US cents, as a string: `"250"` is $2.50.
    - `currency` (string): Always `USD`.
- `worker` (object): `apps` and `tools` for this task alone. Each list given replaces the task's list in full; the worker does not change.

### Returns

The task, changed.

### Example

```bash
curl "https://core.thelittleworker.com/api/v1/tasks/task_01JA8Z6Q4M3T9V2K7X5R1B0C8D" \
  -H "x-api-key: $LITTLE_WORKER_API_KEY" \
  -H "Little-Worker-Version: 2026-10-19" \
  -H "content-type: application/json" \
  -d '{
  "title": "Opening hours email",
  "metadata": {
    "source": "crm"
  }
}'
```

```json
{
  "type": "task",
  "id": "task_01JA8Z6Q4M3T9V2K7X5R1B0C8D",
  "worker": {
    "type": "worker",
    "id": "worker_8c1f4e2a9b7d4f0e8a6c3b5d1e9f7a20",
    "version": 1,
    "name": "Copywriter",
    "description": null,
    "system": "You write short, clear copy for a small shop. Answer with a numbered list.",
    "model": {
      "id": "grok-4.6",
      "effort": {
        "type": "medium"
      },
      "speed": "standard"
    },
    "apps": [],
    "skills": [],
    "tools": [
      {
        "type": "worker_toolset_20260401",
        "default_config": {
          "enabled": true,
          "permission_policy": {
            "type": "always_allow"
          }
        },
        "configs": []
      }
    ],
    "execution_identity": {
      "type": "service_account"
    },
    "multiagent": null
  },
  "computer_id": null,
  "routine_id": null,
  "chat_id": "chat_3b9d2f6a1c8e4b7d9f0a2c4e6b8d1f3a",
  "created_by": "person",
  "title": "Opening hours email",
  "metadata": {
    "source": "crm"
  },
  "ask": "Write three subject lines for an email that says the shop now opens at 7 am.",
  "status": "idle",
  "state": {
    "status": "done",
    "needs": null,
    "waiting_reason": null
  },
  "stop_reason": {
    "type": "end_turn"
  },
  "result_summary": "1. Open at 7 am, starting Monday",
  "archived_at": null,
  "finished_at": null,
  "accepted_at": "2026-10-25T16:04:31.209Z",
  "sent_back_count": 0,
  "budget": {
    "type": "limit",
    "max_list_cost": {
      "amount": "500",
      "currency": "USD"
    }
  },
  "outcome_evaluations": [],
  "usage": {
    "input_tokens": 1840,
    "output_tokens": 96,
    "cache_read_input_tokens": 0,
    "cache_creation": {
      "ephemeral_1h_input_tokens": 0,
      "ephemeral_5m_input_tokens": 0
    },
    "server_tool_use": {
      "web_fetch_requests": 0,
      "web_search_requests": 0
    },
    "list_cost": {
      "amount": "1",
      "currency": "USD"
    },
    "active_seconds": 4.3,
    "charged": {
      "amount": "1",
      "currency": "USD"
    },
    "included": {
      "amount": "1",
      "currency": "USD"
    },
    "own_key_calls": 0
  },
  "stats": {
    "active_seconds": 4.3,
    "duration_seconds": 18.7
  },
  "resources": [],
  "password_set_ids": [
    "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
    "password_set_37cbbff4bc744ede8217773f8a942448"
  ],
  "created_at": "2026-10-25T16:04:12.512Z",
  "updated_at": "2026-10-25T16:04:31.209Z"
}
```

### Errors

- 400 `invalid_request_error`: A field is not valid, or the new budget is not more than the task has spent (`error_code` `budget_not_raised`).
- 401 `authentication_error`: The key is missing, removed, or not a key. Send it in `x-api-key`.
- 404 `not_found_error`: No task in the key's workspace has this id, or it was taken back or deleted (`Task not found.`).
- 409 `conflict_error`: The task is still at work. Interrupt it with a `user.interrupt` event, wait for it to stop, then change it.
- 429 `rate_limit_error`: The workspace made too many requests this minute. Wait the seconds in `Retry-After`, then try again.

## Take a task back

`POST /tasks/{task_id}/withdraw`

Take back a task you gave, whatever its worker is doing. Work under way stops, work that waits never starts, and anything it was asking you is closed.

A task taken back is gone: reading it answers `404`, and lists leave it out. A task that is already done stays done, and this answers `done`. Taking a task back twice answers `withdrawn` both times, so a retry is safe.

### Path parameters

- `task_id` (task id, required): The task, such as `task_01JA8Z6Q4M3T9V2K7X5R1B0C8D`.

### Returns

`type` is `task_withdrawal`, with the `task_id` and the `outcome`: `withdrawn` when the task was taken back, `done` when it was already done and stays.

### Example

```bash
curl "https://core.thelittleworker.com/api/v1/tasks/task_01JA8Z6Q4M3T9V2K7X5R1B0C8D/withdraw" \
  -X POST \
  -H "x-api-key: $LITTLE_WORKER_API_KEY" \
  -H "Little-Worker-Version: 2026-10-19"
```

```json
{
  "type": "task_withdrawal",
  "task_id": "task_01JA8Z6Q4M3T9V2K7X5R1B0C8D",
  "outcome": "withdrawn"
}
```

### Errors

- 400 `invalid_request_error`: `task_id` is not a task id. `error_code` is `validation_error`.
- 401 `authentication_error`: The key is missing, removed, or not a key. Send it in `x-api-key`.
- 404 `not_found_error`: No task in the key's workspace has this id, or it was taken back or deleted (`Task not found.`).
- 429 `rate_limit_error`: The workspace made too many requests this minute. Wait the seconds in `Retry-After`, then try again.

## Archive a task

`POST /tasks/{task_id}/archive`

Archive a task you no longer need. Everything it holds is kept, but it takes no new message, and lists leave it out unless you ask for `include_archived=true`. It cannot be undone. Archiving a task twice changes nothing.

### Path parameters

- `task_id` (task id, required): The task, such as `task_01JA8Z6Q4M3T9V2K7X5R1B0C8D`.

### Returns

The task, with `archived_at` set.

### Example

```bash
curl "https://core.thelittleworker.com/api/v1/tasks/task_01JA8Z6Q4M3T9V2K7X5R1B0C8D/archive" \
  -X POST \
  -H "x-api-key: $LITTLE_WORKER_API_KEY" \
  -H "Little-Worker-Version: 2026-10-19"
```

```json
{
  "type": "task",
  "id": "task_01JA8Z6Q4M3T9V2K7X5R1B0C8D",
  "worker": {
    "type": "worker",
    "id": "worker_8c1f4e2a9b7d4f0e8a6c3b5d1e9f7a20",
    "version": 1,
    "name": "Copywriter",
    "description": null,
    "system": "You write short, clear copy for a small shop. Answer with a numbered list.",
    "model": {
      "id": "grok-4.6",
      "effort": {
        "type": "medium"
      },
      "speed": "standard"
    },
    "apps": [],
    "skills": [],
    "tools": [
      {
        "type": "worker_toolset_20260401",
        "default_config": {
          "enabled": true,
          "permission_policy": {
            "type": "always_allow"
          }
        },
        "configs": []
      }
    ],
    "execution_identity": {
      "type": "service_account"
    },
    "multiagent": null
  },
  "computer_id": null,
  "routine_id": null,
  "chat_id": "chat_3b9d2f6a1c8e4b7d9f0a2c4e6b8d1f3a",
  "created_by": "person",
  "title": "Subject lines",
  "metadata": {},
  "ask": "Write three subject lines for an email that says the shop now opens at 7 am.",
  "status": "idle",
  "state": {
    "status": "done",
    "needs": null,
    "waiting_reason": null
  },
  "stop_reason": {
    "type": "end_turn"
  },
  "result_summary": "1. Open at 7 am, starting Monday",
  "archived_at": "2026-10-25T17:12:03.418Z",
  "finished_at": null,
  "accepted_at": "2026-10-25T16:04:31.209Z",
  "sent_back_count": 0,
  "budget": {
    "type": "limit",
    "max_list_cost": {
      "amount": "500",
      "currency": "USD"
    }
  },
  "outcome_evaluations": [],
  "usage": {
    "input_tokens": 1840,
    "output_tokens": 96,
    "cache_read_input_tokens": 0,
    "cache_creation": {
      "ephemeral_1h_input_tokens": 0,
      "ephemeral_5m_input_tokens": 0
    },
    "server_tool_use": {
      "web_fetch_requests": 0,
      "web_search_requests": 0
    },
    "list_cost": {
      "amount": "1",
      "currency": "USD"
    },
    "active_seconds": 4.3,
    "charged": {
      "amount": "1",
      "currency": "USD"
    },
    "included": {
      "amount": "1",
      "currency": "USD"
    },
    "own_key_calls": 0
  },
  "stats": {
    "active_seconds": 4.3,
    "duration_seconds": 18.7
  },
  "resources": [],
  "password_set_ids": [
    "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
    "password_set_37cbbff4bc744ede8217773f8a942448"
  ],
  "created_at": "2026-10-25T16:04:12.512Z",
  "updated_at": "2026-10-25T16:04:31.209Z"
}
```

### Errors

- 400 `invalid_request_error`: `task_id` is not a task id. `error_code` is `validation_error`.
- 401 `authentication_error`: The key is missing, removed, or not a key. Send it in `x-api-key`.
- 404 `not_found_error`: No task in the key's workspace has this id, or it was taken back or deleted (`Task not found.`).
- 409 `conflict_error`: The task is still at work. Interrupt it with a `user.interrupt` event, wait for it to stop, then archive it.
- 429 `rate_limit_error`: The workspace made too many requests this minute. Wait the seconds in `Retry-After`, then try again.

## Delete a task

`DELETE /tasks/{task_id}`

Delete a task, its events, and the files it made that you did not keep. The task is gone from every read afterwards. It needs a key made with **Can delete tasks** on. Settings does not offer that switch yet, so a key made there cannot delete; archive the task instead.

### Path parameters

- `task_id` (task id, required): The task, such as `task_01JA8Z6Q4M3T9V2K7X5R1B0C8D`.

### Returns

`type` is `task_deleted`, with the task's `id`.

### Example

```bash
curl "https://core.thelittleworker.com/api/v1/tasks/task_01JA8Z6Q4M3T9V2K7X5R1B0C8D" \
  -X DELETE \
  -H "x-api-key: $LITTLE_WORKER_API_KEY" \
  -H "Little-Worker-Version: 2026-10-19"
```

```json
{
  "type": "task_deleted",
  "id": "task_01JA8Z6Q4M3T9V2K7X5R1B0C8D"
}
```

### Errors

- 400 `invalid_request_error`: `task_id` is not a task id. `error_code` is `validation_error`.
- 401 `authentication_error`: The key is missing, removed, or not a key. Send it in `x-api-key`.
- 403 `permission_error`: The key was not made with **Can delete tasks** (`error_code` `person_required`).
- 404 `not_found_error`: No task in the key's workspace has this id, or it was taken back or deleted (`Task not found.`).
- 409 `conflict_error`: The task is still at work. Interrupt it with a `user.interrupt` event, wait for it to stop, then delete it.
- 429 `rate_limit_error`: The workspace made too many requests this minute. Wait the seconds in `Retry-After`, then try again.

## Read what a task cost

`GET /tasks/{task_id}/receipts`

Read a receipt for each finished run of the task, newest first: what it cost, which AI paid for it, and which app actions were allowed or denied along the way. A run is one stretch of work; a task has a new run each time it starts again, such as after a message or a send back.

A run that is still going has no receipt yet. The list covers the task's newest 200 runs.

### Path parameters

- `task_id` (task id, required): The task, such as `task_01JA8Z6Q4M3T9V2K7X5R1B0C8D`.

### Query parameters

- `limit` (integer): How many to answer, 1 to 100. The default is 20.
- `page` (string): The `next_page` of the answer before, to read the next page.
- `order` (string): `desc`, newest first (the default), or `asc`, oldest first. One of `desc`, `asc`.
- `created_at[gt]` (time): Only those made after this time. `created_at[gte]`, `created_at[lt]` and `created_at[lte]` work the same way.

### Returns

A list: `data` holds the receipts, newest first, and `next_page` is the `page` to send for more, or `null` on the last page. Each receipt has these fields.

- `type` (string): Always `receipt`.
- `id` (receipt id): The receipt's id. A run has one receipt, so it matches the run's.
- `task_id` (task id): The task.
- `run_id` (run id): The run it covers.
- `charged` (money): What the workspace was charged, in whole US cents rounded up. A call on your own AI key is charged nothing.
  - `amount` (string): Whole US cents, as a string: `"250"` is $2.50.
  - `currency` (string): Always `USD`.
- `included` (money): The part Little Worker AI paid for, which the plan includes, in the same form.
  - `amount` (string): Whole US cents, as a string: `"250"` is $2.50.
  - `currency` (string): Always `USD`.
- `calls` (object): How many AI calls the run made, by who paid.
  - `included` (integer): Calls Little Worker AI paid for.
  - `own_key` (integer): Calls your own AI key paid for.
  - `unpriced` (integer): Calls served without a price that your own key did not pay for. The amounts are complete only while this is 0.
- `own_key_provider` (string, or null): The company whose key paid, when your own key did. `null` when none did.
- `actions` (array of objects): The app actions decided in the run and in the tasks it started, oldest first. An action still waiting for an answer is not listed, and what the worker sent to the app never shows.
  - `tool_request_id` (tool request id): The worker's request to use the tool.
  - `app_id` (app id, or null): The app. It still names an app that was removed later; `null` only when a workspace restored from a backup no longer had it.
  - `tool` (string): The tool's name in the app.
  - `decision` (string): What was decided. One of `allowed`, `denied`.
  - `decided_by` (string): `setting` when the app's Read or Act setting decided, `person` when someone answered. An answer sent with a key counts as `person`. One of `setting`, `person`.
  - `reason_code` (string): Why it was decided that way. One of `read_on`, `read_off`, `act_allow`, `act_ask`, `act_off`, `tool_off`, `destructive_asks`, `person_action_asks`, `unclassified_asks`, `prohibited`, `may_repeat`.

### Example

```bash
curl https://core.thelittleworker.com/api/v1/tasks/task_01JA8Z6Q4M3T9V2K7X5R1B0C8D/receipts \
  -H "x-api-key: $LITTLE_WORKER_API_KEY" \
  -H "Little-Worker-Version: 2026-10-19"
```

```json
{
  "data": [
    {
      "type": "receipt",
      "id": "receipt_6d2e8f1a3c5b4d7e9f0a1b2c3d4e5f6a",
      "task_id": "task_01JA8Z6Q4M3T9V2K7X5R1B0C8D",
      "run_id": "run_6d2e8f1a3c5b4d7e9f0a1b2c3d4e5f6a",
      "charged": {
        "amount": "1",
        "currency": "USD"
      },
      "included": {
        "amount": "1",
        "currency": "USD"
      },
      "calls": {
        "included": 2,
        "own_key": 0,
        "unpriced": 0
      },
      "own_key_provider": null,
      "actions": []
    }
  ],
  "next_page": null
}
```

### Errors

- 400 `invalid_request_error`: `task_id` is not a task id. `error_code` is `validation_error`.
- 401 `authentication_error`: The key is missing, removed, or not a key. Send it in `x-api-key`.
- 404 `not_found_error`: No task in the key's workspace has this id, or it was taken back or deleted (`Task not found.`).
- 429 `rate_limit_error`: The workspace made too many requests this minute. Wait the seconds in `Retry-After`, then try again.
