用 REST API 接入任何编辑器
为什么是 WP REST
第三方编辑器(Obsidian、Ulysses、脚本)大多已经支持 WordPress REST。与其为每个工具写适配,不如实现它的一个子集:
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /wp-json/wp/v2/posts |
列表 |
| GET | /wp-json/wp/v2/posts/<id> |
单篇 |
| POST | /wp-json/wp/v2/posts |
新建 |
| PUT/PATCH | /wp-json/wp/v2/posts/<id> |
更新 |
| GET | /wp-json/wp/v2/categories |
分类 |
| GET | /wp-json/wp/v2/tags |
标签 |
| POST | /wp-json/wp/v2/media |
上传媒体 |
认证
用 应用密码 + Basic Auth:
curl -u 'admin:xxxx xxxx xxxx xxxx' \
https://example.com/wp-json/wp/v2/posts
应用密码在后台「用户 → 应用密码」生成,明文只显示一次。
不支持 Bearer Token —— JWT 是后台 SPA 用的,第三方入口刻意分开,避免把管理权限暴露给编辑器。
内容格式
请求体里带 content_format: "md" 时,正文按 Markdown 原稿存储,渲染出口用 marked 转 HTML。
不带这个字段则按 HTML 处理,入库前会做一次净化。
防覆盖
这是设计里最容易被忽略的一块。
WordPress 的 save_post 会自动导出,导出 SQL 如果无脑 INSERT OR REPLACE,就会把 Worker 端用 md 写的文章覆盖成 HTML。
现在的规则是:content_format='md' 视为"线上托管"标记,WP 导出时遇到 md 文章直接跳过(不写 D1、不上传 R2)。
含义:
- 从 Obsidian / REST 写入的文章,永远归 CMS 管;
- 想让 WordPress 接管,需要先在 CMS 里把它转成 HTML(或删掉重建);
- 这是一条单向规则,刻意不做"自动合并"。
幂等
- 新建时如果 slug 冲突,会自动追加
-2、-3; - 更新按
wp_id定位,重复提交同一篇不会产生副本; - 媒体上传按文件名 + 日期目录存放,重复上传会覆盖同名文件。
一个最小示例
curl -X POST https://example.com/wp-json/wp/v2/posts \
-u 'admin:app-password' \
-H 'Content-Type: application/json' \
-d '{
"title": "从脚本发布",
"slug": "from-script",
"status": "draft",
"content_format": "md",
"content": "## Hello\n\n这是正文。",
"categories": ["guide"],
"tags": ["api"]
}'
返回的 id 就是 wp_id,后续更新用它。
安全建议
- 应用密码只给需要的权限,不要复用登录密码;
- 生产环境建议加 IP 白名单或 Cloudflare Access;
- 写入口有 IP 限流,但它不是防暴力破解的完整方案;
- 定期在后台清理不再使用的应用密码。