Ghost Admin Pages API
Read-write management of static pages - browse, read by id or slug, create, update, and delete. Pages share the post data model but are not part of the chronological content feed.
Read-write management of static pages - browse, read by id or slug, create, update, and delete. Pages share the post data model but are not part of the chronological content feed.
openapi: 3.0.3
info:
title: Ghost Content and Admin APIs
description: >-
Ghost is an open-source (MIT) publishing platform for professional
publications, newsletters, memberships, and paid subscriptions. Every Ghost
site - whether self-hosted or on managed Ghost(Pro) - exposes two documented
public REST APIs under https://{admin_domain}/ghost/api/.
The Content API is read-only and is authenticated with a Content API key
passed as the `key` query parameter; it serves published posts, pages,
authors, tags, tiers, and public settings for consumption by front-ends and
static sites.
The Admin API is read-write and is authenticated with an Admin API key that
is used to sign a short-lived JWT sent as `Authorization: Ghost {token}` (a
staff access token or user session may also be used). It manages posts,
pages, members, tags, labels, tiers, offers, newsletters, users, images,
themes, and webhooks.
The `{admin_domain}` server variable is the site's domain (for Ghost(Pro),
typically a `*.ghost.io` domain). All requests must use HTTPS. The
`Accept-Version` header (for example `v5.0`) declares the minimum compatible
API version.
version: '5.0'
contact:
name: Ghost
url: https://ghost.org
license:
name: MIT
url: https://github.com/TryGhost/Ghost/blob/main/LICENSE
servers:
- url: https://{admin_domain}/ghost/api
description: A Ghost site's API root (self-hosted or Ghost(Pro))
variables:
admin_domain:
default: demo.ghost.io
description: The domain of the Ghost site (Ghost(Pro) uses *.ghost.io).
security:
- contentApiKey: []
- adminJwt: []
tags:
- name: Content - Posts
description: Read-only published posts.
- name: Content - Pages
description: Read-only published pages.
- name: Content - Authors
description: Read-only authors.
- name: Content - Tags
description: Read-only tags.
- name: Content - Tiers
description: Read-only public subscription tiers.
- name: Content - Settings
description: Read-only public site settings.
- name: Admin - Posts
description: Read-write posts.
- name: Admin - Pages
description: Read-write pages.
- name: Admin - Members
description: Read-write members.
- name: Admin - Tags
description: Read-write tags.
- name: Admin - Labels
description: Read-write member labels.
- name: Admin - Tiers
description: Read-write subscription tiers.
- name: Admin - Offers
description: Read-write promotional offers.
- name: Admin - Newsletters
description: Read-write newsletters.
- name: Admin - Users
description: Read-only staff users.
- name: Admin - Site
description: Read-only public site metadata.
- name: Admin - Images
description: Image uploads.
- name: Admin - Themes
description: Theme upload and activation.
- name: Admin - Webhooks
description: Outbound webhook management.
paths:
# ------------------------- CONTENT API -------------------------
/content/posts/:
get:
operationId: browseContentPosts
tags: [Content - Posts]
summary: Browse posts
description: Returns a paginated list of published posts.
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/Include'
- $ref: '#/components/parameters/Fields'
- $ref: '#/components/parameters/Filter'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Order'
- $ref: '#/components/parameters/Formats'
responses:
'200':
description: A list of posts with pagination meta.
'401':
$ref: '#/components/responses/Unauthorized'
/content/posts/{id}/:
get:
operationId: readContentPostById
tags: [Content - Posts]
summary: Read a post by ID
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/PathId'
- $ref: '#/components/parameters/Include'
responses:
'200':
description: The requested post.
'404':
$ref: '#/components/responses/NotFound'
/content/posts/slug/{slug}/:
get:
operationId: readContentPostBySlug
tags: [Content - Posts]
summary: Read a post by slug
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/PathSlug'
- $ref: '#/components/parameters/Include'
responses:
'200':
description: The requested post.
'404':
$ref: '#/components/responses/NotFound'
/content/pages/:
get:
operationId: browseContentPages
tags: [Content - Pages]
summary: Browse pages
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/Filter'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Page'
responses:
'200':
description: A list of pages.
/content/pages/{id}/:
get:
operationId: readContentPageById
tags: [Content - Pages]
summary: Read a page by ID
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/PathId'
responses:
'200':
description: The requested page.
/content/pages/slug/{slug}/:
get:
operationId: readContentPageBySlug
tags: [Content - Pages]
summary: Read a page by slug
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/PathSlug'
responses:
'200':
description: The requested page.
/content/authors/:
get:
operationId: browseContentAuthors
tags: [Content - Authors]
summary: Browse authors
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/Include'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Page'
responses:
'200':
description: A list of authors.
/content/authors/{id}/:
get:
operationId: readContentAuthorById
tags: [Content - Authors]
summary: Read an author by ID
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/PathId'
responses:
'200':
description: The requested author.
/content/authors/slug/{slug}/:
get:
operationId: readContentAuthorBySlug
tags: [Content - Authors]
summary: Read an author by slug
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/PathSlug'
responses:
'200':
description: The requested author.
/content/tags/:
get:
operationId: browseContentTags
tags: [Content - Tags]
summary: Browse tags
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/Include'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Page'
responses:
'200':
description: A list of tags.
/content/tags/{id}/:
get:
operationId: readContentTagById
tags: [Content - Tags]
summary: Read a tag by ID
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/PathId'
responses:
'200':
description: The requested tag.
/content/tags/slug/{slug}/:
get:
operationId: readContentTagBySlug
tags: [Content - Tags]
summary: Read a tag by slug
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/PathSlug'
responses:
'200':
description: The requested tag.
/content/tiers/:
get:
operationId: browseContentTiers
tags: [Content - Tiers]
summary: Browse public subscription tiers
parameters:
- $ref: '#/components/parameters/ContentKey'
- $ref: '#/components/parameters/Include'
- $ref: '#/components/parameters/Filter'
responses:
'200':
description: A list of public tiers with pricing.
/content/settings/:
get:
operationId: browseContentSettings
tags: [Content - Settings]
summary: Read public site settings
parameters:
- $ref: '#/components/parameters/ContentKey'
responses:
'200':
description: Public settings for the site.
# ------------------------- ADMIN API -------------------------
/admin/posts/:
get:
operationId: browseAdminPosts
tags: [Admin - Posts]
summary: Browse posts
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/Include'
- $ref: '#/components/parameters/Fields'
- $ref: '#/components/parameters/Filter'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Order'
- $ref: '#/components/parameters/Formats'
responses:
'200':
description: A list of posts.
'401':
$ref: '#/components/responses/Unauthorized'
post:
operationId: addAdminPost
tags: [Admin - Posts]
summary: Create a post
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/Source'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PostsRequest'
responses:
'201':
description: The created post.
/admin/posts/{id}/:
get:
operationId: readAdminPostById
tags: [Admin - Posts]
summary: Read a post by ID
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
- $ref: '#/components/parameters/Formats'
responses:
'200':
description: The requested post.
put:
operationId: editAdminPost
tags: [Admin - Posts]
summary: Update a post
description: >-
Updates a post. The current updated_at value must be supplied in the
payload for collision detection.
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
- $ref: '#/components/parameters/Source'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PostsRequest'
responses:
'200':
description: The updated post.
delete:
operationId: deleteAdminPost
tags: [Admin - Posts]
summary: Delete a post
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
responses:
'204':
description: The post was deleted.
/admin/posts/slug/{slug}/:
get:
operationId: readAdminPostBySlug
tags: [Admin - Posts]
summary: Read a post by slug
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathSlug'
responses:
'200':
description: The requested post.
/admin/pages/:
get:
operationId: browseAdminPages
tags: [Admin - Pages]
summary: Browse pages
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/Filter'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Page'
responses:
'200':
description: A list of pages.
post:
operationId: addAdminPage
tags: [Admin - Pages]
summary: Create a page
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/Source'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PagesRequest'
responses:
'201':
description: The created page.
/admin/pages/{id}/:
get:
operationId: readAdminPageById
tags: [Admin - Pages]
summary: Read a page by ID
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
responses:
'200':
description: The requested page.
put:
operationId: editAdminPage
tags: [Admin - Pages]
summary: Update a page
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
- $ref: '#/components/parameters/Source'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PagesRequest'
responses:
'200':
description: The updated page.
delete:
operationId: deleteAdminPage
tags: [Admin - Pages]
summary: Delete a page
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
responses:
'204':
description: The page was deleted.
/admin/members/:
get:
operationId: browseAdminMembers
tags: [Admin - Members]
summary: Browse members
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/Include'
- $ref: '#/components/parameters/Filter'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Page'
responses:
'200':
description: A list of members.
post:
operationId: addAdminMember
tags: [Admin - Members]
summary: Create a member
parameters:
- $ref: '#/components/parameters/AcceptVersion'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/MembersRequest'
responses:
'201':
description: The created member.
/admin/members/{id}/:
get:
operationId: readAdminMemberById
tags: [Admin - Members]
summary: Read a member by ID
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
responses:
'200':
description: The requested member.
put:
operationId: editAdminMember
tags: [Admin - Members]
summary: Update a member
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/MembersRequest'
responses:
'200':
description: The updated member.
/admin/tags/:
get:
operationId: browseAdminTags
tags: [Admin - Tags]
summary: Browse tags
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Page'
responses:
'200':
description: A list of tags.
post:
operationId: addAdminTag
tags: [Admin - Tags]
summary: Create a tag
parameters:
- $ref: '#/components/parameters/AcceptVersion'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TagsRequest'
responses:
'201':
description: The created tag.
/admin/tags/{id}/:
put:
operationId: editAdminTag
tags: [Admin - Tags]
summary: Update a tag
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TagsRequest'
responses:
'200':
description: The updated tag.
delete:
operationId: deleteAdminTag
tags: [Admin - Tags]
summary: Delete a tag
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
responses:
'204':
description: The tag was deleted.
/admin/labels/:
get:
operationId: browseAdminLabels
tags: [Admin - Labels]
summary: Browse member labels
parameters:
- $ref: '#/components/parameters/AcceptVersion'
responses:
'200':
description: A list of labels.
post:
operationId: addAdminLabel
tags: [Admin - Labels]
summary: Create a label
parameters:
- $ref: '#/components/parameters/AcceptVersion'
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'201':
description: The created label.
/admin/labels/{id}/:
put:
operationId: editAdminLabel
tags: [Admin - Labels]
summary: Update a label
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: The updated label.
delete:
operationId: deleteAdminLabel
tags: [Admin - Labels]
summary: Delete a label
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
responses:
'204':
description: The label was deleted.
/admin/tiers/:
get:
operationId: browseAdminTiers
tags: [Admin - Tiers]
summary: Browse tiers
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/Include'
responses:
'200':
description: A list of tiers.
post:
operationId: addAdminTier
tags: [Admin - Tiers]
summary: Create a tier
parameters:
- $ref: '#/components/parameters/AcceptVersion'
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'201':
description: The created tier.
/admin/tiers/{id}/:
put:
operationId: editAdminTier
tags: [Admin - Tiers]
summary: Update a tier
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: The updated tier.
/admin/offers/:
get:
operationId: browseAdminOffers
tags: [Admin - Offers]
summary: Browse offers
parameters:
- $ref: '#/components/parameters/AcceptVersion'
responses:
'200':
description: A list of offers.
post:
operationId: addAdminOffer
tags: [Admin - Offers]
summary: Create an offer
parameters:
- $ref: '#/components/parameters/AcceptVersion'
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'201':
description: The created offer.
/admin/offers/{id}/:
put:
operationId: editAdminOffer
tags: [Admin - Offers]
summary: Update an offer
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: The updated offer.
/admin/newsletters/:
get:
operationId: browseAdminNewsletters
tags: [Admin - Newsletters]
summary: Browse newsletters
parameters:
- $ref: '#/components/parameters/AcceptVersion'
responses:
'200':
description: A list of newsletters.
post:
operationId: addAdminNewsletter
tags: [Admin - Newsletters]
summary: Create a newsletter
parameters:
- $ref: '#/components/parameters/AcceptVersion'
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'201':
description: The created newsletter.
/admin/newsletters/{id}/:
put:
operationId: editAdminNewsletter
tags: [Admin - Newsletters]
summary: Update a newsletter
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
requestBody:
required: true
content:
application/json:
schema:
type: object
responses:
'200':
description: The updated newsletter.
/admin/users/:
get:
operationId: browseAdminUsers
tags: [Admin - Users]
summary: Browse staff users
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/Include'
responses:
'200':
description: A list of staff users.
/admin/users/{id}/:
get:
operationId: readAdminUserById
tags: [Admin - Users]
summary: Read a staff user by ID
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
responses:
'200':
description: The requested user.
/admin/users/slug/{slug}/:
get:
operationId: readAdminUserBySlug
tags: [Admin - Users]
summary: Read a staff user by slug
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathSlug'
responses:
'200':
description: The requested user.
/admin/site/:
get:
operationId: readAdminSite
tags: [Admin - Site]
summary: Read public site metadata
description: Returns basic public site data including title, url, and version.
parameters:
- $ref: '#/components/parameters/AcceptVersion'
responses:
'200':
description: The site metadata.
/admin/images/upload/:
post:
operationId: uploadAdminImage
tags: [Admin - Images]
summary: Upload an image
description: >-
Uploads an image using multipart/form-data and returns the stored URL
for referencing the image in post or page content.
parameters:
- $ref: '#/components/parameters/AcceptVersion'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
purpose:
type: string
enum: [image, profile_image, icon]
ref:
type: string
responses:
'201':
description: The uploaded image URL.
/admin/themes/upload/:
post:
operationId: uploadAdminTheme
tags: [Admin - Themes]
summary: Upload a theme
description: Uploads a theme as a zip package using multipart/form-data.
parameters:
- $ref: '#/components/parameters/AcceptVersion'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
responses:
'201':
description: The uploaded theme.
/admin/themes/{name}/activate/:
put:
operationId: activateAdminTheme
tags: [Admin - Themes]
summary: Activate a theme
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- name: name
in: path
required: true
schema:
type: string
responses:
'200':
description: The activated theme.
/admin/webhooks/:
post:
operationId: addAdminWebhook
tags: [Admin - Webhooks]
summary: Create a webhook
description: >-
Registers an outbound webhook that fires on a Ghost event (for example
post.published, member.added). There is no endpoint to read existing
webhooks.
parameters:
- $ref: '#/components/parameters/AcceptVersion'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WebhooksRequest'
responses:
'201':
description: The created webhook.
/admin/webhooks/{id}/:
put:
operationId: editAdminWebhook
tags: [Admin - Webhooks]
summary: Update a webhook
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WebhooksRequest'
responses:
'200':
description: The updated webhook.
delete:
operationId: deleteAdminWebhook
tags: [Admin - Webhooks]
summary: Delete a webhook
parameters:
- $ref: '#/components/parameters/AcceptVersion'
- $ref: '#/components/parameters/PathId'
responses:
'204':
description: The webhook was deleted.
components:
securitySchemes:
contentApiKey:
type: apiKey
in: query
name: key
description: >-
Content API key from a Custom Integration, passed as the `key` query
parameter. Safe for browser use; grants read-only access to public data.
adminJwt:
type: http
scheme: bearer
bearerFormat: JWT
description: >-
Admin API access. An Admin API key (id:secret) is used to sign a
short-lived JWT sent as `Authorization: Ghost {token}`. A staff access
token or an authenticated user session may also be used.
parameters:
ContentKey:
name: key
in: query
required: true
description: Content API key.
schema:
type: string
AcceptVersion:
name: Accept-Version
in: header
required: false
description: Minimum compatible API version, for example v5.0.
schema:
type: string
example: v5.0
PathId:
name: id
in: path
required: true
description: The resource ID.
schema:
type: string
PathSlug:
name: slug
in: path
required: true
description: The resource slug.
schema:
type: string
Include:
name: include
in: query
required: false
description: Comma-separated related data to include (for example authors,tags).
schema:
type: string
Fields:
name: fields
in: query
required: false
description: Comma-separated list of fields to return.
schema:
type: string
Filter:
name: filter
in: query
required: false
description: Ghost NQL filter expression.
schema:
type: string
Limit:
name: limit
in: query
required: false
description: Number of records per page (default 15, or 'all').
schema:
type: string
default: '15'
Page:
name: page
in: query
required: false
description: Page number of results to return.
schema:
type: integer
default: 1
Order:
name: order
in: query
required: false
description: Sort order, for example 'published_at desc'.
schema:
type: string
Formats:
name: formats
in: query
required: false
description: Content formats to return, for example 'html,lexical'.
schema:
type: string
Source:
name: source
in: query
required: false
description: Set to 'html' to supply post/page content as HTML instead of Lexical.
schema:
type: string
enum: [html]
responses:
Unauthorized:
description: Authentication failed or was missing.
NotFound:
description: The requested resource was not found.
schemas:
PostsRequest:
type: object
properties:
posts:
type: array
items:
type: object
properties:
title:
type: string
lexical:
type: string
html:
type: string
status:
type: string
enum: [draft, published, scheduled]
updated_at:
type: string
format: date-time
PagesRequest:
type: object
properties:
pages:
type: array
items:
type: object
MembersRequest:
type: object
properties:
members:
type: array
items:
type: object
properties:
email:
type: string
name:
type: string
note:
type: string
TagsRequest:
type: object
properties:
tags:
type: array
items:
type: object
properties:
name:
type: string
slug:
type: string
description:
type: string
WebhooksRequest:
type: object
properties:
webhooks:
type: array
items:
type: object
properties:
event:
type: string
example: post.published
target_url:
type: string
format: uri
name:
type: string
secret:
type: string