Slink 1.14.5 API 使用详解
Slink v1.14.5 对外 API 实测详解:JWT 与 API Key 双认证、登录续期、Key 管理增删查、外部上传与错误码矩阵、ShareX 配置生成、收藏夹与分享创建、配置读取接口,全部请求响应实测回抄。
Slink 1.14.5 API 使用详解
目标:讲清 Slink v1.14.5 对外 API 的认证体系与全部可编程调用路径——登录换 JWT、API Key 管理、外部程序化上传、ShareX 配置生成、收藏夹与分享创建、平台配置读取,全部请求与响应均为本地实例实测回抄(环境见第一章)。部署与配置背景见 《Slink 1.14.5 Docker Compose 部署指南》。
一、环境信息
本文接口实测在以下环境完成:
- 操作系统:Ubuntu 24.04.5 LTS(x86_64),客户端 curl 8.x
- Slink 版本:v1.14.5(官方镜像
anirdev/slink:v1.14.5,2026-10-31 发布) - 实例地址:
http://localhost:8130(应用内 3000) - 测试账号:
admin@slink.local/q1w2e3r4(首个管理员,自动创建) - API 调试目录:
/opt/slink,测试图片test-blue.png(64×64 PNG,177 字节)
二、前置条件
- 端点:Slink 对外 API 与 Web 界面同域同端口(本文
http://localhost:8130),路径前缀/api;无需单独开启 API 服务; - 认证方式二选一:
- JWT 会话令牌:
POST /api/auth/login换取access_token,请求头Authorization: Bearer <access_token>,用于管理类接口(Key 管理、上传、收藏夹、分享、配置读取),有效期 1 小时; - 个人 API Key:形如
sk_<64位十六进制>,在 Web 界面个人资料页或POST /api/user/api-keys创建,请求头同为Authorization: Bearer sk_...,用于外部集成上传(ShareX、脚本);
- JWT 会话令牌:
- 同源要求:所有写请求(POST/PATCH/DELETE)必须携带与实例
ORIGIN一致的Origin请求头,否则被同源校验拒绝(403,详见第七章 Q1)——浏览器自动携带,脚本与 curl 必须手动加; - 客户端工具:curl 即可(本文全部用 curl 实测)。
三、API 总览
- 协议:HTTP + JSON;上传类接口为
multipart/form-data,其余为application/json; - 认证:统一
Authorization: Bearer头,令牌分 JWT(1 小时)与 API Key(可设过期)两种; - 错误结构:统一 JSON 对象,形如
{"error":{"title":"<异常类>","message":"<概述>","violations":[{"property":"<字段>","message":"<原因>"}]}}——violations数组是定位参数错误的依据; - 列表结构:列表接口统一返回
{"meta":{"size":<页大小>,"total":<总数>},"data":[...]}; - 限流:官方文档未声明限流约定,本实例未配置。
实测 API 域与端点总表(全部经 curl 实测,状态码为实测值):
| API 域 | 方法与端点 | 认证 | 实测状态码 |
|---|---|---|---|
| 认证 | POST /api/auth/login | 无 | 200 / 400 |
| 认证 | POST /api/auth/refresh | refresh_token | 200 |
| 用户 | GET /api/user | JWT | 200 |
| API Key | POST /api/user/api-keys | JWT | 200 |
| API Key | GET /api/user/api-keys | JWT | 200 |
| API Key | DELETE /api/user/api-keys/{keyId} | JWT | 204 |
| 外部上传 | POST /api/external/upload | API Key | 201 / 401 / 403 |
| ShareX | POST /api/user/sharex-config | JWT | 200 / 422 |
| 会话上传 | POST /api/upload | JWT | 201 |
| 图片管理 | PATCH /api/image/{id} | JWT | 204 |
| 图片浏览 | GET /api/images | 可选 JWT | 200 |
| 收藏夹 | POST /api/collection | JWT | 201 |
| 收藏夹 | GET /api/collections | JWT | 200 |
| 分享 | POST /api/image/{id}/share | JWT | 201 |
| 分享 | POST /api/collection/{id}/share | JWT | 201 |
| 分享 | GET /api/shares | JWT | 200 |
| 配置 | GET /api/settings | JWT(管理员) | 200 / 401 |
四、认证与首次调用
4.1 登录换取 JWT
请求字段名是 username(值可传邮箱),不是 email——传错字段名会得到 422 校验错并提示 username 为空。实测:
curl -s -X POST http://localhost:8130/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin@slink.local","password":"q1w2e3r4"}' \
-w '\nHTTP=%{http_code}\n'
{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3OTM0MTYzMzksImV4cCI6MTc5MzQxOTkzOSwicm9sZXMiOlsiUk9MRV9VU0VSIiwiUk9MRV9BRE1JTiJdLCJ1dWlkIjoiZTkzYjdkYjEtMDY5NS00OGFmLTkwZmEtMmE2NjQ5YjI4YzQwIn0.<…输出节选(实测首尾,JWT 全长约 876 字符)…>","refresh_token":"c7d0694a-2311-4530-8d02-3fd8240e52e4.1796008339"}
HTTP=200
access_token 为 RS256 签名的 JWT,解码载荷含 roles 与用户 uuid,exp 距 iat 恰为 3600 秒(1 小时);refresh_token 用于无感续期。口令错误实测返回 400(注意不是 401):
{"error":{"title":"Slink.User.Domain.Exception.InvalidCredentialsException","message":"Specification Error","violations":[{"property":"credentials","message":"Invalid credentials. Please check your username\/email and password and try again."}]}} [400]
4.2 首个受保护调用
用 JWT 调用用户信息接口验证令牌可用:
TOK='<上一步返回的access_token>'
curl -s http://localhost:8130/api/user -H "Authorization: Bearer $TOK" -w '\nHTTP=%{http_code}\n'
{"data":{"id":"e93b7db1-0695-48af-90fa-2a6649b28c40","displayName":"Admin"}} [200]
4.3 令牌续期
curl -s -X POST http://localhost:8130/api/auth/refresh \
-H 'Content-Type: application/json' \
-d '{"refresh_token":"c7d0694a-2311-4530-8d02-3fd8240e52e4.1796008339"}' \
-w '\nHTTP=%{http_code}\n'
{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE3OTM0MTY0OTIsImV4cCI6MTc5MzQyMDA5Miwicm9sZXMiOlsiUk9MRV9VU0VSIiwiUk9MRV9BRE1JTiJdLCJ1dWlkIjoiZTkzYjdkYjEtMDY5NS00OGFmLTkwZmEtMmE2NjQ5YjI4YzQwIn0.<…输出节选(实测首尾)…>
HTTP=200
返回新的 access_token(iat/exp 已前移),实现 1 小时令牌的无感续期。
五、各 API 域详解
5.1 API Key 管理
API Key 是外部集成(ShareX、脚本、CI)的长期凭证,管理三接口实测如下。
创建(响应体只此一次返回明文 Key,之后无法再查看):
curl -s -X POST http://localhost:8130/api/user/api-keys \
-H "Authorization: Bearer $TOK" -H "Origin: http://localhost:8130" \
-H 'Content-Type: application/json' \
-d '{"name":"docs-test"}' -w '\nHTTP=%{http_code}\n'
{"key":"sk_1684d3d29b75e244db13a76a312318a650e31b6532b46b40fa0bd60561a5992e","keyId":"5e0aba44-ec4c-4ab0-992a-c73a5526722a","name":"docs-test"}
HTTP=200
列表(返回元数据而非明文 Key,lastUsedAt 可用于审计,isExpired 标记过期):
curl -s http://localhost:8130/api/user/api-keys -H "Authorization: Bearer $TOK" -w ' [%{http_code}]\n'
{"data":[{"id":"5e0aba44-ec4c-4ab0-992a-c73a5526722a","name":"docs-test","createdAt":"2026-10-31T11:12:52.000000+08:00","expiresAt":null,"lastUsedAt":"2026-10-31T11:13:13.000000+08:00","isExpired":false}]} [200]
撤销(实测新建再删除):
K2=$(curl -s -X POST http://localhost:8130/api/user/api-keys \
-H "Authorization: Bearer $TOK" -H "Origin: http://localhost:8130" \
-H 'Content-Type: application/json' -d '{"name":"revoke-me"}')
KID=$(echo "$K2" | python3 -c 'import sys,json;print(json.load(sys.stdin)["keyId"])')
curl -s -X DELETE "http://localhost:8130/api/user/api-keys/$KID" \
-H "Authorization: Bearer $TOK" -H "Origin: http://localhost:8130" -w ' [%{http_code}]\n'
[204]
删除后复查列表,revoke-me 已消失、仅剩 docs-test,撤销即时生效。泄漏应急处理即调此接口(或 Web 界面吊销)。
5.2 外部上传(程序化上传主入口)
官方对外承诺的公开上传端点,API Key 认证,multipart 字段名固定为 image:
KEY='sk_1684d3d29b75e244db13a76a312318a650e31b6532b46b40fa0bd60561a5992e'
curl -s -X POST http://localhost:8130/api/external/upload \
-H "Authorization: Bearer $KEY" \
-H "Origin: http://localhost:8130" \
-F "image=@test-blue.png" -w '\nHTTP=%{http_code}\n'
{"url":"i\/KOSzunpg","thumbnailUrl":"i\/Xtpi7XTe","id":"ad765b7f-a8b3-4e3e-b423-31ee86e84578"}
HTTP=201
响应字段:url 为图片短码路径(拼在站点域名后即可访问观看页,如 http://localhost:8130/i/KOSzunpg)、thumbnailUrl 为缩略图路径、id 为图片 UUID(也是存储文件名,对应磁盘 images/ad765b7f-a8b3-4e3e-b423-31ee86e84578.png)。图片默认为私有可见性。
两个必测错误分支(实测回显):
curl -s -X POST http://localhost:8130/api/external/upload \
-H "Authorization: Bearer $KEY" -F "image=@test-blue.png" -w ' [%{http_code}]\n'
Cross-site POST form submissions are forbidden
HTTP=403
缺 Origin 头即 403(第七章 Q1 详述)。
curl -s -X POST http://localhost:8130/api/external/upload \
-H "Authorization: Bearer sk_invalid" -H "Origin: http://localhost:8130" \
-F "image=@test-blue.png" -w ' [%{http_code}]\n'
{"error":{"message":"Authentication failed","code":"INVALID_API_KEY"}} [401]
无效 Key 返回 401,错误码 INVALID_API_KEY——脚本可用它区分「凭证失效」与「网络问题」。
5.3 ShareX 集成配置生成
为截图工具 ShareX 生成开箱即用的上传配置(.sxcu)。注意:官方文档标注为 GET,实测该端点只接受 POST,且参数必须放 JSON 请求体(放查询串会 422)。先看参数位置错误的实测:
curl -s -X POST "http://localhost:8130/api/user/sharex-config?baseUrl=http://localhost:8130&apiKey=$KEY" \
-H "Authorization: Bearer $TOK" -w '\n[%{http_code}]\n'
{"error":{"title":"Symfony.Component.HttpKernel.Exception.HttpException","message":"Validation Error","violations":[{"property":"apiKey","message":"API key is required. Create one first from your profile page."}]}}
[422]
正确姿势(JSON 请求体 + 同源头):
curl -s -X POST http://localhost:8130/api/user/sharex-config \
-H "Authorization: Bearer $TOK" -H "Origin: http://localhost:8130" \
-H 'Content-Type: application/json' \
-d "{\"baseUrl\":\"http://localhost:8130\",\"apiKey\":\"$KEY\"}" -w '\n[%{http_code}]\n'
{"Version":"14.1.0","Name":"Slink Image Upload","DestinationType":"ImageUploader","RequestMethod":"POST","RequestURL":"http:\/\/localhost:8130\/api\/external\/upload","Headers":{"Authorization":"Bearer sk_1684d3d29b75e244db13a76a312318a650e31b6532b46b40fa0bd60561a5992e","Origin":"http:\/\/localhost:8130"},"Body":"MultipartFormData","FileFormName":"image","URL":"http:\/\/localhost:8130\/{json:url}","ThumbnailURL":"http:\/\/localhost:8130\/{json:thumbnailUrl}"}
[200]
生成物把 Authorization、Origin、multipart 字段名、响应取值({json:url})全部编排好——其中自动包含 Origin 头,这正是 ShareX 客户端不会踩 403 坑的原因;自研脚本对照此 JSON 逐项补齐请求要素即可。
5.4 会话上传与图片管理
登录会话下的上传端点是 POST /api/upload,multipart 需同时带 id(客户端生成的 UUID)与 image 两个字段——只传图片会得到 500(UploadImageCommand::$id must not be accessed before initialization),这是实测踩到的真实报错:
NID=$(python3 -c 'import uuid;print(uuid.uuid4())')
curl -s -X POST http://localhost:8130/api/upload \
-H "Authorization: Bearer $TOK" -H "Origin: http://localhost:8130" \
-F "id=$NID" -F "image=@test-orange.png" -w '\nHTTP=%{http_code}\n'
{"id":"1bddea84-36dd-4856-a288-35812a456b44"}
HTTP=201
图片管理走单数路径 /api/image/{id},实测支持 PATCH 与 DELETE(对它发 GET 会得到 405 并在响应头披露 Allow: DELETE, PATCH)。改可见性:
curl -s -X PATCH http://localhost:8130/api/image/1bddea84-36dd-4856-a288-35812a456b44 \
-H "Authorization: Bearer $TOK" -H "Origin: http://localhost:8130" \
-H 'Content-Type: application/json' \
-d '{"visibility":"public"}' -w ' [%{http_code}]\n'
[204]
浏览公开图片池用 GET /api/images(Explore 页数据源,未登录也可访问):
curl -s "http://localhost:8130/api/images" -H "Authorization: Bearer $TOK" -w ' [%{http_code}]\n'
{"meta":{"size":10,"total":0},"data":[]} [200]
注意语义:/api/images 只列公开图片,新建上传默认私有,因此刚上传后此处仍为 total: 0——这是正常行为,不是丢数据;个人上传历史以 Web 界面 History 页为准。
5.5 收藏夹与分享
收藏夹走单数路径 /api/collection(GET 列表则是复数 /api/collections),创建实测:
curl -s -X POST http://localhost:8130/api/collection \
-H "Authorization: Bearer $TOK" -H "Origin: http://localhost:8130" \
-H 'Content-Type: application/json' \
-d '{"name":"docs-col"}' -w '\nHTTP=%{http_code}\n'
{"data":{"id":"ac3145a9-24ce-427d-89a1-1fbbeed8b5f2","name":"docs-col","description":"","createdAt":{"formattedDate":"2026-10-31 11:17:30","timestamp":1793416650},"updatedAt":null,"userId":"e93b7db1-0695-48af-90fa-2a6649b28c40","itemCount":0}}
HTTP=201
图片与收藏夹均可一键生成分享(空 JSON 体即可,密码/过期等属性可在 Web 界面补配):
curl -s -X POST http://localhost:8130/api/image/1bddea84-36dd-4856-a288-35812a456b44/share \
-H "Authorization: Bearer $TOK" -H "Origin: http://localhost:8130" \
-H 'Content-Type: application/json' -d '{}' -w '\nHTTP=%{http_code}\n'
{"shareId":"2d16ad3f-66b0-46e4-a58c-f0334830f909","shareUrl":"http:\/\/localhost:8130\/i\/BjoZB03T","type":"image","created":true,"expiresAt":null,"requiresPassword":false}
HTTP=201
curl -s -X POST http://localhost:8130/api/collection/ac3145a9-24ce-427d-89a1-1fbbeed8b5f2/share \
-H "Authorization: Bearer $TOK" -H "Origin: http://localhost:8130" \
-H 'Content-Type: application/json' -d '{}' -w '\nHTTP=%{http_code}\n'
{"shareId":"86ab20d5-c152-44f3-b7a8-6906dee01946","shareUrl":"http:\/\/localhost:8130\/c\/dmlmvYuH","type":"collection","created":true,"expiresAt":null,"requiresPassword":false}
HTTP=201
图片分享落在 /i/<短码>、收藏夹分享落在 /c/<短码>;shareUrl 为完整可分发链接。分享清单与收藏夹清单分别用 GET /api/shares、GET /api/collections 读取(实测返回 meta/data 结构,初始为空列表)。
5.6 平台配置读取
管理员可程序化读取全量运行时配置(内容样例与字段解读见 《Slink 1.14.5 配置参数详解》第三章):
curl -s http://localhost:8130/api/settings -H "Authorization: Bearer $TOK" -o /dev/null -w '%{http_code}\n'
curl -s http://localhost:8130/api/settings -o /dev/null -w '%{http_code}\n'
200
401
带管理员 JWT 返回 200 与完整配置 JSON;不带凭证返回 401。该接口适合做部署后的配置漂移巡检。
六、分页/过滤/排序通用约定
列表接口统一返回 {"meta":{"size":<每页条数>,"total":<总数>},"data":[...]}:size 是页大小而非本页实际条数,data 才是数据,判断「有没有更多」用 len(data) == size。页码参数实测支持 ?page=1 形式;非法排序参数服务端会拒绝而非静默忽略(v1.13.1 Release Notes 明确此行为)。外部上传响应不含分页信息(单对象返回)。
七、常见问题
Q1:写接口一律 403「Cross-site POST form submissions are forbidden」?
缺 Origin 头或与实例 ORIGIN 不一致。Slink 对所有写请求做同源校验:curl 必须显式 -H "Origin: http://localhost:8130"(值与部署时 ORIGIN 逐字一致);Nginx 反代场景确认没有剥离 Origin 头。实测缺失必现 403,补齐即 201。
Q2:登录返回 400 还是 401?
口令错误返回 400(InvalidCredentialsException,见 4.1 回显);不带凭证访问受保护接口才是 401(如无 JWT 读 /api/settings);API Key 无效在外部上传返回 401 + code: INVALID_API_KEY。三类错误码分开处理。
Q3:422 Validation Error 怎么定位?
读 violations[]:property 指明出错字段。实测两例——登录用 email 字段名 → property: username;sharex-config 把参数放查询串 → property: apiKey。按字段名改请求即消错。
Q4:某个路径返回 405 Method Not Allowed?
这是合法探测手段:响应头 Allow: 列出该路径全部支持方法(实测 GET /api/user/profile → Allow: PATCH、GET /api/image/{id} → Allow: DELETE, PATCH),按 Allow 改方法即可,不必翻文档。
Q5:API Key 创建后忘了保存?
明文 Key 只在创建响应(或 Web 创建弹窗)出现一次,之后列表接口只回元数据。丢了就 DELETE 旧 Key 重建;lastUsedAt 字段可辅助确认旧 Key 是否已被他人使用过。
Q6:上传成功但 /api/images 里看不到?
该端点只列公开图片池(Explore 数据源),新建上传默认私有。要公开需 PATCH /api/image/{id} 改可见性(5.4 实测),或在 Web 界面操作。
八、参考链接
- 官方 API Key 管理文档:https://docs.slinkapp.io/usage/02-api-key-management/
- 官方 ShareX 集成指南:https://docs.slinkapp.io/usage/03-sharex-integration/
- 分享管理:https://docs.slinkapp.io/usage/01-share-management/
- 部署过程:《Slink 1.14.5 Docker Compose 部署指南》
- 配置参数与 Settings 页优先级:《Slink 1.14.5 配置参数详解》
- 产品定位与选型:《Slink 介绍与选型指南》
- 本文实测版本:v1.14.5(2026-10-31 发布,GitHub Releases 实查)