REST API

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

简介

storage.to API 为我们的 命令行界面(CLI)桌面应用网页上传器 以及你想构建的任何第三方客户端提供支持。

上传流程分为三步:

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

基础 URL

https://storage.to/api

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

身份验证

大多数接口不需要身份验证。 匿名上传是核心功能。

身份验证是可选的,可解锁:

  • 上传内容会绑定到你的账户(可在 /dashboard 查看)
  • 高级功能(永久文件、更大存储空间)
  • 基于所有权的变更(删除、设置密码、更改过期时间),无需匹配 visitor-token

我们使用 Laravel Sanctum bearer tokens。通过桌面端 OAuth 交接或网页登录获取令牌,然后以如下方式发送:

Authorization: Bearer <token>

访客令牌

匿名客户端需要一种方式,在不拥有账户的情况下证明其对自身上传内容的所有权。我们使用 访客令牌——由客户端生成的一串随机字符串,只生成一次并重复使用。每次请求都要发送:

X-Visitor-Token: <random-string>

在网页端,令牌会自动存储在 visitor_token 这个 cookie 中。CLI 会将其存储在 ~/.config/storageto/token(见 CLI 文档)。

对于变更端点(删除、设置密码、更改到期时间),当满足 要么(访问者 token 匹配)或 (请求来自创建该文件的同一 IP)时,即可确认所有权。两者都可能丢失(清除 Cookie、网络变更)。从现在开始,所有者 token 是首选的证明。

所有者令牌

每个创建资源的端点(/upload/init multipart、/upload/confirm/upload/reserve/collection)都会在响应中返回一个 owner_token。该 token 是与该特定资源绑定的、经过签名的所有权证明,不依赖你的 IP 或访问者 token。

将 token 与资源 ID 一起保存,并在任何变更请求中按以下方式发送:

Authorization: Owner <token>

或者,如果你已经在已认证的会话中使用 Authorization: Bearer,请按以下方式发送:

X-Owner-Token: <token>

服务器会将 owner token 作为有效的所有权证明,与旧版的 访客令牌 + IP 兜底机制一起接受——持有 token 的客户端在切换网络或清除 Cookie 后仍可继续工作,而不持有 token 的客户端则仍会像以前一样正常工作。

token 的有效期与资源一致:可以安全地长期保存,并且不会单独过期。token 丢失意味着你将失去对该资源(文件/集合/上传)的控制——请把它们当作本地密码来对待。

错误

错误遵循一致的格式:

{
  "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 的文件,响应为分片上传(type: "multipart" 字段);否则为单次预签名 PUT。

请求体

字段类型描述
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, "type": "single", "upload_url": "https://r2.cloudflarestorage.com/...signed...", "headers": { "Host": ["..."] }, "r2_key": "uuid-abc123" }
Response · multipart
{ "success": true, "type": "multipart", "upload_id": "01HXYZ...", "r2_key": "uuid-abc123", "part_size": 33554432, "total_parts": 4, "initial_urls": { "1": "https://...", "2": "https://..." }, "owner_token": "owner_v1_..." }
POST /upload/parts Owner only 120/min

为进行中的分片上传请求更多分片 URL。当 /init 返回的 URL 数量少于你拥有的分片数量(或这些 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 Owner only 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 Owner only 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" }, "owner_token": "owner_v1_..." }
POST /file/reserve 60/min

在字节数据准备好 之前 之前预留文件 ID 和可分享 URL。当你需要先发出链接,之后再完成上传时很有用。所有权绑定到你的访客 token + 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" }, "owner_token": "owner_v1_..." }
POST /upload/init-batch 500/min

/upload/init 的批量等价接口,针对网页上传器进行了优化。一轮请求最多启动 250 个文件。

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

POST /upload/confirm-batch 500/min

/upload/confirm 的批量等价接口。一轮请求确认多个文件。

集合

集合会把多个文件归到同一个分享 URL(/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" }, "owner_token": "owner_v1_..." }
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

设置下载上限(burn-after-N-downloads)。达到上限后集合会自动删除。

请求体

字段类型描述
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 上传

一次性上传端点——发送分片文件,返回可分享的 URL。不需要 init/confirm 的流程。适合截图工具。完整设置指南见 /zh/docs/sharex

POST /sharex/upload 20/day

直接上传图片或文件(multipart 表单,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 token 的已认证客户端(例如桌面应用)。

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

健康检查。会 ping 数据库、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

从 CLI 或桌面应用提交一次使用事件。

请求体

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

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

请求体

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