Update Post
ghost.update_post
ActionBusiness appsconnection required
Calls the Ghost API with the connection's credentials.
Update an existing post. Only the fields you fill in are sent, so a title-only change leaves the body and its tags untouched.
Connection
- Required
- Yes — the node will not save without one
- Auth type
- API key
- Providers
- Ghost
- Secret shape
- {"admin_api_key": "<id>:<secret>", "content_api_key": "…"}
- Config it needs
- admin_url, api_version
- Resolved by
- config.connection_id, else node.connection_id
Configuration
24 fields, 1 required. A dotted path is a nested object and name[] an array of objects — the editor renders the same tree.
| Field | Type | Required | Default | Constraints | Example |
|---|---|---|---|---|---|
post_id Ghost id of the post — the 24-character ObjectID from a previous step. | string | Yes | — | — | — |
updated_at The updated_at you read from the post, sent back so Ghost can refuse an edit that would overwrite a newer change. Leave it empty and the node re-reads the post first, which drops that protection. | string | No | — | iso8601 format | — |
title New title for the post. Left empty, the current title is kept. | string | No | — | — | — |
html Body of the post as HTML. Ghost converts it to Lexical, which is lossy, so keep the markup well formed. Use this or 'lexical', never both. | string | No | — | — | — |
lexical Body of the post as a Lexical JSON document, serialised to a string. This is Ghost's native format and round-trips losslessly. | string | No | — | — | — |
status Publication status. Leave it unset on a create and Ghost saves a draft that is not visible on the site; leave it unset on an update and the current status is kept. 'scheduled' also needs a future published_at. | string | No | — | one of "draft", "published", "scheduled" | — |
visibility Who may read the post: everyone, signed-in members, paying members, or the specific tiers named in extra_fields. Left unset, a new post is public and an existing one keeps the visibility it has. | string | No | — | one of "public", "members", "paid", "tiers" | — |
published_at Publication timestamp in ISO 8601 UTC (2026-09-09T10:00:00.000Z). A future value combined with status 'scheduled' is how Ghost schedules a post. | string | No | — | iso8601 format | — |
featured Whether to flag the post as featured on the site. | boolean | No | — | — | — |
slug URL slug for the post. Ghost derives one from the title when this is empty. | string | No | — | — | — |
custom_excerpt Short summary shown in listings and social cards, replacing the excerpt Ghost generates from the body. | string | No | — | — | — |
feature_image URL of the image shown at the top of the post. Ghost does not fetch it; the URL must already be reachable. | string | No | — | url format | — |
feature_image_alt Alternative text describing the feature image, for screen readers. | string | No | — | — | — |
feature_image_caption Caption rendered under the feature image; accepts inline HTML. | string | No | — | — | — |
canonical_url Canonical URL to credit when the post is republished from somewhere else. | string | No | — | url format | — |
meta_title Title used in the page's meta tags, when it should differ from the post title. | string | No | — | — | — |
meta_description Description used in the page's meta tags and search results. | string | No | — | — | — |
tags Tags for the post, as a JSON array or a comma-separated list of names. Ghost creates a tag it cannot match, and this replaces the post's current tags. | array | No | — | array of string | — |
authors Authors for the post, as a JSON array or a comma-separated list of staff email addresses. Ghost falls back to the site owner when none match. | array | No | — | array of string | — |
extra_fields Any other writable Ghost field, as a JSON object merged into the request body — codeinjection_head, custom_template, og_title, tiers and the rest. | object | No | — | — | — |
save_revision Whether Ghost should store a new revision of the post alongside this edit. | boolean | No | — | — | — |
newsletter Slug of the newsletter to send this post to. Ghost emails a post only when an active newsletter slug is given; leave it empty to publish silently. | string | No | — | — | — |
email_segment An NQL member filter limiting who receives the email, such as 'status:free' or 'status:-free'. Defaults to every subscriber of the newsletter. | string | No | — | — | — |
email_only Whether to send the post as an email without publishing it on the site. Needs a newsletter slug, and leaves the post with status 'sent'. | boolean | No | — | — | — |
Output
One shape.
result
| Field | Type | Example |
|---|---|---|
id Ghost id of the record, a 24-character ObjectID. | string | — |
uuid Stable public uuid of the record. | string | — |
title Title Ghost stored. | string | — |
slug URL slug Ghost stored. | string | — |
status Publication status: draft, published, scheduled or sent. | string | — |
visibility Who may read it: public, members, paid or tiers. | string | — |
featured Whether the record is flagged as featured. | boolean | — |
url Public URL on the site; a draft gets its preview URL. | string | — |
excerpt Custom excerpt when one is set, else one Ghost derived. | string | — |
feature_image URL of the feature image, null when there is none. | string | — |
published_at When it was, or will be, published (ISO 8601 UTC). | string | — |
created_at When the record was created (ISO 8601 UTC). | string | — |
updated_at When it last changed — pass this back on the next edit. | string | — |
html Rendered HTML; present only when formats asked for it. | string | — |
lexical Lexical source of the body, as a JSON string. | string | — |
tags Tags on the record; present only with include=tags. | array | — |
authors Authors of the record; present only with include=authors. | array | — |
email_only True when the post was emailed and not put on the site. | boolean | — |
newsletter.slug Slug of the newsletter the post was sent to. | string | — |
email.status Delivery state of the send: submitted, or failed. | string | — |
email.error Why Ghost could not send it, when the status is failed. | string | — |
email.email_count How many members the email was addressed to. | number | — |
email.delivered_count How many deliveries Ghost has confirmed so far. | number | — |
email.failed_count How many deliveries have failed so far. | number | — |
{
"authors": [],
"created_at": "",
"email": {
"delivered_count": 0,
"email_count": 0,
"error": "",
"failed_count": 0,
"status": ""
},
"email_only": false,
"excerpt": "",
"feature_image": "",
"featured": false,
"html": "",
"id": "",
"lexical": "",
"newsletter": {
"slug": ""
},
"published_at": "",
"slug": "",
"status": "",
"tags": [],
"title": "",
"updated_at": "",
"url": "",
"uuid": "",
"visibility": ""
}Notes
- PUT /ghost/api/admin/posts/{id}/.
- Ghost requires updated_at on an edit: send the value you read from the post, or the node re-reads it first and the collision guard no longer applies.
- Tags and authors are replaced, not merged — read the post first and send the full list you want it to end up with.
See Update Post run in a workflow.
In a technical demo we add the Ghost connection, drop the node on the canvas and let Workflow Health pre-flight it before the first real run.