Using APIs to write content.

Using APIs to write content.

September 6, 2025

TL;DR

As lately im like a kid with APIs, have setup WP and Ghost, just to tinker with them.

⚠️
Ghost and WP both provide a RESTAPI.

Intro

Just because you can…dont become a BOT.

For real, even if you know how to use Codex CLI + HUGO to generate project docs for OSS projects.

For today’s post: with Ghost and Wordpress ready to go into your homelab/server, we are ready to play.

They provide a cool UI.

But come on, do you really want to spend time with drag and drop still?

Even configuring your n8n to write into wordpress for you is possible.

Star History Chart

Because n8n has been taking over lately…

Programatic Posts

Because if LLMs can generate nice markdown, or help you do web research… why should you build all that post skeleton?

Programatic WP

Its all about REST APIs.

WordPress includes a powerful REST API by default, allowing you to interact with your site’s content programmatically.

  • Base URL: $WP_HOME/wp-json/wp/v2/
  • Authentication: For read-only public content, no auth is needed.
    • For creating/updating content, you need to use Application Passwords like so.
  1. List latest 5 posts (public)
source .env
curl "$WP_HOME/wp-json/wp/v2/posts?per_page=5"
  1. Get a post by its slug
# Replace 'hello-world' with your post's slug
curl "$WP_HOME/wp-json/wp/v2/posts?slug=hello-world"
  1. Create a post: this requires wp app pwd
curl -u 'jalcocert:bzkh]FTp3}T]#Mj' -X POST "$WP_HOME/wp-json/wp/v2/posts" \
    -H 'Content-Type: application/json' \
    -d '{
    "title": "Hello from REST API",
    "content": "This post was created programmatically.",
    "status": "draft"
    }'

Setting Up Application Passwords for WP

Important: Application Passwords are different from your WordPress login credentials. They are special passwords created specifically for API access.

  1. Log in to your WordPress Admin dashboard ($WP_HOME/wp-admin)
  2. Go to UsersProfile
  3. Scroll down to the “Application Passwords” section (near the bottom of the page)
  4. In the “New Application Password Name” field, enter a descriptive name (e.g., api-client)
  5. Click “Add New Application Password”
  6. Critical: Copy the generated password immediately - it will only be shown once!
  7. Store this password securely

Authentication Details

  • Username: Your WordPress username (not your email address)
  • Password: The generated application password (not your WordPress login password)
  • User Role: Ensure your user has sufficient permissions (Administrator role recommended)

Programatic Ghost

See https://github.com/JAlcocerT/Home-Lab/blob/main/ghost/API.md after you have done your Ghost setup


Conclusions


FAQ

Ghost Setup

They recently released v6:

MIT | Independent technology for modern publishing, memberships, subscriptions and newsletters.

#cd ghost
echo -e "MYSQL_DATABASE=ghost\nMYSQL_USER=ghostuser\nMYSQL_PASSWORD=$(openssl rand -base64 32)\nMYSQL_ROOT_PASSWORD=$(openssl rand -base64 32)" > .env
docker compose up -d #Grist will be at 8018

http://192.168.1.8:8018/ and http://192.168.1.8:8018/ghost/

  1. Sign in to your Ghost Admin: http://192.168.1.8:8018/ghost (or http://localhost:8018/ghost).
  2. Go to: Settings → Integrations → Add custom integration.
  3. You’ll get:
    • Content API Key
    • Admin API Key (format: <key_id>:<secret>)

The content API is ready only:

source .env
curl "$GHOST_URL/ghost/api/content/posts/?key=$GHOST_CONTENT_API_KEY&limit=1"

But you can use the Admin API via Ghost JS SDK:

#npm i dotenv
#npm i @tryghost/admin-api
node admin-test.js

And to create posts programatically via a markdown:

cd ghost
#npm i gray-matter marked

node scripts/create-post.js
node scripts/create-post.js samples/sample-post-publish.md
# HTML length: 1034
# Uploaded feature image -> http://192.168.1.8:8018/content/images/2025/09/JAlcocerTechlogo-2.png
# Created post: {
#   id: '68bbfbd437865200016ec434',
#   slug: 'hello-from-markdown-6',
#   status: 'published',
#   url: 'http://192.168.1.8:8018/hello-from-markdown-6/'
# }
curl "$GHOST_URL/ghost/api/content/posts/slug/hello-from-markdown-6/?key=$GHOST_CONTENT_API_KEY&formats=html&include=tags,authors"

Wordpress Setup

#cd wordpress


echo -e "MYSQL_DATABASE=wordpress\nMYSQL_USER=wpuser\nMYSQL_PASSWORD=$(openssl rand -base64 32)\nMYSQL_ROOT_PASSWORD=$(openssl rand -base64 32)\nWP_HOME=http://192.168.1.8:8082\nWP_SITEURL=http://192.168.1.8:8082" > .env

docker compose up -d #WP will be at 8082 

http://192.168.1.8:8082/wp-admin/

Rest vs GraphQL vs Gatsby

How Ghost and WordPress function as headless CMS options when used with Gatsby, focusing on their API architectures and how Gatsby interacts with each.

Gatsby acts as a static site generator with a modern twist.

  1. Build-Time Data Layer:

    • At build time, Gatsby fetches data from various sources (like Ghost or WordPress)
    • It creates an in-memory GraphQL data layer that represents all your content
    • This happens once during the build process
  2. Runtime Behavior:

    • The generated site is static HTML/CSS/JS
    • No GraphQL server runs in production
    • All GraphQL queries are executed at build time
    • The result is baked into the final static files
  3. Hybrid Approach:

    • For dynamic content, you can use:
      • Client-side data fetching (e.g., fetch())
      • Serverless functions
      • Incremental Static Regeneration (ISR)
      • Deferred Static Generation (DSG)

Ghost

  • Native API Type: REST
  • Key Features:
    • Content API: Read-only REST API for fetching published content
    • Admin API: Read-write REST API for content management
    • Authentication: API keys (Content API) and JWT (Admin API)
    • No Native GraphQL: Uses REST endpoints exclusively

WordPress

  • Native API Type: REST
  • Key Features:
    • REST API: Built into core, supports CRUD operations
    • Authentication: Application Passwords, OAuth, or JWT (via plugins)
    • GraphQL: Available via plugins (e.g., WPGraphQL)

How Gatsby could Work with These CMSs

  1. Build-Time Data Fetching:

    • Gatsby’s source plugins fetch data during build time
    • For both Ghost and WordPress, this happens via their REST APIs
    • Data is transformed and added to Gatsby’s internal data layer
  2. Ghost with Gatsby:

    • Uses gatsby-source-ghost plugin
    • Fetches content from Ghost’s Content API
    • Makes data available via Gatsby’s GraphQL layer
    • Example query:
      query {
        allGhostPost {
          edges {
            node {
              title
              slug
              excerpt
              published_at
            }
          }
        }
      }
  3. WordPress with Gatsby:

    • Uses gatsby-source-wordpress plugin
    • Can use either REST API or WPGraphQL
    • Transforms data into Gatsby’s GraphQL schema
    • Example query:
      query {
        allWpPost {
          edges {
            node {
              title
              slug
              excerpt
              date
            }
          }
        }
      }

REST API vs GraphQL: Key Differences

FeatureREST APIGraphQL
Data FetchingMultiple endpointsSingle endpoint
Response StructureFixed by serverClient-defined
Over-fetchingCommon (get more than needed)Rare (request only what you need)
Under-fetchingCommon (need multiple calls)Rare (get all in one query)
VersioningRequired (v1/, v2/)Not needed (evolve schema)
CachingBuilt into HTTPRequires custom solution
Learning CurveLowerSteeper
ToolingStandard HTTP toolsSpecialized clients
Real-timeRequires WebSocketsBuilt-in subscriptions
Error HandlingHTTP status codes200 OK with errors in body

CMS-Specific Differences

FeatureGhostWordPress
Native API TypeREST (Content + Admin)REST (Core)
GraphQL SupportNo (REST only)Yes (via WPGraphQL plugin)
AuthenticationAPI Keys + JWTVarious (App Passwords, OAuth)
Content StructureSimpler, more opinionatedHighly flexible, customizable
Media HandlingBuilt-in image optimizationRequires additional plugins
Real-time UpdatesWebhooks availableWebhooks available

Choose Ghost if:

  • You prefer a simpler, more focused content structure
  • Built-in image optimization is important
  • You’re comfortable with REST APIs
  • You want a more streamlined authoring experience

Choose WordPress if:

  • You need maximum flexibility in content modeling
  • You prefer working with GraphQL
  • You have existing WordPress content
  • You need extensive plugin ecosystem

Both Ghost and WordPress can serve as effective headless CMS options for Gatsby.

Ghost offers a more streamlined experience with its focused feature set, while WordPress provides greater flexibility and an extensive plugin ecosystem.

Codex CLI + HUGO

If Codex can generate documentation for QA Trackhttps://youtu.be/e_l6HJISIrs

It can definitely generate markdown posts summaries about it or any other project.

n8n x Wordpress