Skip to content

Ghost Content API — Posts, Pages, Tags, Authors Endpoints with Filtering

DodaTech Updated 2026-06-28 9 min read

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

  1. In Ghost admin, go to Settings > Integrations.
  2. Click "Add custom integration."
  3. Give it a name (e.g., "Mobile App").
  4. 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

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

  1. 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.

  2. 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.

  3. Requesting more than 100 items per page: The maximum limit is 100. For larger datasets, paginate through the results. Requesting a limit above 100 returns an error.

  4. 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.

  5. 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

  1. 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.

  2. 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.

  3. 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.

  4. 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

Is the Content API key safe to expose in client-side code?

Yes. The Content API key is read-only and only provides access to published public content. It is designed to be used in client-side applications. However, treat it with reasonable care — do not post it on public forums.

Can I access member-only content through the Content API?

No. The Content API only returns content with visibility: public. Member-only and paid-only content cannot be accessed via the Content API. For member-specific content, use the Admin API with proper authentication.

Does the Content API support GraphQL?

No. Ghost uses REST, not GraphQL. The Content API is REST-based with filtering, pagination, and resource inclusion. For GraphQL-like flexibility, you can use field selection and includes.

What is the rate limit for the Content API?

Ghost does not enforce a strict rate limit on the Content API. However, aggressive polling (multiple requests per second) may be throttled. Implement reasonable caching to avoid unnecessary requests.

Can I use the Content API with a static site generator?

Yes. Static site generators like Gatsby, Eleventy, and Next.js can use the Content API at build time to fetch all content and generate static pages. This is a common headless Ghost pattern.

Mini Project

Your task: Build a simple client-side application that uses the Ghost Content API.

  1. Create a custom integration in Ghost and save the Content API key.
  2. 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
  3. Add a tag filter that fetches posts for a specific tag when clicked.
  4. Style the page with CSS.
  5. 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:

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro