圣堂之魂
开发指南

无头 API 接口文档

面向后端、脚本和 CLI 的无头 API 指南



一、链路差异

项目标准 API无头 API
路径/api/*/headless/api/*
认证来源X-Token 优先,其次 body.keyX-Headless-Token
服务 Key拒绝接受
CORS使用 panel_origin/domain不设置 CORS
面板开关panel_enabled=false 时关闭不受 panel_enabled 影响
错误体{ "error": "中文" }{ "error": "code", "message": "中文" }
单条查询GET /headless/api/get/{code}

无头链路没有独立的 /headless/api/ping。部署探活使用无需认证的 GET /api/ping,它只检查 PHP 路由可达性。


二、Key 认证与消费语义

X-Headless-Token: {su_你的Key}

无头链路忽略 X-Token 和请求体 key。支持的 Key 类型:

Key 类型有效期/次数无头权限
常驻 Key默认 7 天,不限次数创建、删除、列表、统计、单条查询
一次性 Key验证成功时立即消费创建和当前实现中的单条查询;删除、列表、统计返回 403 onetime_forbidden
服务 Key永不过期,不限次数,仅可保留一个全部无头接口;创建时使用服务配额和 4/5 位短码能力

一次性 Key 在 headless/bootstrap.php 内从 Header 验证并消费,发生在 JSON 解析和业务校验之前。即使请求随后因坏 JSON、无效 URL、冲突、配额或服务器错误失败,Key 也不会退还。它也可以先被删除、列表或统计接口消费,再收到 403 onetime_forbidden

认证错误:

406:缺少 Header
{ "error": "missing_key", "message": "缺少密钥" }
406:无效或过期
{ "error": "invalid_key", "message": "密钥失效或不正确" }

服务端只保存 Key 哈希和前缀。一次性槽被消费后将 key_hash 置为 null,不会自动补充;若消费写盘失败,验证返回无效且代码记录“Key 未消费”。


三、创建短链

POST /headless/api/create
Content-Type: application/json
X-Headless-Token: {su_你的Key}
{
  "url": "https://example.com/path",
  "ttl": 1800,
  "code": "demo",
  "len": 5
}

Prop

Type


四、删除短链

POST /headless/api/delete
Content-Type: application/json
X-Headless-Token: {su_你的Key}
{ "code": "{短链后缀}" }
200
{ "ok": true, "synced": true }

code 必须为非空字符串,随后转小写;该接口按冷存储值查询,没有额外的 1-5 位正则。删除以冷存储为准,先删冷、后删热,并把冷存储确定的 perm/temp 类型提示传给 Lua 以准确递减热计数。synced=false 不回滚已完成的冷删除。

HTTPerrormessage
400bad_request无效的请求体
400missing_code短链后缀必须为字符串 / 缺少短链后缀
403onetime_forbidden一次性密钥无权进行短链管理
404not_found该短链不存在
500data_corrupted数据文件损坏,请检查服务端日志
500write_failed服务器内部错误

五、查询列表

GET /headless/api/list
X-Headless-Token: {su_你的Key}

响应与标准 /api/list 相同:

{
  "permanent": [
    { "id": "a1b2", "url": "https://example.com/", "lurl": "https://{你的域名}/a1b2", "exp": "permanent" }
  ],
  "temporary": []
}

数据来自冷存储,临时列表过滤已过期条目。一次性 Key 返回 403 onetime_forbidden;冷存储损坏返回 500 data_corrupted


六、查询统计

GET /headless/api/stat
X-Headless-Token: {su_你的Key}
热存储可用时
{
  "perm_count": 12,
  "temp_count": 3,
  "perm_limit": 10000,
  "temp_limit": 500,
  "hot_available": true,
  "hot_perm_count": 12,
  "hot_temp_count": 3
}

perm_counttemp_count 始终来自冷存储的有效条目遍历,是权威业务计数。hot_* 只用于诊断,且仅在内部 /internal/stat 成功时出现;失败时 hot_available=false,接口仍返回冷计数和 HTTP 200

即使使用服务 Key,当前 stat 响应的 perm_limit / temp_limit 仍取普通 perm_limit / temp_limit,不会改为 svc_perm_limit / svc_temp_limit。创建时服务 Key 实际执行的却是服务配额。这是 v1.11.0 的实现差异,客户端不要把 stat 返回上限当作服务 Key 的实际配额。


七、查询单条短链

GET /headless/api/get/{code}
X-Headless-Token: {su_你的Key}

Nginx 示例路由接受 1-5 位 [0-9a-zA-Z-],PHP 将短码转小写。PHP 自身从 PATH_INFO 提取值时没有再做长度/字符正则,因此公网约束依赖 Nginx 路由。

永久短链 200
{
  "id": "abcde",
  "url": "https://example.com/path",
  "lurl": "https://{你的域名}/abcde",
  "exp": "permanent"
}
临时短链 200
{
  "id": "demo",
  "url": "https://example.com/path",
  "lurl": "https://{你的域名}/demo",
  "exp": "{ISO 8601 过期时间}"
}

查询顺序为永久冷存储,再查临时冷存储。临时条目已过期时返回 404 expired;不存在返回 404 not_found;条目缺少必要字段返回 500 data_corrupted。与 delete/list/stat 不同,代码没有显式禁止一次性 Key,因此一次性 Key 会被消费后继续完成单条查询。

HTTPerrormessage
400missing_code缺少短链后缀
404not_found该短链不存在
404expired该短链已过期
500data_corrupted数据文件损坏,请检查服务端日志 / 数据条目损坏

八、通用错误与 430

无头错误体固定为:

{ "error": "machine_code", "message": "中文描述" }

数据访问检查优先于认证。当前通用 430 不暴露文件名:

{
  "error": "data_inaccessible",
  "message": "数据文件不可访问,请检查文件权限"
}

具体文件名只写服务器日志。文件存在时检查可读写;不存在时检查父目录是否存在且可写。无头 bootstrap 在 430 检查之前先检查 domain 占位符,因此 domain 未配置时会先返回 500 config_error;标准 bootstrap 的顺序相反。

无头 OPTIONS 由 PHP 返回 204,但不附加 CORS 头。实际请求是否能到达 PHP 仍受 Nginx limit_except 等部署配置影响。


本页目录