Ghost Content API — Posts, Pages, Tags, Authors Endpoints with Filtering
In this tutorial, you'll learn how to use the Ghost Content API — a public read-only REST API that lets you fetch posts, pages, tags, authors, and settings for use in custom frontends, mobile apps, and integrations.
What You'll Learn
- What the Content API is and how it differs from the Admin API
- Authentication with Content API keys
- The posts endpoint and available parameters
- The pages, tags, and authors endpoints
- Filtering with the Ghost filter syntax
- Paginating through large result sets
- Including related resources (authors, tags, images)
- Field selection for optimized responses
- The settings endpoint for site configuration
- Rate limiting and caching considerations
Why It Matters
The Content API is the gateway to using Ghost as a headless CMS. It lets any application — a React website, a mobile app, a smart display — read your content and display it with complete design control. Unlike WordPress's REST API which requires authentication for many operations, Ghost's Content API is public and read-only by design, making it simple and safe to use from client-side applications.
Real-World Use
A news organization builds a mobile app that displays articles from their Ghost CMS. The app uses the Content API to fetch the latest posts, filter by section tags, paginate through results, and display full articles. Because the API is public, no authentication is needed in the app. The same API powers their website, their smart TV app, and their email newsletter.
Learning Path
flowchart LR A["Membership API"] --> B["Content API
You are here"]:::current B --> C["Admin API"] C --> D["Webhooks"] classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px
What is the Content API?
The Content API is a public, read-only REST API that provides access to your Ghost site's published content. It is designed to be used from client-side applications (browsers, mobile apps, smart devices) without exposing sensitive data.
Key Characteristics
- Public: No user authentication required — just an API key embedded in the URL
- Read-only: You can only fetch data, never create, update, or delete
- Fast: Optimized for read performance with built-in caching
- Flexible: Filter, paginate, include related resources, select specific fields
Base URL
https://yoursite.com/ghost/api/content/
Authentication
Every Content API request requires a Content API key as a query parameter.
Getting Your API Key
- In Ghost admin, go to
Settings > Integrations. - Click "Add custom integration."
- Give it a name (e.g., "Mobile App").
- Copy the Content API Key.
Using the API Key
Append the key to every API request:
https://yoursite.com/ghost/api/content/posts/?key=YOUR_CONTENT_API_KEY
The key is safe to include in client-side code because it is read-only and only returns published content.
The Posts Endpoint
The posts endpoint is the most commonly used Content API resource.
Basic Request
GET /ghost/api/content/posts/?key=YOUR_KEY
Response Structure
{
"posts": [
{
"id": "64a1b2c3d4e5f6",
"uuid": "abc-def-ghi",
"title": "My Post Title",
"slug": "my-post-title",
"html": "<p>Post content</p>",
"feature_image": "https://...",
"feature_image_alt": "Alt text",
"feature_image_caption": "Caption",
"featured": false,
"visibility": "public",
"created_at": "2024-01-15T10:00:00.000Z",
"published_at": "2024-01-15T10:00:00.000Z",
"updated_at": "2024-01-20T14:30:00.000Z",
"reading_time": 5,
"excerpt": "Short excerpt..."
}
],
"meta": {
"pagination": {
"page": 1,
"limit": 15,
"pages": 3,
"total": 42,
"prev": null,
"next": 2
}
}
}
Parameters
| Parameter | Description | Example |
|---|---|---|
limit |
Items per page (default 15, max 100) | limit=5 |
page |
Page number for pagination | page=2 |
filter |
Filter expression | filter=featured:true |
include |
Related resources to embed | include=authors,tags |
fields |
Specific fields to return | fields=title,slug,excerpt |
order |
Sort order | order=published_at desc |
The Pages Endpoint
Identical to posts but returns pages instead:
GET /ghost/api/content/pages/?key=YOUR_KEY
Parameters work the same as the posts endpoint.
The Tags Endpoint
GET /ghost/api/content/tags/?key=YOUR_KEY
Additional Include
{
"tags": [
{
"id": "...",
"name": "JavaScript",
"slug": "javascript",
"description": "All about JavaScript",
"feature_image": null,
"parent": null,
"count": {
"posts": 15
}
}
]
}
Include Post Count
GET /ghost/api/content/tags/?key=YOUR_KEY&include=count.posts
The Authors Endpoint
GET /ghost/api/content/authors/?key=YOUR_KEY
Response
{
"authors": [
{
"id": "...",
"name": "Jane Doe",
"slug": "jane",
"profile_image": "https://...",
"cover_image": null,
"bio": "Writer and developer",
"website": "https://janedoe.com",
"location": "San Francisco",
"facebook": "janedoe",
"twitter": "@janedoe",
"count": {
"posts": 42
}
}
]
}
The Settings Endpoint
Returns site-wide settings:
GET /ghost/api/content/settings/?key=YOUR_KEY
Response
{
"settings": {
"title": "My Blog",
"description": "A blog about tech",
"logo": "https://...",
"cover_image": "https://...",
"accent_color": "#15171a",
"locale": "en",
"url": "https://yoursite.com",
"twitter": "@myblog",
"facebook": "myblog"
}
}
Filtering
Ghost uses a powerful filter syntax for querying content.
Basic Filters
| Expression | Meaning |
|---|---|
featured:true |
Featured posts only |
visibility:paid |
Paid-only posts |
tags:[<a href="/programming-languages/javascript/">JavaScript</a>] |
Posts with specific tag |
tags:[javascript, python] |
Posts with any of these tags |
tags:-[internal] |
Exclude posts with specific tag |
published_at:>2024-01-01 |
Published after a date |
primary_tag:javascript |
Posts with primary tag |
Combining Filters
Use + for AND, , for OR:
featured:true+tags:[javascript]
Filter Examples
# Featured posts with tutorial tag
GET /content/posts/?key=KEY&filter=featured:true+tags:[tutorial]
# Posts published this year
GET /content/posts/?key=KEY&filter=published_at:>'2024-01-01'
# Pages with specific slug
GET /content/pages/?key=KEY&filter=slug:about
Including Related Resources
Use the include parameter to embed related data in a single request.
Available Includes
| Resource | Include Value | Description |
|---|---|---|
| Authors | authors |
Post authors |
| Tags | tags |
Post tags |
| Counts | count.posts |
Post count per tag/author |
| Tiers | tiers |
Access tiers |
Examples
# Posts with authors and tags
GET /content/posts/?key=KEY&include=authors,tags
# Tags with post count
GET /content/tags/?key=KEY&include=count.posts
Field Selection
Reduce response size by requesting only the fields you need:
# Get only title, slug, and excerpt
GET /content/posts/?key=KEY&fields=title,slug,excerpt
# Get specific author fields
GET /content/authors/?key=KEY&fields=name,profile_image,bio
Pagination
The meta.pagination object in responses tells you about available pages:
{
"meta": {
"pagination": {
"page": 1,
"limit": 15,
"pages": 5,
"total": 72,
"next": 2,
"prev": null
}
}
}
Iterate through pages by incrementing the page parameter:
GET /content/posts/?key=KEY&page=1
GET /content/posts/?key=KEY&page=2
GET /content/posts/?key=KEY&page=3
Ordering
Control sort order with the order parameter:
# Newest first (default)
order=published_at desc
# Oldest first
order=published_at asc
# By title
order=title asc
# Featured first, then by date
order=featured desc, published_at desc
Example: Using the Content API with Fetch
const API_KEY = 'YOUR_CONTENT_API_KEY';
const API_URL = 'https://yoursite.com';
async function getLatestPosts() {
const response = await fetch(
`${API_URL}/ghost/api/content/posts/?key=${API_KEY}&limit=5&include=authors,tags`
);
const data = await response.json();
return data.posts;
}
async function getPostBySlug(slug) {
const response = await fetch(
`${API_URL}/ghost/api/content/posts/?key=${API_KEY}&filter=slug:${slug}&include=authors,tags`
);
const data = await response.json();
return data.posts[0];
}
Common Mistakes
Using the Content API key on the Admin API: Content API keys only work on the Content API (which has a different base URL). Admin API keys work on the Admin API. They are not interchangeable.
Forgetting the Content API key in every request: Every request must include
?key=YOUR_KEY. Without it, the API returns a 401 Unauthorized error. The key is required even for public content.Requesting more than 100 items per page: The maximum
limitis 100. For larger datasets, paginate through the results. Requesting a limit above 100 returns an error.Using the Content API for member-only content: The Content API only returns content with
visibility: public. Member-only and paid-only content is not accessible through the Content API, even with a valid key.Not caching API responses: The Content API is fast, but requesting the same data on every page load is wasteful. Implement client-side caching (e.g., React Query, SWR, or localStorage) to reduce API calls.
Practice Questions
What is the difference between the Content API and the Admin API? Answer: The Content API is public, read-only, and returns only published content. It requires a Content API key that is safe to use in client-side code. The Admin API is authenticated, supports all CRUD operations, and requires a secret Admin API key that must never be exposed in client-side code.
How do you fetch a single post by its slug using the Content API? Answer: Use the filter parameter:
GET /content/posts/?key=KEY&filter=slug:my-post-slug. This returns an array with one post (or empty if not found). Alternatively, use GET /content/posts/slug/my-post-slug/?key=KEY.What is the maximum number of items you can request per page? Answer: The maximum limit is 100 items per page. For more items, paginate using the page parameter. The default limit is 15 if not specified.
Challenge: Build a simple HTML page that uses the Ghost Content API to display your three most recent posts. Fetch the posts using JavaScript fetch, render them in a styled grid with title, excerpt, feature image, and author name, and implement a "Load more" button that fetches the next page.
FAQ
Mini Project
Your task: Build a simple client-side application that uses the Ghost Content API.
- Create a custom integration in Ghost and save the Content API key.
- Build an HTML page that fetches and displays:
- Site title and description (from /settings/)
- 5 most recent posts with titles, excerpts, and feature images
- Each post linked to its full content page
- Tags as clickable filters
- Add a tag filter that fetches posts for a specific tag when clicked.
- Style the page with CSS.
- Host the HTML page on any static hosting or run it locally.
This exercise gives you practical experience using Ghost as a headless CMS.
What's Next
Now that you understand the Content API, learn about the Admin API:
Continue to Lesson 26: Admin API — Authentication, CRUD operations, and Webhook management.
Related lessons:
- Webhooks — Real-time event notifications
- Headless Ghost — Ghost as a headless CMS
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro