Public Blog API

Separate from the Sites/Posts/Tags management API above, every blog also exposes a small public, unauthenticated JSON API of its own — for building a custom frontend against a blog's published content, or wiring up view tracking from a custom theme.

These endpoints aren't nested under /sites/{siteId} and take no API key. The site is resolved from the request itself, the same way the HTML pages are: by the Host header for a managed subdomain, or by X-Site-Host / X-Forwarded-Prefix for your own domain. Call them against the blog's own domain, not writeinone.com.

List published posts

GET https://myblog.writeinone.com/en/posts?page=0&size=10&tag=intro&search=hello

Same filters as the management list posts endpoint (page, size capped at 100, tag, search), scoped to whichever site the domain resolves to, and implicitly filtered to published posts only.

{
  "content": [
    {
      "post": { "id": 1, "siteId": 42, "status": "PUBLISHED", "coverUrl": null, "viewCount": 12, "publishedAt": "2026-01-10T09:00:00Z", "scheduledAt": null, "createdAt": "...", "updatedAt": "..." },
      "translation": { "id": 1, "postId": 1, "siteId": 42, "lang": "en", "title": "Hello, world", "slug": "hello-world", "body": "# Hi\n\nFirst post.", "excerpt": "Intro", "createdAt": "...", "updatedAt": "..." },
      "tags": [{ "id": 5, "siteId": 42, "name": "intro", "createdAt": "..." }]
    }
  ],
  "page": 0,
  "size": 10,
  "totalElements": 1,
  "totalPages": 1
}

Unlike the management list endpoint, translation here is singular and carries the full translation — body included — since there's only ever one language per request and no owner-only content to hide.

Record a view

POST https://myblog.writeinone.com/en/posts/hello-world/event
{ "type": "view" }

Increments the post's view counter. Returns 204 No Content on success, 400 if type isn't "view" (the only event type currently supported), 404 if the slug doesn't resolve to a published post in that language.

This is what the default post page calls automatically when a reader opens a post; a custom frontend built against the list endpoint above needs to call it itself to keep view counts accurate.

Sitemap

GET https://myblog.writeinone.com/sitemap.xml

A standard XML sitemap listing the blog's home page, one entry per configured language (/en, /es), and one entry per published post in every language, each with a <lastmod> date. Draft and scheduled posts are never included. This is separate from the platform-level https://writeinone.com/sitemap.xml, which only lists writeinone.com itself.

RSS feed

GET https://myblog.writeinone.com/{lang}/rss.xml
GET https://myblog.writeinone.com/rss.xml

An RSS 2.0 feed of the 20 most recent published posts in {lang} (en or es), title and description taken from that language's site config, falling back to the site's name and description. /rss.xml without a language prefix serves the site's default language's feed (the first entry in the site's configured languages). Each item's <guid> is its permalink, and posts with a cover image get an <enclosure> tag.