REST API

通过 HTTP 上传文件、创建集合并管理分享。所有响应均为 JSON;匿名上传无需 API 密钥。

介绍

storage.to API 支持我们的 CLI桌面应用网页上传器 以及你想构建的任何第三方客户端。

上传流程分三步:

  1. 初始化 — 告诉我们你想上传文件。我们会返回一个或多个指向 Cloudflare R2 的预签名 URL。
  2. 上传到 R2PUT 直接上传字节到预签名 URL,字节不会经过我们的服务器。
  3. 确认 — 告诉我们上传完成。我们会创建一个 File 记录并给你一个可分享的链接。

基础 URL

https://storage.to/api

以下所有端点均相对于此基础 URL。例如:POST /upload/init 代表 POST https://storage.to/api/upload/init

认证

大多数端点无需认证。 匿名上传是核心功能。

认证是可选的,开启后可获得:

  • 绑定到你的账户的上传(可在 /dashboard 查看)
  • 高级功能(永久文件、更大存储)
  • 基于所有权的操作(删除、设置密码、修改过期时间),无需匹配访客令牌

我们使用 Laravel Sanctum Bearer 令牌。通过桌面 OAuth 授权或网页登录获取令牌,然后以以下方式发送:

Authorization: Bearer <token>

访客令牌

匿名客户端需要一种方式证明自己上传内容的所有权,无需账户。我们使用 访客令牌 —— 客户端生成并重复使用的随机字符串。每次请求都要发送:

X-Visitor-Token: <random-string>

在网页端,令牌会自动存储在 visitor_token Cookie 中。CLI 会存储在 ~/.config/storageto/token(详见 CLI 文档)。

对于变更端点(删除、设置密码、修改过期时间),如果满足以下任一条件则确认所有权:访客令牌匹配,或请求来自创建文件的同一 IP。

错误

错误格式统一:

{
  "success": false,
  "error": "Human-readable message"
}

常见 HTTP 状态码:

代码含义
200成功。
201已创建。
400请求错误(例如集合大小超限)。
401需要密码或密码错误。
403未授权(不是资源所有者)。
404资源未找到或已过期。
422验证失败,或计划/配额限制。
429达到速率限制或上传配额。
500服务器错误。请检查 状态

速率限制

所有速率限制均基于单个 IP。429 响应包含标准的 Retry-AfterX-RateLimit-LimitX-RateLimit-Remaining 头。

范围限制
上传初始化 / 确认 / 中止60 / 分钟
分片完成500 / 分钟
分片部分 URL120 / 分钟
批量初始化 / 确认500 / 分钟
状态轮询(文件和集合)120 / 分钟
设置(密码、过期、最大下载次数)30 / 分钟
密码验证10 / 分钟
创建集合30 / 分钟
管理(准备、删除)60 / 分钟
缩略图上传120 / 分钟
ShareX 上传20 / 天
应用分析 / 错误120 和 60 / 分钟

上传配额: 匿名客户端有两个并行限额——访客令牌 100 GB / 24 小时每 IP 500 GB / 24 小时(IP 限额用于限制无令牌流量及共享网络)。任一超限时会返回带详情的 429。这仅是 上传 配额——下载不限次数且不受限速(直接通过 R2 签名 URL 提供)。

上传

适用于任何文件的三步上传流程,包括超过 5 GB 的文件(自动分片)。如果只需要快速截图式上传,请使用 ShareX

POST /upload/init 60/min

初始化上传。对于大于 50 MB 的文件,响应包含用于分片上传的 part_urls;否则返回单个 url

请求体

字段类型描述
filenamestring · required原始文件名。最多 255 个字符。
content_typestring · requiredMIME 类型。
sizeinteger · required文件大小(字节)。最小值为 1。
Request
curl -X POST https://storage.to/api/upload/init \ -H "Content-Type: application/json" \ -H "X-Visitor-Token: abc123" \ -d '{ "filename": "report.pdf", "content_type": "application/pdf", "size": 2202009 }'
Response · single upload
{ "success": true, "url": "https://r2.cloudflarestorage.com/...signed...", "r2_key": "uuid-abc123", "upload_id": null, "is_multipart": false }
Response · multipart
{ "success": true, "upload_id": "01HXYZ...", "r2_key": "uuid-abc123", "is_multipart": true, "part_size": 52428800, "part_urls": [ { "partNumber": 1, "url": "https://..." }, { "partNumber": 2, "url": "https://..." } ] }
POST /upload/parts 120/min

请求正在进行的分片上传的额外部分 URL。当 /init 返回的 URL 少于分片数(或已过期)时使用。

请求体

字段类型描述
upload_idstring · required来自 /initupload_id
part_numbersarray<int> · required需要获取 URL 的分片编号。
Request
curl -X POST https://storage.to/api/upload/parts \ -H "Content-Type: application/json" \ -d '{ "upload_id": "01HXYZ...", "part_numbers": [3, 4] }'
Response
{ "success": true, "part_urls": [ { "partNumber": 3, "url": "https://..." }, { "partNumber": 4, "url": "https://..." } ] }
POST /upload/complete-multipart 500/min

所有分片上传完成后,在 R2 上完成分片上传。

请求体

字段类型描述
upload_idstring · required来自 /initupload_id
partsarray · required每条条目:来自 R2 响应的 { partNumber, etag }
Request
curl -X POST https://storage.to/api/upload/complete-multipart \ -H "Content-Type: application/json" \ -d '{ "upload_id": "01HXYZ...", "parts": [ { "partNumber": 1, "etag": "\"abc...\"" }, { "partNumber": 2, "etag": "\"def...\"" } ] }'
Response
{ "success": true }
POST /upload/abort 60/min

取消分片上传并清理 R2 上的所有部分数据。

请求体

字段类型描述
upload_idstring · required要取消的上传。
Request
curl -X POST https://storage.to/api/upload/abort \ -H "Content-Type: application/json" \ -d '{ "upload_id": "01HXYZ..." }'
POST /upload/confirm 60/min

确认上传完成。此时我们会创建 File 记录并返回可分享的 URL。

请求体

字段类型描述
filenamestring · required原始文件名。
sizeinteger · required文件大小(字节)。
content_typestring · requiredMIME 类型。
r2_keystring · required来自 /initr2_key
collection_idstring · optional附加到集合。
crc32integer · optional用于完整性校验的 CRC32 校验和。
file_idstring(9) · optional完成之前的 保留 文件 ID。
Request
curl -X POST https://storage.to/api/upload/confirm \ -H "Content-Type: application/json" \ -H "X-Visitor-Token: abc123" \ -d '{ "filename": "report.pdf", "size": 2202009, "content_type": "application/pdf", "r2_key": "uuid-abc123" }'
Response
{ "success": true, "file": { "id": "FQxyz1234", "url": "https://storage.to/FQxyz1234", "raw_url": "https://storage.to/r/FQxyz1234", "filename": "report.pdf", "size": 2202009, "human_size": "2.1 MB", "expires_at": "2026-04-15T12:00:00Z" } }
POST /file/reserve 60/min

在字节准备好之前预留文件 ID 和可分享 URL 之前。当你需要先发放链接,稍后再完成上传时非常有用。所有权绑定到你的访客令牌和 IP。稍后通过 /upload/init + /upload/confirm 完成上传,传入 file_id 进行确认。

请求体

字段类型描述
filenamestring · optional占位文件名。默认为 "Pending"
content_typestring · optional占位 MIME 类型。
Request
curl -X POST https://storage.to/api/file/reserve \ -H "X-Visitor-Token: abc123"
Response
{ "success": true, "file": { "id": "FQxyz1234", "url": "https://storage.to/FQxyz1234", "raw_url": "https://storage.to/r/FQxyz1234", "expires_at": "2026-04-12T18:00:00Z" } }
POST /upload/init-batch 500/min

批量版 /upload/init,针对网页版上传器优化。一次往返最多启动 250 个文件。

供网页版上传器内部使用。大多数客户端应优先使用单文件 /upload/init

POST /upload/confirm-batch 500/min

批量版 /upload/confirm。一次往返确认多个文件。

收藏夹

集合将多个文件归为一个共享链接 (/c/{id})。最多支持 10,000 个文件,总容量 25 GB。

POST /collection 30/min

创建新集合。之后通过在 /upload/confirm 上传递 collection_id 来附加文件。

请求体

字段类型描述
expected_file_countinteger · optional提示在所有预期文件确认后自动标记集合为可用。
Request
curl -X POST https://storage.to/api/collection \ -H "Content-Type: application/json" \ -H "X-Visitor-Token: abc123" \ -d '{ "expected_file_count": 3 }'
Response
{ "success": true, "collection": { "id": "ABC123xyz", "url": "https://storage.to/c/ABC123xyz", "expires_at": "2026-04-15T12:00:00Z" } }
GET /collection/{id}/status 120/min

轮询集合状态。如果所有预期文件均已确认,也会自动标记集合为可用。

Request
curl https://storage.to/api/collection/ABC123xyz/status
Response
{ "success": true, "files": [ /* file objects: id, url, filename, size, ... */ ], "is_uploading": false, "file_count": 3, "expected_file_count": 3, "total_size": 6291456, "human_total_size": "6 MB" }
POST /collection/{id}/ready Owner only 60/min

将集合标记为可下载。通常不需要——集合在达到 expected_file_count 后会自动变为可用。

DELETE /collection/{id} Owner only 60/min

删除集合及其所有文件。

POST /collection/{id}/password Owner only 30/min

为集合设置密码。需 4–100 字符。

请求体

字段类型描述
passwordstring · required4–100 字符。
Request
curl -X POST https://storage.to/api/collection/ABC123xyz/password \ -H "X-Visitor-Token: abc123" \ -d '{ "password": "hunter22" }'
DELETE /collection/{id}/password Owner only 30/min

移除集合密码。

POST /collection/{id}/verify-password 10/min

验证密码。成功返回 200,密码错误返回 401

请求体

字段类型描述
passwordstring · required
POST /collection/{id}/expiry Owner only 30/min

修改集合过期时间。

请求体

字段类型描述
daysinteger · optional从现在起 1–7 天。省略或使用 null 表示永久(仅限高级用户)。
POST /collection/{id}/max-downloads Owner only 30/min

设置下载上限(下载 N 次后销毁)。达到后集合自动删除。

请求体

字段类型描述
max_downloadsinteger · optional1–1000。必须大于当前下载次数。使用 null 取消限制。

文件

所有文件级设置(密码、过期时间、最大下载次数)与集合端点同步。仅限所有者操作。

GET /file/{id}/status 120/min

检查文件是否仍在等待上传。

Response
{ "pending": false }
DELETE /file/{id} Owner only 60/min

立即删除文件。

POST /file/{id}/thumbnail Owner only 120/min

上传视频或图片文件的缩略图(用于下载页面)。最大 2 MB。

请求体

字段类型描述
thumbnailimage · required分块上传。最大 2 MB。
Response
{ "success": true, "thumbnail_url": "https://..." }
POST /file/{id}/password Owner only 30/min

为文件设置密码。需 4–100 字符。

DELETE /file/{id}/password Owner only 30/min

移除文件密码。

POST /file/{id}/verify-password 10/min

验证文件密码。

POST /file/{id}/expiry Owner only 30/min

修改文件过期时间。

请求体

字段类型描述
daysinteger · optional从现在起 1–7 天。省略或使用 null 表示永久(仅限高级用户)。
POST /file/{id}/max-downloads Owner only 30/min

限制文件总下载次数。达到后自动删除。

ShareX 上传

一次性上传端点 — 发送多部分文件,获取可分享的链接。无需初始化/确认步骤。非常适合截图工具。完整设置指南见 /zh/docs/sharex

POST /sharex/upload 20/day

直接上传图片或文件(分块表单,file 字段)。最大 25 MB。

Request
curl -X POST https://storage.to/api/sharex/upload \ -F "[email protected]"
Response
{ "success": true, "url": "https://storage.to/FQxyz1234", "raw_url": "https://storage.to/r/FQxyz1234", "filename": "screenshot.png", "expires_at": "2026-04-15T12:00:00Z" }

桌面认证

供持有 Sanctum 令牌的认证客户端(如桌面应用)使用。

GET /user Bearer token

返回认证用户信息。

Request
curl https://storage.to/api/user \ -H "Authorization: Bearer <token>"
Response
{ "id": 42, "name": "Ada", "email": "[email protected]", "is_premium": true }
POST /auth/logout Bearer token

撤销当前访问令牌。

其他

GET /health

健康检查。检测数据库、R2 存储和 Redis 缓存。全部正常返回 200,否则返回 503

Response
{ "status": "healthy", "checks": { "database": "ok", "storage": "ok", "cache": "ok" }, "timestamp": "2026-04-12T12:00:00Z" }
GET /activity

首页地球仪的实时活动流。缓存于 Cloudflare 边缘。

GET /bandwidth/status 60/min

调用者当前上传配额使用情况——供 CLI 和桌面应用显示剩余容量。认证用户响应格式不同。尽管 URL 名称如此,此接口仅统计 上传 字节,下载不计入。

Response · anonymous
{ "success": true, "authenticated": false, "has_token": true, "limit_bytes": 107374182400, "limit_gb": 100, "used_bytes": 12345678, "used_gb": 0.01, "remaining_bytes": 107361836722, "remaining_gb": 99.99, "window_hours": 24 }
Response · authenticated
{ "success": true, "authenticated": true, "plan": "premium" }
POST /app-analytics 120/min

从命令行或桌面应用提交使用事件。

请求体

字段类型描述
appstring · requireddesktopcliweb
versionstring · optional客户端版本。
eventstring · required事件名称,例如 upload_complete
contextobject · optional额外元数据。
POST /app-errors 60/min

从命令行或桌面应用提交错误报告。服务器端去重——同一错误每小时最多 10 条。

请求体

字段类型描述
appstring · requireddesktopcliweb
typestring · required错误类别/类型。
messagestring · required错误信息。
stackstring · optional堆栈跟踪。
version, os, os_version, arch, contextvarious · optional诊断元数据。