REST-API
Dateien hochladen, Sammlungen erstellen und Freigaben per HTTP verwalten. Alle Antworten sind JSON; fĂŒr anonyme Uploads ist kein API-SchlĂŒssel erforderlich.
So funktionieren Uploads
Die storage.to-API treibt unsere CLI, Desktop-App, Web-Uploader und alle Drittanbieter-Clients, die du bauen möchtest. Der Upload-Ablauf besteht aus drei Schritten:
PUT deine Bytes direkt in die vorab signierten URL(s). Die Bytes laufen nicht ĂŒber unsere Server.File-Eintrag und geben dir eine teilbare URL.Alle Endpoints unten sind relativ zu dieser Basis. Beispiel: POST /upload/init bedeutet POST https://storage.to/api/upload/init.
Authentifizierung
Anonyme Uploads funktionieren ohne Authentifizierung, aber mit engen Limits. Aufrufe ohne SchlĂŒssel sind auf 50 Dateien pro rollierende 24 Stunden pro GerĂ€t oder IP begrenzt, plus die Bandbreitenkontingente unten, und Dateien laufen nach 3 Tagen ab.
Die Authentifizierung mit einem kostenlosen Konto schaltet frei:
- Kein tÀgliches Datei-Limit
- Keine Upload-Bandbreitenbegrenzung
- Uploads, die mit deinem Konto verknĂŒpft sind (sichtbar unter /dashboard)
- Premium-Funktionen (dauerhafte Dateien, mehr Speicherplatz)
- Mutationen basierend auf Eigentum (löschen, Passwort setzen, Ablauf Àndern), ohne dass der visitor-token-Abgleich nötig ist
Limits auf einen Blick
expiry_daysexpiry_daysEs gibt keine Monatskontingente - alle Limits sind rollierende 24-Stunden-Fenster oder Limits pro Minute. Der Gratis-Tarif hat keinen festen Speicherplatz: Jede Datei lÀuft von selbst ab, es sammelt sich also nichts gegen ein Kontingent an.
EigentĂŒmerschaft nachweisen
/upload/init multipart, /upload/confirm, /file/reserve, /collection) gibt in seiner Antwort ein owner_token zurĂŒck. Das Token ist ein signierter Nachweis der Inhaberschaft, der an diese spezielle Ressource gebunden istâunabhĂ€ngig von deiner IP oder deinem Visitor-Token. Tokens leben so lange wie die Ressource, sind sicher zum Speichern und laufen nicht unabhĂ€ngig ab. Ein verlorenes Token bedeutet, die Kontrolle ĂŒber diese Ressource (Datei/Sammlung/Upload) zu verlieren â behandle sie wie lokale Passwörter.# oder, zusĂ€tzlich zu einer Bearer-Sitzung
X-Owner-Token: <token>
visitor_token-cookie gespeichert. Die CLI speichert es unter ~/.config/storageto/token (siehe CLI-Dokumentation).Bei Mutation-Endpunkten (löschen, Passwort setzen, Ablauf Ă€ndern) ist die Inhaberschaft bestĂ€tigt, wenn entweder das Visitor-Token ĂŒbereinstimmt oder die Anfrage von derselben IP kommt, die die Datei erstellt hat. Beides kann verloren gehen (gelöschte Cookies, Netzwerkwechsel). Das Owner-Token ist der bevorzugte Nachweis fĂŒr die Zukunft.
Fehler
Fehler folgen einem einheitlichen Schema: { "success": false, "error": "âŠ" }
Ratenbegrenzungen
Alle Ratelimits gelten pro IP. Eine 429-Antwort enthÀlt die Standard-Header Retry-After, X-RateLimit-Limit und X-RateLimit-Remaining.
Upload-Kontingent: Anonyme Clients haben zwei parallele Limits â 100 GB / 24 h pro visitor-token und 500 GB / 24 h pro IP (das IP-Limit fĂ€ngt tokenlosen Traffic und geteilte Netzwerke ab). Wenn eines davon ĂŒberschritten wird, bekommst du einen 429 mit Details. Das ist nur ein Upload-Limit â Downloads sind unbegrenzt und ohne Drosselung.
Upload
8 EndpointsDer Drei-Schritte-Upload-Flow fĂŒr jede Dateiâinklusive Dateien ĂŒber 5 GB (automatisch multipart). Wenn du nur einen schnellen Upload im Screenshot-Stil brauchst, schau stattdessen bei ShareX vorbei.
Starte einen Upload. Bei Dateien >50 MB ist die Antwort ein Multipart-Upload (Feld type: "multipart"); ansonsten ein einzelnes presigned PUT.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
filename | string · required | UrsprĂŒnglicher Dateiname. Max. 255 Zeichen. |
content_type | string · required | MIME-Typ. |
size | integer · required | DateigröĂe in Bytes. Min. 1. |
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 }'
{ "success": true, "type": "single", "upload_url": "https://r2.cloudflarestorage.com/...signed...", "headers": { "Host": ["..."] }, "r2_key": "uuid-abc123" }
{ "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_..." }
Fordert zusĂ€tzliche Part-URLs fĂŒr einen laufenden Multipart-Upload an. Wird verwendet, wenn /init weniger URLs zurĂŒckgegeben hat als du Parts hast (oder sie abgelaufen sind).
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
upload_id | string · required | Die upload_id von /init. |
part_numbers | array<int> · required | Part-Nummern, fĂŒr die URLs abgerufen werden sollen. |
curl -X POST https://storage.to/api/upload/parts \ -H "Content-Type: application/json" \ -d '{ "upload_id": "01HXYZ...", "part_numbers": [3, 4] }'
{ "success": true, "part_urls": [ { "partNumber": 3, "url": "https://..." }, { "partNumber": 4, "url": "https://..." } ] }
SchlieĂt einen Multipart-Upload ab, sobald alle Parts hochgeladen sind.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
upload_id | string · required | Die upload_id von /init. |
parts | array · required | Jeder Eintrag: { partNumber, etag } aus der Antwort des Part-Uploads. |
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...\"" } ] }'
{ "success": true }
Bricht einen Multipart-Upload ab und rÀumt alle unvollstÀndigen Daten auf.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
upload_id | string · required | Der Upload, der abgebrochen werden soll. |
curl -X POST https://storage.to/api/upload/abort \ -H "Content-Type: application/json" \ -d '{ "upload_id": "01HXYZ..." }'
BestĂ€tige, dass der Upload abgeschlossen ist. In diesem Schritt erstellen wir den File-Eintrag und geben die freigabefĂ€hige URL zurĂŒck.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
filename | string · required | UrsprĂŒnglicher Dateiname. |
size | integer · required | DateigröĂe in Bytes. |
content_type | string · required | MIME-Typ. |
r2_key | string · required | Die r2_key von /init. |
collection_id | string · optional | An eine Sammlung anhÀngen. |
crc32 | integer · optional | CRC32-Checksumme zur IntegritĂ€tsprĂŒfung. |
file_id | string(9) · optional | ErfĂŒlle eine zuvor reserviert-Datei-ID. |
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" }'
{ "success": true, "file": { "id": "FQxyz1234", "url": "https://storage.to/FQxyz1234", "filename": "report.pdf", "size": 2202009, "human_size": "2.1 MB", "expires_at": "2026-04-15T12:00:00Z" }, "owner_token": "owner_v1_..." }
Reserviere eine Date-ID und eine freigabefĂ€hige URL vor die Bytes bereit sind. Praktisch, wenn du zuerst einen Link weitergeben und den Upload danach erfĂŒllen musst. Die Berechtigung ist an dein Visitor-Token + deine IP gebunden. SchlieĂe den Upload spĂ€ter mit /upload/init + /upload/confirm ab und ĂŒbergib dabei file_id zur BestĂ€tigung.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
filename | string · optional | Platzhalter-Dateiname. Standard: "Pending". |
content_type | string · optional | Platzhalter-MIME-Typ. |
curl -X POST https://storage.to/api/file/reserve \ -H "X-Visitor-Token: abc123"
{ "success": true, "file": { "id": "FQxyz1234", "url": "https://storage.to/FQxyz1234", "expires_at": "2026-04-12T18:00:00Z" }, "owner_token": "owner_v1_..." }
Batch-Ăquivalent von /upload/init, optimiert fĂŒr den Web-Uploader. Startet bis zu 250 Dateien in einem einzigen Round-Trip.
Wird intern vom Web-Uploader verwendet. Die meisten Clients sollten lieber single-file /upload/init verwenden.
Batch-Ăquivalent von /upload/confirm. BestĂ€tigt viele Dateien in einem einzigen Round-Trip.
Sammlungen
9 EndpointsEine Sammlung gruppiert mehrere Dateien unter einer einzigen Freigabe-URL (/c/{id}). Bis zu 10.000 Dateien und insgesamt 25 GB.
Erstelle eine neue Sammlung. HĂ€nge Dateien danach an, indem du collection_id an /upload/confirm ĂŒbergibst.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
expected_file_count | integer · optional | Hinweis fĂŒr die automatische Markierung der Sammlung als bereit, sobald alle erwarteten Dateien bestĂ€tigt wurden. |
curl -X POST https://storage.to/api/collection \ -H "Content-Type: application/json" \ -H "X-Visitor-Token: abc123" \ -d '{ "expected_file_count": 3 }'
{ "success": true, "collection": { "id": "ABC123xyz", "url": "https://storage.to/c/ABC123xyz", "expires_at": "2026-04-15T12:00:00Z" }, "owner_token": "owner_v1_..." }
Frage den Status einer Sammlung ab. Markiert die Sammlung auĂerdem automatisch als bereit, wenn alle erwarteten Dateien bestĂ€tigt wurden.
curl https://storage.to/api/collection/ABC123xyz/status
{ "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" }
Markiere die Sammlung als bereit zum Download. Normalerweise nicht nötig â Sammlungen werden automatisch bereit, sobald expected_file_count erreicht ist.
Lösche eine Sammlung und alle ihre Dateien.
Setze ein Passwort fĂŒr die Sammlung. Erfordert 4â100 Zeichen.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
password | string · required | 4â100 Zeichen. |
curl -X POST https://storage.to/api/collection/ABC123xyz/password \ -H "X-Visitor-Token: abc123" \ -d '{ "password": "hunter22" }'
Entferne das Passwort aus der Sammlung.
PrĂŒfe ein Passwort. Gibt 200 bei Erfolg zurĂŒck, 401 bei falschem Passwort.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
password | string · required |
Ăndere die Ablaufzeit einer Sammlung.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
days | integer · optional | In 1â7 Tagen, aber nie spĂ€ter als 7 Tage nach dem Upload (oder dem aktuellen Ablaufdatum, falls spĂ€ter). Weglassen oder null fĂŒr dauerhaft (nur Premium). |
Setze ein Download-Limit (burn-after-N-downloads). Die Sammlung wird automatisch gelöscht, sobald es erreicht ist.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
max_downloads | integer · optional | 1â1000. Muss den aktuellen Download-ZĂ€hler ĂŒbersteigen. null, um das Limit zu entfernen. |
Dateien
8 EndpointsAlle Einstellungen auf Dateiebene (Passwort, Ablauf, max-downloads) spiegeln die Collection-Endpunkte wider. Nur fĂŒr den Owner.
PrĂŒfe, ob eine Datei noch auf ihren Upload wartet.
{ "pending": false }
Lösche eine Datei sofort.
Lade ein Vorschaubild fĂŒr eine Video- oder Bilddatei hoch (wird auf der Download-Seite verwendet). Max. 2 MB.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
thumbnail | image · required | Multipart-Upload. Max. 2 MB. |
{ "success": true, "thumbnail_url": "https://..." }
Setze ein Passwort fĂŒr eine Datei. Erfordert 4â100 Zeichen.
Entferne das Passwort einer Datei.
ĂberprĂŒfe das Passwort einer Datei.
Ăndere die Ablaufzeit einer Datei.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
days | integer · optional | In 1â7 Tagen, aber nie spĂ€ter als 7 Tage nach dem Upload (oder dem aktuellen Ablaufdatum, falls spĂ€ter). Weglassen oder null fĂŒr dauerhaft (nur Premium). |
Begrenze die Gesamtzahl der Downloads einer Datei. Wird automatisch gelöscht, wenn das Limit erreicht ist.
Desktop-Authentifizierung
2 EndpointsFĂŒr angemeldete Clients wie die Desktop-App, die ein Bearer-Token besitzen.
Gibt den authentifizierten Benutzer zurĂŒck.
curl https://storage.to/api/user \ -H "Authorization: Bearer <token>"
{ "id": 42, "name": "Ada", "email": "ada@example.com", "is_premium": true }
Widerruft das aktuelle Zugriffstoken.
Verschiedenes
5 EndpointsStatus, Kontingente und Client-Telemetrie.
Liveness-Check. Gibt 200 mit { "status": "ok" } zurĂŒck, wenn der API-Worker lĂ€uft.
{ "status": "ok" }
Live-AktivitĂ€tsstream fĂŒr den Globus auf der Startseite. Im Edge-Cache gespeichert.
Aktuelle Upload-Kontingentnutzung fĂŒr den Aufrufer â genutzt von der CLI und der Desktop-App, um die verbleibende KapazitĂ€t anzuzeigen. Das Antwortformat unterscheidet sich fĂŒr authentifizierte Nutzer. Trotz des URL-Namens werden hier nur Upload-Bytes erfasst; Downloads werden nicht mitgezĂ€hlt.
{ "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 }
{ "success": true, "authenticated": true, "plan": "premium" }
Sende ein Nutzungsereignis ĂŒber die CLI oder die Desktop-App.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
app | string · required | desktop, cli oder web. |
version | string · optional | Client-Version. |
event | string · required | Ereignisname, z. B. upload_complete. |
context | object · optional | ZusÀtzliche Metadaten. |
Sende einen Fehlerbericht aus der CLI oder der Desktop-App. Serverseitig dedupliziert â maximal 10 vom gleichen Fehler pro Stunde.
Request-Body
| Feld | Typ | Beschreibung |
|---|---|---|
app | string · required | desktop, cli oder web. |
type | string · required | Fehlerklasse/-typ. |
message | string · required | Fehlermeldung. |
stack | string · optional | Stacktrace. |
version, os, os_version, arch, context | various · optional | Diagnose-Metadaten. |