Docs Pagination

Pagination

All list endpoints in Tiqora use cursor-based pagination. This approach is more efficient than offset-based pagination for large datasets and guarantees consistent results even when data is being added or removed.

How It Works

Every list endpoint accepts two pagination parameters:

Parameter Type Default Description
per_page integer 25 Number of items per page (max: 100)
cursor string Opaque cursor for the next page

The response includes a meta object with pagination information:

{
  "data": [...],
  "meta": {
    "per_page": 25,
    "has_more": true,
    "next_cursor": "eyJpZCI6IjAxOTEyMzQ1LTY3ODktN2FiYy1kZWYwLTEyMzQ1Njc4OWFiYyJ9"
  }
}
Meta Field Description
per_page Items returned per page
has_more true if more items exist
next_cursor Opaque string to pass as cursor param for next page. null when no more pages.

Fetching Pages

First Page

GET /api/v1/external/tickets?per_page=25

Next Page

Take next_cursor from the previous response and pass it as cursor:

GET /api/v1/external/tickets?per_page=25&cursor=eyJpZCI6IjAxOTEyMzQ1In0=

Complete Traversal

async function fetchAllTickets() {
  const allTickets = [];
  let cursor = null;

  do {
    const params = new URLSearchParams({ per_page: '100' });
    if (cursor) params.set('cursor', cursor);

    const response = await tiqoraRequest(
      'GET',
      `/api/v1/external/tickets?${params}`
    );

    allTickets.push(...response.data);
    cursor = response.meta.has_more ? response.meta.next_cursor : null;
  } while (cursor);

  return allTickets;
}

Python

def fetch_all_tickets():
    all_tickets = []
    cursor = None

    while True:
        params = {'per_page': 100}
        if cursor:
            params['cursor'] = cursor

        query = '&'.join(f'{k}={v}' for k, v in params.items())
        response = tiqora_request('GET', f'/api/v1/external/tickets?{query}')

        all_tickets.extend(response['data'])

        if not response['meta']['has_more']:
            break

        cursor = response['meta']['next_cursor']

    return all_tickets

Combining Pagination with Filters

Filters and pagination work together. Filters are applied first, then results are paginated:

GET /api/v1/external/tickets?status=open&priority=high&per_page=50

The cursor encodes the filter state, so you can safely paginate through filtered results without them changing.

Important Notes

  • Cursors are opaque — Don't try to decode, construct, or modify cursor values. Treat them as opaque strings.
  • Cursors expire — Cursors are tied to a specific query. Don't reuse cursors across different filter combinations.
  • Use per_page=100 for bulk operations — This minimizes the number of API calls needed.
  • Order is consistent — Results are ordered by created_at DESC by default (newest first). You can change the sort order with sort_by and sort parameters where supported.

Hint: If you need to sync all data, paginate through the entire dataset once, then use webhooks to stay up-to-date with changes going forward. This avoids repeated full scans.