<!-- BusyBot node reference — https://busybot.net/tools/ghost/ -->

> Node: Ghost (`ghost`) · Action · v1
> Category: Marketing · Credentials: Ghost Admin API (`ghostAdminApi`), Ghost Content API (`ghostContentApi`)
> Updated: 2026-08-16

# Ghost

> Manage posts on a Ghost CMS instance.

## Overview

The Ghost tool interacts with a Ghost CMS instance. It supports two API sources: the Content API (read-only, for fetching published posts) and the Admin API (full CRUD for creating, reading, updating, and deleting posts). The Content API uses a simple API key as a query parameter, while the Admin API uses JWT-based authentication generated from an admin API key in id:secret format. Supports pagination for listing posts, multiple content formats (HTML, MobileDoc, Lexical), and post metadata including SEO, Open Graph, and Twitter card fields.

**Category:** Marketing  
**Tool Name:** `ghost`  
**Version:** 1

**Appearance:** Icon: `si-ghost` | Color: `#15171A`

## Node Type

**Action** — processes input items and produces output

## Input / Output

| Direction | Port(s) |
|-----------|--------|
| Input | `Input` |
| Output | `Output`, `Error` |

## Credentials

This tool uses **Ghost Admin API** and **Ghost Content API** credentials. Configure the one that matches the Source you select — the Content API key for read-only operations, the Admin API key for everything else.
See the [Credentials Guide](https://busybot.net/credentials/) for setup instructions.

### Resources

| Resource | Value |
|----------|-------|
| Post | `post` |

### Operations

Which operations are available depends on **Source**, not on the resource — the Content API is read-only, the Admin API can also write. Pick the source first, then the operation.

| Source | Operation | Value | Description |
|--------|-----------|-------|-------------|
| Content API (`contentApi`) | Get | `get` | Get a post |
| Content API (`contentApi`) | Get Many | `getAll` | Get many posts |
| Admin API (`adminApi`) | Create | `create` | Create a post |
| Admin API (`adminApi`) | Delete | `delete` | Delete a post |
| Admin API (`adminApi`) | Get | `get` | Get a post |
| Admin API (`adminApi`) | Get Many | `getAll` | Get many posts |
| Admin API (`adminApi`) | Update | `update` | Update a post |

### Parameters

Source and Operation are the two selectors that decide everything else. Source, Operation, By, Identifier, Title, Content and Post ID accept expressions, so they can be driven from the incoming item; values placed **inside** the Additional Fields, Update Fields and Options collections are sent exactly as typed.

#### All Operations

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Source | `options` | No | `contentApi` | Pick where your data comes from: Content API (read-only) or Admin API (full CRUD). |
| | | | | Options: `adminApi`, `contentApi` |
| Max Concurrency | `number` | No | `10` | Maximum number of items to process concurrently (1–100). |

#### Content API: Get

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| By | `options` | Yes | `id` | Get the post either by slug or ID. |
| | | | | Options: `id`, `slug` |
| Identifier | `string` | Yes | — | The ID or slug of the post to get. |
| Options | `collection` | No | `{}` | Query options for the request. |
| — Fields (`fields`) | `string` | No | — | Limit the fields returned in the response object. E.g. fields=title,url. |
| — Formats (`formats`) | `multiOptions` | No | `['html']` | Content formats to return. |
| | | | | Options: `html`, `plaintext` |

#### Content API: Get Many

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Return All | `boolean` | No | `false` | Whether to return all results or only up to a given limit. |
| Limit | `number` | No | `50` | Max number of results to return (1–100). _(shown when Return All is `false`)_ |
| Options | `collection` | No | `{}` | Query options for the listing. |
| — Include (`include`) | `multiOptions` | No | `[]` | Tells the API to return additional data related to the resource. |
| | | | | Options: `authors`, `tags` |
| — Fields (`fields`) | `string` | No | — | Limit the fields returned in the response object. E.g. fields=title,url. |
| — Formats (`formats`) | `multiOptions` | No | `['html']` | Content format(s) to return. By default only html is returned. |
| | | | | Options: `html`, `plaintext`, `lexical` |

#### Admin API: Create

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Title | `string` | Yes | — | Post's title. |
| Content Format | `options` | No | `html` | The format of the post content. |
| | | | | Options: `html`, `mobileDoc`, `lexical` |
| Content | `string` | No | — | The HTML content of the post to create. _(shown when Content Format is `html`)_ |
| Content (JSON) | `json` | No | — | Mobiledoc is the raw JSON format that Ghost uses to store post contents. Must parse as valid JSON or the item fails. _(shown when Content Format is `mobileDoc`)_ |
| Content (JSON) | `json` | No | — | Lexical is the JSON format returned by the Ghost Default editor. Must parse as valid JSON or the item fails. _(shown when Content Format is `lexical`)_ |
| Additional Fields | `collection` | No | `{}` | Optional properties to set on the new post. |
| — Authors (`authors`) | `string` | No | — | Comma-separated list of author IDs. Find author IDs via the Ghost Admin API /users endpoint. |
| — Canonical URL (`canonical_url`) | `string` | No | — | Canonical URL for the post. |
| — Code Injection Foot (`codeinjection_foot`) | `string` | No | — | Code injection snippet for the footer. |
| — Code Injection Head (`codeinjection_head`) | `string` | No | — | Code injection snippet for the header. |
| — Featured (`featured`) | `boolean` | No | `false` | Whether the post is featured. |
| — Meta Description (`meta_description`) | `string` | No | — | SEO meta description. |
| — Meta Title (`meta_title`) | `string` | No | — | SEO meta title. |
| — Open Graph Description (`og_description`) | `string` | No | — | Open Graph description. |
| — Open Graph Image (`og_image`) | `string` | No | — | URL of the image. |
| — Open Graph Title (`og_title`) | `string` | No | — | Open Graph title. |
| — Published At (`published_at`) | `dateTime` | No | — | Required when status is "scheduled". |
| — Slug (`slug`) | `string` | No | — | URL slug for the post. |
| — Status (`status`) | `options` | No | `draft` | Publication state of the post. |
| | | | | Options: `draft`, `published`, `scheduled` |
| — Tags (`tags`) | `string` | No | — | Comma-separated list of tag names. Ghost will create tags if they do not exist. |
| — Twitter Description (`twitter_description`) | `string` | No | — | Twitter card description. |
| — Twitter Image (`twitter_image`) | `string` | No | — | URL of the image. |
| — Twitter Title (`twitter_title`) | `string` | No | — | Twitter card title. |

#### Admin API: Delete

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Post ID | `string` | Yes | — | The ID of the post to delete. |

#### Admin API: Get

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| By | `options` | Yes | `id` | Get the post either by slug or ID. |
| | | | | Options: `id`, `slug` |
| Identifier | `string` | Yes | — | The ID or slug of the post to get. |
| Options | `collection` | No | `{}` | Query options for the request. |
| — Fields (`fields`) | `string` | No | — | Limit the fields returned in the response object. E.g. fields=title,url. |
| — Formats (`formats`) | `multiOptions` | No | `['mobiledoc']` | Content formats to return. |
| | | | | Options: `html`, `mobiledoc`, `lexical` |

#### Admin API: Get Many

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Return All | `boolean` | No | `false` | Whether to return all results or only up to a given limit. |
| Limit | `number` | No | `50` | Max number of results to return (1–100). _(shown when Return All is `false`)_ |
| Options | `collection` | No | `{}` | Query options for the listing. |
| — Include (`include`) | `multiOptions` | No | `[]` | Tells the API to return additional data related to the resource. |
| | | | | Options: `authors`, `tags` |
| — Fields (`fields`) | `string` | No | — | Limit the fields returned in the response object. E.g. fields=title,url. |
| — Formats (`formats`) | `multiOptions` | No | `['mobiledoc']` | Content formats to return. |
| | | | | Options: `html`, `mobiledoc`, `lexical` |

#### Admin API: Update

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Post ID | `string` | Yes | — | The ID of the post to update. |
| Content Format | `options` | No | `html` | The format of the post content. It decides which content field below is used. |
| | | | | Options: `html`, `mobileDoc`, `lexical` |
| Update Fields | `collection` | No | `{}` | Fields to change. Only the fields you add are sent. |
| — Authors (`authors`) | `string` | No | — | Comma-separated list of author IDs. Find author IDs via the Ghost Admin API /users endpoint. |
| — Canonical URL (`canonical_url`) | `string` | No | — | Canonical URL for the post. |
| — Code Injection Foot (`codeinjection_foot`) | `string` | No | — | Code injection snippet for the footer. |
| — Code Injection Head (`codeinjection_head`) | `string` | No | — | Code injection snippet for the header. |
| — Content (`content`) | `string` | No | — | HTML content of the post. _(shown when Content Format is `html`)_ |
| — Content (JSON) (`contentJson`) | `json` | No | — | Mobiledoc JSON content of the post. _(shown when Content Format is `mobileDoc`)_ |
| — Content (JSON) (`contentJson`) | `json` | No | — | Lexical JSON content of the post. _(shown when Content Format is `lexical`)_ |
| — Featured (`featured`) | `boolean` | No | `false` | Whether the post is featured. |
| — Meta Description (`meta_description`) | `string` | No | — | SEO meta description. |
| — Meta Title (`meta_title`) | `string` | No | — | SEO meta title. |
| — Open Graph Description (`og_description`) | `string` | No | — | Open Graph description. |
| — Open Graph Image (`og_image`) | `string` | No | — | URL of the image. |
| — Open Graph Title (`og_title`) | `string` | No | — | Open Graph title. |
| — Published At (`published_at`) | `dateTime` | No | — | Required when status is "scheduled". |
| — Slug (`slug`) | `string` | No | — | URL slug for the post. |
| — Status (`status`) | `options` | No | `draft` | Publication state of the post. |
| | | | | Options: `draft`, `published`, `scheduled` |
| — Tags (`tags`) | `string` | No | — | Comma-separated list of tag names. Ghost will create tags if they do not exist. |
| — Title (`title`) | `string` | No | — | Post's title. |
| — Twitter Description (`twitter_description`) | `string` | No | — | Twitter card description. |
| — Twitter Image (`twitter_image`) | `string` | No | — | URL of the image. |
| — Twitter Title (`twitter_title`) | `string` | No | — | Twitter card title. |

## Output Data

The post returned by Ghost is **merged onto the input item's JSON** at the top level — the fields the item already carried survive, and a post field with the same name overwrites the item's value. Downstream nodes address the post directly (`{{ $json.id }}`, `{{ $json.title }}`). Binary data on the input item is forwarded unchanged.

| Operation | Output |
|-----------|--------|
| Get Many (either source) | **One output item per post returned.** Return All keeps paging until Ghost runs out of posts, so this can be a large fan-out from a single input item. |
| Get, Create, Update (either source) | One output item carrying the post. |
| Delete | One output item carrying `id` and `deleted: true` — Ghost returns no body for a delete. |

When a request comes back with no posts, the input item is still passed through unchanged, so an empty result is an item with no post fields on it rather than a missing item. Check for `id` before treating the branch as a hit.

## Usage Examples

- Get all published posts from Ghost blog
- Create a new draft post on Ghost
- Update an existing Ghost post with new content
- Delete a Ghost post by ID
- Fetch a post by slug from Ghost Content API

## Example Configuration

Create an HTML post as a draft:

```json
{
  "type": "ghost",
  "parameters": {
    "source": "adminApi",
    "resource": "post",
    "operation": "create",
    "title": "{{ $json.title }}",
    "contentFormat": "html",
    "content": "<h1>{{ $json.title }}</h1><p>{{ $json.body }}</p>",
    "additionalFields": {
      "slug": "my-new-blog-post",
      "status": "draft",
      "meta_description": "A great blog post about something interesting",
      "featured": false,
      "tags": "technology,blog"
    }
  }
}
```

Create a post from Mobiledoc JSON, scheduled for a fixed time:

```json
{
  "type": "ghost",
  "parameters": {
    "source": "adminApi",
    "resource": "post",
    "operation": "create",
    "title": "Mobile Doc Post",
    "contentFormat": "mobileDoc",
    "content": "{\"version\":\"0.3.1\",\"atoms\":[],\"cards\":[],\"markups\":[],\"sections\":[[1,\"p\",[[0,[],0,\"This is a mobile doc post.\"]]]]}",
    "additionalFields": {
      "slug": "mobile-doc-post",
      "status": "scheduled",
      "published_at": "2026-01-01T12:00:00Z"
    }
  }
}
```

Read one published post by ID through the Content API:

```json
{
  "type": "ghost",
  "parameters": {
    "source": "contentApi",
    "resource": "post",
    "operation": "get",
    "by": "id",
    "identifier": "{{ $json.postId }}",
    "options": {
      "fields": "id,title,slug,html,published_at",
      "formats": ["html"]
    }
  }
}
```

Read a post by slug:

```json
{
  "type": "ghost",
  "parameters": {
    "source": "contentApi",
    "resource": "post",
    "operation": "get",
    "by": "slug",
    "identifier": "my-new-blog-post",
    "options": {
      "formats": ["html", "plaintext"]
    }
  }
}
```

List the ten most recent posts with their tags and authors:

```json
{
  "type": "ghost",
  "parameters": {
    "source": "adminApi",
    "resource": "post",
    "operation": "getAll",
    "returnAll": false,
    "limit": 10,
    "options": {
      "include": ["tags", "authors"],
      "fields": "id,title,slug,status,published_at",
      "formats": ["html", "mobiledoc"]
    }
  }
}
```

Publish an existing draft:

```json
{
  "type": "ghost",
  "parameters": {
    "source": "adminApi",
    "resource": "post",
    "operation": "update",
    "postId": "{{ $json.id }}",
    "contentFormat": "html",
    "updateFields": {
      "title": "Updated Post Title",
      "content": "<h1>Updated Content</h1><p>This post has been updated.</p>",
      "status": "published",
      "meta_title": "Updated Meta Title",
      "featured": true
    }
  }
}
```

Delete a post:

```json
{
  "type": "ghost",
  "parameters": {
    "source": "adminApi",
    "resource": "post",
    "operation": "delete",
    "postId": "{{ $json.id }}"
  }
}
```

### Error Handling

| Mode | Behavior |
|------|----------|
| **stop** | Halts workflow on first error |
| **continue** | Skips failed items, passes successful ones through |
| **errorPort** | Routes failed items to Error output port |

## Tips

Manages posts on a Ghost CMS instance via Content API (read) or Admin API (CRUD) with JWT authentication.

- **Source picks the credential too.** Content API operations authenticate with the Content API key, Admin API operations with the Admin API key, so the credential you have configured has to match the source you selected.
- **Update replaces the content field it is told to.** Content Format decides which of the content fields inside Update Fields is sent, and on HTML the field is always sent — leaving it empty on an HTML update blanks the post body. Set Content Format to match the editor format the post already uses.
- **Updates are collision-safe.** Before writing, the node reads the post's current timestamp and sends it back with the change, so a post edited elsewhere in the meantime is rejected rather than silently overwritten.
- **Scheduling needs a date.** Setting Status to `scheduled` without Published At fails the item.
- **Tags are created on demand.** Tag names that do not exist yet are created by Ghost; author values must be existing author IDs.