Pagination
How EPD list endpoints page through results — and how to walk every page safely.
What this is and who needs it
Any list endpoint — customers, orders, transactions, subscriptions — returns at most a single page of results. To see the rest you have to ask for the next page. EPD uses cursor pagination, which is stable even when new records are being added in real time.
If you build dashboards, run exports, or sync EPD data into your warehouse, you need this page.
Request parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 10 | Page size, between 1 and 100. |
starting_after | string | — | Cursor of the last item on the previous page; returns items after it. |
ending_before | string | — | Cursor of the first item on the next page; returns items before it. |
Send starting_after or ending_before, never both.
Response shape
{
"object": "list",
"data": [
/* up to `limit` items */
],
"has_more": true,
"url": "/v1/customers",
"total_count": 1247,
"cursors": {
"next": "550e8400-e29b-41d4-a716-446655440000",
"previous": null
}
}
| Field | Description |
|---|---|
object | Always "list". |
data | Array of resources for this page. |
has_more | true if more results exist beyond this page in the current direction. |
url | Endpoint path that produced this response. |
total_count | Total matching rows. Returned when feasible — do not assume it is always present. |
cursors.next | Pass as starting_after to fetch the next page. null on the last page. |
cursors.previous | Pass as ending_before to fetch the previous page. null on the first page. |
Walking every page
let cursor;
do {
const url = new URL("https://api.epd.com/v1/customers");
url.searchParams.set("limit", "100");
if (cursor) url.searchParams.set("starting_after", cursor);
const res = await fetch(url, {
headers: {
Authorization: `Bearer ${process.env.EPD_KEY}`,
"epd-version": "2026-02-11",
},
});
const page = await res.json();
for (const customer of page.data) {
// process
}
cursor = page.has_more ? page.cursors.next : undefined;
} while (cursor);
import os, requests
cursor = None
while True:
params = {"limit": 100}
if cursor:
params["starting_after"] = cursor
r = requests.get(
"https://api.epd.com/v1/customers",
params=params,
headers={
"Authorization": f"Bearer {os.environ['EPD_KEY']}",
"epd-version": "2026-02-11",
},
)
page = r.json()
for customer in page["data"]:
# process
...
if not page["has_more"]:
break
cursor = page["cursors"]["next"]
Cursor values are the id of the last (or first) item in the page — UUIDs today. Treat them as opaque: do not parse them, do not assume the format will stay this way, and do not persist them past the lifetime of one walk.
For exports, prefer limit=100 to minimize round-trips. For interactive UIs, prefer limit=20 and let the user pull more.