---
title: "List tasks"
method: GET
path: "/v1/tasks"
tags: ["tasks"]
---

# List tasks

`GET /v1/tasks`

## Request

- Base URL: `https://api.indraft.io`
- URL: `https://api.indraft.io/v1/tasks`
- Auth: HTTP bearer

List tasks by status or assignee, newest first, with a cursor for the next page. Narrow with filter, for example filter: ['owner_actor_id:eq:act_...', 'expected_close_date:isNotNull'] and sort: '-expected_close_date'; get_crm_schema lists the fields each type accepts.

## Query parameters

- `limit` integer: How many to return. The page bound is published in the schema call, and asking for more is refused rather than quietly truncated.
- `cursor` string: The opaque marker from the previous page. Store it and hand it back; do not parse it. A cursor is only ever emitted when another row really exists, so a page you were given is never empty.
- `updatedSince` string: Only rows changed after this instant. The incremental read: without it a service syncing a large workspace has to walk all of it every time.
- `status` 'open' | 'done' | 'cancelled': Only records with this status. Status is derived from the stage's kind rather than set separately, so a deal cannot be open and won at once.
- `assigneeActorId` string: Only tasks assigned to this actor. The actor id comes back on every change and in the schema call for the caller themselves.
- `filter` union: Predicates, all of which must hold, written field:op:value. Only fields an index serves are accepted, and asking for one that is not names the ones that are.
  - string
  - string[]
- `or` union: Alternatives, ORed with each other and ANDed with filter. One level and never a tree: owned by me or owned by nobody is the question people ask, and anything deeper has a cost the caller cannot read off it.
  - string
  - string[]
- `sort` string: A field to order by, with a leading minus for descending. Indexed fields only, for the same reason as filter.

## Response `200`

Success

- object
  - `items` object[], required: This page of results, in the order you asked for.
    - `id` string, required
    - `title` string, required
    - `status` 'open' | 'done' | 'cancelled', required
    - `assigneeActorId` string, required
    - `assignee` object
      - `id` string, required
      - `kind` 'human' | 'agent' | 'api_token' | 'system', required
      - `label` string, required
    - `dueAt` string, required
    - `priority` 'low' | 'normal' | 'high', required
    - `completedAt` string, required
    - `ownerActorId` string, required
    - `version` integer, required
    - `links` object[], required
      - `objectType` 'company' | 'contact' | 'opportunity', required
      - `objectId` string, required
    - `createdAt` string, required
    - `updatedAt` string, required
    - `archivedAt` string, required
  - `nextCursor` string, required: Hand this back to get the next page, or null when there is no next page. Null is the end of the list and an empty `items` is not: a cursor is only emitted when another row really exists.
  - `requestId` string, required

## Other responses

- `401`: No credential, or one that has been revoked.
- `403`: Authenticated, and this capability is not held.
- `422`: The request does not satisfy the schema on this page.
- `429`: Infrastructure protection tripped. This is not a product quota.
- `500`: A defect on our side. The hint says so, and carries an incident id.

---

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