这是面向 脚本与 AI Agent 的接口说明:复用主站全部权限与规则(帖子、作业、投票、公告、共享文件、画板、标签、围棋、维基与哈基八)。本页由 api/endpoints.php 的端点登记表生成,与网关上实际生效的路由、/openapi.json 同源。
| 入口 | 地址 | 用途 |
|---|---|---|
| API 基地址(主) | https://api.forum18.cn |
机器调用,下面所有路径都接在它后面 |
| API 基地址(旧域名族) | https://api.forum18.top |
机器调用(同一份实现与数据;日常请用 .cn) |
| 机器可读描述 | https://api.forum18.cn/openapi.json |
OpenAPI 3.1,无需令牌,可直接喂给 Agent 或代码生成器 |
| 本页 | https://docs.forum18.cn/api.html | 给人看的说明(访问 api.forum18.cn/ 会 301 跳到这里) |
v1(新调用一律用它)
/client/v1/… 是 Cloudflare 风格的调用方式:恒定信封 {success, errors, messages, result, result_info}、数字错误码、page/per_page 分页、Idempotency-Key 幂等写、每个响应带 Forum18-Request-Id。接口契约的唯一权威是仓库里的 docs/api-spec.md;机器可读版是 https://api.forum18.cn/client/v1/openapi.json。
鉴权有两条通道(任选其一,详见 docs/api-spec.md §3.2):Authorization: Bearer <令牌>(脚本 / Agent / 第三方),或第一方页面的浏览器会话(Cookie PHPSESSID,写请求必须再带 X-CSRF-Token,缺失返回 2008;会话通道不支持 Idempotency-Key)。只读令牌只能发 GET,写方法(POST/PUT/DELETE)必须用写入令牌,否则 403 2004。
| 方法 | 路径 | 说明 | 所需范围 |
|---|---|---|---|
| GET | /client/v1/health |
网关存活探针 | — |
| GET | /client/v1/openapi.json |
OpenAPI 3.1 描述 | — |
| GET | /client/v1/mc/releases |
MC 客户端更新清单 | — |
| GET | /client/v1/mc/releases/download |
下载 MC 客户端更新文件 | — |
| POST | /client/v1/mc/sessions |
用论坛账号换取 MC 客户端登录令牌 | — |
| POST | /client/v1/mc/sessions/verify |
校验 MC 客户端登录令牌 | — |
| DELETE | /client/v1/mc/sessions |
注销 MC 客户端登录令牌 | — |
| GET | /client/v1/user/tokens/verify |
校验令牌并返回其能力 | — |
| GET | /client/v1/user |
令牌所属账号 | account |
| GET | /client/v1/users/{id_or_username} |
公开资料 | profile |
| GET | /client/v1/forum/posts |
帖子列表 | posts |
| GET | /client/v1/forum/posts/{post_id} |
帖子详情 | posts |
| POST | /client/v1/forum/posts |
发布帖子 | posts |
| POST | /client/v1/forum/homework |
发布作业 | homework |
| GET | /client/v1/forum/homework/{homework_id} |
作业详情 | homework |
| POST | /client/v1/forum/polls |
发起投票 | poll |
| GET | /client/v1/forum/polls/{poll_id} |
投票详情 | poll |
| PUT | /client/v1/forum/posts/{post_id}/like |
点赞 | posts |
| DELETE | /client/v1/forum/posts/{post_id}/like |
取消赞 | posts |
| POST | /client/v1/forum/posts/{post_id}/coins |
投币 | posts |
| POST | /client/v1/forum/comments |
发表评论或回复 | 按目标类型 |
| GET | /client/v1/forum/announcements |
公告列表 | announcements |
| GET | /client/v1/forum/tags |
标签列表 | posts |
| GET | /client/v1/canvas/boards |
公开画板列表 | canvas |
| GET | /client/v1/canvas/boards/{board_id} |
画板内容 | canvas |
| GET | /client/v1/go/rooms |
围棋房间列表 | go |
| GET | /client/v1/files |
共享文件总览(directory 参数启用目录分页) | shared_files |
| GET | /client/v1/files/{file_id}/content/chunks |
下载共享文件的1MiB base64分片 | shared_files |
| GET | /client/v1/files/{file_id}/content |
带身份下载共享文件 | shared_files |
| GET | /client/v1/files/directories |
共享目录树 | shared_files |
| GET | /client/v1/files/{file_id}/location |
files.locate | shared_files |
| POST | /client/v1/files/{file_id}/rename |
本人文件改名(保留扩展名) | shared_files |
| POST | /client/v1/files/{file_id}/move |
本人文件移动目录 | shared_files |
| DELETE | /client/v1/files/{file_id} |
本人文件软删除 | shared_files |
| POST | /client/v1/files/uploads |
创建或恢复目录绑定上传 | shared_files |
| POST | /client/v1/files/uploads/chunk |
写入原始字节分片 | shared_files |
| POST | /client/v1/files/uploads/finish |
提交分片上传 | shared_files |
| GET | /client/v1/me/deleted |
本人已删除内容分页列表 | 按目标类型 |
| POST | /client/v1/me/deleted/restore |
还原本人删除的内容 | 按目标类型 |
| POST | /client/v1/me/deleted/requests |
申请还原已删除内容 | 按目标类型 |
| GET | /client/v1/admin/restore-requests |
管理员待审批还原申请 | 按目标类型 |
| POST | /client/v1/admin/restore-requests/{request_id} |
管理员批准或拒绝还原 | 按目标类型 |
| GET | /client/v1/wiki/pages |
条目列表 | wiki |
| GET | /client/v1/wiki/pages/{page_id} |
条目内容 | wiki |
| GET | /client/v1/wiki/pages/{page_id}/revisions |
条目版本列表(含条目上下文) | wiki |
| POST | /client/v1/wiki/pages |
新建或编辑条目(乐观锁:base_rev) | wiki |
| GET | /client/v1/wiki/search |
搜索条目(含 create_url 提示) | wiki |
| GET | /client/v1/wiki/recent-changes |
最近更改 | wiki |
| GET | /client/v1/wiki/meta |
维基统计与索引 | wiki |
| POST | /client/v1/ai/chat |
哈基八对话(非流式) | ai |
| GET | /client/v1/blog/sites |
本人博客列表 | blog_read |
| GET | /client/v1/blog/sites/{site_id}/releases |
本人博客发布版本 | blog_read |
| POST | /client/v1/blog/sites/{site_id}/deployments |
上传 ZIP 并发布到本人博客 | blog_upload |
| GET | /client/v1/blog/sites/{site_id}/deployments/{job_id} |
查询本人博客部署任务状态 | blog_read |
| GET | /client/v1/blog/sites/{site_id}/download |
下载本人博客发布包 | blog_download |
| POST | /client/v1/blog/sites/{site_id}/deployments/git |
从公开或私有 Git 仓库异步发布 | blog_upload |
| POST | /client/v1/blog/sites/{site_id}/redeploy |
重新部署当前版本源码 | blog_upload |
| POST | /client/v1/blog/sites/{site_id}/rollback |
回滚本人博客版本 | blog_upload |
| POST | /client/v1/blog/sites/{site_id}/packages |
创建一小时有效的 ZIP 暂存包 | blog_upload |
| POST | /client/v1/blog/sites/{site_id}/packages/{package_id}/chunks |
写入最多 1MiB 的 ZIP 分片 | blog_upload |
| POST | /client/v1/blog/sites/{site_id}/packages/{package_id}/deploy |
核对摘要并发布暂存 ZIP | blog_upload |
| DELETE | /client/v1/blog/sites/{site_id}/packages/{package_id} |
删除本人暂存 ZIP | blog_upload |
| GET | /client/v1/blog/sites/{site_id}/credentials |
查看本人博客仓库凭据元数据 | blog_credentials |
| POST | /client/v1/blog/sites/{site_id}/credentials |
加密保存 HTTPS 或 SSH 仓库凭据 | blog_credentials |
| DELETE | /client/v1/blog/sites/{site_id}/credentials/{credential_id} |
撤销仓库凭据 | blog_credentials |
| GET | /client/v1/blog/sites/{site_id}/download/chunks |
下载本人发布包的 1MiB base64 分片 | blog_download |
| POST | /client/v1/blog/sites/{site_id}/ssh |
获取本人博客受限 SSH 连接信息 | blog_ssh |
Agent MCP / OAuth
本地mcp/server.mjs以stdio接入,FORUM18_API_URL/FORUM18_API_TOKEN读取现有令牌。远程POST /mcp使用论坛OAuth授权码+PKCE S256及resource绑定(普通API令牌不可用);元数据在/.well-known/oauth-protected-resource/mcp及发行方/.well-known/oauth-authorization-server,注册/令牌/撤销在/oauth/register、/oauth/token、/oauth/revoke。主站/oauth/authorize.php复用登录/2FA并显式确认范围;账号设置/oauth/grants.php可撤销整组授权。支持2026-07-28无状态HTTP与2025-11-25初始化;没有旧HTTP+SSE。工具来自v1用户路由,不开放管理员、MC原生接口或通用宿主命令。本地ZIP文件工具仅接受明确的绝对路径,远程ZIP以base64分片暂存;下载同样有限分片。业务失败返回structuredContent/isError,202受理须另查job_id。blog_credentials与blog_ssh必须显式授权;缺Git出口/硬池时拒绝,不在宿主拉仓库。此功能仅本机实现,尚未部署生产,Docker Git/运行时与真实2FA投递未验。
博客 API
博客部署 POST 使用 multipart/form-data 的单个 file ZIP 字段(最大50MiB)及可选config JSON,支持packages原始1MiB分片、git异步发布、redeploy与rollback。其幂等指纹包含文件SHA-256/配置;下载成功为 ZIP 二进制,失败仍是恒定信封。所有操作仅限本人所选 site_id,清理过的本地发布包无法下载。 SSH 必须显式授予 blog_ssh 的写令牌,旧空范围全量令牌不能用于 SSH。只允许本人容器非 root shell/workspace,拒绝 SFTP/SCP 与 TCP/Unix/Agent/X11 转发。CLI 密码提示可粘贴该令牌;不得放入 argv、URL 或日志。撤销/到期后至多 30 秒断开。共享硬资源池及网关未完成时 SSH 返回 3002,不因 API 上线而开放。
令牌与鉴权(弃用路径)
在 设置中心 → 账号 → API 令牌 生成:填写自定义名称并勾选范围,密钥为 32 位区分大小写随机字符,只在创建成功时一次性展示(库中仅存哈希)。令牌分两种:
| 类型 | URL 前缀 | 能力 |
|---|---|---|
| 只读 read | /r/… |
内容信息、维基、画板、标签、围棋、账号自助、/ai |
| 写入 write | /w/… |
发布 / 评论 / 点赞 / 投币 / 维基编辑 / 哈基八 |
密钥不放在 URL 路径里(避免进入访问日志与 Referer),改用请求头或请求体携带:
# 方式一:请求头(推荐,GET/POST 通用)
-H "Authorization: Bearer <密钥>"
-H "X-API-Token: <密钥>"
# 方式二:POST 请求体字段
-d "token=<密钥>" # 表单
{"token": "<密钥>", ...} # JSON
令牌范围
创建令牌时按区域勾选,越权返回 403 insufficient_scope。没有勾选范围的旧令牌视为全量;显式勾过范围的旧令牌不会自动获得新范围,要用维基等新接口请在设置页补勾或重新创建。
| 范围 | 覆盖内容 |
|---|---|
posts |
帖子(读取/发布/评论/点赞/投币) |
homework |
作业(读取/发布/评论) |
poll |
投票(读取/发布/评论) |
profile |
用户资料 |
announcements |
公告 |
shared_files |
共享文件 |
ai |
哈基八对话 |
canvas |
画板(读取/评论) |
wiki |
维基(读取条目/编辑条目) |
go |
围棋(房间信息) |
account |
账号自助(我的资料/签到/通知/收藏/关注) |
blog_read |
博客:读取本人站点与版本 |
blog_upload |
博客:上传 ZIP / 发布 |
blog_download |
博客:下载本人发布包 |
blog_credentials |
博客:私有仓库凭据管理 |
blog_ssh |
博客:容器终端(写令牌,须显式勾选) |
无需令牌
GET /file/lead— 共享文件总览:id、文件名、大小(字节)、简介、下载次数、下载直链(jump_url)GET /file/{id}— 下载共享文件:文件流;支持 Range 单段续传,受全服连接数与带宽限制;无身份,不计账号日限额GET /openapi.json— OpenAPI 3.1 描述:本网关全部端点的机器可读描述(OpenAPI 3.1),可直接喂给 Agent 或代码生成器
只读接口
响应统一为 {"success":true,"data":{…}};令牌无效返回 401,范围不足返回 403,内容不可见返回 404。
| 路径 | 参数 | 返回 | 所需范围 |
|---|---|---|---|
GET /r/thread |
id(必填,帖子 id) |
帖子:作者、正文、可见性、点赞/评论/投币/收藏数 | posts |
GET /r/posts |
limit(默认 20,返回条数 1-50);offset(默认 0,偏移量(分页)) |
最近可见帖子列表(按 id 倒序) | posts |
GET /r/homework |
id(必填,作业 id) |
作业:描述、网盘链接与提取码、下载/评论/答案数 | homework |
GET /r/poll |
id(必填,投票 id) |
投票:全部选项、实时票数、我的选择 | poll |
GET /r/profile |
id(用户 id(与 username 二选一));username(用户名(与 id 二选一)) |
用户信息(等级、角色、金币、简介、头像)与公开帖子数 | profile |
GET /r/announcements |
limit(默认 20,返回条数 1-50) |
公告:类型、重要程度、正文、展示位置开关(重要置顶) | announcements |
GET /r/shared_files |
— | 共享文件列表:文件名、大小、简介、下载次数、下载直链(最多 200 条) | shared_files |
GET /r/tags |
q(按标签名模糊筛选(可省略));limit(默认 50,返回条数 1-200) |
标签:id、名称、颜色、帖子数、站内地址(按帖子数倒序) | posts |
GET /r/canvas |
id(画布 id;省略时返回公开画布列表);limit(默认 50,列表模式返回条数 1-50) |
带 id:单块画布的图形数据(items/strokes/connections)与版本号;不带 id:公开画布列表 | canvas |
GET /r/go/rooms |
limit(默认 50,返回条数 1-100) |
房间:标题、棋盘大小、房主、人数、是否满员、是否需要密码(不含密码本身) | go |
GET /r/me |
— | 令牌所属账号:等级、经验、金币、今日签到与连续天数、未读通知、收藏/关注/粉丝/勋章数 | account |
GET /r/wiki/page |
id(条目 id(与 title 二选一));title(条目标题,可带命名空间前缀(如「分类:人物」));ns(默认 main,命名空间(main/talk/category/help/template/project/user));format(默认 both,取值 wikitext/html/both,返回格式:wikitext / html / both) |
条目:正文(维基语法与渲染后的 HTML)、目录、分类、标签、版本号、查看数、作者、站内地址 | wiki |
GET /r/wiki/list |
ns(默认 main,命名空间);sort(默认 title,取值 title/updated/created,排序:title / updated / created);limit(默认 50,返回条数 1-500);offset(默认 0,偏移量(分页)) |
条目列表:标题、命名空间、版本号、查看数、创建/更新时间、站内地址 | wiki |
GET /r/wiki/search |
q(必填,搜索词);limit(默认 20,返回条数 1-50) |
命中条目:标题、摘要(正文片段)、更新时间、站内地址;标题命中优先 | wiki |
GET /r/wiki/recent |
ns(只保留某个命名空间(可省略));limit(默认 30,返回条数 1-100);offset(默认 0,偏移量(分页)) |
版本条目:条目名、版本号、编辑者、摘要、字节变化、时间 | wiki |
GET /r/wiki/history |
id(条目 id(与 title 二选一));title(条目标题,可带命名空间前缀);rev(指定版本号时连同该版本正文一起返回);limit(默认 50,版本条数 1-100);offset(默认 0,偏移量(分页)) |
条目元信息 + 版本列表(版本号、编辑者、摘要、字节数、时间);带 rev 时含该版本正文 | wiki |
GET /r/wiki/meta |
— | 统计(条目/编辑/编辑者/今日编辑)、命名空间表、标签与分类(含成员数) | wiki |
GET/POST /r/ai |
q(GET 方式的一句话提问(POST 用 JSON 的 messages)) |
哈基八的回复(非流式 JSON);GET 用 ?q=,POST 提交 {"messages":[{"role":"user","content":"…"}]} | ai |
写接口
表单字段用 application/x-www-form-urlencoded;维基编辑与哈基八也接受 JSON 请求体。成功通常返回 302 与 location 字段;JSON 端点(like/coin/chat)原样透传主站响应。
| 路径 | 字段 | 说明 | 所需范围 |
|---|---|---|---|
POST /w/post |
type(必填,默认 post,取值 post/homework/poll,内容类型);title(必填,标题(不超过 30 字));content(必填,正文(帖子/作业不超过 200 字,投票不超过 500 字));visibility(默认 public,可见性:public / private / selected 等);markdown_enabled(默认 0,是否按 Markdown 渲染(0/1));options[](投票选项(type=poll 时必填,2-10 个,每个不超过 60 字));netdisk_url(作业网盘链接(type=homework 时必填,http/https));netdisk_code(作业网盘提取码(不超过 30 字));access_user_ids[](visibility=selected 时的可见用户 id) |
发布结果;成功返回 302 与 location,失败把上游错误原样返回 | 按 target_type |
| 所需范围按 type 判定:post→posts、homework→homework、poll→poll | |||
POST /w/comment |
content(必填,评论内容(不超过 1000 字));target_type(必填,默认 post,取值 post/homework/poll/canvas,目标类型);target_id(必填,目标 id);parent_id(默认 0,回复的评论 id(顶层评论省略)) |
评论结果(转发主站评论区) | 按 target_type |
| 所需范围按 target_type 判定:post/homework/poll/canvas | |||
POST /w/like |
target_type(必填,默认 post,取值 post/homework/poll/canvas,目标类型);target_id(必填,目标 id);action(默认 like,取值 like/unlike,like(默认)或 unlike) |
转发主站点赞接口的原始 JSON 响应 | 按 target_type |
| 所需范围按 target_type 判定 | |||
POST /w/coin |
target_type(必填,默认 post,取值 post/homework/poll/canvas,目标类型);target_id(必填,目标 id);amount(默认 1,投币数量 1-5) |
转发主站投币接口的原始 JSON 响应(自投等语义限制由主站判定) | 按 target_type |
| 所需范围按 target_type 判定 | |||
POST /w/chat |
messages(必填,对话消息数组);token(令牌(也可改用请求头携带)) |
哈基八的回复;请求体原样转发主站 /api/chat.php | ai |
POST /w/wiki/edit |
title(必填,条目标题,可带命名空间前缀(如「分类:人物」));ns(默认 main,命名空间(title 已带前缀时可省略));content(必填,正文(维基语法,最多 200000 字));summary(编辑摘要(不超过 200 字));base_rev(编辑前看到的版本号;与当前版本不一致时判为编辑冲突(409));is_minor(默认 0,标记为小编辑(0/1));create_only(默认 0,只允许新建,条目已存在时报错(0/1)) |
保存结果:条目元信息、新版本号、是否新建、编辑冲突状态、站内地址 | wiki |
| 复用维基的权限与闸门:全保护仅管理员、半保护仅管理员/风纪委员、编辑冷却(管理员 2 秒、风纪委员 5 秒、其他 15 秒),账号状态必须是 active | |||
| 仅支持上面列出的写端点;未知端点返回 404,不会转发到主站。 |
示例
# 查看帖子信息
curl "https://api.forum18.cn/r/thread?id=1" -H "Authorization: Bearer <密钥>"
# 下载共享文件(无需令牌)
curl -O "https://api.forum18.cn/file/12"
# 查看维基条目(含维基语法与渲染后的 HTML)
curl "https://api.forum18.cn/r/wiki/page?title=十八中" -H "Authorization: Bearer <密钥>"
# 搜索维基 / 看最近更改
curl "https://api.forum18.cn/r/wiki/search?q=校园" -H "X-API-Token: <密钥>"
curl "https://api.forum18.cn/r/wiki/recent?limit=20" -H "X-API-Token: <密钥>"
# 新建或编辑维基条目(写入令牌,JSON 提交)
curl -X POST "https://api.forum18.cn/w/wiki/edit" \
-H "X-API-Token: <密钥>" -H "Content-Type: application/json" \
-d '{"title":"十八中","content":"== 简介 ==\n学校条目。","summary":"首次创建"}'
# 发布帖子
curl -X POST "https://api.forum18.cn/w/post" \
-H "X-API-Token: <密钥>" \
-d "type=post" -d "title=你好" -d "content=正文"
# 当前令牌账号(金币、签到、未读通知)
curl "https://api.forum18.cn/r/me" -H "X-API-Token: <密钥>"
# 询问哈基八(令牌放 JSON body)
curl -X POST "https://api.forum18.cn/r/ai" \
-H "Content-Type: application/json" \
-d '{"token":"<密钥>","messages":[{"role":"user","content":"今天有什么新帖子?"}]}'
# 拉取 OpenAPI
curl "https://api.forum18.cn/openapi.json"