Q for developers

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
}
FieldDescription
dataArray of items for the current page
has_moretrue when next_cursor is non-null
next_cursorOpaque cursor to pass as ?cursor= for the next page; null on the last page
previous_cursorCursor 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

ParameterDefaultMaxDescription
cursor—2,048 charactersOpaque cursor from a previous response's next_cursor
limit20100Number 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

EndpointDescription
GET /v1/webhooksWebhook subscriptions
GET /v1/spacesSpaces for the current tenant
GET /v1/artifactsGenerated artifacts
GET /v1/skillsRegistered skills
GET /v1/logsRequest 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).


On this page