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
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/v1/posts | Optional | List posts with filters and pagination |
GET | /api/v1/posts/authors/:id | Public | Get author profile |
GET | /api/v1/posts/:slug | Optional | Read one post by slug |
GET | /api/v1/posts/id/:id | Optional | Read one post by id |
POST | /api/v1/posts | Session + writer role | Create a post |
PUT | /api/v1/posts/:id | Session + owner/admin | Update a post |
DELETE | /api/v1/posts/:id | Session + owner/admin | Delete a post |
POST | /api/v1/posts/:id/publish | Session + owner/admin | Publish a draft |
POST | /api/v1/posts/:id/unpublish | Session + owner/admin | Return a post to draft |
POST | /api/v1/posts/:id/schedule | Session + owner/admin | Schedule a post |
POST | /api/v1/posts/:id/restore | Session + admin | Restore a soft-deleted post |
POST | /api/v1/posts/:id/featured-image | Session + owner/admin | Upload featured image |
DELETE | /api/v1/posts/:id/featured-image | Session + owner/admin | Delete featured image |
GET | /api/v1/posts/categories | Public | List categories |
POST | /api/v1/posts/categories | Session + admin | Create a category |
PUT | /api/v1/posts/categories/:id | Session + admin | Update a category |
DELETE | /api/v1/posts/categories/:id | Session + admin | Delete a category |
GET | /api/v1/posts/tags | Public | List tags |
POST | /api/v1/posts/tags | Session + admin | Create a tag |
PUT | /api/v1/posts/tags/:id | Session + admin | Update a tag |
DELETE | /api/v1/posts/tags/:id | Session + admin | Delete a tag |
GET | /api/v1/posts/:id/comments | Optional | List comments |
POST | /api/v1/posts/:id/comments | Conditional | Create a comment |
GET | /api/v1/posts/:id/reactions | Optional | Read reaction counts |
POST | /api/v1/posts/:id/reactions | Session | Add or toggle a reaction |
POST | /api/v1/posts/:id/bookmark | Session | Bookmark a post |
GET | /api/v1/posts/me/bookmarks | Session | List bookmarks |
POST | /api/v1/posts/:id/view | Public | Track a view |
GET | /api/v1/posts/:id/stats | Optional | Read aggregated stats |
GET | /api/v1/posts/seo/sitemap.xml | Public | Generate 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:
pagelimitsortorderstatusvisibilitycategorytagauthorqlang
Example response:
{
"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:
titleslugbodybody_formatvisibility
Optional body fields:
excerptcomments_enabledreactions_enabledscheduled_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 /api/v1/posts/:id/featured-image
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:
{
"data": {},
"user_context": {
"authenticated": true
},
"meta": {}
}Why that matters
dataholds the useful payload.user_contextexplains how the response was interpreted for the current viewer.metacarries pagination and query information.
Example: list posts
GET /api/v1/posts?page=1&limit=10&sort=created_at&order=descExample response:
{
"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
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:
{
"data": {
"id": "post_2",
"slug": "why-modular-docs-matter",
"status": "draft"
},
"user_context": {
"authenticated": true,
"user_type": "writer"
},
"meta": {
"cached": false
}
}Typical flow
- List posts publicly.
- Create or edit a post as an authenticated writer.
- Publish or schedule the post.
- Allow comments and reactions if enabled.
- 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.