Pagination & filtering
The three list conventions the Fungies API uses, plus sorting and archived-record semantics.
List endpoints don't all paginate the same way. The Fungies API ships three conventions, and which one an endpoint uses depends on the resource. Check this page before you write a paging loop.
The array of results is keyed by the resource name, not a generic items — data.orders,
data.products, data.subscriptions, and so on. The exact key for each endpoint is in its
reference page.
1. Offset pagination — skip / take
The most common convention. Pass skip (how many records to step over) and take (page size).
| Endpoint | Result key |
|---|---|
GET /v0/orders/list | orders |
GET /v0/payments/list | payments |
GET /v0/products/list | products |
GET /v0/offers/list | offers |
GET /v0/discounts/list | discounts |
GET /v0/elements/checkout/list | checkoutElements |
GET /v0/webhooks/{webhookId}/attempts | attempts |
curl "https://api.fungies.io/v0/orders/list?skip=0&take=20&returnCount=true" \
-H "x-fngs-public-key: pub_your_public_key"{
"status": "success",
"data": {
"orders": [{ "object": "order", "id": "550e8400-e29b-41d4-a716-446655440000" }],
"count": 143
}
}take has a default and a cap
On orders, payments, products, and offers, take defaults to 20 and is capped at
100. GET /v0/elements/checkout/list and GET /v0/webhooks/{webhookId}/attempts default to 10,
also capped at 100.
Omitting take gives you 20 records, not the whole result set — and nothing in the response says
so, since count is null unless you ask for it. If you are exporting or reconciling, always page
explicitly.
Asking for more than the cap is not an error: take=500 returns the first 100 records with a 200.
Because the response looks like any other full page, a loop that assumes it received 500 rows will
skip the ones in between — step skip by the number of records you actually got back, not by the
number you asked for. A take below 1 is raised to 1.
count is opt-in
On orders, payments, products, offers, and discounts, count is null unless you pass
returnCount=true. Counting is a second query, so it's off by default. If you're driving a
"page 3 of 8" UI, ask for it; if you're just walking pages, don't.
GET /v0/elements/checkout/list and GET /v0/webhooks/{webhookId}/attempts don't take
returnCount — they always return a count.
Without a count, page until a response comes back with fewer records than you asked for:
const take = 100;
let skip = 0;
for (;;) {
const url = `https://api.fungies.io/v0/orders/list?skip=${skip}&take=${take}`;
const { data } = await get(url);
yield* data.orders;
if (data.orders.length < take) break;
skip += take;
}2. Page pagination — page / limit
Used by the user endpoints. page is 1-based, and the count is always returned, together with
the total number of pages.
| Endpoint | Result key |
|---|---|
GET /v0/users/list | users |
GET /v0/users/{userId}/inventory | inventory |
curl "https://api.fungies.io/v0/users/list?page=1&limit=25" \
-H "x-fngs-public-key: pub_your_public_key"{
"status": "success",
"data": {
"users": [{ "object": "user", "id": "550e8400-e29b-41d4-a716-446655440000" }],
"count": 143,
"pages": 6
}
}Stop when page reaches pages.
3. Cursor pagination — cursor / take
Only GET /v0/subscriptions/list. Pass take (1–100, default 10) and, from the second page on,
the cursor returned by the previous response.
{
"status": "success",
"data": {
"subscriptions": [{ "object": "subscription", "id": "550e8400-e29b-41d4-a716-446655440000" }],
"count": 10,
"cursor": "c3Vic2NyaXB0aW9uXzEyMw",
"hasMore": true
}
}Loop on hasMore, not on count — count is a total where one is available, and it can be
null.
let cursor;
for (;;) {
const query = new URLSearchParams({ take: "50", ...(cursor ? { cursor } : {}) });
const { data } = await get(`https://api.fungies.io/v0/subscriptions/list?${query}`);
yield* data.subscriptions;
if (!data.hasMore || !data.cursor) break;
cursor = data.cursor;
}GET /v0/webhooks/list is not paginated at all — it returns every webhook on the workspace in one
response.
Sorting
Most offset-paginated endpoints accept orderDirection:
ASC— ascending (oldest or lowest first)DESC— descending (newest or highest first)
The resource lists also accept orderBy to choose the field. Accepted values differ per resource,
and a few endpoints (such as GET /v0/elements/checkout/list) have a fixed order and take neither
parameter — check the endpoint's reference page.
Sort order is not a stable snapshot. Records created while you're paging can shift rows between
pages. For a consistent export, pin a window with the endpoint's createdFrom / createdTo
filters.
Archived records
Archiving is a soft delete — the record stays readable but drops out of normal listings. Two independent flags give you three behaviours:
| Query | Returns |
|---|---|
| (neither flag) | Active records only — the default. |
archived=true | Only archived records. |
withArchived=true | Active and archived records together. |
archived=true is not "include archived" — it is "archived only". If you want both, use
withArchived=true. When both flags are sent, archived=true wins and you get archived records
only.
This is also why a GET by id can return 404 right after you archive something: the record still
exists, but the default read excludes it.
Filtering
Filters are per-resource query parameters — status, currency, country, date windows, custom fields, and more. They combine with AND. See each endpoint's reference page for the full list.
Two things catch people out on order, payment, and subscription filters:
- Numbers are matched verbatim. The dashboard shows a leading
#; it is not part of the stored value. SendL8VQK3N2M7KpQ9nR, not#L8VQK3N2M7KpQ9nR, or the filter returns no rows. - Money is in the smallest currency unit.
valueFrom=1000means 10.00 USD, and ¥1000 in JPY.
Last updated