REST API

HTTP経由でファイルのアップロード、コレクションの作成、共有の管理が可能。すべてのレスポンスはJSONで、匿名アップロードにAPIキーは不要です。

はじめに

storage.to APIは、CLIデスクトップアプリウェブアップローダー、そしてあなたが作りたいあらゆるサードパーティクライアントを支えています。

アップロードの流れは3ステップです:

  1. 初期化 — ファイルをアップロードしたいことを伝えてください。Cloudflare R2を指す1つ以上のプリサインURLを返します。
  2. R2へアップロードPUT でバイトを直接プリサインURLに送信します。バイトは当社サーバーを経由しません。
  3. 確認 — アップロード完了を伝えてください。Fileレコードを作成し、共有可能なURLをお渡しします。

ベースURL

https://storage.to/api

以下のすべてのエンドポイントはこのベースに対する相対パスです。例:POST /upload/initPOST https://storage.to/api/upload/initを意味します。

認証

ほとんどのエンドポイントは認証不要です。 匿名アップロードはコア機能です。

認証は任意で、以下を利用可能にします:

  • アカウントに紐づくアップロード(/dashboardで確認可能)
  • プレミアム機能(永久ファイル、大容量ストレージ)
  • 訪問者トークンの一致なしで所有権ベースの操作(削除、パスワード設定、有効期限変更)

Laravel Sanctumベアラートークンを使用します。デスクトップのOAuth引き継ぎまたはウェブログインでトークンを発行し、以下のように送信してください:

Authorization: Bearer <token>

ビジタートークン

匿名クライアントはアカウントなしで自身のアップロードの所有権を証明する方法が必要です。ビジタートークンを使います — クライアントが一度生成し再利用するランダムな文字列です。すべてのリクエストに送信してください:

X-Visitor-Token: <random-string>

ウェブではトークンは自動的にvisitor_tokenクッキーに保存されます。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時間 の2つの制限が並行して適用されます(IP制限はトークンなしのトラフィックや共有ネットワークを検知します)。いずれかを超えると詳細付きの 429 が返されます。これは アップロード のクォータのみで、ダウンロードは無制限かつ制限なし(R2署名URLから直接配信)です。

アップロード

5GBを超えるファイルも含むあらゆるファイルのための3ステップアップロードフロー(自動的にマルチパート対応)。手軽なスクリーンショット風アップロードだけなら、代わりに ShareX をご利用ください。

POST /upload/init 60/min

アップロードを開始します。ファイルが50MBを超える場合、レスポンスにはマルチパートアップロード用の 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/init からの upload_id
part_numbersarray<int> · requiredURLを取得するパート番号。
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/init からの upload_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/init からの r2_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 のバッチ版です。1回の往復で最大250ファイルを開始します。

ウェブアップローダー内部で使用されます。ほとんどのクライアントは単一ファイルの /upload/init を推奨します。

POST /upload/confirm-batch 500/min

/upload/confirm のバッチ版です。1回の往復で複数ファイルを確認します。

コレクション

コレクションは複数のファイルを単一の共有URL(/c/{id})にまとめます。最大10,000ファイル、合計25GBまで。

POST /collection 30/min

新しいコレクションを作成します。後で /upload/confirmcollection_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

動画または画像ファイルのサムネイル画像をアップロードします(ダウンロードページで使用)。最大2MB。

リクエストボディ

フィールドタイプ説明
thumbnailimage · requiredマルチパートアップロード。最大2MB。
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が返ってきます。初期化や確認の手順は不要。スクリーンショットツールに最適です。完全なセットアップガイドは /ja/docs/sharex でご覧ください。

POST /sharex/upload 20/day

画像またはファイルを直接アップロードします(マルチパートフォーム、file フィールド)。最大25MB。

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キャッシュにpingを送ります。すべて正常なら 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 · requireddesktopcli、または web
versionstring · optionalクライアントバージョン。
eventstring · requiredイベント名(例:upload_complete)。
contextobject · optional追加メタデータ。
POST /app-errors 60/min

CLIまたはデスクトップアプリからエラー報告を送信します。サーバー側で重複排除され、同一エラーは1時間あたり最大10件まで。

リクエストボディ

フィールドタイプ説明
appstring · requireddesktopcli、または web
typestring · requiredエラーのクラス/タイプ。
messagestring · requiredエラーメッセージ。
stackstring · optionalスタックトレース。
version, os, os_version, arch, contextvarious · optional診断用メタデータ。