The Ghost Admin API in 2026.The email goes out on publish.
To publish to a Ghost site from code, add a custom integration in Ghost Admin, sign a short-lived JWT with its Admin API key, and call POST /ghost/api/admin/posts/?source=html. Sending the post as a newsletter takes a second call: a PUT that moves the draft to published with ?newsletter=. The API is free on self-hosted Ghost; on Ghost(Pro) it starts with the Publisher plan, $29 a month billed yearly.
Northbeam Coffeecoffee
How we roast Morning Light
Oct 8 · 1 min read

Eleven minutes from green bean to bag. We start low to dry the beans, push through first crack, then stop early to keep the honey and orange notes.
That early stop is why it tastes lighter than our other coffees, and why it works as well in a latte as in a pour-over.
The Ghost API at a glanceWhat it takes before the first post.
- Price
- Free on self-hosted Ghost, open source under MIT. On Ghost(Pro), Publisher ($29 a month billed yearly) and up; Starter has no Admin API
- Auth
- A custom integration's Admin API key (id:secret), signed as an HS256 JWT that lasts 5 minutes, sent as Authorization: Ghost <token>
- Getting one
- Ghost Admin → Settings → Integrations → Add custom integration. Each staff user also has a personal token on their profile
- Posting
- POST /admin/posts/?source=html with title, html, status, tags and feature_image; 201 with the post's id and url
- Newsletters
- PUT /admin/posts/{id}/?newsletter={slug}&email_segment=… when the post moves to published. A POST never sends email
- Media
- POST /admin/images/upload/ for JPEG, PNG, GIF, WebP and SVG; POST /admin/media/upload/ for MP4, WebM and audio
- Rate limit
- None published, and Ghost's code doesn't limit integration requests; Ghost(Pro) has a fair-use policy
- Scheduling
- status scheduled with a future published_at; a PUT that also carries ?newsletter= emails it at that time
Checked on October 8, 2026, from Ghost's developer documentation and terms.
To post to Ghost from your product, use Breakreach's API.We built it, so here's the case.
See the request- The post, its newsletter, and its LinkedIn and X posts in one request, for the same morning
- No JWT to sign and no second call for the email: articleSettings.newsletter sends it, to all, free or paid members
- Your users connect their own Ghost sites on a hosted page, with the address and an Admin API key
When to use Ghost's API directly. Breakreach publishes posts only, without pages, members-only visibility, authors or excerpts, and reads back only the member count. For anything else on the site, call the Admin API directly: it's free and documented, and every Ghost site has it except on Ghost(Pro) Starter.
How to get access to the Ghost APIFrom a developer account to your first real post.
- 1Check the planSelf-hosted Ghost has the Admin API built in. On Ghost(Pro), custom integrations, the Admin API and webhooks start with Publisher; on Starter, every integration request answers 403 HostLimitError.
- 2Add a custom integrationIn Ghost Admin, Settings → Integrations → Add custom integration, then name it. Ghost shows a Content API key, an Admin API key and the API URL. Settings are an Administrator's job.
- 3Call the API URLOn Ghost(Pro), the admin domain (yoursite.ghost.io) can differ from the site's. The Admin API answers the site's domain with a 301 to it, which many HTTP clients follow as a GET without the body, so call the API URL, or resolve it once with GET /admin/site/, which needs no key.
- 4Sign a token per requestSplit the key at the colon. The id goes in the JWT header as kid; the hex-decoded secret signs it with HS256, aud /admin/, and an exp at most 5 minutes after iat. Send it as Authorization: Ghost <token>.
No app review and no OAuth: the key belongs to the integration, not to a person, and deleting the integration revokes it. A staff user's own token, on their profile, works the same way with that user's role; an Administrator's reaches every endpoint.
How to post with the Ghost APIThe requests in the demo above, one by one.
- 1Upload the mediaPOST /admin/images/upload/ as multipart, with file and purpose image; it returns the image's url on the site. A video goes to POST /admin/media/upload/, with an optional thumbnail in the same request.
- 2Create the postPOST /admin/posts/?source=html with title, html, status (draft, published or scheduled), feature_image, tags and canonical_url. Tags that don't exist yet are created. It answers 201 with id, url and updated_at.
- 3Publish and emailTo send it as a newsletter, create it as a draft, then PUT /admin/posts/{id}/?newsletter={slug}&email_segment=all with status published and the updated_at you got back. email_segment is a member filter, usually all, status:free or status:-free.
Without ?source=html, Ghost drops the html field and the post comes out empty. The conversion is lossy: images become image cards, but a bare <video> disappears, since only Ghost's kg-video-card markup becomes a video card. Posts made with an integration key are credited to the site's Owner unless you set authors.
Common Ghost API errorsWhat they mean and how to fix them.
| Error | What it means | Fix |
|---|---|---|
401 Unknown Admin API Key | The integration was deleted, or the key's id is wrong. | Copy the Admin API key again from Settings → Integrations. |
401 Invalid API Key type | The Content API key was used to sign the token. | Use the Admin API key. |
403 HostLimitError | The site is on Ghost(Pro) Starter, which has no custom integrations. | Move to Publisher or above. |
403 API tokens do not have permission to access this endpoint | An integration called /stats/, /emails/ or another endpoint outside its list. | Use a staff access token from an Administrator. |
400 The newsletter parameter doesn't match any active newsletter | The slug is wrong, or the newsletter is archived. | Read the slugs from GET /admin/newsletters/?filter=status:active. |
409 UpdateCollisionError | The PUT carried an old updated_at. | Send the updated_at from the latest response. |
Ghost API limitsRate limits, text and media.
- PlansGhost(Pro) Starter, $18 a month billed yearly, has no custom integrations, Admin API, webhooks or Zapier. Publisher, $29, adds them, and Business is $199; those prices cover up to 1,000 members.
- UploadsGhost(Pro) caps media files at 5 MB on Starter, 100 MB on Publisher, 250 MB on Business and 1 GB on Custom. Self-hosted, Ghost's docs point at nginx's default limit of 50 MB.
- EmailGhost(Pro) includes delivery, with unlimited sends on every plan. Self-hosted sites need Mailgun, the only bulk email provider Ghost supports. A post is emailed once, when it first moves to published.
- Rate limitsGhost publishes no number. Since Ghost 6, a list returns 100 records at most and limit=all is gone, and Ghost asks for small delays in bulk jobs.
Is the Ghost API free?
Yes. Ghost is open-source software under the MIT license, and the Admin API is part of every self-hosted install, at no cost.
On Ghost(Pro), the API comes with the plan: Publisher at $29 a month billed yearly for up to 1,000 members, Business at $199. Starter, at $18, doesn't include it. Newsletter sends are unlimited on every plan.
Through Breakreach, a Ghost site counts like any other connected account: $5 a month each up to 20, $3 up to 100, then $2.
Ways to post to Ghost from code
| What you set up | Price | Posts to Ghost | |
|---|---|---|---|
| Breakreach | An API key. Sites connect with the Admin API key of a custom integration, or your users connect theirs on a hosted page | $5 a month per account, less from 21 | Yes, Self-hosted and Ghost(Pro) Publisher and up, newsletter included |
| Ghost's own API | A custom integration's Admin API key per site, signed as a JWT for each request | Free self-hosted; Ghost(Pro) from $29 a month (Publisher) | Yes |
| Upload-Post | An API key | Free for 2 profiles and 10 uploads a month; Basic $24 a month for 5 profiles | No |
| Zernio | An API key | First 2 accounts free, then $6 per account up to 10, $3 up to 100, $1 after | No |
| Ayrshare | An API key | From $149 a month for 1 profile, no free plan | No |
| Outstand | An API key | $19 a month for 3,000 posts, then per post | No |
What the Ghost API can't do
- Send email from the POST that creates a post: only the PUT to published does
- Email a post that's already published, unless it goes back to draft first
- Read web analytics with an integration key: /stats/ is closed to integrations
- Turn a bare <video> into a video card: it needs Ghost's own markup
- Work on Ghost(Pro) Starter
Post to Ghost with Breakreach's APIOne request, scheduled, with retries.
What it posts on Ghost
- Blog postsThe first line is the title. Paragraphs, ## headings, lists, bold, links and code blocks go to Ghost as HTML, which it turns into editor cards.
- Feature image, photos and videoThe first photo is uploaded to the site as the feature image; up to 9 more follow as image cards, and a video is uploaded as a video card.
- NewsletterarticleSettings.newsletter, default or a slug, with emailSegment all, status:free or status:-free. If Ghost won't send the email, the post still goes out on the site and its error says why.
- Tags, canonical URL and draftsTags are created when new, canonicalUrl points at the original, and asDraft leaves the post in Ghost Admin to finish.
Not yet
- Pages, and members-only or paid posts
- Authors, excerpts and meta fields
- Views and email opens: the member count only
- Ghost(Pro) Starter
The full reference, webhooks and the price per connected account are on the developers page, and the OpenAPI spec is at api.breakreach.com/v1/openapi.json.
Questions, answered.
Short answers about the Ghost API.
Yes on self-hosted Ghost, where it's part of the open-source install. On Ghost(Pro) it takes the Publisher plan or above, from $29 a month billed yearly; Starter has no Admin API.
In Ghost Admin, Settings → Integrations → Add custom integration. The integration shows a Content API key, an Admin API key and the API URL. Use the Admin API key, written id:secret, to sign a JWT for each request.
POST /ghost/api/admin/posts/?source=html with {"posts": [{"title": …, "html": …, "status": "published"}]} and the header Authorization: Ghost <token>. Without ?source=html, Ghost ignores the html and the post comes out empty.
Create it as a draft, then PUT /admin/posts/{id}/?newsletter={slug}&email_segment=all with status published and its updated_at. Ghost only emails a post on that move to published, never from the POST that creates it.
Yes: status scheduled with a future published_at. To email it too, schedule it with a PUT that carries ?newsletter=, since a POST ignores it. At that time Ghost publishes the post and sends the email.
On Ghost(Pro) Starter, every integration request answers HostLimitError, since the plan has no Admin API. Otherwise, the endpoint is outside what integrations can reach, like /stats/, which takes a staff access token.
$5 a month per connected account up to 20, $3 up to 100, then $2. Each Ghost site is one account. You pay per connected account, never per post or per request.
Keep reading
Put your socials on autopilot.Live in two minutes.
Plans from $29 a month. Cancel anytime.