page is 1-based, defaults to 1
and has no upper bound. page_size defaults to 25 and is capped at 200 — one default and
one ceiling, on GET /v1/blocks, GET /v1/properties, GET /v1/bookings,
GET /v1/listings/{listing_id}/reviews and GET /v1/webhooks/deliveries alike.
Send a page_size above the ceiling and the request is refused with validation_failed
naming the parameter — never silently clamped to 200, because a caller who believes they asked
for 500 and quietly received 200 stops walking a set they have not finished.
Keep asking for the next page while has_more is true. That is the entire loop:
A collection is items, paged or not
Every collection this API returns is called items, and a paged one carries has_more
beside it. That is the only difference: GET /v1/catalog/amenities and
GET /v1/listings/{listing_id}/calendar answer items too, and simply have no has_more,
because a reference catalogue and a date window are bounded by something other than a page.
If a field is called nights, it is a count — Block.nights is how many nights a block
holds — never a collection.
A page is a page number, and the list moves
Every paginated read here is newest first, and a page is a number rather than a cursor — so a row that lands while you are walking shifts everything behind it. On a long walk that means you can see a row twice, or miss one entirely. Two things make it a non-problem, and both are worth doing:- Key what you collect by its own id, not by its position. Every row carries one, and every one of them is stable.
- Narrow before you walk.
GET /v1/blockstakesfrom/to,GET /v1/bookingstakesstatus,listing_idand a check-in window, andGET /v1/webhooks/deliveriestakesstatusandevent_type. A set that cannot move while you page is the real fix.
There is no total, on purpose
The response tells you whether another page exists, not how many rows exist. Counting the whole set to answer one page is work neither side needs — and for a reconciliation read, “walk untilhas_more is false” is the correct loop anyway. If you need a count,
count as you walk.
Narrowing before paging
Where an endpoint offers filters —from/to on GET /v1/blocks bound the result to
blocks holding a night inside the window — prefer narrowing over walking the whole set.
A block whose check_out equals from holds no night in the window (departure day is
exclusive) and is not returned. Each page is bounded by the same filters, so the
has_more loop composes with them unchanged.