无头 API 接口文档
面向后端、脚本和 CLI 的无头 API 指南
一、链路差异
| 项目 | 标准 API | 无头 API |
|---|---|---|
| 路径 | /api/* | /headless/api/* |
| 认证来源 | X-Token 优先,其次 body.key | 仅 X-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。
认证错误:
{ "error": "missing_key", "message": "缺少密钥" }{ "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": "{短链后缀}" }{ "ok": true, "synced": true }code 必须为非空字符串,随后转小写;该接口按冷存储值查询,没有额外的 1-5 位正则。删除以冷存储为准,先删冷、后删热,并把冷存储确定的 perm/temp 类型提示传给 Lua 以准确递减热计数。synced=false 不回滚已完成的冷删除。
| HTTP | error | message |
|---|---|---|
400 | bad_request | 无效的请求体 |
400 | missing_code | 短链后缀必须为字符串 / 缺少短链后缀 |
403 | onetime_forbidden | 一次性密钥无权进行短链管理 |
404 | not_found | 该短链不存在 |
500 | data_corrupted | 数据文件损坏,请检查服务端日志 |
500 | write_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_count、temp_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 路由。
{
"id": "abcde",
"url": "https://example.com/path",
"lurl": "https://{你的域名}/abcde",
"exp": "permanent"
}{
"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 会被消费后继续完成单条查询。
| HTTP | error | message |
|---|---|---|
400 | missing_code | 缺少短链后缀 |
404 | not_found | 该短链不存在 |
404 | expired | 该短链已过期 |
500 | data_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 等部署配置影响。