Pagination
Cursor pagination with limit and starting_after, used by every list endpoint.
List endpoints page the same way: limit and starting_after, returning has_more and next_cursor.
That is the envelope a stock OpenAI client already understands, so GET /v1/models, GET /v1/files,
GET /v1/batches, and GET /v1/limits all share it.
GET /v1/usage/entities is not a list. It returns one totals object, plus groups
when you ask for them. GET /v1/requests/{request_id} is a retrieve, not a list.
The cursor envelope
{
"object": "list",
"data": [{ "id": "batch_5Rj8Lm2Q" }, { "id": "batch_4Qh7Kp1P" }],
"has_more": true,
"next_cursor": "batch_4Qh7Kp1P"
}Prop
Type
Results are newest first. Keep requesting while has_more is true, passing the previous
next_cursor as starting_after. Offsets aren't supported, because the list grows while you're
reading it and page 3 would quietly shift under you.
# First page
curl -G https://REGION.api.lararouter.com/v1/batches \
-H "Authorization: Bearer $LARAROUTER_API_KEY" \
-d "limit=100"
# Next page, using next_cursor from the response above
curl -G https://REGION.api.lararouter.com/v1/batches \
-H "Authorization: Bearer $LARAROUTER_API_KEY" \
-d "limit=100" \
-d "starting_after=batch_4Qh7Kp1P"Exporting rather than paging
If you're walking every job to build a report, check whether
GET /v1/usage/entities can answer the question directly. It aggregates
server-side, and format=csv streams the result in one request.
Cursors and retention
A cursor is an object ID, so it stays valid as long as the object does. Paging slowly through a month
of batches on Pay-as-you-go is fine; resuming with a cursor from 91 days ago is not, and returns
404.