跳到主要内容

LOADING

Developers · REST API

全部是 WordPress REST,
没有第二套鉴权。

One namespace, one nonce, twenty routes.

星群的接口不引入自建 Token、不套 GraphQL 网关。命名空间 starmap-cluster/v1,鉴权就是 WordPress 的 cookie + REST nonce。这意味着任何已经会写 WP REST 的人,五分钟就能上手。

命名空间 starmap-cluster/v1 版本 v0.6.0

01五分钟上手

公开读端点不需要任何凭据。写端点需要登录态,凭据通过 X-WP-Nonce 头传递——nonce 由服务端在页面里下发(window.smcConfig.nonce),不要自己伪造,它是与当前登录用户绑定的。

读取帖子流 / 发一条星藏shell
# 公开端点,无需凭据
curl "https://example.com/wp-json/starmap-cluster/v1/posts?order=recent&page=1"

# 写端点:带 REST nonce
curl -X POST "https://example.com/wp-json/starmap-cluster/v1/posts" \
  -H "X-WP-Nonce: <nonce>" \
  -H "Content-Type: application/json" \
  -d '{"body":"今夜视宁度 1.4 角秒,M42 尘埃带清晰。","title":"冷湖夜记"}'
一个真实踩过的坑

响应不是 JSON 而是 <!DOCTYPE html>,几乎总是因为重写规则没刷新。启用插件后必须跑一次 wp rewrite flush --hard,否则 /wp-json/ 会落回 WordPress 的 404 页面。前端脚本对这种情况有专门提示,但你自己的客户端要自己判断 content-type。

02鉴权与访客可读

读端点是否对访客开放,取决于站长在后台的「访客可读」开关。这是一个站点级策略,不是单条内容的可见性:

访客可读 · 开
/posts /posts/{id} /posts/{id}/replies /groups /groups/{key}/members /media/resolve 对未登录请求返回数据。
访客可读 · 关
上述端点返回 401。帖子详情也一起关——这是「私有社区」的语义,不是 bug。已分享的链接在登录后会跳回原页。
永远需要登录
所有写操作、/feed、/me、/me/inbox、/me/stars、/media、/reports、/bugs。
信息页例外
本站的关于 / 礼仪 / 暗夜 / API / 联系五页永远公开,不受上面这个开关影响——它们是介绍,不是内容。

nonce 的有效期与 WordPress 登录 cookie 绑定。过期后写操作会返回 403 rest_cookie_invalid_nonce,正确做法是刷新页面重新取 smcConfig.nonce,而不是重试。

03路由总表

按资源分组。「登录」一列指是否要求登录态。

方法路径说明登录
GET/posts帖子流。支持 order / page / per_page / author / group / search否
POST/posts发星藏。body 必填,可选 title / star_url / group_key / media[]是
GET/posts/{id}单帖详情,附首屏楼层否
DELETE/posts/{id}删帖(软删,保留行做审计)是
GET/posts/{id}/replies楼层分页否
POST/posts/{id}/replies回应。支持 parent_id 形成子楼层是
DELETE/posts/{id}/replies/{reply_id}删除单条楼层(作者本人 / 组主 / 站长)是
POST/posts/{id}/pin置顶 / 取消置顶组内帖子(仅组主,单组上限 2 条)。pinned 取 true/false是
DELETE/posts/{id}/group把帖子移出小组(不删帖)。作者本人或组主可调是
POST/reactions切换共鸣 / 收藏。type 取 like 或 star是
POST/follow关注 / 取关某位观星者是
GET/feed我的关注流是
POST/reports举报帖子、楼层或私信。object_type 取 post / reply / message是
POST/bugs提交 Bug 反馈是
POST/bugs/{id}/statusBug 状态流转(修复 / 驳回 / 打回)是
GET/me我的计数:关注 / 关注者 / 星藏 / 未读是
GET/me/inbox降级收件箱(子主题不在线时才有内容)是
POST/me/inbox标记已读,id 留空表示全部是
GET/me/stars我收藏的星,按收藏时间倒序。返回结构与 /posts 相同,多一个 truncated是
GET/me/discussions我的讨论:我发过的 + 我回复过的帖子。每条多 myLastAt / isMine / newReplies 三个字段是
GET/me/notification-preferences我的通知偏好(降级模式下唯一能关掉通知的地方)是
GET/mentions@ 提及自动补全的候选用户,按前缀匹配是
POST/messages给某位观星者发私信,peer + body是
POST/messages/block拒收 / 恢复接收某人的私信与通知。拒收后对方发不进私信,他的 @ 与回复也不再通知你(内容本身仍然可见)是
GET/announcements公告列表,支持 level 与 page否
GET/announcements/banner当前应展示的公告条(未过期、已到生效时间)否
GET/announcements/{id}单条公告详情否
GET/groups小组索引,支持 order=active|new 与 search否
POST/groups建组是
POST/groups/join加入 / 退出小组是
PATCH/groups/{key}改组资料(仅组主)是
DELETE/groups/{key}解散小组(仅组主,需组名确认)是
POST/groups/{key}/owner转让组主是
GET/groups/{key}/members成员列表否
DELETE/groups/{key}/members/{user_id}把成员移出小组(仅组主)是
POST/groups/{key}/subscription订阅 / 退订「组内新帖」通知。on 取 true/false;仅成员可调是
POST/media上传媒体(multipart),返回 attachment_id是
POST/media/resolve解析外链。只解析不入库,无副作用否
DELETE/media/{id}删除媒体(仅作者)是
GET/plans观测计划列表。scope 取 upcoming / mine / past,可按 group 过滤。坐标只给到 0.1°(约 11km)否
POST/plans发起观测计划。title + starts_at 必填;starts_at 接受时间戳或 datetime-local 串(按站点时区解释)。每人同时最多 5 个未开始的计划是
GET/plans/{id}单条计划详情,附报名名单。exact 字段只有发起者与已报名者能拿到,其余人为 null否
POST/plans/{id}/rsvp报名 / 改意向 / 退出。state 取 going / maybe / cancelled。名额是软上限,满了仍可进是
POST/plans/{id}/status取消或恢复整场计划。status 取 cancelled / publish;仅发起者与站长可调是

04一条星藏的字段

星藏的结构是星群的核心契约。媒体只存结构化引用、不存 HTML——这样渲染永远由插件自己的模板负责,客户端拿到的永远是数据。字段全部 camelCase,转换发生在 Posts::prepare_post() 一处。

GET /posts/{id} 响应(节选)json
{
  "id": 101,
  "title": "零下十八度,等到了 M42 的尘埃带",
  "body": "冷湖的风把视宁度压到 1.2 角秒…",
  "url": "https://example.com/cluster/p/101/",
  "createdAt": 1761926400,
  "starCount": 1284,
  "replyCount": 96,
  "views": 41209,
  "liked": false,
  "starred": false,
  "author": { "id": 2, "name": "沈墨白", "avatar": "…", "isFollowing": true },
  "group": { "key": "deep-sky", "name": "深空摄影研习社", "url": "…" },
  "star": { "url": "…", "title": "M42 猎户座大星云", "icon": "…" },
  "media": [
    { "kind": "image", "provider": "attachment", "url": "…", "thumb": "…" }
  ]
}

05限流档位

限流按「用户 + 动作」计数,用 transient 实现。触发时返回 429 与错误码 smc_throttled,响应里没有 Retry-After——按下面的窗口自己退避。

动作上限窗口为什么是这个数
post105 分钟正常观星一晚发不了十条
reply205 分钟讨论比发帖频繁,给两倍额度
reaction601 分钟点赞是低成本的,只看是否脚本刷量
follow301 分钟同上
report55 分钟举报比发帖「重」,正常不会连发五条
bug310 分钟要写清楚,连发三条已是异常信号
upload205 分钟按文件数计,不按字节
group_create51 小时建组是重操作

06错误码

错误响应是 WordPress 标准结构。message 是可以直接展示给用户的中文,code 才是给你做分支的。

codeHTTP含义 / 处理建议
smc_forbidden403不是内容作者且无审核权限。不要重试。
smc_forbidden_group403不是组主。不要重试。
smc_no_post404帖子已删或不存在。引导回列表。
smc_no_group404小组不存在或已解散。
smc_no_reply404楼层已删。
smc_throttled429触发限流。按窗口退避,别立刻重试。
smc_empty_body400正文为空。前端应提前拦截。
smc_key_taken409组标识被占用。让用户换一个。
smc_media_unsupported415媒体类型不在白名单。SVG 一律拒绝。
smc_too_large413超出体积上限(按类型分别限)。
smc_unrecognized422外链解析不出平台 ID。提示用户换链接。
smc_no_table500数据表缺列 / 缺表,通常是升级没跑完。访问任意前台页触发升级。

07用过滤器扩展,而不是改插件

星群把可扩展点都做成了 apply_filters。改插件源码的代价是下次升级必然冲突,而下面这些钩子是有意暴露的稳定接口。

常用的四个钩子php
// 1) 注入设计令牌(颜色 / 间距),作用域限定 .smc-app
add_filter( 'starmap_cluster_theme_tokens', function ( $tokens, $view ) {
    $tokens['--smc-gold'] = '#7fb6ff';   // 换强调色
    return $tokens;
}, 10, 2 );

// 2) 扩展可嵌入的外部平台白名单
add_filter( 'starmap_cluster_media_providers', function ( $providers ) {
    $providers['vimeo']['enabled'] = true;
    return $providers;
} );

// 3) 追加通知类型(需与子主题的通知面板成对实现)
add_filter( 'starmap_cluster_notification_types', function ( $types ) {
    $types['smc_mention'] = '有人在星群里 @ 了你';
    return $types;
} );

// 4) 追加 body class / head 片段
add_filter( 'starmap_cluster_body_class', function ( $classes ) {
    $classes[] = 'my-custom-theme';
    return $classes;
} );
令牌钩子的两条硬约束

第一,令牌名必须匹配 --[a-z0-9-]+——这些值最终拼进 <style>,一个右花括号就能闭合规则注入任意 CSS。

第二,不要返回空值。--x: ; 会让 var(--x, 16px) 的 fallback 失效(未定义才走 fallback,空值不走)。要「不设置」就把整个键删掉。

08明确没有的东西

避免你在文档里找半天:

  • 没有 OAuth。第三方应用无法代用户操作,只能读公开数据或在用户自己的 cookie 会话里跑。
  • 没有 webhook。想要实时推送请用子主题的 VAPID 链路,那是另一个模块。
  • 没有批量端点。不要并发打出上百个请求,限流会按用户维度拦住你。
  • 没有历史版本。帖子软删保留行做审计,但没有版本回滚 API。
需要新端点

到联系我们页走 Bug / 需求反馈,附上你的使用场景。我们优先做「现有数据结构能支撑」的端点,而不是为了接口好看新增表。

省钱助手

每天帮你省一点!
先领券,再点餐 更多优惠券
本地生活·出行必备 更多优惠券
超值福利 更多福利

优惠说明
领取方法
微信扫一扫

↑↓ 选择↵ 打开esc 关闭共 5,895 个站点