Skip to content
On this page

Blog API

The Blog API covers the modular content system used for posts, categories, tags, comments, reactions, bookmarks, views, translations, and SEO support.

This page is written to help developers understand the moving parts quickly, not just memorize endpoints.

How to read this page

Each route is documented like a normal operation page:

  • what it does
  • who can call it
  • the relevant request shape
  • a concrete response example

Base path

All routes live under /api/v1/posts.

What the API is for

  • Reading and listing posts
  • Creating and updating posts
  • Managing categories and tags
  • Handling comments and moderation
  • Tracking reactions, bookmarks, views, and stats
  • Supporting translations and SEO routes

Route map

MethodPathAuthPurpose
GET/api/v1/postsOptionalList posts with filters and pagination
GET/api/v1/posts/authors/:idPublicGet author profile
GET/api/v1/posts/:slugOptionalRead one post by slug
GET/api/v1/posts/id/:idOptionalRead one post by id
POST/api/v1/postsSession + writer roleCreate a post
PUT/api/v1/posts/:idSession + owner/adminUpdate a post
DELETE/api/v1/posts/:idSession + owner/adminDelete a post
POST/api/v1/posts/:id/publishSession + owner/adminPublish a draft
POST/api/v1/posts/:id/unpublishSession + owner/adminReturn a post to draft
POST/api/v1/posts/:id/scheduleSession + owner/adminSchedule a post
POST/api/v1/posts/:id/restoreSession + adminRestore a soft-deleted post
POST/api/v1/posts/:id/featured-imageSession + owner/adminUpload featured image
DELETE/api/v1/posts/:id/featured-imageSession + owner/adminDelete featured image
GET/api/v1/posts/categoriesPublicList categories
POST/api/v1/posts/categoriesSession + adminCreate a category
PUT/api/v1/posts/categories/:idSession + adminUpdate a category
DELETE/api/v1/posts/categories/:idSession + adminDelete a category
GET/api/v1/posts/tagsPublicList tags
POST/api/v1/posts/tagsSession + adminCreate a tag
PUT/api/v1/posts/tags/:idSession + adminUpdate a tag
DELETE/api/v1/posts/tags/:idSession + adminDelete a tag
GET/api/v1/posts/:id/commentsOptionalList comments
POST/api/v1/posts/:id/commentsConditionalCreate a comment
GET/api/v1/posts/:id/reactionsOptionalRead reaction counts
POST/api/v1/posts/:id/reactionsSessionAdd or toggle a reaction
POST/api/v1/posts/:id/bookmarkSessionBookmark a post
GET/api/v1/posts/me/bookmarksSessionList bookmarks
POST/api/v1/posts/:id/viewPublicTrack a view
GET/api/v1/posts/:id/statsOptionalRead aggregated stats
GET/api/v1/posts/seo/sitemap.xmlPublicGenerate the sitemap

Route details

Posts

GET /api/v1/posts/authors/:id

Get one public author profile by id.

Auth: public.

GET /api/v1/posts

List posts with pagination and filters.

Auth: optional.

Returns: a paginated list of posts.

Query params:

  • page
  • limit
  • sort
  • order
  • status
  • visibility
  • category
  • tag
  • author
  • q
  • lang

Example response:

json
{
  "data": [],
  "user_context": {
    "authenticated": false
  },
  "meta": {
    "page": 1,
    "limit": 10,
    "total": 0,
    "hasMore": false
  }
}

GET /api/v1/posts/:slug

Read one post by slug.

GET /api/v1/posts/id/:id

Read one post by id.

POST /api/v1/posts

Create a new post.

Auth: session + writer role.

Required body fields:

  • title
  • slug
  • body
  • body_format
  • visibility

Optional body fields:

  • excerpt
  • comments_enabled
  • reactions_enabled
  • scheduled_at

PUT /api/v1/posts/:id

Update an existing post.

Auth: session + owner/admin.

DELETE /api/v1/posts/:id

Delete a post.

Auth: session + owner/admin.

POST /api/v1/posts/:id/publish

Publish a draft post.

Auth: session + owner/admin.

POST /api/v1/posts/:id/unpublish

Return a published post to draft.

Auth: session + owner/admin.

POST /api/v1/posts/:id/schedule

Schedule a post for later publishing.

Auth: session + owner/admin.

POST /api/v1/posts/:id/restore

Restore a previously soft-deleted post.

Auth: session + admin.

POST /api/v1/posts/:id/featured-image

Upload featured image using multipart form-data.

Auth: session + owner/admin.

Delete the current featured image.

Auth: session + owner/admin.

Categories and tags

GET /api/v1/posts/categories

List categories.

Auth: public.

POST /api/v1/posts/categories

Create a category.

Auth: session + admin.

PUT /api/v1/posts/categories/:id

Update a category.

Auth: session + admin.

DELETE /api/v1/posts/categories/:id

Delete a category.

Auth: session + admin.

GET /api/v1/posts/tags

List tags.

Auth: public.

POST /api/v1/posts/tags

Create a tag.

Auth: session + admin.

PUT /api/v1/posts/tags/:id

Update a tag.

Auth: session + admin.

DELETE /api/v1/posts/tags/:id

Delete a tag.

Auth: session + admin.

Comments

GET /api/v1/posts/:id/comments

List comments for a post.

Auth: optional.

POST /api/v1/posts/:id/comments

Create a comment.

Auth: conditional.

PUT /api/v1/posts/:id/comments/:commentId

Update a comment.

Auth: session.

DELETE /api/v1/posts/:id/comments/:commentId

Delete a comment.

Auth: session.

POST /api/v1/posts/comments/:commentId/moderate

Moderate a comment.

Auth: session + moderator/admin.

Engagement

GET /api/v1/posts/:id/reactions

Read reaction counters for one post.

Auth: optional.

POST /api/v1/posts/:id/reactions

Add or toggle a reaction.

Auth: session.

POST /api/v1/posts/:id/bookmark

Bookmark a post.

Auth: session.

DELETE /api/v1/posts/:id/bookmark

Remove a bookmark.

Auth: session.

GET /api/v1/posts/me/bookmarks

List current user bookmarks.

Auth: session.

POST /api/v1/posts/:id/view

Track a view.

Auth: public.

GET /api/v1/posts/:id/stats

Read aggregated stats.

Auth: optional.

Translations and SEO

GET /api/v1/posts/id/:id/translations

List translations for a post.

Auth: optional.

POST /api/v1/posts/id/:id/translations

Create a translation.

Auth: session + writer role.

PUT /api/v1/posts/id/:id/translations/:lang

Update a translation.

Auth: session + owner/admin.

DELETE /api/v1/posts/id/:id/translations/:lang

Delete a translation.

Auth: session + owner/admin.

GET /api/v1/posts/seo/sitemap.xml

Generate the SEO sitemap.

Auth: public.

Response shape

Most blog routes use a consistent envelope:

json
{
  "data": {},
  "user_context": {
    "authenticated": true
  },
  "meta": {}
}

Why that matters

  • data holds the useful payload.
  • user_context explains how the response was interpreted for the current viewer.
  • meta carries pagination and query information.

Example: list posts

http
GET /api/v1/posts?page=1&limit=10&sort=created_at&order=desc

Example response:

json
{
  "data": [
    {
      "id": "post_1",
      "slug": "hello-world",
      "title": "Hello World",
      "body": "# Hello",
      "status": "published",
      "visibility": "public"
    }
  ],
  "user_context": {
    "authenticated": false
  },
  "meta": {
    "page": 1,
    "limit": 10,
    "total": 1,
    "hasMore": false
  }
}

Example: create a post

http
POST /api/v1/posts
Content-Type: application/json

{
  "title": "Why modular docs matter",
  "slug": "why-modular-docs-matter",
  "body": "# Why modular docs matter",
  "body_format": "markdown",
  "visibility": "public",
  "comments_enabled": true
}

Example response:

json
{
  "data": {
    "id": "post_2",
    "slug": "why-modular-docs-matter",
    "status": "draft"
  },
  "user_context": {
    "authenticated": true,
    "user_type": "writer"
  },
  "meta": {
    "cached": false
  }
}

Typical flow

  1. List posts publicly.
  2. Create or edit a post as an authenticated writer.
  3. Publish or schedule the post.
  4. Allow comments and reactions if enabled.
  5. Use stats and bookmarks for engagement.

Practical notes

  • The API is easiest to understand when you think in layers: content, moderation, engagement, and metadata.
  • Use the response envelope to keep frontend code predictable.
  • Treat publish and schedule as workflow actions, not just CRUD operations.

Next