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

# Pagination

> Cursor based, because a support queue moves while you read it.

List endpoints return a page and a cursor:

```json theme={null}
{
  "data": [ ... ],
  "next_cursor": "eyJpZCI6..."
}
```

Send `next_cursor` back as the `cursor` query parameter to fetch the next
page. When `next_cursor` is `null`, you have reached the end.

```bash theme={null}
# First page
curl "https://api.minidesk.ai/v1/tickets?limit=50" \
  -H "Authorization: Bearer $MINIDESK_TOKEN"

# The next one
curl "https://api.minidesk.ai/v1/tickets?limit=50&cursor=eyJpZCI6..." \
  -H "Authorization: Bearer $MINIDESK_TOKEN"
```

`limit` runs from 1 to 100 and defaults to 25.

## Why not page numbers

A support queue changes while you are reading it. With offsets, a ticket
arriving between two of your requests shifts every row down, so page 2 repeats
a row from page 1. A ticket being resolved shifts them up, so a row is skipped
altogether.

A cursor points at a position in the results, not a count from the start, so
neither happens.

## Walking every page

```js theme={null}
async function everyTicket(token, query = {}) {
  const tickets = [];
  let cursor;

  do {
    const params = new URLSearchParams({ ...query, limit: "100" });
    if (cursor) params.set("cursor", cursor);

    const response = await fetch(
      `https://api.minidesk.ai/v1/tickets?${params}`,
      { headers: { Authorization: `Bearer ${token}` } },
    );

    if (!response.ok) throw new Error(`${response.status}`);

    const page = await response.json();
    tickets.push(...page.data);
    cursor = page.next_cursor;
  } while (cursor);

  return tickets;
}
```

<Note>
  An empty `data` array with a non-null `next_cursor` is possible. Stop when
  `next_cursor` is `null`, not when a page comes back empty.
</Note>

## Filtering

Filters go on the query string and combine with AND. They are part of the
cursor, so keep them identical across a walk. Changing a filter mid-walk makes
the cursor meaningless.

| Parameter     | Notes                                                            |
| ------------- | ---------------------------------------------------------------- |
| `status`      | One status, or several separated by commas: `open` or `new,open` |
| `priority`    | `low`, `normal`, `high`, `urgent`                                |
| `category`    | Exact match                                                      |
| `assignee_id` | A member id                                                      |
| `q`           | Full text over requester details and message bodies              |

The comma form exists because the queue's idea of "ongoing" is `new` and `open`
seen together, and inventing a sixth status for that would have meant a filter
vocabulary that does not match the state machine.

```bash theme={null}
curl "https://api.minidesk.ai/v1/tickets?status=new,open&priority=urgent" \
  -H "Authorization: Bearer $MINIDESK_TOKEN"
```
