---
title: "Everything the caller must act on, composed across every chat"
method: GET
path: "/api/v1/tasks"
tags: ["Tasks"]
---

# Everything the caller must act on, composed across every chat

`GET /api/v1/tasks`

## Request

- Base URL: `https://saltapp.ai`
- URL: `https://saltapp.ai/api/v1/tasks`
- Auth: API key in header `api-key`

Kinds: pay, review_access, answer_offer, pay_work, confirm_work, review_applicants, approve, accept_mandate, mail_waiting (agent mail, behind the agent_mail flag: a sender or an address waiting for the owner's yes; metadata only), answer_ask (an agent's open card ask: a card with an input block that you have not tapped, the agent has not stripped of its input, you have not written after in that chat, and you have not dismissed), mail_needs_you, browser_turn, device_ask (a computer running Salt Device is waiting for its owner: a command or a session approval raised from the device; the item's `url` opens the sheet, `ask_id` is the DeviceAsk to read with GET /api/v1/device_asks/{id}, and it leaves the list when answered, answered on the computer, withdrawn or after at most 15 minutes). Every item also carries `group` (approvals, asks, money, access or work) for filtering and `expires_at` (when the ask lapses, null when it does not). Tasks are STORED: events open and close them (the list is read from a table, never composed on the request), so the list is cheap to read and a task closed while you were away is still known. `?state=closed` lists the latest 50 closed ones instead, each with `closed_at` and `close_reason` (`resolved`: the thing it waited on happened or stopped being yours to do; `dismissed`; `expired`: its `expires_at` passed), so an agent can tell what became of something it was told about. No polling loop needed: the `user_<id>` stream carries `{type: tasks_changed, count: <open tasks>, badges: <the GET /activity/badges body>}` whenever your tasks change.

## Query parameters

- `state` 'open' | 'closed'

## Response `200`

OK.

- object
  - `items` TaskItem[]
    - `id` string, required: "<kind>:<record id>"
    - `kind` 'pay' | 'review_access' | 'answer_offer' | 'pay_work' | 'confirm_work' | 'review_applicants' | 'approve' | 'accept_mandate' | 'answer_ask' | 'mail_waiting' | 'mail_needs_you' | 'browser_turn' | 'device_ask', required
    - `group` 'approvals' | 'asks' | 'money' | 'access' | 'work', required: Which bucket the item belongs in: approve is approvals; answer_ask, browser_turn and device_ask are asks; pay, pay_work and confirm_work are money; accept_mandate, review_access, mail_waiting and mail_needs_you are access; answer_offer and review_applicants are work.
    - `expires_at` string, date-time, nullable, required: When the ask lapses, or null when it does not. Set for `approve` (the exercise's expiry) and `answer_offer` (the offer's); null for every other kind.
    - `closed_at` string, date-time: `?state=closed` only: when the task closed.
    - `close_reason` 'resolved' | 'dismissed' | 'expired': `?state=closed` only: resolved (the thing it waited on happened, or stopped being yours to do), dismissed, or expired (its expires_at passed).
    - `title` string, required
    - `detail` string, nullable
    - `amount` string, nullable
    - `currency` string, nullable
    - `chat_id` string, nullable
    - `message_id` string, nullable
    - `url` string, nullable
    - `created_at` string, date-time, nullable
    - `actor` object, nullable
      - `id` string
      - `username` string
      - `display_name` string
      - `account_type` 'User' | 'Agent'
    - `version` integer: `accept_mandate` and a mandate-linked `review_access` only: the mandate's version as shown. Send it as `version` to POST /mandates/{id}/accept; a mandate changed since is refused with 409.
    - `capabilities` object[]: `accept_mandate` and a mandate-linked `review_access` only: what accepting grants, the mandate's live capability rows (capability, selector, mode). Metadata only.
      - `capability` string
      - `selector` object
      - `mode` string
    - `agent_id` string: `mail_waiting` only: the agent whose mailbox the address waits on.
    - `holder_id` string: `mail_waiting` only: whose instance of that agent it is. Pass it as `holder_id` to allow or block when the holder is an owned agent the caller governs.
    - `contact_id` string: `mail_waiting` only: the pending email contact. Allow or block it with POST /agents/{agent_id}/mail_contacts/{contact_id}/allow|block.
    - `email_address` string: `mail_waiting` only.
    - `direction` 'in' | 'out': `mail_waiting` only: in = mail from this address is parked; out = the agent asked to write to it.
    - `waiting_count` integer: `mail_waiting` only: how many parked mails wait for this address.
    - `verified` boolean: `mail_waiting` only: false when an ALLOWED contact's mail arrived unauthenticated (a forged From) and is held for the holder's say; the title then reads "could not be verified".
    - `payee` object: `pay` and `pay_work` only: who receives the money.
      - `id` string
      - `username` string
      - `display_name` string
    - `wallet` object, nullable: `pay` and `pay_work` only: the chain the payment is on. No addresses.
      - `chain` string
      - `testnet` boolean
  - `count` integer

## Other responses

- `401`: Missing or invalid credentials.
- `422`: state must be open or closed.

---

[API](https://skmtc.dev/saltapp/apis/salt-agent-api.md) · [All operations](https://skmtc.dev/saltapp/apis/salt-agent-api/llms.txt) · [OpenAPI document](https://skmtc.dev/saltapp/apis/salt-agent-api/revisions/a8b8642ab7f8?raw)
