背景

最近在做博客自动化,想通过 AI Agent 每天自动发布技术文章。在对接 Halo CMS API 时踩了不少坑,记录一下。

问题现象

使用 Extension API 创建文章:

POST /apis/content.halo.run/v1alpha1/posts

返回 201 创建成功,但文章无法发布

原因分析

检查文章状态发现:

| 字段 | Extension API 创建 | Console API 创建 | |------|-------------------|-----------------| | headSnapshot | N/A | 有值 | | releaseSnapshot | N/A | 有值 | | phase | DRAFT | DRAFT → PUBLISHED |

Halo 的 Snapshot 机制:文章内容存储在 Snapshot 中,没有 Snapshot 的文章无法发布。

正确方式

创建文章(Console API)

POST /apis/api.console.halo.run/v1alpha1/posts

请求体:

{
  "post": {
    "apiVersion": "content.halo.run/v1alpha1",
    "kind": "Post",
    "metadata": {"name": ""},
    "spec": {
      "title": "标题",
      "slug": "slug",
      "publish": false
    }
  },
  "content": {
    "raw": "Markdown内容",
    "content": "HTML内容",
    "rawType": "markdown"
  }
}

发布文章

PUT /apis/api.console.halo.run/v1alpha1/posts/{name}/publish

经验总结

1. Extension API 是底层 CRUD,不会创建 Snapshot

  • Console API 是业务 API,自动处理 Snapshot
  • 返回码:Console API 返回 200(不是 201)
  • 遇到问题看 Halo CLI 源码

  • 完整代码

    import requests
    import uuid

    def create_and_publish(title, slug, content, token): headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json" } # 创建 name = str(uuid.uuid4()) resp = requests.post( "https://blog.example.com/apis/api.console.halo.run/v1alpha1/posts", headers=headers, json={ "post": { "apiVersion": "content.halo.run/v1alpha1", "kind": "Post", "metadata": {"name": name}, "spec": {"title": title, "slug": slug, "publish": False} }, "content": { "raw": content, "content": content, "rawType": "markdown" } } ) if resp.status_code == 200: # 发布 requests.put( f"https://blog.example.com/apis/api.console.halo.run/v1alpha1/posts/{name}/publish", headers=headers )