> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.v2.rasen.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.v2.rasen.ai/_mcp/server.

# Pagination

Every list answers one page:

```json
{"items": [ … ], "next_cursor": "eyJwYWdlIjoyfQ"}
```

* `limit` sets the page size: 1 to 200, 50 by default.
* Follow `next_cursor` until it is `null`. Send the cursor back as `?cursor=` on a GET list, or as
  `"cursor"` in the body of `POST /calls/search` and `POST /usage/query`.
* A cursor is opaque. It is bound to your workspace, every filter, the grouping and the limit: send
  them unchanged with it. A changed filter or limit with an old cursor is refused.
* A cursor expires after **24 hours**.
* An invalid, expired or foreign cursor answers `400 invalid_request` with
  `details.field = "cursor"`, and never returns another workspace's data. Start again without the
  cursor.

```bash
curl -sS "$RASEN_API_BASE/agents?limit=100" -H "Authorization: Bearer $RASEN_API_KEY"
curl -sS "$RASEN_API_BASE/agents?limit=100&cursor=$NEXT_CURSOR" -H "Authorization: Bearer $RASEN_API_KEY"
```

## Campaign transcript CSV pages

`GET /batch-calls/{batch_id}/transcripts/export` uses the same opaque-cursor rules, but each
response is a CSV file instead of a JSON page:

* `limit` is 1 to 500 and defaults to 500. Keep it unchanged for the complete download.
* Read the continuation from the `X-Next-Cursor` response header. Its absence means the download
  is complete.
* The first request fixes an upper watermark. Attempts created later do not enter the remaining
  pages of that download.
* Save each page separately or parse its CSV rows. Do not append complete page files blindly,
  because each page contains its own CSV header.
* If a transfer breaks, discard that incomplete page and retry it with the same cursor. For the
  first page, retry without a cursor.

The cursor is bound to the workspace, campaign and limit, and expires after 24 hours. See
[Calls and results](/guides/calls#export-campaign-evidence) for request examples.

## Ordering

Each operation in the API reference states its order. Agent, version, secret and call lists are
newest first; `GET /calls` orders by creation time and then ID, both descending.

## Keeping a copy in sync

`GET /calls?updated_since=…` switches the call list to a changes scan: items come oldest change
first, and the last page carries `scanned_through`, where the next scan starts. See
[Calls and results](/guides/calls#keep-a-copy-in-sync).

A transcript page is bound to the transcript it came from: if a newer transcript replaces it, the
old cursor answers `invalid_request` with `details.field = "cursor"`. Start again without it.

## Date ranges

Operations with `start` and `end` take UTC timestamps. `start` is inclusive and `end` exclusive, a
range covers at most 93 days, and the default is the trailing 30 days.