Request
Passpage (1-indexed) and optionally per_page (defaults to 20 for posts and media, 50 for profiles; capped at 100):
Response shape
Paginated responses includemeta and links objects alongside data:
- Stop iterating when
meta.current_pageequalsmeta.last_page(or whenlinks.nextisnull). meta.totalis the total count across all pages, useful for “X of Y” UI counters.- The posts list adds
meta.status_counts: the number of posts per status (waiting,publishing,published,failed,needs_approval,draft) for the current filters, independent of the page you are on.
Iterating in code
Sensible per_page values
Do not go above 100. It is the hard cap on every list endpoint, and the request fails validation with
422 if you exceed it.
Ordering
Posts are ordered by their planned publish time (scheduled_for), earliest first. There is one exception: when published is the only status you filter on, the default is the actual publish time (published_at), newest first.
filters[sort_by] replaces the default order:
Any other value is
422.
Profiles accept a sort parameter: name, -name, created_at, or -created_at (a leading - means descending). The default is created_at, oldest first.
Media is returned in the same order the dashboard’s library shows it.
Filtering by date
Pagination is stable as long as nothing is inserted ahead of your cursor mid-iteration. For long-running exports of posts, narrow the set withfilters[publish_range][] (planned publish time) or filters[date_range][] (actual publish time) so the result set does not shift under you.
Each range takes exactly two YYYY-MM-DD dates, the first and the last day to include. The -g flag stops curl from treating the brackets as a pattern:
scheduled_for, which ignores the account’s timezone, these filters use it. Posts with no value in the filtered column are left out, so filters[date_range][] only ever returns published posts, and filters[publish_range][] leaves out posts that have no planned time yet. A range that is not exactly two YYYY-MM-DD dates is 422.