> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pendpost.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ghost

> Set up Ghost posting with an Admin API key from a custom integration.

The Ghost lane publishes posts to a Ghost publication through its Admin API. It publishes only once a Ghost credential is present in your `.env`; until then the lane is live-but-unauthenticated and waits for you to connect it (set `PENDPOST_MODE=mock` to exercise it through the mock driver).

You own your Ghost site and are responsible for its terms of service. pendpost drafts and schedules, but a human approves before anything goes live.

## Setup ceremony

The engine talks to the Admin API at `<site>/ghost/api/admin`. Authentication is a custom integration's Admin API key, so there is no review.

1. **Record the site URL.** Record the publication's root URL, for example `https://blog.example.com`.
2. **Create a custom integration.** In Ghost admin open Settings > Integrations > Add custom integration, name it (for example `pendpost`), and save. Copy the **Admin API key**, the long `id:secret` pair. The Content API key is read-only and not enough.

Then validate. It mints a short-lived JWT from the key and reads the site record:

```bash theme={null}
node scripts/ghost-social.mjs auth
```

> [!NOTE]
>
> **Newsletter opt-in (optional).** A post with "also send as newsletter" enabled emails your members on publish, via the first active newsletter. Ghost only sends that email on the draft-to-published transition, so the flag cannot be re-fired later.

## Environment variables

| Variable | Purpose |
| - | - |
| `GHOST_SITE_URL` | The publication's root URL, for example `https://blog.example.com`. |
| `GHOST_ADMIN_API_KEY` | The Admin API key (`id:secret`) from the custom integration. |

> [!NOTE]
>
> A lane publishes only once its credential is present. If the Ghost variables are blank, the Ghost lane is live-but-unauthenticated and waits for you to connect it. Set `PENDPOST_MODE=mock` to exercise it through the mock driver.

## Validate the lane

A present credential is not the same as a working one. After setup, validate the Ghost lane in the **Setup** tab, or run a live probe with the `health_recheck` tool, to confirm the credential is live and not just configured. The lane is ready when it reports live.

> [!NOTE]
>
> **Over MCP.** Setup and rotation are an interactive human ceremony; secrets are never written through MCP. An agent can still check status (`account_status`), run a live liveness probe (`health_recheck`), and read non-secret config (`config_get`) over MCP without touching credentials.

## Common failures

| Symptom | Cause | Fix |
| - | - | - |
| HTTP 401 UNAUTHORIZED on every call. | The Content API key was copied instead of the Admin API key, or the integration was deleted. | Copy the Admin API key (`id:secret`) from the custom integration and reconnect. |
| Publish succeeds but no newsletter email arrives. | No active newsletter exists, members are zero, or the post was already published without the flag. | Activate a newsletter under Settings > Newsletters and re-check member signups; the email only fires on first publish. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.