Pagination and filtering
For engineers reading lists from the Quant Flow Platform. The four paging styles the API uses, which endpoints use which, and how ordering, page size and filters behave.
Who this is for
Integration engineers writing list readers, exports and reconciliation jobs.
Four paging styles
List endpoints use one of four styles. Build a small reader per style and map each endpoint to it. Do not assume one envelope across the API.
| Style | Request parameters | Response envelope | Total count |
|---|---|---|---|
A. Page number, content | page (zero-based), size | content, page, size, totalElements, totalPages | Yes |
B. Page number, data | page (zero-based), size | data, page, size, totalItems, totalPages | Yes |
C. Page number, items | page (zero-based), size, sort | items, pageNumber, pageSize, totalResults | Yes, no totalPages |
| D. Cursor | limit, cursor | items, nextCursor, limit | No |
page defaults to 0 and size or limit to 20 on every paged endpoint.
Which endpoint uses which style
| Endpoint | Style | Order | Page size rule |
|---|---|---|---|
GET /api/customers | A | Oldest first, fixed | 1 to 100. Outside the range is a 400. |
GET /api/accounts | A | Oldest first, fixed | 1 to 100, 400 outside |
GET /api/contracts | A | Oldest first, fixed | 1 to 100, 400 outside |
GET /api/transactions | A or D | Newest first, fixed | 1 to 100, 400 outside |
GET /api/transactions/breaks | A | Newest first, fixed | 1 to 100, 400 outside |
GET /api/automations | A | sort, default createdAt,desc | Above 100 returns 100; below 1 returns 1 |
GET /api/automations/{automationId}/history | A | sort, default createdAt,desc | As above |
GET /api/audit/events | B | sort, default occurredAt,desc | Above 100 is reduced to 100 without an error |
GET /api/policies | B | No default order is guaranteed by the contract; use returned identifiers for deduplication. | Not specified; use the returned page size. |
GET /api/policies/{policyId}/versions | B | Newest version first, fixed | Not specified; use the returned page size. |
GET /api/templates | B | Fixed: SYSTEM scope first, then key ascending | ignorePaging=true returns everything in one page |
GET /api/approvals/tasks | B | Newest first (createdAt), fixed | Not specified; use the returned page size. |
GET /api/approvals/requests | B | resolvedAt descending, fixed | Not specified; use the returned page size. |
GET /api/tenants/{id}/users | C | sort | Not specified; use the returned page size. |
GET /api/tenants/{id}/roles | C | sort, default name,asc | Not specified; use the returned page size. |
GET /api/tenants/{id}/groups | C | sort, default name,asc | Not specified; use the returned page size. |
GET /api/webhooks | D | Newest first, fixed | limit 1 to 100, 400 outside |
GET /api/webhook-events | D | Newest first on occurredAt, fixed | limit 1 to 100, 400 outside |
Two single-resource reads also page a nested list. GET /api/tenants/{id}/roles/{roleId} pages the role's holders, and GET /api/tenants/{id}/groups/{groupId} pages the group's members. Both default to first name then last name ascending.
Always read the page size from the response. Endpoints differ on whether an oversized value is rejected, reduced or accepted.
Page number styles (A, B, C)
Request pages from 0 upwards until the page index reaches the last page (totalPages - 1) or a page comes back shorter than the page size.
- Counts are a snapshot. On transactions,
totalElementschanges if operations are accepted while you page. The transaction list does not offer a date-range filter. Deduplicate by transaction ID and retain your own reconciliation cut-off and record set. - Newest-first lists shift. New records arriving at the front move older records onto later pages, so a record can appear on two pages. Deduplicate on the record's identifier.
- An empty result is an empty page. A filter matching nothing returns an empty page with status
200.
Transaction log: choose a paging style
GET /api/transactions supports both page/size and cursor/limit. Choose one style per request; mixing their parameters produces 400. For cursor paging, start with limit, then pass nextCursor unchanged with the same filters. The response contains items, nextCursor (null on the last page) and limit, with no totals. The page-based envelope remains unchanged.
Cursor style (D)
Omit cursor for the first page. Pass the previous response's nextCursor to get the next. nextCursor is always present and is null on the last page.
- The cursor is opaque. Do not construct, parse or store one beyond the current read. A cursor the endpoint did not issue is a
400. - On
GET /api/webhook-events, a cursor replayed with different filters is a400. Keep filters constant for the whole read. - There is no total count.
Sorting
Only some endpoints take sort. Where it is taken, the form is property or property,asc|desc, and it can be repeated.
| Endpoint | Sortable properties | Unknown property |
|---|---|---|
GET /api/audit/events | occurredAt, createdAt, action, category, source, actorId, resourceType, resourceId, outcome | 400 |
GET /api/tenants/{id}/users | firstName, lastName, email, status, createdAt, updatedAt, id, and paths such as role.name | 500 |
GET /api/tenants/{id}/roles | name, description, createdAt, updatedAt, id | 500 |
GET /api/tenants/{id}/groups | key, name, status, createdAt, updatedAt, id | 500 |
GET /api/automations, .../history | Use only sorting fields documented by the endpoint or validated in your environment; no complete property allow-list is published. | Do not depend on an undocumented error message; handle the returned status and fall back to the endpoint's default order. |
On every other list, ordering is fixed and there is no sort parameter. Use only the listed properties.
Filtering
Filters are optional query parameters and combine with AND. The main ones:
| Endpoint | Filters |
|---|---|
GET /api/customers | status |
GET /api/accounts | customerRef, status, assetId |
GET /api/contracts | assetId (case-insensitive), status |
GET /api/transactions | state, accountRef, txType. An unknown state or txType is a 400. |
GET /api/transactions/breaks | reason, accountRef (originating account only), from (inclusive), to (exclusive), both ISO 8601. An unknown reason returns an empty page, since the set of reasons is open. |
GET /api/audit/events | occurredFrom, occurredTo, actorIds (repeatable or comma-separated), requestId, action, source, resourceType, resourceId, and query (case-insensitive prefix match on identifier fields, at most 128 characters) |
GET /api/webhook-events | type, from (inclusive), to (exclusive), status, webhookId. from and to accept ISO 8601 or yyyy-MM-dd HH:mm:ss.SSS. |
GET /api/automations | status, triggerType, scriptId, rootScriptId, userId |
GET /api/approvals/tasks | status (one per call, default PENDING) |
GET /api/approvals/requests | status, actedBy, resolvedFrom, resolvedTo, action, resourceId |
GET /api/policies | status, ruleType |
GET /api/tenants/{id}/users | search, status, role |
Time windows on breaks and delivery history are half-open (from inclusive, to exclusive), so consecutive windows cover a timeline without overlap.
On GET /api/approvals/requests, either resolvedFrom or resolvedTo excludes every unresolved request. Leave both off to see PENDING requests.
The automation status filter accepts values that an automation does not reach (PAUSED, IN_PROGRESS, COMPLETED, FAILED, DRAFT). The lifecycle statuses are ACTIVE, INACTIVE, DISABLED and DELETED. Filtering by another value returns an empty page.
Exports
GET /api/audit/events/export takes the same filters as the audit list and returns the whole filtered set as CSV, newest first. It is not paged. See Audit and evidence.
Worked example
Read operations for one account, page by page.
Illustrative example built from the schema.
GET /api/transactions?accountRef=ACC-000184-GBP&txType=TRANSFER&page=0&size=2 HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer eyJraWQiOiJ...
API-Version: 1.0.0HTTP/1.1 200 OK
Content-Type: application/json
{
"content": [
{
"transactionId": "6a2e9c14-8b37-4f0d-a5c1-3e7b9d2f4a80",
"txType": "TRANSFER",
"assetId": "GBP",
"accountRef": "ACC-000184-GBP",
"customerRef": "CUST-000184",
"counterpartyRef": "ACC-000207-GBP",
"amount": "250.00",
"params": {},
"state": "CONFIRMED",
"txHash": "0x9f2c1d5e4b8a37c06d1e5f9a2b4c7d8e0f1a2b3c4d5e6f708192a3b4c5d6e7f8",
"blockNumber": 18446744,
"createdAt": "2026-08-06T10:02:41.310Z",
"updatedAt": "2026-08-06T10:03:05.877Z"
},
{
"transactionId": "1d8f5b30-2c64-4e9a-b7f2-0a4c6e8d1b95",
"txType": "TRANSFER",
"assetId": "GBP",
"accountRef": "ACC-000184-GBP",
"customerRef": "CUST-000184",
"counterpartyRef": "ACC-000311-GBP",
"amount": "75.20",
"params": {},
"state": "SUBMITTED",
"txHash": "0x4b7e2a9c1f3d58e06a2c4b8d9e0f1a3b5c7d9e2f4a6b8c0d1e3f5a7b9c2d4e6f",
"createdAt": "2026-08-06T09:58:12.004Z",
"updatedAt": "2026-08-06T09:58:40.512Z"
}
],
"page": 0,
"size": 2,
"totalElements": 7,
"totalPages": 4
}Read the next page with page=1, and stop after page=3.
Read delivery history with a cursor:
GET /api/webhook-events?status=PARKED&limit=20 HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer eyJraWQiOiJ...
API-Version: 1.0.0The response carries nextCursor. Send it back unchanged, with the same filters:
GET /api/webhook-events?status=PARKED&limit=20&cursor=eyJrIjpbIjIwMjYtMDgtMjhUMDk6MTU6MTFaIiwiMDE5OGMyZjctYWFkZC04ZmNjLWUwYTEtM2M0ZDVlNmY3YThiIl0sImYiOiI3YTJmOWMxNCJ9 HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer eyJraWQiOiJ...
API-Version: 1.0.0View in API Reference
Errors and edge cases
| Situation | Response |
|---|---|
Negative page | 400 on style A endpoints. |
size outside 1 to 100 on customers, accounts, contracts, transactions, breaks | 400, not reduced. |
limit outside 1 to 100 on cursor endpoints | 400, not reduced. |
| Unknown or altered cursor, or cursor reused with different filters | 400. Restart from the first page. |
Unknown sort property | 400 on audit search, 500 on identity lists. |
| Inverted time range | 400 on audit, breaks, approvals and delivery history. |
API Reference
Open an endpoint for request fields, response examples and the interactive API console.
Related pages
Updated 4 days ago

