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

# Pagination

Paged lists use **cursors**. You ask for a page, and the response tells you where the next one starts.

## Cursor pages

A paged response is an object with the page's `items` and a `nextCursor`:

```json
{
  "items": [
    { "number": 5, "reason": "save", "createdAt": "2026-11-09T14:32:34.155Z", "changedFields": ["voiceConfig"] },
    { "number": 4, "reason": "save", "createdAt": "2026-11-09T14:32:30.168Z", "changedFields": ["voiceConfig"] }
  ],
  "nextCursor": 4,
  "latest": 5
}
```

* To get the next page, send `nextCursor` back as the `cursor` query parameter.
* `nextCursor` is `null` on the last page.
* Treat a cursor as opaque: pass it back exactly as you got it.
* `limit` sets the page size.

Newest items come first.

**`curl`**

```bash title="curl"
# First page
curl "https://api.rydhm.ai/v1/agents/$EXPERT_ID/versions?limit=2" \
  -H "Authorization: Bearer $RYDHM_API_KEY"

# Next page: pass nextCursor back as cursor
curl "https://api.rydhm.ai/v1/agents/$EXPERT_ID/versions?limit=2&cursor=4" \
  -H "Authorization: Bearer $RYDHM_API_KEY"
```

**`TypeScript`**

```typescript title="TypeScript"
import { RydhmClient } from "@rydhm/sdk";

const client = new RydhmClient();
let cursor: number | undefined;
do {
  const page = await client.experts.versions.list(expertId, { cursor, limit: 30 });
  for (const version of page.items) console.log(version.number, version.reason);
  cursor = page.nextCursor ?? undefined;
} while (cursor !== undefined);
```

**`Python`**

```python title="Python"
from rydhm import Rydhm

client = Rydhm()
cursor = None
while True:
    page = client.experts.versions.list(expert_id, cursor=cursor, limit=30)
    for version in page.items:
        print(version.number, version.reason)
    if page.next_cursor is None:
        break
    cursor = page.next_cursor
```

### Paged routes

| Route                                                        | Page size                        | Order                |
| ------------------------------------------------------------ | -------------------------------- | -------------------- |
| `GET /v1/agents/{id}/versions` (an expert's version history) | `limit`, default 30, at most 100 | Newest version first |

## Lists that are not paged

The other lists return everything in one response, up to a fixed cap. Filter them where the route allows it.

| Route                                      | What it returns                                                                                   |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| `GET /v1/agents`                           | Every expert the key can see.                                                                     |
| `GET /v1/agents/{id}/kb`                   | Every document of the expert.                                                                     |
| `GET /v1/chat/conversations`               | The 50 most recently updated conversations that have at least one message. Filter with `agentId`. |
| `GET /v1/chat/conversations/{id}/messages` | Every message of the conversation, oldest first.                                                  |
| `GET /v1/meetings`                         | The 500 most recent meetings, newest first.                                                       |
| `GET /v1/workspace-tools/{id}/calls`       | The most recent calls of a tool: `take` sets how many, default 20, at most 100.                   |

To poll a live meeting's transcript without downloading all of it each time, pass `segmentsSince` (an ISO 8601 time) to `GET /v1/meetings/{id}`. Only transcript lines created at or after that time come back.

For events as they happen, instead of polling lists, use [webhooks](/developers/webhooks).