Skip to content

Pagination

List endpoints are cursor-paginated. Cursors are stable and efficient even over large datasets, and there is deliberately no total count.

Every list response has the same shape:

{
"object": "list",
"data": [ { "object": "reservation", "id": "resv_…" } ],
"has_more": true
}
  • data — the page of results.
  • has_moretrue if more results exist after this page.

There is no total_count: computing an exact total is expensive and race-prone on live data. Page until has_more is false.

Without updated_since, each list endpoint has a stable default sort (newest-first), with the resource id as a tie-breaker so the keyset cursor is total:

EndpointDefault order
GET /v1/reservationsby service_date descending, then id descending — the most recent service dates first.
GET /v1/guestsby created_at descending, then id descending — most recently created guests first.
GET /v1/reservations/{id}/eventsby created_at ascending, then id ascending — oldest event first (chronological).

Passing updated_since to /v1/reservations or /v1/guests changes the sort to (updated_at, id) ascending (see below), so a “changed since” feed reads oldest-change-first.

ParameterDescription
limitPage size. Default 20, maximum 100. (When you expand objects, the maximum is lowered.)
starting_afterA resource id (resv_… / gst_…). Returns the page of results after that object.
ending_beforeA resource id. Returns the page of results before that object.

Use the id of the last item in a page as starting_after to fetch the next page:

Terminal window
# First page
curl "https://api.useservice.app/v1/reservations?limit=20" \
-H "Authorization: Bearer $SERVICE_API_KEY"
# Next page — pass the last id you saw
curl "https://api.useservice.app/v1/reservations?limit=20&starting_after=resv_8xKQ2m4Vd0pErJ7sN1aZ9bQ" \
-H "Authorization: Bearer $SERVICE_API_KEY"

Keep going while has_more is true.

List endpoints accept filters alongside the pagination parameters (see the API reference for the full set per endpoint). A few matching rules worth knowing:

  • email (guests) is matched case-insensitively as an exact address — [email protected] and [email protected] return the same guest.
  • phone (guests) is normalized to E.164 before matching, using the restaurant’s country. Pass the number however the guest gave it (local or international); it is canonicalized before the lookup.
  • query (guests) is an accent-insensitive substring match over first name, last name, and email.

Filters combine with AND. An unknown filter value (for example an unknown status or a malformed date) returns a 400 with the offending param — see Errors.

To keep a local copy in sync without re-reading everything, pass updated_since (an ISO-8601 timestamp) to GET /v1/reservations or GET /v1/guests. You get back only records changed at or after that time, sorted by (updated_at, id) ascending. Combine it with cursor pagination as usual:

Terminal window
curl "https://api.useservice.app/v1/reservations?updated_since=2026-06-27T00:00:00Z&limit=100" \
-H "Authorization: Bearer $SERVICE_API_KEY"

On the next sync, use the most recent updated_at you have seen as the new updated_since.