# List posts

> Every published post, newest first, with cursor paging and filters by content type and time.

Canonical: https://revnu.com/docs/content-posts
Last updated: 2026-11-07

```bash
curl -H "Authorization: Bearer $REVNU_CONTENT_API_KEY" \
  "https://revnu.com/api/content/v1/posts?limit=50"
```

## Query

| Param | Meaning |
|---|---|
| `type` | Filter by content type: a built-in such as `how_to`, or one of your own, such as `locations`. |
| `since` | Epoch milliseconds: only posts published or updated after this. |
| `limit` | Default 50, up to 200. |
| `cursor` | The `cursor` from the previous page. |

## Response

`{ "blog": {…}, "nav": […], "types": […], "posts": [summary, …], "cursor": "…" | null }`. Each summary carries `slug`, `title`, `contentType`, `type`, `format`, `slots`, `metaDescription`, `canonicalPath`, `canonicalUrl`, `heroImageUrl`, `readingMinutes`, `publishedAt` and `updatedAt`, which is everything a listing page or a sitemap needs. Keep requesting with the returned `cursor` until it is `null` to get every post.

The unfiltered list is the source of truth for what exists. A post that disappears from it was removed: drop its page and its sitemap entry. A `since` filter only returns changed posts, so it never tells you about removals.

Revnu counts your site as connected when it reads the first page of the unfiltered list. A site that only ever sends filtered requests is never counted: **I've Connected It** is refused, and its posts show as **Ready** in the dashboard. See [Before you click I've Connected It](https://revnu.com/docs/content-api.md).

`400` for a `type` that is neither a built-in nor one of yours, or a non-numeric `since` or `limit`.

## Your own content types

Revnu can write kinds of page beyond blog posts for your site: a page per town you serve, recipes, a page per industry. Ask the agent in chat and it creates a type with a key, a label and a path, such as `locations` at `/locations`. Each post of that type has `type` set to the key and a `canonicalPath` under that path (`/locations/leeds`), from the root of your site rather than under your blog's path. `contentType` stays the built-in it is written like, usually `blog`, so code that only knows the built-ins keeps working.

`types` lists your own types with `key`, `label`, `path` and `url`. To show one, add a route at its path that lists `?type=<key>` and renders each post from the [post endpoint](https://revnu.com/docs/content-post.md), the same way your blog does. A built-in can be moved the same way, for example comparisons to `/comparisons`; it then appears in `types` with `builtIn: true`.

### Page types: words for your own template

Some types are pages, not articles: a solutions page, an industry page, a page per town. Your site already has the template; Revnu only writes the words for its fields. A post of a page type has `format: "page"` and `slots`, an object keyed by your template's field names:

```json
{
  "format": "page",
  "type": "solutions",
  "slots": {
    "headline": "The AI SDR that books the meeting.",
    "subline": "Revnu finds buyers worth talking to, writes to each one in your voice, handles the replies and books the call.",
    "bullets": ["No list to build.", "No template.", "Every reply drafted for your yes."],
    "faq": [{ "question": "…", "answer": "…" }]
  }
}
```

A text field is a string, a list field an array of strings, and an FAQ field an array of `{question, answer}`. Point your template's fields at `slots` once; every new page of the type then fills it. A page already on your site has no `slots` until it is imported, so ask the agent to import the type's existing pages before your template reads them from Revnu. `body.markdown` still carries a plain copy of the words for anything that only reads articles. Ask the agent which fields a type has; it reads them from one of your pages, and uses your field names if you tell it yours.

If a type's path changes, its posts move with it: their `canonicalPath` changes, a `post.updated` event is sent for each live one, and your site should redirect the old addresses.

## Frequently asked questions

### How do I build a sitemap from this?

One entry per post: `canonicalUrl` as the location and `updatedAt` as the last-modified time, falling back to `publishedAt` when `updatedAt` is null. Refresh it on the same schedule as your listing page. [Render posts in Next.js or Astro](https://revnu.com/docs/host-your-blog.md) has both versions.

### How often should I poll?

With ISR or a revalidate window of a few minutes you never need to. Build-time frameworks should use the rebuild hook instead of polling; see [the Content API](https://revnu.com/docs/content-api.md).
