Ghost Pages API
Create, read, update, and delete pages. Pages share the same structure as posts but are used for static content.
Create, read, update, and delete pages. Pages share the same structure as posts but are used for static content.
openapi: 3.1.0
info:
title: Ghost Admin Authors Pages API
description: The Ghost Admin API provides full read and write access to all content and configuration within a Ghost publication. It enables developers to create, update, and delete posts, pages, tags, members, tiers, newsletters, and offers programmatically. Authentication is handled via JSON Web Tokens generated from an Admin API key, integration tokens, or staff access tokens. The Admin API supports everything the Ghost Admin interface can do and more, making it suitable for building custom publishing workflows, content automation, member management systems, and advanced integrations.
version: '5.0'
contact:
name: Ghost Foundation
url: https://ghost.org/docs/admin-api/
termsOfService: https://ghost.org/terms/
servers:
- url: https://{site}.ghost.io/ghost/api/admin
description: Ghost Pro Hosted Site
variables:
site:
default: your-site
description: Your Ghost site subdomain
- url: '{protocol}://{domain}/ghost/api/admin'
description: Self-Hosted Ghost Instance
variables:
protocol:
default: https
enum:
- https
- http
domain:
default: localhost:2368
description: Your Ghost instance domain and port
security:
- adminApiToken: []
tags:
- name: Pages
description: Create, read, update, and delete pages. Pages share the same structure as posts but are used for static content.
paths:
/pages/:
get:
operationId: adminBrowsePages
summary: Browse pages
description: Retrieve a paginated list of pages including draft and published pages.
tags:
- Pages
parameters:
- $ref: '#/components/parameters/includePostRelations'
- $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 pages
content:
application/json:
schema:
type: object
properties:
pages:
type: array
items:
$ref: '#/components/schemas/Post'
meta:
$ref: '#/components/schemas/PaginationMeta'
'401':
$ref: '#/components/responses/Unauthorized'
post:
operationId: adminCreatePage
summary: Create a page
description: Create a new page. Pages share the same structure as posts and require a title field.
tags:
- Pages
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- pages
properties:
pages:
type: array
items:
$ref: '#/components/schemas/PostInput'
minItems: 1
maxItems: 1
responses:
'201':
description: Page created successfully
content:
application/json:
schema:
type: object
properties:
pages:
type: array
items:
$ref: '#/components/schemas/Post'
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/ValidationError'
/pages/{id}/:
get:
operationId: adminReadPage
summary: Read a page by ID
description: Retrieve a single page by its unique identifier.
tags:
- Pages
parameters:
- $ref: '#/components/parameters/resourceId'
- $ref: '#/components/parameters/includePostRelations'
- $ref: '#/components/parameters/fields'
- $ref: '#/components/parameters/formats'
responses:
'200':
description: A single page
content:
application/json:
schema:
type: object
properties:
pages:
type: array
items:
$ref: '#/components/schemas/Post'
minItems: 1
maxItems: 1
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
put:
operationId: adminUpdatePage
summary: Update a page
description: Update an existing page. The updated_at field must be included to prevent update collisions.
tags:
- Pages
parameters:
- $ref: '#/components/parameters/resourceId'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- pages
properties:
pages:
type: array
items:
$ref: '#/components/schemas/PostInput'
minItems: 1
maxItems: 1
responses:
'200':
description: Page updated successfully
content:
application/json:
schema:
type: object
properties:
pages:
type: array
items:
$ref: '#/components/schemas/Post'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: Update collision due to stale updated_at value
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
$ref: '#/components/responses/ValidationError'
delete:
operationId: adminDeletePage
summary: Delete a page
description: Permanently delete a page by its unique identifier.
tags:
- Pages
parameters:
- $ref: '#/components/parameters/resourceId'
responses:
'204':
description: Page deleted successfully
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/pages/slug/{slug}/:
get:
operationId: readPageBySlug
summary: Read a page by slug
description: Retrieve a single published page by its URL slug.
tags:
- Pages
parameters:
- $ref: '#/components/parameters/resourceSlug'
- $ref: '#/components/parameters/includePostRelations_2'
- $ref: '#/components/parameters/fields_2'
- $ref: '#/components/parameters/formats_2'
responses:
'200':
description: A single page
content:
application/json:
schema:
type: object
properties:
pages:
type: array
items:
$ref: '#/components/schemas/Page'
minItems: 1
maxItems: 1
'401':
$ref: '#/components/responses/Unauthorized_2'
'404':
$ref: '#/components/responses/NotFound'
components:
schemas:
Post_2:
type: object
description: A post represents a piece of published content in a Ghost publication.
properties:
id:
type: string
format: uuid
description: Unique identifier for the post
uuid:
type: string
format: uuid
description: Universally unique identifier for the post
title:
type: string
description: Title of the post
slug:
type: string
description: URL-safe slug derived from the title
html:
type: string
description: HTML content of the post
plaintext:
type: string
description: Plain text content of the post, available when requested via formats
comment_id:
type: string
description: Identifier used for the commenting system
feature_image:
type: string
format: uri
description: URL of the featured image for the post
nullable: true
feature_image_alt:
type: string
description: Alt text for the featured image
nullable: true
feature_image_caption:
type: string
description: Caption for the featured image
nullable: true
featured:
type: boolean
description: Whether the post is marked as featured
visibility:
type: string
description: Visibility level of the post
enum:
- public
- members
- paid
- tiers
created_at:
type: string
format: date-time
description: Timestamp when the post was created
updated_at:
type: string
format: date-time
description: Timestamp when the post was last updated
published_at:
type: string
format: date-time
description: Timestamp when the post was published
nullable: true
custom_excerpt:
type: string
description: Custom excerpt for the post
nullable: true
codeinjection_head:
type: string
description: Code injected into the head of the post page
nullable: true
codeinjection_foot:
type: string
description: Code injected into the foot of the post page
nullable: true
custom_template:
type: string
description: Custom template assigned to the post
nullable: true
canonical_url:
type: string
format: uri
description: Canonical URL for the post
nullable: true
url:
type: string
format: uri
description: Full URL of the post on the Ghost site
excerpt:
type: string
description: Auto-generated excerpt from the post content
reading_time:
type: integer
description: Estimated reading time in minutes
minimum: 0
access:
type: boolean
description: Whether the current request has access to the full post content
og_image:
type: string
format: uri
description: Open Graph image URL
nullable: true
og_title:
type: string
description: Open Graph title
nullable: true
og_description:
type: string
description: Open Graph description
nullable: true
twitter_image:
type: string
format: uri
description: Twitter card image URL
nullable: true
twitter_title:
type: string
description: Twitter card title
nullable: true
twitter_description:
type: string
description: Twitter card description
nullable: true
meta_title:
type: string
description: SEO meta title
nullable: true
meta_description:
type: string
description: SEO meta description
nullable: true
email_subject:
type: string
description: Custom subject for email newsletters
nullable: true
frontmatter:
type: string
description: Custom frontmatter data
nullable: true
tags:
type: array
description: Tags associated with the post, included when requested
items:
$ref: '#/components/schemas/Tag_2'
authors:
type: array
description: Authors of the post, included when requested
items:
$ref: '#/components/schemas/Author'
primary_author:
description: Primary author of the post, included when authors are requested
$ref: '#/components/schemas/Author'
primary_tag:
description: Primary tag of the post, included when tags are requested
$ref: '#/components/schemas/Tag_2'
nullable: true
Tag:
type: object
description: A tag for organizing and categorizing content.
properties:
id:
type: string
format: uuid
description: Unique identifier
name:
type: string
description: Tag name
slug:
type: string
description: URL-safe slug
description:
type: string
description: Tag description
nullable: true
feature_image:
type: string
format: uri
description: Featured image URL
nullable: true
visibility:
type: string
description: Visibility setting
enum:
- public
- internal
og_image:
type: string
format: uri
nullable: true
description: Open Graph image URL
og_title:
type: string
nullable: true
description: Open Graph title
og_description:
type: string
nullable: true
description: Open Graph description
twitter_image:
type: string
format: uri
nullable: true
description: Twitter card image URL
twitter_title:
type: string
nullable: true
description: Twitter card title
twitter_description:
type: string
nullable: true
description: Twitter card description
meta_title:
type: string
nullable: true
description: SEO meta title
meta_description:
type: string
nullable: true
description: SEO meta description
codeinjection_head:
type: string
nullable: true
description: Code injection in the head
codeinjection_foot:
type: string
nullable: true
description: Code injection in the foot
canonical_url:
type: string
format: uri
nullable: true
description: Canonical URL
accent_color:
type: string
nullable: true
description: Accent color hex code
pattern: ^#[0-9a-fA-F]{6}$
url:
type: string
format: uri
description: Full URL of the tag page
created_at:
type: string
format: date-time
description: Creation timestamp
updated_at:
type: string
format: date-time
description: Last update timestamp
ErrorResponse:
type: object
description: Standard Ghost API error response
properties:
errors:
type: array
items:
type: object
properties:
message:
type: string
description: Human-readable error message
type:
type: string
description: Error type identifier
context:
type: string
description: Additional error context
nullable: true
Tag_2:
type: object
description: A tag is used to organize and categorize content in Ghost. Tags with slugs starting with hash are internal tags not visible to readers.
properties:
id:
type: string
format: uuid
description: Unique identifier for the tag
name:
type: string
description: Name of the tag
slug:
type: string
description: URL-safe slug for the tag
description:
type: string
description: Description of the tag
nullable: true
feature_image:
type: string
format: uri
description: Featured image URL for the tag
nullable: true
visibility:
type: string
description: Visibility of the tag
enum:
- public
- internal
og_image:
type: string
format: uri
description: Open Graph image for the tag page
nullable: true
og_title:
type: string
description: Open Graph title for the tag page
nullable: true
og_description:
type: string
description: Open Graph description for the tag page
nullable: true
twitter_image:
type: string
format: uri
description: Twitter card image for the tag page
nullable: true
twitter_title:
type: string
description: Twitter card title for the tag page
nullable: true
twitter_description:
type: string
description: Twitter card description for the tag page
nullable: true
meta_title:
type: string
description: SEO meta title for the tag page
nullable: true
meta_description:
type: string
description: SEO meta description for the tag page
nullable: true
codeinjection_head:
type: string
description: Code injected into the head on tag pages
nullable: true
codeinjection_foot:
type: string
description: Code injected into the foot on tag pages
nullable: true
canonical_url:
type: string
format: uri
description: Canonical URL for the tag page
nullable: true
accent_color:
type: string
description: Accent color for the tag
nullable: true
pattern: ^#[0-9a-fA-F]{6}$
url:
type: string
format: uri
description: Full URL of the tag page
count:
type: object
description: Count data, included when requested via include=count.posts
properties:
posts:
type: integer
description: Number of posts with this tag
minimum: 0
Author:
type: object
description: An author represents a staff user who creates content in a Ghost publication.
properties:
id:
type: string
format: uuid
description: Unique identifier for the author
name:
type: string
description: Display name of the author
slug:
type: string
description: URL-safe slug for the author
profile_image:
type: string
format: uri
description: Profile image URL
nullable: true
cover_image:
type: string
format: uri
description: Cover image URL for the author page
nullable: true
bio:
type: string
description: Author biography
nullable: true
website:
type: string
format: uri
description: Author personal website URL
nullable: true
location:
type: string
description: Author location
nullable: true
facebook:
type: string
description: Facebook username
nullable: true
twitter:
type: string
description: Twitter handle
nullable: true
meta_title:
type: string
description: SEO meta title for the author page
nullable: true
meta_description:
type: string
description: SEO meta description for the author page
nullable: true
url:
type: string
format: uri
description: Full URL of the author page
count:
type: object
description: Count data, included when requested via include=count.posts
properties:
posts:
type: integer
description: Number of posts by this author
minimum: 0
User:
type: object
description: A staff user account in the Ghost publication.
properties:
id:
type: string
format: uuid
description: Unique identifier
name:
type: string
description: Display name
slug:
type: string
description: URL-safe slug
email:
type: string
format: email
description: Email address
profile_image:
type: string
format: uri
description: Profile image URL
nullable: true
cover_image:
type: string
format: uri
description: Cover image URL
nullable: true
bio:
type: string
description: Biography
nullable: true
website:
type: string
format: uri
description: Personal website URL
nullable: true
location:
type: string
description: Location
nullable: true
facebook:
type: string
description: Facebook username
nullable: true
twitter:
type: string
description: Twitter handle
nullable: true
accessibility:
type: string
description: Accessibility settings JSON
nullable: true
status:
type: string
description: User account status
enum:
- active
- inactive
- locked
meta_title:
type: string
nullable: true
description: SEO meta title
meta_description:
type: string
nullable: true
description: SEO meta description
tour:
type: string
description: Onboarding tour progress JSON
nullable: true
last_seen:
type: string
format: date-time
description: Last login timestamp
nullable: true
url:
type: string
format: uri
description: Full URL of the author page
roles:
type: array
description: Assigned roles
items:
type: object
properties:
id:
type: string
format: uuid
description: Role identifier
name:
type: string
description: Role name
description:
type: string
description: Role description
created_at:
type: string
format: date-time
description: Account creation timestamp
updated_at:
type: string
format: date-time
description: Last update timestamp
PostInput:
type: object
description: Input fields for creating or updating a post or page.
properties:
title:
type: string
description: Title of the post
slug:
type: string
description: Custom URL slug
lexical:
type: string
description: Content in Lexical editor format (JSON string)
html:
type: string
description: Content in HTML format, converted to Lexical on save
status:
type: string
description: Publication status
enum:
- published
- draft
- scheduled
visibility:
type: string
description: Access visibility level
enum:
- public
- members
- paid
- tiers
featured:
type: boolean
description: Whether the post is featured
feature_image:
type: string
format: uri
description: Featured image URL
nullable: true
feature_image_alt:
type: string
description: Alt text for the featured image
nullable: true
feature_image_caption:
type: string
description: Caption for the featured image
nullable: true
custom_excerpt:
type: string
description: Custom excerpt
nullable: true
codeinjection_head:
type: string
description: Code injection in the head
nullable: true
codeinjection_foot:
type: string
description: Code injection in the foot
nullable: true
custom_template:
type: string
description: Custom template name
nullable: true
canonical_url:
type: string
format: uri
description: Canonical URL
nullable: true
published_at:
type: string
format: date-time
description: Scheduled publication time
nullable: true
updated_at:
type: string
format: date-time
description: Required for updates to prevent collisions
tags:
type: array
description: Tags to associate, can be name strings or tag objects
items:
oneOf:
- type: object
properties:
name:
type: string
slug:
type: string
- $ref: '#/components/schemas/Tag'
authors:
type: array
description: Authors to associate
items:
type: object
properties:
id:
type: string
format: uuid
slug:
type: string
email:
type: string
format: email
email_subject:
type: string
description: Custom email newsletter subject
nullable: true
og_image:
type: string
format: uri
nullable: true
description: Open Graph image URL
og_title:
type: string
nullable: true
description: Open Graph title
og_description:
type: string
nullable: true
description: Open Graph description
twitter_image:
type: string
format: uri
nullable: true
description: Twitter card image URL
twitter_title:
type: string
nullable: true
description: Twitter card title
twitter_description:
type: string
nullable: true
description: Twitter card description
meta_title:
type: string
nullable: true
description: SEO meta title
meta_description:
type: string
nullable: true
description: SEO meta description
PaginationMeta:
type: object
description: Pagination metadata
properties:
pagination:
type: object
properties:
page:
type: integer
description: Current page
minimum: 1
limit:
type: integer
description: Items per page
minimum: 1
pages:
type: integer
description: Total pages
minimum: 1
total:
type: integer
description: Total items
minimum: 0
next:
type: integer
description: Next page number
nullable: true
prev:
type: integer
description: Previous page number
nullable: true
Post:
type: object
description: A post or page resource with all content, metadata, and relationships.
properties:
id:
type: string
format: uuid
description: Unique identifier
uuid:
type: string
format: uuid
description: Universally unique identifier
title:
type: string
description: Title of the post
slug:
type: string
description: URL-safe slug
lexical:
type: string
description: Post content in Lexical editor format (JSON string)
html:
type: string
description: Rendered HTML content
plaintext:
type: string
description: Plain text content
comment_id:
type: string
description: Commenting system identifier
feature_image:
type: string
format: uri
description: Featured image URL
nullable: true
feature_image_alt:
type: string
description: Alt text for the featured image
nullable: true
feature_image_caption:
type: string
description: Caption for the featured image
nullable: true
featured:
type: boolean
description: Whether the post is featured
status:
type: string
description: Publication status
enum:
- published
- draft
- scheduled
- sent
visibility:
type: string
description: Access visibility level
enum:
- public
- members
- paid
- tiers
created_at:
type: string
format: date-time
description: Creation timestamp
updated_at:
type: string
format: date-time
description: Last update timestamp
published_at:
type: string
format: date-time
description: Publication timestamp
nullable: true
custom_excerpt:
type: string
description: Custom excerpt
nullable: true
codeinjection_head:
type: string
description: Code injection in the page head
nullable: true
codeinjection_foot:
type: string
description: Code injection in the page foot
nullable: true
custom_template:
type: string
description: Custom Handlebars template name
nullable: true
canonical_url:
type: string
format: uri
description: Canonical URL
nullable: true
url:
type: string
format: uri
description: Full URL on the Ghost site
excerpt:
type: string
description: Auto-generated excerpt
reading_time:
type: integer
description: Estimated reading time in minutes
minimum: 0
email_subject:
type: string
description: Custom email newsletter subject
nullable: true
frontmatter:
type: string
description: Custom frontmatter
nullable: true
og_image:
type: string
format: uri
nullable: true
description: Open Graph image URL
og_title:
type: string
nullable: true
description: Open Graph title
og_description:
type: string
nullable: true
description: Open Graph description
twitter_image:
type: string
format: uri
nullable: true
description: Twitter card image URL
twitter_title:
type: string
nullable: true
description: Twitter card title
twitter_description:
type: string
nullable: true
description: Twitter card description
meta_title:
type: string
nullable: true
description: SEO meta title
meta_description:
type: string
nullable: true
description: SEO meta description
tags:
type: array
description: Associated tags
items:
$ref: '#/components/schemas/Tag'
authors:
type: array
description: Post authors
items:
$ref: '#/components/schemas/User'
primary_author:
$ref: '#/components/schemas/User'
description: Primary auth
# --- truncated at 32 KB (37 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/ghost/refs/heads/main/openapi/ghost-pages-api-openapi.yml