Wiki.js 2.5 API 使用详解
Wiki.js 2.5.315 GraphQL API 实战详解:JWT 与 API Key 双认证、登录与错误分支、pages/users/groups/system 各域读写实测、分页排序约定、限流与错误码体系,全部请求响应真实回显。
Wiki.js 2.5 API 使用详解
目标:以 GraphQL API 为核心,系统讲解 Wiki.js 2.5.315 的程序化调用方式——端点与认证体系(JWT / API Key)、登录与首次调用、页面/用户/组/系统各域 mutation 与 query 的请求格式与真实响应、错误码体系与限流约定,所有请求与响应 JSON 均在 Ubuntu 22.04 的 2.5.315 实例上 curl 实测采集,已在 Ubuntu 22.04 实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04 LTS(x86_64)
- Wiki.js 版本:2.5.315(
system.info实查currentVersion) - 数据库:PostgreSQL 16.15(
dbVersion实查) - API 端点:
http://192.168.146.128:3101/graphql(Wiki.js 服务地址 +/graphql路径) - 认证:本地(Local)策略管理员 administrator / admin@example.com / q1w2e3r4(实测演示账号)
- 客户端工具:curl 7.81(系统自带);浏览器 GraphiQL 调试台(Wiki.js 内置,见 2.3)
- 实例状态:已启用 API(管理后台 API 开关,开启方式见第八章实测)
- 测试数据:中文页面
zh/home(欢迎页)、zh/getting-started(入门指南,标签「指南」)、英文页面en/home(Welcome)
二、前置条件
2.1 端点
Wiki.js 全部管理与数据接口统一暴露在一个 GraphQL 端点:
POST http://<服务器IP>:<端口>/graphql
- 请求头必须带
Content-Type: application/json,请求体为{"query": "..."}形式的 JSON。 - 读操作(query)与写操作(mutation)都走同一端点,通过 query 语句中的
query/mutation关键字区分。
2.2 开启 API 访问
Wiki.js 默认关闭 API。用 API Key 调用前必须先开启(管理员登录后:管理后台 → API(接口) 菜单 → 打开 API 开关)。未开启时实测响应:
{
"data": {},
"errors": [
{
"message": "API is disabled. You must enable it from the Administration Area first.",
"path": []
}
]
}
💡 说明:携带管理员 JWT 的会话调用不受该开关限制;该开关约束的是 API Key 方式的调用(第八章实测)。生产环境建议保持「后台开关关闭 + 临时需要时再开」的最小暴露面。
2.3 客户端工具
- curl:本文全部实测使用 curl,命令可直接复制执行。
- GraphiQL 调试台:浏览器打开
http://<服务器IP>:<端口>/graphql(GET 方式访问)即进入内置 GraphiQL 界面,左侧写查询、右侧出结果,自带 schema 自动补全与文档面板(DOCS),是探索全部类型定义的最快途径。 - 命令行探索 schema:实例文件内含全部类型定义(
server/graph/schemas/*.graphql),按域拆分(page/user/group/system 等),字段拼写存疑时直接检索该文件最准确。
三、API 总览
3.1 认证方式
| 方式 | 获取 | 传递 | 适用 |
|---|---|---|---|
| 匿名(Guest) | 无 | 无 | 未认证请求自动以 Guest 身份执行,权限 = Guests 组 |
| JWT | mutation authentication.login 签发 | 请求头 Authorization: Bearer <jwt> | 脚本/自动化,默认 30 分钟过期 |
| API Key | mutation authentication.createApiKey 创建 | 请求头 Authorization: Bearer <key> | 长期集成,有效期可配(默认建议) |
JWT 的有效期为 30 分钟(tokenExpiration: '30m',系统初始化默认值),过期需重新登录换取;API Key 按创建时传入的 expiration 生效(如 100Y 即近乎永久),撤销走 revokeApiKey。
3.2 响应结构约定
业务 mutation 的响应普遍嵌套 responseResult(ResponseStatus 类型):
| 字段 | 类型 | 含义 |
|---|---|---|
succeeded | Boolean | 业务是否成功 |
errorCode | Int | 0 为成功;失败为业务错误码 |
slug | String | 错误标识(如 ok、AuthLoginFailed) |
message | String | 人类可读消息 |
错误体系分三层,实测样例见各域小节:
| 层级 | 判别特征 | 示例 |
|---|---|---|
| schema 校验错误 | errors[].extensions.code = GRAPHQL_VALIDATION_FAILED | 字段名拼错、必填参数缺失 |
| 权限错误 | errors[].message = "Forbidden" | 匿名调用需 manage:system 的 query |
| 业务错误 | responseResult.succeeded = false + errorCode/slug | 密码错误 AuthLoginFailed(1002) |
3.3 限流约定
写操作与认证操作带服务端速率限制(schema 声明):authentication.login 为每 60 秒 5 次(@rateLimit(limit: 5, duration: 60)),loginTFA、forgotPassword 同样受限。脚本批量调用时注意节流,超限返回 Too Many Requests 类错误。
四、认证与首次调用
4.1 登录获取 JWT
本地账号登录(用户名传邮箱或用户名,strategy 固定 local):
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' \
-d '{"query":"mutation { authentication { login(username: \"admin@example.com\", password: \"q1w2e3r4\", strategy: \"local\") { responseResult { succeeded errorCode slug message } jwt mustChangePwd continuationToken } } }"}'
实测回显(JWT 为超长字符串,节选首尾):
{
"data": {
"authentication": {
"login": {
"responseResult": {
"succeeded": true,
"errorCode": 0,
"slug": "ok",
"message": "Login success"
},
"jwt": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZW1haWwiOiJhZG1pbkBleGFtcGxlLmNvbSIsIm5hbWUiOiJBZG1pbmlzdHJhdG9yIiwiYXYiOm51bGwsInR6IjoiQW1lcmljYS9OZXdfWW9yayIsImxjIjoiZW4iLCJkZiI6IiIsImFwIjoiIiwicGVybWlzc2lvbnMiOlsibWFuYWdlOnN5c3RlbSJdLCJncm91cHMiOlsxXSwiaWF0IjoxNzkyMzEwMDYxLCJleHAiOjE3OTIzMTE4NjEsImF1ZCI6InVybjp3aWtpLmpzIiwiaXNzIjoidXJuOndpa2kuanMifQ.hfTlvPqRpOftbDJubrCBX6cGmm61nv96qO8gxjHVufI2dMYJGugGEzmewQZke9ctWcmlzZzRRKoIYv4EQDeAuaJaPC8TSEMg4w2HGd9edNG3OZQI8nq90dJ0MIkjlFtia_J241EuumIs4CvdQfrSwVctdcUlUcP6MNq6zS8ZNshdaXuUQbjkaCyvA1ssZS7rkWzG3ubyKQLhKxGvWWa1uFz-QA3sVU_e7QlmlopKLuRgGljIj7ur3RYudi6v4a6GpQ83VxexkOvTC34y7202COeRI7Yequ79gKou39TfOHzfqgvY3eJQ_zaaKiA_c-HE2LwZ0RvzhCZrJ1MQ",
"mustChangePwd": null,
"continuationToken": null
}
}
}
}
关键解读:JWT 为 RS256 签名令牌(实测长度约 700 字符),其 payload 部分解码可见用户身份与权限(id、email、name、permissions: ["manage:system"]、groups: [1]、iat/exp 时间戳);mustChangePwd 非 null 时表示管理员要求强制改密,需走 loginChangePassword 流程。
之后所有需要认证的调用把 JWT 放进请求头:
JWT="<上一步返回的jwt>"
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' \
-H "Authorization: Bearer $JWT" -d '{"query":"..."}'
4.2 错误密码(业务错误分支实测)
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' \
-d '{"query":"mutation { authentication { login(username: \"admin@example.com\", password: \"wrong-pass\", strategy: \"local\") { responseResult { succeeded errorCode slug message } jwt } } }"}'
实测回显:
{
"data": {
"authentication": {
"login": {
"responseResult": {
"succeeded": false,
"errorCode": 1002,
"slug": "AuthLoginFailed",
"message": "Invalid email / username or password."
},
"jwt": null
}
}
}
}
关键解读:注意 HTTP 状态仍是 200,判断成败要看 responseResult.succeeded 与 slug(AuthLoginFailed/1002),不能依赖 HTTP 层状态码。
4.3 字段拼错(schema 校验错误分支实测)
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' \
-d '{"query":"mutation { authentication { login(username: \"admin@example.com\", password: \"q1w2e3r4\", strategy: \"local\") { responseResult { succeeded } jwt mustChangePassword } } }"}'
实测回显(节选):
{
"errors": [
{
"message": "Cannot query field \"mustChangePassword\" on type \"AuthenticationLoginResponse\". Did you mean \"mustChangePwd\"?",
"locations": [{ "line": 1, "column": 165 }],
"extensions": { "code": "GRAPHQL_VALIDATION_FAILED", ... }
}
]
}
关键解读:GraphQL 的友好之处是错误消息直接给出「Did you mean」提示,照提示修正字段名即可;extensions.code 统一为 GRAPHQL_VALIDATION_FAILED。
五、页面域 API(pages)
页面是 Wiki.js 的核心对象,读(PageQuery)写(PageMutation)覆盖全生命周期。以下全部实测。
5.1 查询页面列表(pages.list)
JWT=$(cat /tmp/jwt.txt); curl -s -X POST http://localhost:3101/graphql \
-H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"query { pages { list { id path title locale isPublished updatedAt } } }"}'
实测回显:
{
"data": {
"pages": {
"list": [
{
"id": 2,
"path": "home",
"title": "欢迎页(中文示例)",
"locale": "zh",
"isPublished": true,
"updatedAt": "2026-10-18T07:56:06.217Z"
}
]
}
}
}
💡 说明:不带 Authorization 头调用同一 query 不会报错,而是以 Guest 身份返回「Guest 组有权看到的页面」(Guests 默认有
read:pages)——本实例初期无页面时实测返回{"data":{"pages":{"list":[]}}}。需要管理权限的 query(如users.list)匿名调用则直接Forbidden(见 4.x 错误体系)。
5.2 查询单页(pages.single)与页面树(pages.tree)
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"query { pages { single(id: 2) { id path title description updatedAt } } }"}'
实测回显:
{
"data": {
"pages": {
"single": {
"id": 2,
"path": "home",
"title": "欢迎页(中文示例)",
"description": "GraphQL API 创建的示例页面(已更新)",
"updatedAt": "2026-10-18T07:56:58.863Z"
}
}
}
}
页面树(含层级深度):
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"query { pages { tree(locale: \"zh\", path: \"\", mode: ALL) { id path title locale depth } } }"}'
实测回显:
{
"data": {
"pages": {
"tree": [
{ "id": 2, "path": "getting-started", "title": "入门指南", "locale": "zh", "depth": 1 },
{ "id": 3, "path": "home", "title": "欢迎页(中文示例)", "locale": "zh", "depth": 1 }
]
}
}
}
5.3 创建页面(pages.create)
创建中文页面(tags 为必填参数,空标签传 []):
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"mutation { pages { create(content: \"# 欢迎使用 Wiki.js\\n\\n这是通过 GraphQL API 创建的第一篇中文页面。\", description: \"GraphQL API 创建的示例页面\", editor: \"markdown\", isPublished: true, isPrivate: false, locale: \"zh\", path: \"home\", title: \"欢迎页(中文示例)\", tags: []) { responseResult { succeeded errorCode slug message } page { id path title locale updatedAt } } } }"}'
实测回显(响应节选,含已知瑕疵):
{
"errors": [
{
"message": "Cannot return null for non-nullable field Page.locale.",
"path": ["pages", "create", "page", "locale"],
"extensions": { "code": "INTERNAL_SERVER_ERROR", ... }
}
],
"data": {
"pages": {
"create": {
"responseResult": {
"succeeded": true,
"errorCode": 0,
"slug": "ok",
"message": "Page created successfully."
},
"page": null
}
}
}
}
关键解读:页面实际已创建成功(succeeded: true,用 pages.list 复查可见),仅响应体回填的 page 对象在 2.5.315 下缺 locale 字段序列化而报错——写脚本时以 responseResult 为准,page 字段不可依赖。
⚠️ 注意:
locale: "zh"要求中文语言包已安装,否则报外键错误ForeignKeyViolationError(详见第十章 FAQ Q1)。
校验错误实测:漏传必填的 tags 时(实测回显,节选):
{
"errors": [
{
"message": "Field \"create\" argument \"tags\" of type \"[String]!\" is required, but it was not provided.",
"extensions": { "code": "GRAPHQL_VALIDATION_FAILED", ... }
}
]
}
权限错误实测:不带任何认证头匿名调用 pages.create(实测回显,节选):
{"errors":[{"message":"Forbidden","path":["pages","create"],"extensions":{"code":"INTERNAL_SERVER_ERROR","exception":{"stacktrace":["Error: Forbidden"," at field.resolve (/wiki/server/graph/directives/auth.js:47:17)",...]}}}]}
5.4 更新页面(pages.update)
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"mutation { pages { update(id: 2, content: \"# 欢迎使用 Wiki.js\\n\\n## 更新说明\\n\\n本段为 pages.update 追加的内容。\", description: \"GraphQL API 创建的示例页面(已更新)\", editor: \"markdown\", isPublished: true, isPrivate: false, locale: \"zh\", path: \"home\", title: \"欢迎页(中文示例)\", tags: []) { responseResult { succeeded errorCode slug message } page { id updatedAt } } } }"}'
实测回显:
{
"data": {
"pages": {
"update": {
"responseResult": {
"succeeded": true,
"errorCode": 0,
"slug": "ok",
"message": "Page has been updated."
},
"page": { "id": 2, "updatedAt": "2026-10-18T07:56:58.863Z" }
}
}
}
}
5.5 版本历史(pages.history)
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"query { pages { history(id: 2) { trail { versionId versionDate authorName actionType } total } } }"}'
实测回显:
{
"data": {
"pages": {
"history": {
"trail": [
{
"versionId": 1,
"versionDate": "2026-10-18T07:56:06.217Z",
"authorName": "Administrator",
"actionType": "initial"
}
],
"total": 1
}
}
}
}
关键解读:trail 为版本轨迹(新→旧),actionType 取值 initial(创建)/edit/move 等;配合 pages.version(pageId, versionId) 可取任意版本全文。该 query 需要 manage:system 或 read:history 权限。
5.6 站内搜索(pages.search)与标签检索(pages.searchTags)
中文关键词搜索:
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"query { pages { search(query: \"入门\") { results { id title path locale } suggestions totalHits } } }"}'
实测回显:
{
"data": {
"pages": {
"search": {
"results": [
{ "id": "4", "title": "入门指南", "path": "getting-started", "locale": "zh" }
],
"suggestions": [],
"totalHits": 1
}
}
}
}
标签模糊检索(创建 zh/getting-started 时打了标签「指南」):
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"query { pages { searchTags(query: \"指\") } }"}'
实测回显:
{
"data": {
"pages": {
"searchTags": ["指南"]
}
}
}
六、用户与组域 API(users / groups)
6.1 用户列表(users.list)
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"query { users { list { id name email providerKey } } }"}'
实测回显:
{
"data": {
"users": {
"list": [
{ "id": 2, "name": "Guest", "email": "guest@example.com", "providerKey": "local" },
{ "id": 1, "name": "Administrator", "email": "admin@example.com", "providerKey": "local" }
]
}
}
}
权限错误实测(同一 query 不带认证头,回显节选):
{
"errors": [
{ "message": "Forbidden", "path": ["users", "list"], "extensions": { "code": "INTERNAL_SERVER_ERROR", ... } }
]
}
💡 说明:
users.list属管理操作,需manage:system或read:users权限;字段选择注意UserMinimal类型只有id/name/email/providerKey等精简字段,误选providerName会得到Did you mean "providerKey"?的校验错误(实测)。
6.2 组列表与权限详情(groups.list / groups.single)
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"query { groups { list { id name userCount isSystem } } }"}'
实测回显:
{
"data": {
"groups": {
"list": [
{ "id": 1, "name": "Administrators", "userCount": 1, "isSystem": true },
{ "id": 2, "name": "Guests", "userCount": 1, "isSystem": true }
]
}
}
}
单组详情(含权限位与页面规则,实测回显):
{
"data": {
"groups": {
"single": {
"id": 1,
"name": "Administrators",
"permissions": ["manage:system"],
"pageRules": []
}
}
}
}
💡 说明:
groups.list返回的是GroupMinimal精简类型(无 permissions 字段);要拿权限必须走groups.single(id)。写操作groups.update可直接改权限位与页面规则,是实现「脚本化权限管理」的入口。
七、系统与本地化域 API(system / localization)
7.1 系统信息(system.info)
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"query { system { info { dbType dbVersion latestVersion nodeVersion platform currentVersion } } }"}'
实测回显:
{
"data": {
"system": {
"info": {
"dbType": "PostgreSQL",
"dbVersion": "16.15",
"latestVersion": "2.5.316",
"nodeVersion": "24.21.0",
"platform": "docker",
"currentVersion": "2.5.315"
}
}
}
}
关键解读:currentVersion 与 latestVersion 对比即升级检查;巡检脚本可直接解析该 JSON。
7.2 安装语言包(localization.downloadLocale)
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"mutation { localization { downloadLocale(locale: \"zh\") { responseResult { succeeded errorCode slug message } } } }"}'
实测回显:
{
"data": {
"localization": {
"downloadLocale": {
"responseResult": {
"succeeded": true,
"errorCode": 0,
"slug": "ok",
"message": "Locale downloaded successfully"
}
}
}
}
}
该 mutation 需 manage:system 权限;成功后即可创建该语种页面(对照实测:安装前创建 zh 页面报 pages_localecode_foreign 外键错误,安装后成功)。
八、API Key 长期鉴权
JWT 30 分钟即过期,长期集成(CI/CD、巡检脚本、第三方系统对接)应使用 API Key。完整链路实测如下。
8.1 创建 API Key
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"mutation { authentication { createApiKey(name: \"docs-api-key\", expiration: \"100Y\", fullAccess: true, group: 1) { responseResult { succeeded errorCode slug message } key } } }"}'
实测回显(key 节选首尾):
{
"data": {
"authentication": {
"createApiKey": {
"responseResult": {
"succeeded": true,
"errorCode": 0,
"slug": "ok",
"message": "API Key created successfully"
},
"key": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcGkiOjEsImdycCI6MSwiaWF0IjoxNzkyMzEwMzkxLCJleHAiOjQ5NDgwNzAzOTEsImF1ZCI6InVybjp3aWtpLmpzIiwiaXNzIjoidXJuOndpa2kuanMifQ.G1vNHhtct4Ug1XAaPvDZ8FcsDp6EbJsKiU_hau70ThkcweEwyffOyV1ePuPIh74FcevkDY_oi42JZuZ6IxrNgonZaZrNTK_wd5KplvjsLZDX9CQJWiwpfUIZIJYEwUJyUVNPTB2CDsFWP9lEDOA95l7bRl98U239qFqYbiD1YERNjE8EGTPu8AGvwKblm7f1PREF-0y707c1PPCmWivyamE0uQ95JSTL59qey5VG73iIG_0nq2jThupM6X6CVPQsEKI6f0rK-rXUkomnuzX9FZKyvErROoaIsEfAsabdjHxKBYpBba5AvhZgKMLrMVcxZwzdAa9eB_zwgzjMXuROkA"
}
}
}
}
参数说明:
| 参数 | 说明 |
|---|---|
name | Key 名称(管理后台可见) |
expiration | 有效期(30d/12M/100Y 等时长格式) |
fullAccess | true 时继承所绑定组的全部权限 |
group | 绑定组 ID(权限边界即该组的权限位 + 页面规则) |
⚠️ 注意:
key响应字段是标量字符串(AuthenticationCreateApiKeyResponse.key: String),写成key { id name }会报Field "key" must not have a selection...校验错误(实测踩坑)。key 值仅此一次展示,务必立即保存;遗失只能 revoke 后重建。
8.2 用 API Key 调用(需先开启 API 开关)
AK="<createApiKey 返回的 key>"
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' \
-H "Authorization: Bearer $AK" \
-d '{"query":"query { users { list { id name email } } }"}'
未在管理后台开启 API 时的实测回显:
{
"data": {},
"errors": [
{ "message": "API is disabled. You must enable it from the Administration Area first.", "path": [] }
]
}
开启 API 开关(管理员 JWT 调用;等价于管理后台 API 页的开关,实测回显):
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"mutation { authentication { setApiState(enabled: true) { responseResult { succeeded message } } } }"}'
{
"data": {
"authentication": {
"setApiState": {
"responseResult": { "succeeded": true, "message": "API State changed successfully" }
}
}
}
}
再次用同一 API Key 调用(实测回显):
{
"data": {
"users": {
"list": [
{ "id": 2, "name": "Guest", "email": "guest@example.com" },
{ "id": 1, "name": "Administrator", "email": "admin@example.com" }
]
}
}
}
8.3 撤销与轮换
撤销走 authentication.revokeApiKey(id)(需 Key 的数字 ID,可用 authentication { apiKeys { id name isRevoked } } 查询获得)。轮换节奏建议:季度级轮换、人员离职即撤销、Key 命名带用途与日期(如 ci-docs-2026Q4)便于审计。
九、分页/过滤/排序通用约定
pages.list 是分页参数最全的 query,其约定可推广到多数列表型接口:
curl -s -X POST http://localhost:3101/graphql -H 'Content-Type: application/json' -H "Authorization: Bearer $JWT" \
-d '{"query":"query { pages { list(limit: 2, orderBy: UPDATED, orderByDirection: DESC, locale: \"zh\") { id path title updatedAt } } }"}'
实测回显:
{
"data": {
"pages": {
"list": [
{ "id": 2, "path": "home", "title": "欢迎页(中文示例)", "updatedAt": "2026-10-18T07:56:58.863Z" },
{ "id": 4, "path": "getting-started", "title": "入门指南", "updatedAt": "2026-10-18T07:56:41.338Z" }
]
}
}
}
标签过滤(实测回显,命中打了「指南」标签的页面):
{
"data": {
"pages": {
"list": [
{ "id": 4, "path": "getting-started", "title": "入门指南" }
]
}
}
}
通用约定要点:
limit:返回条数上限;orderBy:排序键(如UPDATED/TITLE/ID,枚举型);orderByDirection:ASC/DESC。locale:按语种过滤(注意参数名是locale,写localeCode会报Unknown argument,实测踩坑);tags: [String!]:按标签精确过滤。- 无偏移游标体系:大数据量翻页用
history类接口的offsetPage/offsetSize分页参数,pages.list以orderBy + limit组合近似实现。
十、常见问题(FAQ)
Q1:创建页面报 ForeignKeyViolationError ... pages_localecode_foreign?
- 实测现象:
locale: "zh"创建页面时返回succeeded: false, slug: "ForeignKeyViolationError"。 - 定位:页面表的
localeCode外键指向语言包表,zh未安装则插入被拒。 - 解决:先
localization { downloadLocale(locale: "zh") }(或管理后台 Locale 页下载)再创建。
Q2:带着 JWT 调用还是 Forbidden?
- ① JWT 过期(30 分钟,重登录即可);② 该 query/mutation 要求的权限超出账号所在组的权限位(如
users.list需manage:system或read:users);③ 页面类操作还受页面规则(Page Rules)约束——权限位过了、规则没放行同样 Forbidden。逐项比对groups.single返回的permissions与目标操作的@auth(requires: [...])要求。
Q3:API Key 报 API is disabled?
- 管理后台 API 开关未开启(GraphQL 等价操作
authentication.setApiState(enabled: true),见第八章实测)。开启后无需重启,立即生效。
Q4:登录接口频繁返回限流错误?
login限流为 60 秒 5 次(schema 声明@rateLimit(limit: 5, duration: 60))。脚本重试务必加退避间隔;集成场景改用 API Key(不受该限流约束)。
Q5:createApiKey 的 key 响应字段选了子字段报错?
key是标量 String,直接key平取,不能key { id name }(实测报Field "key" must not have a selection since type "String" has no subfields)。
Q6:分页参数 localeCode 报 Unknown argument?
pages.list的语种过滤参数名为locale(错误消息会提示Did you mean "locale"?)。各接口参数名以 GraphiQL 文档面板为准,勿凭直觉拼写。
十一、参考链接
- Wiki.js 官方 GraphQL 文档(Dev → API):https://docs.requarks.io/dev/api
- GraphQL 官网(查询语言规范):https://graphql.org/learn/
- schema 定义源码(v2.5.315,server/graph/schemas/):https://github.com/requarks/wiki/tree/v2.5.315/server/graph/schemas
- 本专栏相关篇目:《Wiki.js 2.5 介绍与选型指南》、《Wiki.js Docker Compose 部署指南》、《Wiki.js 2.5 配置参数详解》