Card 05/ 10
List Responses: Items, a Cursor and Links
A list response wraps its items with what the client needs to fetch the next page.
A list endpoint should return a JSON object holding an array of items, not a bare array, so the response can also carry what the client needs to fetch the next page, such as a cursor or a next link. The wrapper is what lets the list grow new fields later without breaking any client.
{
"items": [
{"id": "43", "status": "open"},
{"id": "42", "status": "paid"}
],
"nextCursor": "b3JkZXI6NDI",
"links": {"next": "/orders?cursor=b3JkZXI6NDI&limit=2"}
}Why not a bare array. [{"id":"43"},{"id":"42"}] is valid JSON, but there is nowhere to add a cursor or a total once clients depend on it. Turning it into an object later changes the type of the whole response and breaks every client.
A cursor is an opaque string the server gives the client to fetch the next page: GET /orders?cursor=b3JkZXI6NDI. It usually encodes the last item returned, so the next page starts after it even if new orders arrive meanwhile. The client must not take it apart; the server may change what it contains.
A next link is the cursor already built into a URL, so the client follows it without assembling parameters. When there is no next page, omit the field or send null, as the contract says.
Page size. Let the client ask for a size with a limit parameter, set a maximum, and use a default when none is given, such as 20. Return fewer items than asked for only at the end, or say so in the contract.
Totals cost. A total count is convenient but can be expensive on a large table. Offer it only if clients need it.
So wrap every list in an object, and give the client a cursor or link rather than a page number to compute.
← → move through sections and cards