外部管理 API 接入文档
本 API 用于让脚本、CI 或自建面板在站外管理这座站点:账户、权限组、内容、图片、日志、设置与访问统计。
它没有独立的「管理员」概念——一个 API Key 就是以它的主人身份调用,能做什么完全取决于主人在后台上拥有的权限。
- 基地址:
https://www.mqgmc.com/api/v1 - 认证:
Authorization: Bearer mqg_[0-9a-f]{48} - 响应:JSON,统一信封(见「响应格式」)
- 限流:每个 Key 60 次 / 分钟
想改代码前先看/docs/api(本文档的同源页面)与仓库里的app/api.php。
---
1. 创建密钥
- 登录站点,进入 我的账户 → API 密钥(
/me/api)。 - 填写可选备注(例如「部署脚本」)与可选过期日期,点「创建密钥」。
- 页面会显示一次明文密钥
mqg_…。只显示这一次,请立刻保存;丢了只能吊销重建。
要求:账号需要有「管理 API 密钥」权限(api.manage)。超级管理员默认拥有。
服务端只保存 sha256(key),所以任何日志、备份里都拿不到明文。
2. 第一条请求
curl -s -H "Authorization: Bearer mqg_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
https://www.mqgmc.com/api/v1/me
{
"ok": true,
"data": {
"account": {
"id": 1,
"username": "admin",
"role": "admin",
"status": "active",
"group": {"id": 1, "name": "超级管理员"},
"permissions": ["*"]
},
"key": {"prefix": "mqg_1a2b3c4d"},
"site": {"name": "沐清阁", "url": "https://www.mqgmc.com/"}
}
}
3. 鉴权与权限
| 事项 | 规则 |
| 请求头 | Authorization: Bearer <key>,缺了返回 401 missing_key |
| 密钥形态 | mqg_ + 48 位小写十六进制 |
| 吊销 / 过期 | 立即返回 401 revoked_key / expired_key |
| 账号被封禁 | 返回 403 account_banned |
| 权限判定 | 每次请求实时读取账号当前权限组,改权限或改组后立即生效,不需要换 Key |
| 限流 | 每个 Key 每分钟 60 次,超出返回 429 rate_limited(Retry-After 语义:等一分钟) |
| 审计 | 写操作会写进站点日志(操作者是 Key 的主人),页面上「日志」里能看到 |
账号/权限组的写操作只有超级管理员能做。 普通成员即使拥有 content.* 权限,调用 /accounts、/groups 也会得到 403。
4. 响应格式
成功:
{"ok": true, "data": { ... }}
失败:
{"ok": false, "error": {"code": "forbidden", "message": "当前账户没有「发布与下线」权限。"}}
错误码
| code | HTTP | 含义 |
missing_key | 401 | 没有 Authorization 头 |
invalid_key | 401 | 头格式不对、Key 格式不对或不存在 |
revoked_key | 401 | Key 已被吊销 |
expired_key | 401 | Key 已过期 |
account_banned | 403 | Key 所属账号被封禁 |
forbidden | 403 | 当前账号权限不足(或成员想改账号/权限组) |
not_found | 404 | 资源或接口不存在 |
invalid_json | 400 | 请求体不是合法 JSON |
invalid_request | 422 | 参数不合法(消息里会说明是哪一项) |
payload_too_large | 413 | 请求体超过 1 MB,或设置内容超过 256 KB |
in_use | 409 | 图片仍被内容引用(可加 ?force=1) |
conflict | 409 | 状态冲突(例如没有正文的内容不能发布) |
method_not_allowed | 405 | 方法不对 |
rate_limited | 429 | Key 每分钟调用次数超限 |
server_error | 500 | 服务端异常(细节只写进服务器日志) |
5. 端点总览
| 方法 | 路径 | 需要的权限 |
| GET | /api/v1 | 无(免鉴权,返回能力清单) |
| GET | /api/v1/me | 任意有效 Key |
| GET / POST | /api/v1/keys | api.manage |
| DELETE | /api/v1/keys/{id} | api.manage |
| GET / POST | /api/v1/accounts | 超级管理员 |
| PATCH / DELETE | /api/v1/accounts/{id} | 超级管理员 |
| POST | /api/v1/accounts/{id}/unbind | 超级管理员 |
| GET / POST | /api/v1/groups | 超级管理员 |
| PATCH / DELETE | /api/v1/groups/{id} | 超级管理员 |
| GET / POST | /api/v1/contents | content.view / content.create |
| GET / PATCH / DELETE | /api/v1/contents/{id} | 见「内容」一节 |
| POST | /api/v1/contents/{id}/publish、/unpublish | content.publish |
| GET / POST | /api/v1/media | media.view / media.upload |
| DELETE | /api/v1/media/{id} | media.delete |
| GET | /api/v1/logs | logs.view(或只看自己的 profile.logs) |
| GET / PUT | /api/v1/settings | settings.view / settings.edit |
| GET | /api/v1/stats | analytics.view |
6. 账户
GET /api/v1/accounts
返回全部账户:
{"ok": true, "data": {"accounts": [
{"id": 1, "username": "admin", "role": "admin", "status": "active",
"group_id": 1, "group": "超级管理员", "github_login": "cjd54288",
"nav_bound": false, "media_quota": null, "media_used": 0,
"created_at": "2026-10-26T20:00:00+08:00", "last_login_at": null}
], "total": 1}}
POST /api/v1/accounts
{"username": "new-player", "group_id": 2, "media_quota_bytes": 104857600}
username必填,规则同后台(3–60 字,[\p{L}\p{N}][\p{L}\p{N}_.-]*)group_id省略时落到「默认」组media_quota_bytes省略 = 继承权限组;0= 不限- 成功 201,返回新账户对象
PATCH /api/v1/accounts/{id}
{"status": "banned"} // banned / active
{"group_id": 3} // 改组,null = 未分配
{"media_quota_bytes": 0} // 0 = 不限,null = 继承组
不能改自己的状态(403),也不能删自己。
POST /api/v1/accounts/{id}/unbind
{"provider": "github"} // 或 "nav"
权限组
curl -X POST -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"name":"内容编辑","permissions":["profile.view","content.view","content.create","content.edit_own"],"media_quota_bytes":0}' \
https://www.mqgmc.com/api/v1/groups
权限节点取值见「权限对照表」。PATCH /api/v1/groups/{id} 同样接受 name、permissions、media_quota_bytes;DELETE 删除组(组内账户会变成「未分配」)。
7. 内容
列表
GET /api/v1/contents?kind=news&status=published&q=更新&limit=20&offset=0
kind:news/doc/pagestatus:all(默认)/published/draft- 没有
content.edit_all的成员只能看到自己写的内容 - 返回
{contents, total, limit, offset}
创建 / 更新
curl -X POST -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"kind":"news","title":"周末活动","summary":"周六晚八点","body":"## 活动内容\n\n集合点见群公告。"}' \
"https://www.mqgmc.com/api/v1/contents?publish=1"
字段(与后台编辑器一致):
| 字段 | 说明 |
kind | 新建时必填:news / doc / page |
title | 标题 |
summary | 摘要(列表与搜索用) |
body | 正文,Markdown;图片只能用站内地址 |
path | 文档/页面的路径;news 会强制成 /news/{id} |
date | 公告发布时间 YYYY-MM-DDTHH:MM,省略则取当前时间 |
pinned | 公告置顶 |
cover | 封面图地址(站内) |
doc_category | 文档分类 |
code / mode | 页面代码模式(仅超级管理员) |
PATCH /api/v1/contents/{id} 只需传要改的字段;?publish=1 表示保存并发布。发布时会自动刷新路由并触发 IndexNow 推送。
发布 / 下线 / 删除
curl -X POST -H "Authorization: Bearer $KEY" https://www.mqgmc.com/api/v1/contents/12/publish
curl -X POST -H "Authorization: Bearer $KEY" https://www.mqgmc.com/api/v1/contents/12/unpublish
curl -X DELETE -H "Authorization: Bearer $KEY" https://www.mqgmc.com/api/v1/contents/12
删除会同时清掉版本与路由,不可恢复(版本历史最多保留 10 条)。
8. 图片
上传(multipart)
curl -X POST -H "Authorization: Bearer $KEY" \
-F "file=@/path/to/screenshot.png" \
https://www.mqgmc.com/api/v1/media
- 字段名
file(兼容image) - 限制与后台一致:≤5 MB、PNG/JPEG/WebP/GIF、去掉脚本片段、按 MIME 重新编码(GIF 需完整到 trailer)
- 受账号的媒体配额约束,超出返回 422 并提示已用/配额/本次需要
- 返回
{id, path, url, size}
删除
DELETE /api/v1/media/{id}:被内容引用时返回 409 in_use,加 ?force=1 强删。成员只能删自己的图。
9. 设置、日志、统计
# 读设置
curl -H "Authorization: Bearer $KEY" "https://www.mqgmc.com/api/v1/settings?key=site"
# 写设置(只允许下列键)
curl -X PUT -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"key":"site","value":{"name":"沐清阁","tagline":"方块之间,与好友一起生存。"}}' \
https://www.mqgmc.com/api/v1/settings
- 可读:
siteservernavcommunitiesblocksfeaturescategoriesgithubnavloginanalyticsindexnow(github/navlogin的client_secret会打码) - 可写:
siteservernavcommunitiesblocksfeaturescategories - 密钥类设置(GitHub / 导航站登录 / IndexNow)只能在后台上改,API 一律 403
# 最近日志(成员只能看到自己的)
curl -H "Authorization: Bearer $KEY" "https://www.mqgmc.com/api/v1/logs?limit=50"
# 访问统计
curl -H "Authorization: Bearer $KEY" "https://www.mqgmc.com/api/v1/stats?days=7"
统计返回:range、totals(浏览量/访客/爬虫/平均响应)、daily、top_pages、referrers、statuses。
10. 权限对照表
| 权限节点 | 能做的事 |
api.manage | 创建/查看/吊销自己的 Key(/keys) |
content.view | 列出与查看内容 |
content.create | 新建内容 |
content.edit_own | 编辑自己写的内容 |
content.edit_all | 编辑所有人的内容 |
content.publish | 发布 / 下线 |
content.delete | 删除内容 |
media.view / media.upload / media.delete | 看图 / 上传 / 删图(删除仍限自己的图,除非是管理员) |
logs.view | 全站日志;没有时若有 profile.logs 只能看自己的 |
settings.view / settings.edit | 读 / 写设置 |
analytics.view | 访问统计 |
| —(超级管理员) | 账户、权限组的全部写操作 |
11. 注意事项
- Key 等于账号:不要写进前端代码、公开仓库或日志。给每个脚本单独建 Key,出事只吊销那一个。
- 超管边界:账户与权限组的写操作只认超级管理员;成员即使有
content.*也只能动自己的内容。 - 页面(
page)仅超级管理员可维护,因为页面允许代码模式。 - 图片只能用站内地址:正文里写外站图片会在渲染时被丢弃。
- 删除不可恢复,
DELETE前先GET确认id。 - 限流是每 Key 每分钟 60 次;批量任务请自行在脚本里 sleep,或分多个 Key。
- 所有时间均为站点时区(
Asia/Shanghai)的 ISO 8601 字符串。
12. 变更记录
- 2026-11-03:首版。支持密钥自助管理、账户与权限组管理、内容 CRUD 与发布、图片上传、日志、设置读写、访问统计。

沐清阁