Referenz

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.

Basis-URLhttps://storage.to/api
33 Endpoints · JSON

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:

01 · POST /upload/init
Initialisieren
Sag uns, dass du eine Datei hochladen möchtest. Wir geben dir eine oder mehrere vorab signierte URLs zurĂŒck, die auf unser Storage-Edge zeigen.
02 · PUT {upload_url}
Upload
PUT deine Bytes direkt in die vorab signierten URL(s). Die Bytes laufen nicht ĂŒber unsere Server.
03 · POST /upload/confirm
BestÀtigen
Sag uns, dass der Upload fertig ist. Wir erstellen einen 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

Ohne Token (anonym)
Token eines Gratis-Kontos
Token eines Bezahl-Kontos
Dateien pro Tag
50 / 24 Stunden
Unbegrenzt
Unbegrenzt
Upload-Bandbreite
100 GB / 24 Stunden (500 GB pro IP)
Unbegrenzt
Unbegrenzt
Maximale DateigrĂ¶ĂŸe
25 GB
25 GB
100 GB
Ablauf der Datei
StandardmĂ€ĂŸig 3 Tage, bis zu 7 ĂŒber expiry_days
StandardmĂ€ĂŸig 3 Tage, bis zu 7 ĂŒber expiry_days
Nie (Dateien bleiben dauerhaft)
Speicherplatz
Keiner (Dateien laufen ab)
Keiner (Dateien laufen ab)
100 GB - 1 TB dauerhaft, je nach Tarif
Preise ansehen →

Es 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.

Um dich zu authentifizieren, erstelle in deinem Konto ein persönliches API-Token und sende es bei jeder Anfrage als Bearer-Token: Du musst angemeldet sein. Das vollstĂ€ndige Token wird nur einmal bei der Erstellung angezeigt — kopiere es an einen sicheren Ort. Du kannst ein Token jederzeit auf derselben Seite widerrufen. API-Token erstellen →
Authorization: Bearer <token>

EigentĂŒmerschaft nachweisen

Owner-TokenEmpfohlen
Jeder Endpunkt zum Erstellen von Ressourcen (/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.
Authorization: Owner <token>
# oder, zusÀtzlich zu einer Bearer-Sitzung
X-Owner-Token: <token>
Besuchertoken
Anonyme Clients brauchen eine Möglichkeit, die Inhaberschaft ihrer eigenen Uploads ohne Konto nachzuweisen. Wir verwenden ein visitor-token – eine zufĂ€llige Zeichenkette, die der Client einmal erzeugt und danach wiederverwendet. Mit jeder Anfrage senden: Im Web wird das Token automatisch im visitor_token-cookie gespeichert. Die CLI speichert es unter ~/.config/storageto/token (siehe CLI-Dokumentation).
X-Visitor-Token: <random-string>

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": "
" }

200OK.
201Erstellt.
400UngĂŒltige Anfrage (z. B. GrĂ¶ĂŸenlimit der Sammlung ĂŒberschritten).
401Passwort erforderlich oder falsch.
403Nicht autorisiert (nicht der Besitzer der Ressource).
404Ressource nicht gefunden oder abgelaufen.
422Validierung fehlgeschlagen oder EinschrÀnkung durch Tarif/Kontingent.
429Ratelimit oder Upload-Kontingent erreicht.
500Serverfehler. PrĂŒfe Status.

Ratenbegrenzungen

Alle Ratelimits gelten pro IP. Eine 429-Antwort enthÀlt die Standard-Header Retry-After, X-RateLimit-Limit und X-RateLimit-Remaining.

Upload initialisieren / bestÀtigen / abbrechen60 / Minute
Multipart-Abschluss500 / Minute
Multipart-Teil-URLs120 / Minute
Batch-Initialisierung / -BestÀtigung500 / Minute
Statusabfragen (Datei & Sammlung)120 / Minute
Einstellungen (Passwort, Ablauf, max. Downloads)30 / Minute
PasswortĂŒberprĂŒfung10 / Minute
Sammlung erstellen30 / Minute
Verwalten (bereit, löschen)60 / Minute
Thumbnail-Upload120 / Minute
ShareX-Upload20 / Tag
App-Analytics / Fehler120 und 60 / Minute

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 Endpoints

Der 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.

POST/upload/init60/min

Starte einen Upload. Bei Dateien >50 MB ist die Antwort ein Multipart-Upload (Feld type: "multipart"); ansonsten ein einzelnes presigned PUT.

Request-Body

FeldTypBeschreibung
filenamestring · requiredUrsprĂŒnglicher Dateiname. Max. 255 Zeichen.
content_typestring · requiredMIME-Typ.
sizeinteger · requiredDateigrĂ¶ĂŸe in Bytes. Min. 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/partsNur EigentĂŒmer120/min

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

FeldTypBeschreibung
upload_idstring · requiredDie upload_id von /init.
part_numbersarray<int> · requiredPart-Nummern, fĂŒr die URLs abgerufen werden sollen.
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-multipartNur EigentĂŒmer500/min

Schließt einen Multipart-Upload ab, sobald alle Parts hochgeladen sind.

Request-Body

FeldTypBeschreibung
upload_idstring · requiredDie upload_id von /init.
partsarray · requiredJeder Eintrag: { partNumber, etag } aus der Antwort des Part-Uploads.
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/abortNur EigentĂŒmer60/min

Bricht einen Multipart-Upload ab und rÀumt alle unvollstÀndigen Daten auf.

Request-Body

FeldTypBeschreibung
upload_idstring · requiredDer Upload, der abgebrochen werden soll.
Request
curl -X POST https://storage.to/api/upload/abort \
  -H "Content-Type: application/json" \
  -d '{ "upload_id": "01HXYZ..." }'
POST/upload/confirm60/min

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

FeldTypBeschreibung
filenamestring · requiredUrsprĂŒnglicher Dateiname.
sizeinteger · requiredDateigrĂ¶ĂŸe in Bytes.
content_typestring · requiredMIME-Typ.
r2_keystring · requiredDie r2_key von /init.
collection_idstring · optionalAn eine Sammlung anhÀngen.
crc32integer · optionalCRC32-Checksumme zur IntegritĂ€tsprĂŒfung.
file_idstring(9) · optionalErfĂŒlle eine zuvor reserviert-Datei-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",
    "filename": "report.pdf",
    "size": 2202009,
    "human_size": "2.1 MB",
    "expires_at": "2026-04-15T12:00:00Z"
  },
  "owner_token": "owner_v1_..."
}
POST/file/reserve60/min

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

FeldTypBeschreibung
filenamestring · optionalPlatzhalter-Dateiname. Standard: "Pending".
content_typestring · optionalPlatzhalter-MIME-Typ.
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",
    "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 Endpoints

Eine Sammlung gruppiert mehrere Dateien unter einer einzigen Freigabe-URL (/c/{id}). Bis zu 10.000 Dateien und insgesamt 25 GB.

POST/collection30/min

Erstelle eine neue Sammlung. HĂ€nge Dateien danach an, indem du collection_id an /upload/confirm ĂŒbergibst.

Request-Body

FeldTypBeschreibung
expected_file_countinteger · optionalHinweis fĂŒr die automatische Markierung der Sammlung als bereit, sobald alle erwarteten Dateien bestĂ€tigt wurden.
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_..."
}

Frage den Status einer Sammlung ab. Markiert die Sammlung außerdem automatisch als bereit, wenn alle erwarteten Dateien bestĂ€tigt wurden.

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}/readyNur EigentĂŒmer60/min

Markiere die Sammlung als bereit zum Download. Normalerweise nicht nötig – Sammlungen werden automatisch bereit, sobald expected_file_count erreicht ist.

DELETE/collection/{id}Nur EigentĂŒmer60/min

Lösche eine Sammlung und alle ihre Dateien.

POST/collection/{id}/passwordNur EigentĂŒmer30/min

Setze ein Passwort fĂŒr die Sammlung. Erfordert 4–100 Zeichen.

Request-Body

FeldTypBeschreibung
passwordstring · required4–100 Zeichen.
Request
curl -X POST https://storage.to/api/collection/ABC123xyz/password \
  -H "X-Visitor-Token: abc123" \
  -d '{ "password": "hunter22" }'
DELETE/collection/{id}/passwordNur EigentĂŒmer30/min

Entferne das Passwort aus der Sammlung.

PrĂŒfe ein Passwort. Gibt 200 bei Erfolg zurĂŒck, 401 bei falschem Passwort.

Request-Body

FeldTypBeschreibung
passwordstring · required
POST/collection/{id}/expiryNur EigentĂŒmerDauerhaft: kostenpflichtig30/min

Ändere die Ablaufzeit einer Sammlung.

Request-Body

FeldTypBeschreibung
daysinteger · optionalIn 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).
POST/collection/{id}/max-downloadsNur EigentĂŒmer30/min

Setze ein Download-Limit (burn-after-N-downloads). Die Sammlung wird automatisch gelöscht, sobald es erreicht ist.

Request-Body

FeldTypBeschreibung
max_downloadsinteger · optional1–1000. Muss den aktuellen Download-ZĂ€hler ĂŒbersteigen. null, um das Limit zu entfernen.

Dateien

8 Endpoints

Alle 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.

Response
{ "pending": false }
DELETE/file/{id}Nur EigentĂŒmer60/min

Lösche eine Datei sofort.

POST/file/{id}/thumbnailNur EigentĂŒmer120/min

Lade ein Vorschaubild fĂŒr eine Video- oder Bilddatei hoch (wird auf der Download-Seite verwendet). Max. 2 MB.

Request-Body

FeldTypBeschreibung
thumbnailimage · requiredMultipart-Upload. Max. 2 MB.
Response
{
  "success": true,
  "thumbnail_url": "https://..."
}
POST/file/{id}/passwordNur EigentĂŒmer30/min

Setze ein Passwort fĂŒr eine Datei. Erfordert 4–100 Zeichen.

DELETE/file/{id}/passwordNur EigentĂŒmer30/min

Entferne das Passwort einer Datei.

ÜberprĂŒfe das Passwort einer Datei.

POST/file/{id}/expiryNur EigentĂŒmerDauerhaft: kostenpflichtig30/min

Ändere die Ablaufzeit einer Datei.

Request-Body

FeldTypBeschreibung
daysinteger · optionalIn 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).
POST/file/{id}/max-downloadsNur EigentĂŒmer30/min

Begrenze die Gesamtzahl der Downloads einer Datei. Wird automatisch gelöscht, wenn das Limit erreicht ist.

ShareX-Upload

1 Endpoint

One-Shot-Upload-Endpunkt – sende eine Multipart-Datei und erhalte eine teilbare URL zurĂŒck. Kein Init/Confirm-Tanz. Ideal fĂŒr Screenshot-Tools. VollstĂ€ndige Anleitung unter /docs/sharex.

POST/sharex/upload20/day

Lade ein Bild oder eine Datei direkt hoch (multipart-Formular, Feld file). Max. 25 MB.

Request
curl -X POST https://storage.to/api/sharex/upload \
  -F "file=@screenshot.png"
Response
{
  "success": true,
  "url": "https://storage.to/FQxyz1234",
  "filename": "screenshot.png",
  "expires_at": "2026-04-15T12:00:00Z"
}

Desktop-Authentifizierung

2 Endpoints

FĂŒr angemeldete Clients wie die Desktop-App, die ein Bearer-Token besitzen.

GET/userBearer-Token

Gibt den authentifizierten Benutzer zurĂŒck.

Request
curl https://storage.to/api/user \
  -H "Authorization: Bearer <token>"
Response
{
  "id": 42,
  "name": "Ada",
  "email": "ada@example.com",
  "is_premium": true
}
POST/auth/logoutBearer-Token

Widerruft das aktuelle Zugriffstoken.

Verschiedenes

5 Endpoints

Status, Kontingente und Client-Telemetrie.

Liveness-Check. Gibt 200 mit { "status": "ok" } zurĂŒck, wenn der API-Worker lĂ€uft.

Response
{ "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.

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-analytics120/min

Sende ein Nutzungsereignis ĂŒber die CLI oder die Desktop-App.

Request-Body

FeldTypBeschreibung
appstring · requireddesktop, cli oder web.
versionstring · optionalClient-Version.
eventstring · requiredEreignisname, z. B. upload_complete.
contextobject · optionalZusÀtzliche Metadaten.
POST/app-errors60/min

Sende einen Fehlerbericht aus der CLI oder der Desktop-App. Serverseitig dedupliziert – maximal 10 vom gleichen Fehler pro Stunde.

Request-Body

FeldTypBeschreibung
appstring · requireddesktop, cli oder web.
typestring · requiredFehlerklasse/-typ.
messagestring · requiredFehlermeldung.
stackstring · optionalStacktrace.
version, os, os_version, arch, contextvarious · optionalDiagnose-Metadaten.