YOURLS 1.10.6 API 使用详解

YOURLS 1.10.6 内置 REST API 实战详解:认证方式(用户名密码与 1.10.5 起新 sha256 签名 token)、shorturl/stats/db-stats/url-stats/expand/version 六大 action 参数与实测响应、分页过滤与输出格式、错误码汇总与常见问题排查,全部回显为 Ubuntu 22.04 服务器实测真实结果。

YOURLSYOURLS自托管PHP2026/10/30

YOURLS 1.10.6 API 使用详解

目标:完整覆盖 YOURLS 1.10.6 内置 REST API 的 6 个 action——认证方式(含 1.10.5 起的新签名机制)、参数、实测响应与错误码,每条请求与回显均为 2026-10-30 在 Ubuntu 22.04 服务器实测真实结果(实例部署见 《YOURLS 1.10.6 Docker Compose 部署指南》)。

一、环境信息

  • 操作系统:Ubuntu 22.04(IP 192.168.1.200);
  • YOURLS:1.10.6(Apache 2.4.69 + PHP 8.5.12,MySQL 8.0);
  • API 端点:http://192.168.1.200:8134/yourls-api.php;
  • 实例模式:私密模式(YOURLS_PRIVATE=true 默认值,参数见 《YOURLS 1.10.6 配置参数详解》);
  • 演示账号:admin / q1w2e3r4;
  • 客户端工具:curl(任意 Linux 发行版自带)。

二、前置条件

  • 一个可用的 YOURLS 1.10.6 实例(部署见本专栏部署篇);
  • 端点确认:API 入口固定为应用根目录下的 yourls-api.php,先验证可达性:
curl -s -o /dev/null -w '%{http_code}\n' http://192.168.1.200:8134/yourls-api.php

实测回显:

200
  • 私密模式下需预先取得两套凭据之一:管理账号(用户名+密码)或 Secret signature token(登录后台 admin/tools.php 页面查看,官方标注「Your secret signature token」)。

三、API 总览

YOURLS 内置 REST API 的全貌(action 清单来自源码 includes/functions-api.php 实查,2026-10-30):

action功能核心参数
shorturl创建短链url(必填)、keyword(可选自定义短码)、title(可选标题)
stats短链列表统计filter(排序筛选)、limit(条数)、start(偏移)
db-stats全局统计无
url-stats单条短链统计shorturl(短码或完整短链)
expand短码还原长链shorturl
version查询 YOURLS 版本无

统一约定:

  • 协议与入口:HTTP(S) 单端点 yourls-api.php,全部参数走查询串或表单(POST/GET 均可,含敏感凭据时建议 POST);
  • 输出格式:format 参数支持 json(默认建议)、xml、jsonp、simple 四种(源码 yourls_api_output 的取值集合实查);
  • 认证:私密模式下每次请求必须携带凭据(见第四节),公开模式(YOURLS_PRIVATE=false)下无需;
  • 限流:内置 API 无内建限流机制,高频调用方需自行节流(如需强限流可装社区插件或在反向代理层实现);
  • 能做的与不能做的:内置 action 仅「创建 + 各类查询」,没有编辑与删除短链的 API——这两类操作走管理后台 UI 或安装社区插件补齐。这与 Shlink 的 CRUD 全集 API 形成鲜明对比(对比分析见 《Shlink 5.1.8 REST API 与 CLI 命令详解》,极简派参考 《Chhoto URL 7.10.3 REST API 使用详解》)。

四、认证与首次调用

4.1 方式一:用户名 + 密码参数

最直接的方式:每次请求带 username 与 password 参数。首次调用(查询全局统计):

curl -s "http://192.168.1.200:8134/yourls-api.php" \
  --data-urlencode 'action=db-stats' --data-urlencode 'format=json' \
  --data-urlencode 'username=admin' --data-urlencode 'password=q1w2e3r4'

实测回显:

{"db-stats":{"total_links":7,"total_clicks":1},"statusCode":"200","message":"success"}

凭据错误或缺失时的统一拒绝形态:

curl -s -w '\nHTTP:%{http_code}\n' "http://192.168.1.200:8134/yourls-api.php" \
  --data-urlencode 'action=db-stats' --data-urlencode 'format=json'

实测回显:

{"message":"Please log in","errorCode":"403","callback":""}
HTTP:403

4.2 方式二:signature token 签名(1.10.5 起新机制)

不想把账号密码传给第三方调用方时,用后台 Tools 页的 Secret signature token。1.10.5 起 md5 签名已弃用,当前规则(源码 functions-auth.php 实查):默认哈希算法 sha256,允许 sha256/sha384/sha512(可用 hash 参数指定),签名公式为 sha256(timestamp + token),timestamp 有效期与登录 nonce 一致(默认约 ±一个 nonce 生命周期)。

先实测「旧 md5 写法已被拒」(排障要点——大量老教程仍是 md5):

TS=$(date +%s)
SIG_MD5=$(python3 -c "import hashlib; print(hashlib.md5(('$TS'+'admin'+'q1w2e3r4').encode()).hexdigest())")
curl -s "http://192.168.1.200:8134/yourls-api.php?action=db-stats&format=json&timestamp=$TS&signature=$SIG_MD5"

实测回显(md5 计算的签名不再被接受):

{"message":"Please log in","errorCode":"403","callback":""}

正确的 sha256 签名调用(token 取自后台 Tools 页,本文实例为 200dba9cfd92ef3ec78d00b38863462d):

TS=$(date +%s)
SIG=$(python3 -c "import hashlib; print(hashlib.sha256(('$TS'+'200dba9cfd92ef3ec78d00b38863462d').encode()).hexdigest())")
curl -s "http://192.168.1.200:8134/yourls-api.php?action=db-stats&format=json&timestamp=$TS&signature=$SIG"

实测回显:

{"db-stats":{"total_links":7,"total_clicks":1},"statusCode":"200","message":"success"}

💡 技术拓展:API 凭据传递的常见三种流派——每次请求传用户名密码(YOURLS 方式一,简单但凭据暴露面大)、静态签名 token(YOURLS 方式二,token 只能用于 API 不能登录后台,泄露面更小)、带时效的动态签名(YOURLS 的 timestamp + signature,兼顾防重放)。生产对外发 API 凭据时优先用方式二的签名 token,并为不同调用方各发一个独立账号。

五、各 API 域详解

5.1 shorturl:创建短链

参数:action=shorturl、url(长链,必填)、keyword(自定义短码,可选)、title(标题,可选)、format。

curl -s "http://192.168.1.200:8134/yourls-api.php" \
  --data-urlencode 'url=https://www.quzuo.net/' \
  --data-urlencode 'title=Quzuo 主站' \
  --data-urlencode 'keyword=quzuo' \
  --data-urlencode 'action=shorturl' --data-urlencode 'format=json' \
  --data-urlencode 'username=admin' --data-urlencode 'password=q1w2e3r4'

实测回显:

{
    "status": "success",
    "code": "",
    "message": "https://www.quzuo.net/ added to database",
    "errorCode": "",
    "statusCode": "200",
    "url": {
        "keyword": "quzuo",
        "url": "https://www.quzuo.net/",
        "title": "Quzuo \u4e3b\u7ad9",
        "date": "2026-10-30 07:21:34",
        "ip": "192.168.1.200"
    },
    "title": "Quzuo \u4e3b\u7ad9",
    "shorturl": "http://192.168.1.200:8134/quzuo"
}

关键错误——重复长链返回 409 Conflict(1.10.5 起从 400 改为 409):

curl -s -w '\nHTTP:%{http_code}\n' "http://192.168.1.200:8134/yourls-api.php" \
  --data-urlencode 'url=https://www.quzuo.net/' \
  --data-urlencode 'action=shorturl' --data-urlencode 'format=json' \
  --data-urlencode 'username=admin' --data-urlencode 'password=q1w2e3r4'

实测回显:

{"status":"fail","code":"error:url","message":"https:\/\/www.quzuo.net\/ already exists in database (short URL: 192.168.1.200:8134\/quzuo)","errorCode":"409","statusCode":"409","url":{"keyword":"quzuo","url":"https:\/\/www.quzuo.net\/","title":"Quzuo \u4e3b\u7ad9","date":"2026-10-30 07:21:34","ip":"192.168.1.200","clicks":1},"title":"Quzuo \u4e3b\u7ad9","shorturl":"http:\/\/192.168.1.200:8134\/quzuo"}
HTTP:409

(YOURLS_UNIQUE_URLS=false 时不触发 409,同一长链可重复建码,配置见配置篇 5.3 节实测。)

5.2 stats:短链列表统计

参数:action=stats、filter(top 按点击降序 / last 按时间最新 / bottom 按点击升序 / rand 随机)、limit(返回条数)、start(分页偏移)。

curl -s "http://192.168.1.200:8134/yourls-api.php" \
  --data-urlencode 'action=stats' --data-urlencode 'filter=last' \
  --data-urlencode 'limit=2' --data-urlencode 'format=json' \
  --data-urlencode 'username=admin' --data-urlencode 'password=q1w2e3r4'

实测回显(json.tool 格式化展示,响应尾部含 statusCode/message):

{
    "links": {
        "link_1": {
            "shorturl": "http://192.168.1.200:8134/3",
            "url": "https://example.org/test-3",
            "title": "Example Domain",
            "timestamp": "2026-10-30 07:23:36",
            "ip": "192.168.1.200",
            "clicks": 0
        },
        "link_2": {
            "shorturl": "http://192.168.1.200:8134/2",
            "url": "https://example.org/test-2",
            "title": "Example Domain",
            "timestamp": "2026-10-30 07:23:35",
            "ip": "192.168.1.200",
            "clicks": 0
        }
    },
    "stats": {"total_links": 7, "total_clicks": 1},
    "statusCode": "200",
    "message": "success"
}

filter=bottom 实测(取点击最少的 2 条):

curl -s "http://192.168.1.200:8134/yourls-api.php" \
  --data-urlencode 'action=stats' --data-urlencode 'filter=bottom' \
  --data-urlencode 'limit=2' --data-urlencode 'format=json' \
  --data-urlencode 'username=admin' --data-urlencode 'password=q1w2e3r4'

实测回显:

{"links":{"link_1":{"shorturl":"http:\/\/192.168.1.200:8134\/ozh","url":"https:\/\/ozh.org\/","title":"ozh.org","timestamp":"2026-10-30 07:20:39","ip":"10.89.59.1","clicks":0},"link_2":{"shorturl":"http:\/\/192.168.1.200:8134\/yourlsblog","url":"https:\/\/blog.yourls.org\/","title":"YOURLS' Blog","timestamp":"2026-10-30 07:20:39","ip":"10.89.59.1","clicks":0}},"stats":{"total_links":7,"total_clicks":1},"statusCode":"200","message":"success"}

5.3 db-stats:全局统计

参数仅 action 与 format。这是最小的一个 action,也是验证认证是否打通的探针(见 4.1 节实测):

{"db-stats":{"total_links":7,"total_clicks":1},"statusCode":"200","message":"success"}

5.4 url-stats:单条短链统计

参数:shorturl(短码 quzuo 或完整短链 URL 均可):

curl -s "http://192.168.1.200:8134/yourls-api.php" \
  --data-urlencode 'action=url-stats' --data-urlencode 'shorturl=quzuo' \
  --data-urlencode 'format=json' \
  --data-urlencode 'username=admin' --data-urlencode 'password=q1w2e3r4'

实测回显(中文标题以 \u4e3b\u7ad9 形式转义返回,为 API 原始输出):

{"statusCode":"200","message":"success","link":{"shorturl":"http:\/\/192.168.1.200:8134\/quzuo","url":"https:\/\/www.quzuo.net\/","title":"Quzuo \u4e3b\u7ad9","timestamp":"2026-10-30 07:21:34","ip":"192.168.1.200","clicks":1}}

短码不存在时的错误形态:

curl -s -w '\nHTTP:%{http_code}\n' "http://192.168.1.200:8134/yourls-api.php" \
  --data-urlencode 'action=url-stats' --data-urlencode 'shorturl=noexist9z' \
  --data-urlencode 'format=json' \
  --data-urlencode 'username=admin' --data-urlencode 'password=q1w2e3r4'

实测回显:

{"statusCode":"404","message":"Error: short URL not found"}
HTTP:404

5.5 expand:还原长链

参数:shorturl(短码或完整短链):

curl -s "http://192.168.1.200:8134/yourls-api.php" \
  --data-urlencode 'action=expand' --data-urlencode 'shorturl=quzuo' \
  --data-urlencode 'format=json' \
  --data-urlencode 'username=admin' --data-urlencode 'password=q1w2e3r4'

实测回显:

{"keyword":"quzuo","shorturl":"http:\/\/192.168.1.200:8134\/quzuo","longurl":"https:\/\/www.quzuo.net\/","title":"Quzuo \u4e3b\u7ad9","message":"success","statusCode":"200"}

5.6 version:查询版本

需要认证(未认证返回 403,实测见下):

curl -s "http://192.168.1.200:8134/yourls-api.php" \
  --data-urlencode 'action=version' --data-urlencode 'format=json' \
  --data-urlencode 'username=admin' --data-urlencode 'password=q1w2e3r4'

实测回显:

{"version":"1.10.6"}

六、分页、过滤与输出格式通用约定

  • 分页:仅 stats 支持,limit(默认 10,源码函数签名 yourls_api_stats($filter = 'top', $limit = 10, $start = 0))+ start(跳过前 N 条)组合翻页;db-stats/url-stats 无分页概念;
  • 过滤排序:filter 四个取值 top(点击降序,默认,实测 quzuo 因 clicks=1 排首位)/last(时间倒序)/bottom(点击升序)/rand(随机),实测 5.2 节已验证 last/bottom/top/rand 全部取值;
  • 输出格式切换:同一请求换 format 即得不同形态,format=xml 实测:
curl -s "http://192.168.1.200:8134/yourls-api.php" \
  --data-urlencode 'action=db-stats' --data-urlencode 'format=xml' \
  --data-urlencode 'username=admin' --data-urlencode 'password=q1w2e3r4'

实测回显:

<?xml version="1.0" encoding="UTF-8"?>
<root><db-stats><total_links>7</total_links><total_clicks>1</total_clicks></db-stats><statusCode>200</statusCode><message>success</message></root>

format=simple 输出无格式的纯文本(只回显 simple 键值,适合脚本取值),format=jsonp 需配 callback 函数名用于浏览器跨域。

错误码汇总(全部实测确认):

HTTP 状态码触发场景响应体特征
200成功"statusCode":"200" + 对应数据
400action 缺失或未知{"errorCode":"400","message":"Unknown or missing \"action\" parameter"}
403凭据缺失/错误/签名过期{"message":"Please log in","errorCode":"403"}
409长链已存在且 YOURLS_UNIQUE_URLS=true"status":"fail","code":"error:url","errorCode":"409"
404url-stats 短码不存在{"statusCode":"404","message":"Error: short URL not found"}

400 形态实测(不带 action):

curl -s "http://192.168.1.200:8134/yourls-api.php" --data-urlencode 'format=json' \
  --data-urlencode 'username=admin' --data-urlencode 'password=q1w2e3r4'

实测回显:

{"errorCode": "400", "message": "Unknown or missing \"action\" parameter"}

七、常见问题

Q1:老脚本用 md5 签名突然全部 403? 1.10.5 弃用 md5(本文 4.2 节实测老写法被拒),改用 sha256(timestamp + token);确有 md5 依赖且能接受风险时,可用插件通过 allowed_hash_algos 过滤器重新放行(源码注释明确该扩展点),但强烈建议直接升级调用方。

Q2:如何删除或修改一条短链? 内置 API 没有这两个 action(源码 functions-api.php 实查仅 6 个)。临时改用后台 UI 操作;自动化场景安装社区 API 扩展插件(官方 awesome 列表有收录 delete/edit 类插件)。

Q3:signature token 泄露了怎么办? token 与 YOURLS_COOKIEKEY 盐和账号体系绑定,修改 YOURLS_COOKIEKEY(容器 env 或 config.php)并重启服务即可使所有旧 token 与会话失效,再到 Tools 页取新 token。

Q4:API 创建的短链打不开? 短链域名前缀来自 YOURLS_SITE(响应里 shorturl 字段可见),YOURLS_SITE 与实际访问地址不一致就会出现「API 说建成了、浏览器打不开」的现象——排查配置见配置篇 Q3。

Q5:想批量导入已有短链数据? API 逐条调用 shorturl 即可(注意 409 处理);更高效的方式是直接写库(yourls_url 表结构见配置篇 5.1 节实测),批量后无需重启。

八、参考链接