The Flowlix API uses cursor-based pagination for list endpoints. This approach is more reliable than offset-based pagination because it handles concurrent inserts and deletions gracefully.
How it works
List endpoints (like GET /v1/payments) return a page of results along with a has_more boolean. To fetch the next page, pass the id of the last item as the starting_after cursor.
Response structure
{
"object": "list",
"url": "/v1/payments",
"data": [
{ "id": "pay_3...", ... },
{ "id": "pay_2...", ... },
{ "id": "pay_1...", ... }
],
"has_more": true
}
| Field | Type | Description |
|---|
object | string | Always "list". |
url | string | The URL for this list endpoint. |
data | array | The page of results, sorted by creation date descending (newest first). |
has_more | boolean | true if there are more results after this page. |
| Parameter | Type | Description |
|---|
limit | integer | Number of results per page. Range: 1-100. Default: 10. |
starting_after | string | Fetch results after this payment ID (forward pagination). |
ending_before | string | Fetch results before this payment ID (backward pagination). |
Do not use starting_after and ending_before in the same request.
To get the next page, pass the id of the last item in the current data array:
# First page
curl "https://api.flowlix.eu/v1/payments?limit=10" \
-H "Authorization: Bearer fl_test_sk_abc123"
# Second page (pay_1... was the last item on the first page)
curl "https://api.flowlix.eu/v1/payments?limit=10&starting_after=pay_1abc" \
-H "Authorization: Bearer fl_test_sk_abc123"
To get the previous page, pass the id of the first item in the current data array:
# Go back to the previous page (pay_3... was the first item on the current page)
curl "https://api.flowlix.eu/v1/payments?limit=10&ending_before=pay_3xyz" \
-H "Authorization: Bearer fl_test_sk_abc123"
Iterating through all results
Here is a complete example of paginating through all payments:
import requests
API_KEY = "fl_test_sk_abc123"
all_payments = []
cursor = None
while True:
params = {"limit": 100}
if cursor:
params["starting_after"] = cursor
response = requests.get(
"https://api.flowlix.eu/v1/payments",
headers={"Authorization": f"Bearer {API_KEY}"},
params=params,
)
page = response.json()
all_payments.extend(page["data"])
if not page["has_more"]:
break
cursor = page["data"][-1]["id"]
print(f"Fetched {len(all_payments)} payments")
const API_KEY = "fl_test_sk_abc123";
const allPayments = [];
let cursor = null;
while (true) {
const params = new URLSearchParams({ limit: "100" });
if (cursor) params.set("starting_after", cursor);
const response = await fetch(
`https://api.flowlix.eu/v1/payments?${params}`,
{ headers: { Authorization: `Bearer ${API_KEY}` } }
);
const page = await response.json();
allPayments.push(...page.data);
if (!page.has_more) break;
cursor = page.data[page.data.length - 1].id;
}
console.log(`Fetched ${allPayments.length} payments`);
Combining with filters
You can combine pagination with filters. Filters apply to the full result set before pagination:
# Page through succeeded payments from June 2026
curl "https://api.flowlix.eu/v1/payments?status=succeeded&created[gte]=1717200000&created[lt]=1719792000&limit=25" \
-H "Authorization: Bearer fl_test_sk_abc123"
Tips
- Use the largest
limit you can (up to 100) to reduce the number of API calls.
- Do not assume page sizes — the actual number of results may be less than
limit even when has_more is true.
- Store cursors, not offsets — cursor-based pagination is stable under concurrent inserts and deletions.
- Check
has_more instead of checking data.length < limit to determine if there are more pages.