---
title: "List recent posts"
method: GET
path: "/posts"
---

# List recent posts

`GET /posts`

## Request

- Base URL: `https://xpost.to/api/v1`
- URL: `https://xpost.to/api/v1/posts`
- Auth: HTTP bearer

Posts for the project, newest first, filterable by `status` and bounded by `limit`. Ask for what you want: `?status=pending_approval` answers "what is waiting on me?" on its own, and several may be named at once (`?status=pending_approval,scheduled`). The reply echoes `filter` — what actually applied — because a filter that matched everything and a filter that never reached the query look identical in the rows. Rows carry status (pending_approval, scheduled, processing, posted, partial, failed, rejected, draft). A `pending_approval` row also carries `approval_url` — its one-click approve/reject page. A `rejected` row carries `rejectionReason`: what the person actually objected to, which is what to fix before sending it again. `publishes` says what has to happen before a row goes out: `at_time` (`scheduledAt` is a slot somebody chose), `on_approval` (a person's yes, `scheduledAt: null`), or `now` (nothing — it is on its way). It is **null** on a parked row — a draft or a rejected one — because nothing is going to happen to those until somebody decides something; read `status`.

## Query parameters

- `status` string
- `limit` integer
- `from` string, date-time
- `to` string, date-time

## Response `200`

Post list

- object
  - `filter` object
    - `status` string[], nullable
    - `limit` integer
  - `data` object[]

## Other responses

- `400`: Unknown status, or a limit outside 1-100
- `401`: Missing or invalid API key
- `429`: Rate limited

---

[API](https://skmtc.dev/xpost/apis/xpost-api.md) · [All operations](https://skmtc.dev/xpost/apis/xpost-api/llms.txt) · [OpenAPI document](https://skmtc.dev/xpost/apis/xpost-api/revisions/9f570fcfed6d?raw)
