ghost-content-api
Ghost Content API
Overview
The Ghost Content API provides read-only access to published content on a Ghost site. It is designed for public consumption in browsers, static site generators, and headless CMS frontends. All requests are GET-only, fully cacheable, and authenticated via a simple query parameter key.
When to Use
- Fetching published posts, pages, tags, authors, tiers, or settings from Ghost
- Building headless frontends (Next.js, Nuxt, Gatsby, Eleventy, etc.) powered by Ghost
- Displaying Ghost content in external applications
- Implementing search, filtering, or content aggregation from Ghost data
Authentication
Content API keys are obtained from Ghost Admin > Settings > Integrations > Custom Integration.
GET https://{admin_domain}/ghost/api/content/{resource}/?key={content_api_key}
- Keys are safe for public/browser use (read-only access)
- Regeneratable anytime from Ghost Admin
- Include
Accept-Version: v5.0header for API version targeting
Base URL: https://{admin_domain}/ghost/api/content/
Note: The admin domain may differ from the site domain. Ghost(Pro) sites use *.ghost.io.
JavaScript SDK (@tryghost/content-api)
Installation
npm install @tryghost/content-api
# or
yarn add @tryghost/content-api
Initialization
import GhostContentAPI from '@tryghost/content-api';
const api = new GhostContentAPI({
url: 'https://demo.ghost.io',
key: '22444f78447824223cefc48062',
version: 'v5.0'
});
Methods
All resources support browse() (list) and read() (single):
// Posts
const posts = await api.posts.browse({limit: 5, include: 'tags,authors'});
const post = await api.posts.read({slug: 'my-post'}, {formats: ['html']});
// Pages
const pages = await api.pages.browse({limit: 'all'});
const page = await api.pages.read({id: '5c7e...'});
// Authors
const authors = await api.authors.browse({page: 2});
const author = await api.authors.read({slug: 'jane'}, {include: 'count.posts'});
// Tags
const tags = await api.tags.browse({order: 'slug ASC', include: 'count.posts'});
const tag = await api.tags.read({slug: 'fiction'});
// Tiers
const tiers = await api.tiers.browse();
// Settings
const settings = await api.settings.browse();
Endpoints
| Resource | Endpoints | Methods | Default Sort |
|---|---|---|---|
| Posts | /posts/, /posts/{id}/, /posts/slug/{slug}/ |
Browse, Read | published_at DESC |
| Pages | /pages/, /pages/{id}/, /pages/slug/{slug}/ |
Browse, Read | title ASC |
| Authors | /authors/, /authors/{id}/, /authors/slug/{slug}/ |
Browse, Read | name ASC |
| Tags | /tags/, /tags/{id}/, /tags/slug/{slug}/ |
Browse, Read | name ASC |
| Tiers | /tiers/ |
Browse | monthly_price ASC |
| Settings | /settings/ |
Browse | N/A (single object) |
Not available in Content API: Newsletters, Offers, Members — these are Admin API only.
Important behaviors:
- Authors without published posts are not returned
- Tags without associated posts are not returned
- Internal tags (slug prefixed with
#) are included by default — usefilter=visibility:publicto exclude - Settings endpoint accepts no query parameters beyond
key
Query Parameters
| Parameter | Available On | Description |
|---|---|---|
include |
All | Embed related data (e.g., tags,authors) |
fields |
All | Select specific response fields |
formats |
Posts, Pages | Content format: html, plaintext, lexical |
filter |
Browse | NQL filter expression |
limit |
Browse | Results per page (default 15, max 100 in Ghost 6.0+) |
page |
Browse | Page number for pagination |
order |
Browse | Sort field and direction (e.g., published_at desc) |
Include Values by Resource
- Posts/Pages:
tags,authors - Authors:
count.posts - Tags:
count.posts
Important Gotcha
Always use include=tags,authors when fetching posts - without it, related data is not returned.
Response Format
{
"posts": [
{
"id": "5b7...",
"uuid": "22e...",
"title": "My Post",
"slug": "my-post",
"html": "<p>Content...</p>",
"excerpt": "Preview text...",
"custom_excerpt": null,
"feature_image": "https://...",
"feature_image_alt": "",
"feature_image_caption": "",
"featured": false,
"visibility": "public",
"created_at": "2024-01-01T00:00:00.000Z",
"updated_at": "2024-01-02T00:00:00.000Z",
"published_at": "2024-01-01T12:00:00.000Z",
"url": "https://site.com/my-post/",
"meta_title": null,
"meta_description": null,
"og_image": null,
"twitter_image": null,
"canonical_url": null,
"reading_time": 3,
"access": true,
"tags": [],
"authors": [],
"primary_author": {},
"primary_tag": {}
}
],
"meta": {
"pagination": {
"page": 1,
"limit": 15,
"pages": 3,
"total": 45,
"next": 2,
"prev": null
}
}
}
NQL Filtering Syntax
Ghost uses NQL (Node Query Language) for filtering. Refer to references/nql_reference.md for the complete syntax guide.
Quick Reference
# Basic equality
filter=featured:true
# Negation
filter=-featured:true
filter=tag:-fiction
# Comparison
filter=published_at:>'2024-01-01'
filter=published_at:<='2024-06-30'
# Combining (+ = AND, , = OR)
filter=featured:true+tag:news
filter=tag:photo,tag:video
# IN groups
filter=tag:[photo,video,audio]
filter=-tag:[draft,internal]
# Contains / starts with / ends with
filter=title:~'ghost'
filter=slug:~^'getting-started'
# Relative dates
filter=published_at:>now-30d
filter=created_at:>now-1y
# Precedence grouping
filter=(tag:news,tag:blog)+featured:true
Filterable Post Fields
id, uuid, title, slug, status, visibility, featured, published_at, created_at, updated_at, tag, tags, author, authors, primary_tag, primary_author
Pagination
Handle pagination by checking meta.pagination:
async function getAllPosts(api) {
let allPosts = [];
let page = 1;
let lastPage = 1;
while (page <= lastPage) {
const response = await api.posts.browse({
page,
limit: 15,
include: 'tags,authors'
});
allPosts = allPosts.concat(response);
lastPage = response.meta.pagination.pages;
page++;
}
return allPosts;
}
cURL Examples
# Fetch posts with tags and authors
curl "https://demo.ghost.io/ghost/api/content/posts/?key=KEY&include=tags,authors"
# Fetch a single post by slug
curl "https://demo.ghost.io/ghost/api/content/posts/slug/welcome/?key=KEY&formats=html"
# Fetch featured posts
curl "https://demo.ghost.io/ghost/api/content/posts/?key=KEY&filter=featured:true&limit=5"
# Fetch settings
curl "https://demo.ghost.io/ghost/api/content/settings/?key=KEY"
# Fetch tags with post counts
curl "https://demo.ghost.io/ghost/api/content/tags/?key=KEY&include=count.posts&order=count.posts%20desc"
Resources
references/nql_reference.md
Complete NQL (Node Query Language) filtering syntax reference with all operators, value types, and examples.
More from bowtiedswan/ghost-cms-skills
ghost-admin-api
Create, update, and manage Ghost CMS content via the Admin API. This skill should be used when creating or editing posts/pages, managing members, newsletters, tiers, offers, tags, users, uploading images/themes, or configuring webhooks. Covers JWT authentication from Admin API keys, the JavaScript SDK (@tryghost/admin-api), Lexical content format, and all CRUD endpoints.
2ghost-cli
Ghost CLI tool for installing, configuring, and managing Ghost CMS instances. This skill should be used when installing Ghost, configuring a production server, managing Ghost processes (start/stop/restart), updating Ghost, setting up SSL/NGINX, backing up sites, or troubleshooting Ghost installations.
2ghost-webhooks
Ghost CMS webhooks and integrations for event-driven workflows. This skill should be used when setting up webhooks for Ghost events (post.published, member.added, etc.), building custom integrations, automating content workflows, or connecting Ghost to external services. Covers all 31 webhook events, payload handling, JavaScript SDKs, headless CMS setups, and migration tools.
2