Skip to main content

Pagination

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
}
FieldTypeDescription
objectstringAlways "list".
urlstringThe URL for this list endpoint.
dataarrayThe page of results, sorted by creation date descending (newest first).
has_morebooleantrue if there are more results after this page.

Pagination parameters

ParameterTypeDescription
limitintegerNumber of results per page. Range: 1-100. Default: 10.
starting_afterstringFetch results after this payment ID (forward pagination).
ending_beforestringFetch results before this payment ID (backward pagination).
Do not use starting_after and ending_before in the same request.

Forward pagination (next page)

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"

Backward pagination (previous page)

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.