AgentSkillsCN

ghost-admin-api-html-source

解决在使用 HTML 时,Ghost Admin API 创建的帖子内容为空的问题。适用场景:(1) Ghost 帖子成功创建,但正文内容为空;(2) POST 请求中已发送 HTML 字段,但发布的帖子却显示为空;(3) 标题正常显示,但 HTML/正文部分一片空白;(4) 在集成 Ghost Admin API 时,需使用 HTML 内容。解决方法是:将 source=html 作为 QUERY PARAMETER 使用,而非放入 JSON 请求体中。

SKILL.md
--- frontmatter
name: ghost-admin-api-html-source
description: |
  Fix for Ghost Admin API posts created with empty content when using HTML. Use when:
  (1) Ghost posts are created successfully but have no body content, (2) HTML field is
  sent in POST request but post appears empty, (3) title appears but html/body is blank,
  (4) implementing Ghost Admin API integration with HTML content. The fix is to use
  source=html as a QUERY PARAMETER, not in the JSON request body.
author: Claude Code
version: 1.0.0
date: 2026-01-21

Ghost Admin API HTML Source Parameter

Problem

When creating posts via the Ghost Admin API with HTML content, posts are created successfully (201 response, post ID returned) but the HTML content is empty. Only the title appears in the Ghost editor.

Context / Trigger Conditions

  • POST to /ghost/api/admin/posts/ returns 201 success
  • Post is created with correct title
  • HTML content in response/editor is empty (0 chars)
  • You're sending html field in the JSON body
  • You may have tried adding source: "html" to the JSON body (this doesn't work)

Root Cause

Ghost's Admin API requires source=html as a query parameter, not in the JSON request body. The Ghost JavaScript SDK handles this automatically, but raw HTTP implementations need to add it manually.

The JS SDK call:

javascript
api.posts.add({ title, html }, { source: "html" })

Translates to the raw API as:

code
POST /ghost/api/admin/posts/?source=html

Solution

Correct Approach (Query Parameter)

code
POST /ghost/api/admin/posts/?source=html
Content-Type: application/json
Authorization: Ghost {jwt_token}

{
  "posts": [{
    "title": "My Post",
    "html": "<h2>Content here</h2><p>This will work!</p>",
    "status": "draft"
  }]
}

Incorrect Approach (Body Parameter - Does NOT Work)

code
POST /ghost/api/admin/posts/
Content-Type: application/json

{
  "posts": [{ "title": "My Post", "html": "<p>Content</p>" }],
  "source": "html"  // <-- This is IGNORED!
}

Implementation Examples

Python (requests):

python
url = f"{ghost_url}/ghost/api/admin/posts/?source=html"
response = requests.post(url, json={"posts": [post_data]}, headers=headers)

Rust (reqwest):

rust
let url = format!("{}/ghost/api/admin/posts/?source=html", base_url);
client.post(&url).json(&request_body).send().await?;

For updates (PUT), also use the query parameter:

code
PUT /ghost/api/admin/posts/{id}/?source=html

Verification

After creating a post, fetch it back and check the HTML length:

python
get_url = f"{ghost_url}/ghost/api/admin/posts/{post_id}/?formats=html"
response = requests.get(get_url, headers=headers)
html = response.json()["posts"][0].get("html", "")
print(f"HTML length: {len(html)}")  # Should be > 0

Example

Before fix:

code
Created post: 6970a142...
HTML length: 0  # Empty!

After fix:

code
Created post: 6970a3f0...
HTML length: 938  # Content preserved!

Notes

  • This applies to both POST (create) and PUT (update) operations
  • The formats=html query parameter on GET requests is separate - that's for specifying the return format
  • Ghost internally converts HTML to its mobiledoc/lexical format for storage
  • The conversion is "lossy" - some HTML elements may not be preserved exactly
  • For complex HTML, consider using mobiledoc format directly

References