Paginate lists
Walk any list with a cursor. The SDKs fetch each page only as your loop needs it.
pagination-iterate.sh
# The next page: pass the previous page's nextCursor back, verbatim, as cursor, until hasMore is# false (nextCursor is present only while hasMore is true).curl "https://api.qbitflow.app/v2/payments?createdAfter=2026-10-01T00:00:00Z&limit=50&cursor=$NEXT_CURSOR" \ -H "X-API-Key: $QBITFLOW_API_KEY"# 200: a page of Payment ({ items, hasMore, nextCursor? })// Every payment of the last 30 days: the iterator fetches the pages one at a time, as the loop// consumes them, and stops when you break (or after the page whose hasMore is false).const since = new Date(Date.now() - 30 * 24 * 3600 * 1000);let count = 0;for await (const payment of client.payments.iterate({ createdAfter: since, limit: 50 })) { count++; console.log(payment.uuid, payment.amountUsd, 'USD');}console.log(`${count} payments over the last 30 days`);# Fetches one page at a time, only as the loop consumes it; break stops the fetching. It# stops after the page whose has_more is False.for payment in client. payments. iterate( limit=50): print(payment.uuid, payment.amount_usd, "USD")// Fetches one page at a time, only as the loop consumes it; break stops the fetching.// It stops after the page whose HasMore is false.count := 0for payment, err := range client.Payments.Iterate(ctx, &qbitflow. PaymentListParams{Limit: 50}) { if err != nil { log.Fatal(err) } count++ fmt.Println(payment.UUID, payment.AmountUSD, "USD")}fmt.Println(count, "payments")// The next page is fetched when the loop needs it; it stops after the page whose hasMore is false.$count = 0;foreach ($client->payments->iterate(new \QBitFlow\Params\PaymentListParams( limit: 50)) as $payment) { $count++; echo "{$payment->uuid} {$payment->amountUsd} USD\n";}echo "{$count} payments\n";Without an SDK
- Your code → QBitFlow API: GET the list, with limit
- QBitFlow API → Your code: items, hasMore: true, nextCursor: A
- Your code → QBitFlow API: The same list, cursor=A
- QBitFlow API → Your code: items, hasMore: true, nextCursor: B
- Your code → QBitFlow API: The same list, cursor=B
- QBitFlow API → Your code: The last items, hasMore: false
- Ask for the first page with
limitand nocursor. - Each page is
{ "items": [ … ], "hasMore": true, "nextCursor": "…" }. - Send
nextCursorback ascursor, verbatim. - Stop when
hasMoreisfalse(nextCursoris then absent). A full last page already answersfalse: no extra empty page.
The rules
limitis clamped, never refused. Absent or0: the default; above the maximum: the maximum. Alimitthat isn't an integer answers400 validation_failed.- No skips, no repeats on the newest-first lists of payments, bills and subscriptions
(
createdAt, thenuuid). Newer rows wait for the next walk. - A cursor belongs to its list. A cursor the API didn't give answers
400 validation_failedoncursor: start again. - Filters may change between pages; the cursor keeps its place.
- Dates (
createdAfter,createdBefore) are RFC 3339 instants or plain dates (midnight UTC), both bounds excluded. Encode a+offset as%2B.
Avoid
Poll for new payments
Polling burns your rate limits and still lags behind.
Do
Let webhooks tell you
Must poll? Overlap each window and deduplicate on
uuid.Page sizes
Every list takes the same limit: 20 by default, at most 100. A short catalog (currencies, your
wallets) answers its one page with hasMore: false, and ignores limit and cursor.