Pagination
Cursor pagination on every listing that can grow without bound.
Three listings take a cursor: GET /posts, GET /projects/{id}/radar/inspirations and GET /projects/{id}/reports/performance. Every other listing has a fixed ceiling, by business rule or by plan, and needs no cursor.
GET /projects/{id}/reports/performance is the one with TWO cursors, and it is not a quirk: it answers two independent lists, a ranking by views and a list waiting to be measured, ordered by different columns. One cursor would compare the key of one ordering against the column of the other and return the wrong rows without erroring. So it takes cursorMeasured and cursorWithoutMetrics, answers nextMeasured and nextWithoutMetrics, and paging one does not disturb the other.
The cursor is opaque. Do not read one or build one: pass back in cursor exactly what came in the next field of the previous response. When next comes back null, the pages are over.
curl -H "Authorization: Bearer ptr_live_..." \
"https://api.posttar.com/v1/posts?limit=2&cursor=eyJrZXkiOiIyMDI2LTA5LTEzVDA1OjE4OjA2LjkxOD..."A malformed cursor is refused with invalid_input. It never silently falls back to page one, which would make a while (next) loop spin forever on the same rows.