Overview
Postnomic provides unauthenticated public endpoints for accessing published blog content. These endpoints are served by the PublicBlogsController, PublicPostsController, and PublicAnalyticsController and do not require JWT or API Key authentication.
Public endpoints are ideal for:
- Building custom frontends that display blog content
- Static site generators that fetch content at build time
- Third-party integrations that need read-only access
The API is mounted at the root of its host — there is no
/apipath prefix. Public routes begin with/public/.
Blog Information
Get Blog Info
Retrieve public information about a blog by its slug.
curl -X GET https://api.postnomic.com/public/blogs/my-dev-blog
Response:
{
"name": "My Dev Blog",
"slug": "my-dev-blog",
"description": "A blog about software development",
"defaultLayout": "Default",
"showBranding": true
}
Get Tags, Categories, and Authors
curl -X GET https://api.postnomic.com/public/blogs/my-dev-blog/tags
curl -X GET https://api.postnomic.com/public/blogs/my-dev-blog/categories
curl -X GET https://api.postnomic.com/public/blogs/my-dev-blog/authors
curl -X GET https://api.postnomic.com/public/blogs/my-dev-blog/authors/jane-developer
Tags and categories are returned as objects with name, slug, and postCount:
[
{ "name": "Docker", "slug": "docker", "postCount": 7 },
{ "name": "DevOps", "slug": "devops", "postCount": 12 }
]
The tag list is capped at the blog's configured sidebar tag limit (most-used first, then sorted alphabetically). Pass ?limit=0 for the full list.
Posts
List Published Posts
Retrieve a paginated list of published posts for a blog.
curl -X GET "https://api.postnomic.com/public/blogs/my-dev-blog/posts?page=1&pageSize=10"
Response:
{
"items": [
{
"slug": "getting-started-with-docker",
"title": "Getting Started with Docker",
"excerpt": "Learn the fundamentals of containerization...",
"thumbnailImageUrl": "/media/blob/blog-media/my-dev-blog/docker-thumb.jpg",
"authorName": "Jane Developer",
"authorSlug": "jane-developer",
"publishedAt": "2026-03-01T10:00:00Z",
"commentCount": 4,
"language": "en",
"availableLanguages": ["en", "de"],
"tags": [
{ "name": "Docker", "slug": "docker", "postCount": 7 }
],
"categories": [
{ "name": "Tutorials", "slug": "tutorials", "postCount": 21 }
]
}
],
"page": 1,
"pageSize": 10,
"totalCount": 42,
"totalPages": 5
}
Get Post by Slug
Retrieve the full content of a specific published post. Approved comments are embedded in this response — there is no separate public comments endpoint.
curl -X GET https://api.postnomic.com/public/blogs/my-dev-blog/posts/getting-started-with-docker
Response:
{
"slug": "getting-started-with-docker",
"title": "Getting Started with Docker",
"content": "<h2>Introduction</h2><p>Docker is a platform for...</p>",
"excerpt": "Learn the fundamentals of containerization...",
"canonicalUrl": "https://example.com/blog/post/getting-started-with-docker",
"coverImageUrl": "/media/blob/blog-media/my-dev-blog/docker-cover.jpg",
"authorName": "Jane Developer",
"authorSlug": "jane-developer",
"publishedAt": "2026-03-01T10:00:00Z",
"language": "en",
"availableLanguages": ["en", "de"],
"commentsEnabled": true,
"commentRequireModeration": true,
"commentRequireFirstname": true,
"commentRequireLastname": false,
"commentRequireEmail": true,
"commentRequirePhone": false,
"commentRequireSubject": false,
"tags": [
{ "name": "Docker", "slug": "docker", "postCount": 7 }
],
"categories": [
{ "name": "Tutorials", "slug": "tutorials", "postCount": 21 }
],
"comments": [
{
"publicId": "d4e5f6a7-b8c9-0123-def4-56789012345a",
"subject": "Great intro",
"body": "This cleared up a lot for me, thanks.",
"authorName": "Sam Reader",
"createdAt": "2026-03-02T08:15:00Z",
"replies": []
}
]
}
Comments are nested: each comment carries its own replies collection.
Query Parameters
The post list accepts the following query parameters:
| Parameter | Type | Default | Notes |
|---|---|---|---|
page |
int | 1 |
Page number. |
pageSize |
int | 5 |
Values below 1 fall back to 5; values above 50 are capped at 50. |
tag |
string | — | Filter by tag slug. |
category |
string | — | Filter by category slug. |
author |
string | — | Filter by the author's full name ("Firstname Lastname"), matched exactly. Note this is the name, not the authorSlug returned on each post. |
search |
string | — | Substring match against post title, excerpt, and content. |
lang |
string | — | Requested language (ISO-639-1). |
# Filter by category
curl -X GET "https://api.postnomic.com/public/blogs/my-dev-blog/posts?category=tutorials"
# Filter by tag
curl -X GET "https://api.postnomic.com/public/blogs/my-dev-blog/posts?tag=docker"
# Filter by author (full name)
curl -X GET "https://api.postnomic.com/public/blogs/my-dev-blog/posts?author=Jane%20Developer"
# Search
curl -X GET "https://api.postnomic.com/public/blogs/my-dev-blog/posts?search=containers"
# Request German content
curl -X GET "https://api.postnomic.com/public/blogs/my-dev-blog/posts?lang=de"
lang is also accepted on the post detail endpoint. When no lang is given, the Accept-Language header is used; if neither resolves to an available translation, the blog's default language is served. A missing translation falls back to the default language rather than returning 404. The language field on the response reports the language actually served.
Popular Posts
curl -X GET "https://api.postnomic.com/public/blogs/my-dev-blog/posts/top-commented?count=3"
curl -X GET "https://api.postnomic.com/public/blogs/my-dev-blog/posts/most-read?count=3"
Both return a list of { "slug", "title", "count" } objects.
Comments
Submit a Comment
curl -X POST https://api.postnomic.com/public/blogs/my-dev-blog/posts/getting-started-with-docker/comments \
-H "Content-Type: application/json" \
-d '{ "authorFirstname": "Sam", "authorEmail": "sam@example.com", "body": "Nice write-up." }'
Which fields are mandatory depends on the blog's comment settings, which the post detail response exposes as the commentRequire* flags. If the blog requires moderation, the comment is created as Pending and is not returned by public reads until it is approved.
Analytics
The public analytics endpoints are write-only. They record visitor activity; they do not read view counts back.
# Record a page view
curl -X POST https://api.postnomic.com/public/blogs/my-dev-blog/analytics/pageview \
-H "Content-Type: application/json" \
-d '{ "sessionId": "5f2c...", "postSlug": "getting-started-with-docker" }'
A PATCH on the same path updates the recorded read duration for a session. View counts are read through the authenticated analytics endpoints in the dashboard.
Response Format
All public endpoints return JSON responses with consistent field naming:
- Posts, blogs, tags, and categories are addressed by
slug— public responses do not exposepublicId(comments are the exception; a comment'spublicIdis needed to reply to it) - Dates are formatted in ISO 8601 UTC (e.g.,
2026-03-01T10:00:00Z) - Image URLs are relative paths through the blob proxy (e.g.,
/media/blob/blog-media/...), which you resolve against the API base address - Pagination uses
page,pageSize,totalCount, andtotalPagesfields alongsideitems
Published Content Only
Public endpoints return only posts in the Published status. Drafts, scheduled, unpublished, and archived posts are not reachable through them. Posts cross-posted to a blog are included alongside the blog's own posts.