Cursor-based Pagination
Cursor-based Pagination for Q integrations.
Several public list endpoints use cursor-based pagination. Read each operation’s x-q-pagination metadata: legacy offset responses and unpaginated arrays retain their existing formats. Cursors are opaque position tokens with ID tie-breaking; they do not create a snapshot or guarantee unchanged results while rows are inserted, updated or deleted.
Base URL: https://api.qdivision.ai/v1
Response shape
Every cursor-paginated list returns a CursorPage:
{
"data": [ ... ],
"has_more": true,
"next_cursor": "eyJzb3J0IjoiMjAyNi0wNi0xNFQxMDozMDowMCswMDowMCIsImlkIjoiNDIifQ",
"previous_cursor": null
}| Field | Description |
|---|---|
data | Array of items for the current page |
has_more | true when next_cursor is non-null |
next_cursor | Opaque cursor to pass as ?cursor= for the next page; null on the last page |
previous_cursor | Cursor to page backward; null on the first page |
Some endpoints (e.g. GET /v1/webhooks) include additional top-level fields alongside the page envelope.
Query parameters
| Parameter | Default | Max | Description |
|---|---|---|---|
cursor | — | 2,048 characters | Opaque cursor from a previous response's next_cursor |
limit | 20 | 100 | Number of items per page |
Malformed or wrongly typed cursor anchors return HTTP 400 invalid_cursor; schema length violations return 422. Forward and backward navigation use the same ordering. Use previous_cursor to request the nearest preceding page. Resource permissions are checked on every request; a cursor grants no access.
Manual pagination
# First page
curl -sS "https://api.qdivision.ai/v1/webhooks?limit=20" \
-H "Authorization: Bearer $Q_API_KEY"
# Next page
curl -sS "https://api.qdivision.ai/v1/webhooks?limit=20&cursor=eyJ..." \
-H "Authorization: Bearer $Q_API_KEY"Continue requesting pages while has_more is true, passing next_cursor as the cursor query parameter.
Endpoints with cursor pagination
| Endpoint | Description |
|---|---|
GET /v1/webhooks | Webhook subscriptions |
GET /v1/spaces | Spaces for the current tenant |
GET /v1/artifacts | Generated artifacts |
GET /v1/skills | Registered skills |
GET /v1/logs | Request logs for the authenticated API key |
GET /v1/spaces/{space_id}/pages is an unpaginated items collection; supply a space and omit cursor/limit. SDK helpers reject malformed/repeated forward cursors.
SDK auto-pagination helpers
Both SDKs provide helpers that iterate all pages automatically — you receive individual items without managing cursors yourself.
Python — auto_paging_iter
The webhooks client exposes a convenience method; the same pattern works for any cursor-paginated endpoint:
import os
from q_client import Q
from q_client.pagination import auto_paging_iter
async def main() -> None:
q = Q(api_key=os.environ["Q_API_KEY"])
# Built-in on webhooks
async for webhook in q.webhooks.auto_paging_iter():
print(webhook["id"], webhook["url"])
# Generic pattern for spaces, logs, etc.
async def fetch_spaces(cursor: str | None) -> dict:
params = {"limit": 50}
if cursor:
params["cursor"] = cursor
return await q.get_json("/spaces", params=params)
async for space in auto_paging_iter(fetch_spaces):
print(space["name"])
await q.aclose()Collect all items at once with list_all_pages(fetch_page).
TypeScript — autoPagingEach
import { Q } from "@getq/sdk";
import { autoPagingEach } from "@getq/sdk";
const q = new Q({ apiKey: process.env.Q_API_KEY! });
// Built-in on webhooks
for await (const webhook of q.webhooks.autoPagingEach()) {
console.log(webhook.id, webhook.url);
}
// Generic pattern for other list endpoints
for await (const log of autoPagingEach(async (cursor) => {
return q.getJson("/logs", { limit: 50, ...(cursor ? { cursor } : {}) });
})) {
console.log(log.request_id, log.path);
}Collect all items at once with listAllPages(fetchPage).
Related
- Request Logs — filtered log listing with cursor pagination
- Webhooks — subscription management