Pagination
List endpoints return 25 records by default, up to 100, and page with an opaque cursor.
List envelope
Section titled “List envelope”{ "object": "list", "data": [ /* up to `limit` objects */ ], "has_more": true, "next_cursor": "MjAyNi0wNy0xOVQxMjowNDoxMS4wMDBa"}data— the resources, sorted bycreated_atdescending (newest first) on every paginated endpoint.has_more—truewhen more records exist beyond this page.next_cursor— an opaque string to pass ascursoron the next request. It isnullwheneverhas_moreisfalse.
Parameters
Section titled “Parameters”| Name | Type | Default | Notes |
|---|---|---|---|
limit | integer | 25 | Clamped to a maximum of 100. A value that is non-numeric, zero, or negative falls back to 25. |
cursor | string | null | The next_cursor from the previous page. |
Fetching pages
Section titled “Fetching pages”curl "https://app.nativpost.com/api/v1/content?limit=25" \ -H "Authorization: Bearer $NATIVPOST_API_KEY"Then follow the cursor:
curl "https://app.nativpost.com/api/v1/content?limit=25&cursor=MjAyNi0wNy0xOVQxMjowNDoxMS4wMDBa" \ -H "Authorization: Bearer $NATIVPOST_API_KEY"Continue until has_more is false.
The cursor is not an id
Section titled “The cursor is not an id”next_cursor encodes the created_at timestamp of the last record on the page, not its id. Treat it as opaque — read it from a response and hand it straight back. Do not construct one from a record id, and do not assume it stays a fixed length or format.
Because paging is by timestamp with a strict comparison, two records sharing an identical created_at on a page boundary can cause one to be skipped. This is rare in practice, and only affects records created in the same millisecond.
Invalid cursors are ignored, not rejected
Section titled “Invalid cursors are ignored, not rejected”A cursor that is malformed, truncated, or decodes to something that is not a date does not return an error. It is silently dropped and you get the first page back. There is no 400 for a bad cursor, and cursors do not expire — one saved a month ago still works, as long as you kept it verbatim.
The practical consequence: if a paging loop appears to restart from the top, suspect a corrupted cursor rather than a server error. Compare the first id of the new page against the previous page’s ids and stop if they repeat.
Filtering while paginating
Section titled “Filtering while paginating”Filters such as status on /content or asset_type on /media-library are independent of the cursor. Pass the same filter values on every request in the sequence — dropping one mid-loop silently widens the result set.
Which endpoints paginate
Section titled “Which endpoints paginate”Cursor pagination is supported on:
GET /api/v1/contentGET /api/v1/campaignsGET /api/v1/media-libraryGET /api/v1/templates
GET /api/v1/social-accounts and GET /api/v1/webhooks return the full set in one response. They use the same envelope for consistency, but always report has_more: false and next_cursor: null, and they ignore limit and cursor.