Pagination

How pagination works across all list endpoints: parameters, defaults, and iteration patterns.

Pagination

List endpoints in the UrbanPayX API return paginated results. This guide covers the pagination parameters, response format, and how to iterate through all results.


How it works

Most list endpoints use page-based pagination with two query parameters:

ParameterDescriptionDefault
pagePage number (starts at 1)1
page_sizeNumber of items per pageVaries by endpoint

Results are always sorted by creation date, newest first.


Paginated response format

Most paginated responses put the rows in a resource-named array and the counters in a nested pagination object. The array key varies by endpoint - it is never literally items:

{
  "transactions": [ ... ],
  "pagination": {
    "total": 142,
    "page": 1,
    "page_size": 10,
    "total_pages": 15
  }
}
FieldDescription
<resource>Array of rows for the current page. Key name depends on the endpoint: transactions, users, business_customers, opcos, projects, tickets, invoices, notifications, ...
pagination.totalTotal number of items matching the query, across all pages
pagination.pageCurrent page number
pagination.page_sizeItems per page (what you requested or the default)
pagination.total_pagesTotal number of pages (ceil(total / page_size))

Always check the endpoint's API reference for its exact array key before writing a client. A few endpoints deviate from the shape above:

ShapeWhere
Counters at the top level instead of nested (records, page, page_size, total, total_pages)Transaction monitoring, wallet screening, travel-rule transfers, activity logs
Only a total, with limit / offset instead of page / page_sizeGET /webhooks/deliveries, GET /webhooks/destinations
No pagination at all - the full list is returnedGET /kyc/levels, GET /kyb/levels, contract template lists

Endpoint-specific defaults and limits

EndpointArray keyDefaultMax
GET /transactionstransactions10200
GET /kyc/listsusers20200
GET /kyb/businessesbusiness_customers20200
GET /opcosopcos20200
GET /projectsprojects20200
GET /ticketstickets20200
GET /webhooks/deliveriesdeliveries50 (limit)200

Requesting a page_size above the maximum is a validation error (422), not a silent cap.


Iterating through all results

To retrieve all items, increment the page parameter until you have fetched all pages:

import requests

def get_all_transactions(base_url, token):
    headers = {"Authorization": f"Bearer {token}"}
    all_items = []
    page = 1
    
    while True:
        resp = requests.get(
            f"{base_url}/api/v1/transactions",
            params={"page": page, "page_size": 100},
            headers=headers
        )
        data = resp.json()
        all_items.extend(data["transactions"])
        
        if page >= data["pagination"]["total_pages"]:
            break
        page += 1
    
    return all_items
async function getAllTransactions(baseUrl, token) {
  const allItems = [];
  let page = 1;
  
  while (true) {
    const resp = await fetch(
      `${baseUrl}/api/v1/transactions?page=${page}&page_size=100`,
      { headers: { Authorization: `Bearer ${token}` } }
    );
    const data = await resp.json();
    allItems.push(...data.transactions);
    
    if (page >= data.pagination.total_pages) break;
    page++;
  }
  
  return allItems;
}

Webhook delivery history

The webhook deliveries endpoint uses offset-based pagination instead of page-based:

ParameterDescriptionDefault
limitNumber of items to return50
offsetNumber of items to skip0
GET /api/v1/webhooks/deliveries?limit=50&offset=0
GET /api/v1/webhooks/deliveries?limit=50&offset=50
GET /api/v1/webhooks/deliveries?limit=50&offset=100

The response includes total and items fields. Increment offset by limit until offset >= total.


Filtering

Some endpoints support additional query parameters to narrow results before pagination:

Transactions:

FilterDescription
statusFilter by transaction status (e.g., success, pending)
project_idFilter by project
user_idFilter by user
GET /api/v1/transactions?status=success&project_id=uuid&page=1&page_size=50

Filters are applied server-side before pagination, so total reflects the filtered count.


Best practices

Use the largest reasonable page_size. If you need all results, use the maximum allowed page_size to minimize the number of requests.

Check pagination.total_pages before iterating. If it is 1, you already have all the data.

Handle empty results. If pagination.total is 0, the resource array will be empty and pagination.total_pages will be 0.

Do not assume stable ordering during writes. If items are being created while you paginate, you may see duplicates or miss items. For critical data, use timestamps or IDs to deduplicate.


Related guides