Skip to content

Public changelog

rollout doesn’t host a changelog page. Instead it serves your published announcements as a public, cacheable API that you render on your own site, in your own design, plus RSS and JSON Feed for feed readers.

  1. Open Settings → Changelog in the dashboard.
  2. Enter your Changelog page: the URL where you show it, e.g. https://example.com/changelog. Feed items link there (https://example.com/changelog#ann_…).
  3. Switch the changelog on.

It lists announcements whose Public changelog channel is on and that aren’t targeted, newest first. While it’s off, every endpoint answers 404.

No key or identity is needed. {slug} is your project’s slug.

Endpoint Format
GET /v1/changelogs/{slug} JSON, paginated (limit 1–50, cursor).
GET /v1/changelogs/{slug}/announcements/{id} One entry as JSON.
GET /v1/changelogs/{slug}/rss.xml RSS 2.0, latest 50.
GET /v1/changelogs/{slug}/feed.json JSON Feed 1.1, latest 50.
{
"project": { "name": "Acme", "slug": "acme", "url": "https://example.com/changelog" },
"announcements": [
{
"id": "ann_…",
"title": "Spring release",
"publishedAt": "2026-03-04T09:00:00.000Z",
"image": { "url": "…", "thumbnailUrl": "…", "alt": "", "width": 1920, "height": 1080 },
"tags": ["new", "fixed"],
"html": "<div class=\"rollout-intro\">…</div>…",
"markdown": "…",
"text": "…"
}
],
"nextCursor": null
}

Pass nextCursor as cursor for the next page. html excludes the title, so you can render it as you like; markdown and text carry the same body.

const res = await fetch('https://api.rollout.so/v1/changelogs/acme')
const { announcements } = await res.json()
for (const a of announcements) {
render(`<article id="${a.id}"><h2>${a.title}</h2>${a.html}</article>`)
}

Fetch it at build time for a static site, or on request with your framework’s cache.

Responses carry Cache-Control: public, max-age=60, stale-while-revalidate=60 and an ETag, and allow any origin (Access-Control-Allow-Origin: *). A published or updated announcement shows up within about a minute.