REST API
Carica file, crea collezioni e gestisci le condivisioni via HTTP. Tutte le risposte sono in formato JSON; per i caricamenti anonimi non è richiesta alcuna chiave API.
Introduzione
La API di storage.to alimenta CLI, app desktop, caricatore web e qualsiasi client di terze parti che vuoi creare.
Il flusso di caricamento è in tre passaggi:
- Inizializza - ci dici che vuoi caricare un file. Ti restituiamo uno o più URL presignati che puntano a Cloudflare R2.
- Carica su R2 -
PUTi tuoi byte direttamente nell’URL(i) presigned. I byte non passano dai nostri server. - Conferma - ci dici che il caricamento è terminato. Creiamo un record
Filee ti forniamo un URL condivisibile.
URL di base
https://storage.to/apiTutti gli endpoint qui sotto sono relativi a questa base. Esempio: POST /upload/init significa POST https://storage.to/api/upload/init.
Autenticazione
I caricamenti anonimi funzionano senza autenticazione, ma con limiti stretti. Le chiamate senza chiave sono limitate a 50 file per 24 ore mobili per dispositivo o IP, oltre alle quote di banda qui sotto, e i file scadono dopo 3 giorni.
Autenticarsi con un account gratuito sblocca:
- Nessun limite giornaliero di file
- Nessuna quota di banda di caricamento
- Caricamenti associati al tuo account (visibili su /dashboard)
- Funzionalità premium (file permanenti, spazio maggiore)
- Modifiche basate sulla proprietà (elimina, imposta password, cambia scadenza) senza dover corrispondere al visitor-token
Limiti a colpo d'occhio
| Limite | Senza token (anonimo) | Token di account gratuito | Token di account a pagamento |
|---|---|---|---|
| File al giorno | 50 / 24 ore | Illimitato | Illimitato |
| Banda di caricamento | 100 GB / 24 ore (500 GB per IP) | Illimitato | Illimitato |
| Dimensione massima del file | 25 GB | 25 GB | 100 GB |
| Scadenza del file | 3 giorni di default, fino a 7 con expiry_days | 3 giorni di default, fino a 7 con expiry_days | Mai (i file sono permanenti) |
| Spazio di archiviazione | Nessuno (i file scadono) | Nessuno (i file scadono) | 100 GB - 1 TB permanente, in base al piano |
Non ci sono quote mensili: tutti i limiti sono finestre mobili di 24 ore o limiti al minuto. Il piano gratuito non ha uno spazio di archiviazione fisso: ogni file scade da solo, quindi nulla si accumula contro una quota.
Per autenticarti, genera un token API personale dal tuo account e invialo come bearer token su ogni richiesta:
Authorization: Bearer <token>Devi aver effettuato l’accesso. Il token completo viene mostrato solo una volta al momento della creazione, quindi copialo in un posto sicuro. Puoi revocare un token in qualsiasi momento dalla stessa pagina.
Token visitatore
I client anonimi hanno bisogno di un modo per dimostrare la proprietà dei propri upload senza un account. Usiamo una visitor token: una stringa casuale che il client genera una volta e riutilizza. Inviatela con ogni richiesta:
X-Visitor-Token: <random-string>Sul web, il token viene salvato automaticamente nel cookie visitor_token. La CLI lo salva in ~/.config/storageto/token (vedi Documentazione CLI).
Per gli endpoint di mutazione (elimina, imposta password, cambia scadenza), la proprietà è confermata se oppure il token del visitatore corrisponde o la richiesta proviene dallo stesso IP che ha creato il file. Entrambi possono andare persi (cookie cancellati, cambi di rete). Da ora in poi, la prova preferita è token dell’owner.
Token proprietario
Ogni endpoint che crea risorse (/upload/init multipart, /upload/confirm, /file/reserve, /collection) restituisce un owner_token nella risposta. Il token è una prova firmata di proprietà legata a quella specifica risorsa, indipendente dal tuo IP o dal token del visitatore.
Salva il token insieme all’ID della risorsa e invialo in qualsiasi mutazione come:
Authorization: Owner <token>Oppure, se stai già usando Authorization: Bearer per una sessione autenticata, invialo come:
X-Owner-Token: <token>Il server accetta il token del proprietario come prova valida di proprietà insieme al vecchio fallback visitor token + IP: i client che hanno il token continuano a funzionare anche dopo aver cambiato rete o cancellato i cookie, mentre quelli che non ce l’hanno funzionano esattamente come prima.
I token durano quanto dura la risorsa, sono sicuri da mantenere e non scadono in modo indipendente. Un token smarrito significa perdere il controllo di quella risorsa (file/collezione/upload): trattali come password locali.
Errori
Gli errori seguono una struttura coerente:
{
"success": false,
"error": "Human-readable message"
}Codici di stato HTTP comuni:
| Codice | Significato |
|---|---|
200 | OK. |
201 | Creato. |
400 | Richiesta non valida (es. limite di dimensione della collezione superato). |
401 | Password richiesta o non corretta. |
403 | Non autorizzato (non sei il proprietario della risorsa). |
404 | Risorsa non trovata o scaduta. |
422 | Validazione non riuscita, oppure restrizione di piano/quota. |
429 | Limite di rate o quota di upload superata. |
500 | Errore del server. Controlla stato. |
Limiti di velocità
Tutti i limiti di rate sono per IP. Una risposta 429 include gli header standard Retry-After, X-RateLimit-Limit e X-RateLimit-Remaining.
| Ambito | Limite |
|---|---|
| Avvio / conferma / annullamento upload | 60 / minuto |
| Completamento multipart | 500 / minuto |
| URL delle parti multipart | 120 / minuto |
| Avvio / conferma batch | 500 / minuto |
| Verifiche dello stato (file e collezione) | 120 / minuto |
| Impostazioni (password, scadenza, max-download) | 30 / minuto |
| Verifica password | 10 / minuto |
| Creazione collezione | 30 / minuto |
| Gestione (pronto, elimina) | 60 / minuto |
| Caricamento thumbnail | 120 / minuto |
| Upload con ShareX | 20 / giorno |
| Analytics dell’app / errori | 120 e 60 / minuto |
Quota di upload: I client anonimi hanno due limiti in parallelo: 100 GB / 24 h per visitor token e 500 GB / 24 h per IP (il limite IP intercetta il traffico senza token e le reti condivise). Quando uno dei due viene superato riceverai un 429 con i dettagli. È solo una quota upload: i download sono illimitati e senza limitazioni (serviti direttamente da URL firmati R2).
Carica
Il flusso di upload in tre passaggi per qualsiasi file, inclusi quelli oltre 5 GB (multipart in automatico). Se ti serve solo un upload rapido in stile screenshot, guarda invece ShareX.
/upload/init60/minAvvia un upload. Per i file >50 MB la risposta è un upload multipart (campo type: "multipart"); altrimenti un singolo PUT presigned.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
filename | string · required | Nome file originale. Max 255 caratteri. |
content_type | string · required | Tipo MIME. |
size | integer · required | Dimensione del file in byte. Min 1. |
/upload/partsOwner only120/minRichiedi URL aggiuntivi per le parti di un upload multipart in corso. Usato quando /init ha restituito meno URL di quante parti hai (oppure sono scaduti).
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
upload_id | string · required | L'upload_id da /init. |
part_numbers | array<int> · required | Numeri delle parti per cui ottenere gli URL. |
/upload/complete-multipartOwner only500/minCompleta un upload multipart su R2 una volta caricate tutte le parti.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
upload_id | string · required | L'upload_id da /init. |
parts | array · required | Ogni voce: { partNumber, etag } dalla risposta di R2. |
/upload/abortOwner only60/minAnnulla un upload multipart e ripulisci eventuali dati parziali su R2.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
upload_id | string · required | L'upload da annullare. |
/upload/confirm60/minConferma che l'upload è completato. È qui che creiamo il record File e restituiamo l'URL condivisibile.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
filename | string · required | Nome file originale. |
size | integer · required | Dimensione del file in byte. |
content_type | string · required | Tipo MIME. |
r2_key | string · required | L'r2_key da /init. |
collection_id | string · optional | Aggiungi a una raccolta. |
crc32 | integer · optional | Checksum CRC32 per la verifica dell'integrità. |
file_id | string(9) · optional | Completa un ID file precedentemente riservato. |
/file/reserve60/minRiserva un ID file e un URL condivisibile prima che i byte siano pronti. Utile quando devi consegnare prima un link e completare l'upload dopo. La proprietà è legata al tuo token visitatore + IP. Completa l'upload più tardi con /upload/init + /upload/confirm, passando file_id per la conferma.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
filename | string · optional | Nome file segnaposto. Impostazione predefinita: "Pending". |
content_type | string · optional | Tipo MIME segnaposto. |
/upload/init-batch500/minEquivalente batch di /upload/init, ottimizzato per l'uploader web. Avvia fino a 250 file in un solo round-trip.
Usato internamente dall'uploader web. La maggior parte dei client dovrebbe preferire /upload/init per singolo file.
/upload/confirm-batch500/minEquivalente batch di /upload/confirm. Conferma molti file in un solo round-trip.
Raccolte
Una raccolta raggruppa più file sotto un unico URL di condivisione (/c/{id}). Fino a 10.000 file e 25 GB totali.
/collection30/minCrea una nuova raccolta. Aggiungi i file in seguito passando collection_id su /upload/confirm.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
expected_file_count | integer · optional | Suggerimento per contrassegnare automaticamente la raccolta come pronta una volta che tutti i file previsti sono stati confermati. |
/collection/{id}/status120/minControlla lo stato di una raccolta. Contrassegna automaticamente la raccolta come pronta anche se tutti i file previsti sono stati confermati.
/collection/{id}/readyOwner only60/minSegna la collezione come pronta per il download. Di solito non serve: le collezioni diventano automaticamente pronte quando si raggiunge expected_file_count.
/collection/{id}Owner only60/minElimina una raccolta e tutti i suoi file.
/collection/{id}/passwordOwner only30/minImposta una password sulla raccolta. Richiede 4–100 caratteri.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
password | string · required | 4–100 caratteri. |
/collection/{id}/passwordOwner only30/minRimuovi la password da una raccolta.
/collection/{id}/verify-password10/minVerifica una password. Restituisce 200 in caso di successo, 401 se la password è errata.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
password | string · required |
/collection/{id}/expiryOwner only30/minCambia la scadenza di una raccolta.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
days | integer · optional | Da 1 a 7 giorni da oggi. Ommetti o null per la durata permanente (solo premium). |
/collection/{id}/max-downloadsOwner only30/minImposta un limite di download (burn-after-N-downloads). La raccolta viene eliminata automaticamente quando viene raggiunto il limite.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
max_downloads | integer · optional | 1–1000. Deve superare il numero di download attuale. null per rimuovere il limite. |
File
Tutte le impostazioni a livello file (password, scadenza, max-downloads) rispecchiano gli endpoint della raccolta. Solo il proprietario.
/file/{id}/status120/minControlla se un file è ancora in attesa del caricamento.
/file/{id}Owner only60/minElimina un file immediatamente.
/file/{id}/thumbnailOwner only120/minCarica un'immagine thumbnail per un file video o immagine (usata nella pagina di download). Max 2 MB.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
thumbnail | image · required | Upload multipart. Max 2 MB. |
/file/{id}/passwordOwner only30/minImposta una password su un file. Richiede 4–100 caratteri.
/file/{id}/passwordOwner only30/minRimuovi la password di un file.
/file/{id}/verify-password10/minVerifica la password di un file.
/file/{id}/expiryOwner only30/minCambia la scadenza di un file.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
days | integer · optional | Da 1 a 7 giorni da oggi. Ommetti o null per la durata permanente (solo premium). |
/file/{id}/max-downloadsOwner only30/minLimita il numero totale di download di un file. Si elimina automaticamente quando viene raggiunto il limite.
Upload con ShareX
Endpoint di upload one-shot: invia un file multipart e ricevi un URL condivisibile. Niente passaggi di init/conferma. Ideale per strumenti di screenshot. Guida completa alla configurazione su /docs/sharex.
Autenticazione desktop
Per client autenticati (ad es. l'app desktop) che hanno un token Sanctum.
/userBearer tokenRestituisci l’utente autenticato.
/auth/logoutBearer tokenRevoca il token di accesso corrente.
Varie
/healthControllo di disponibilità. Restituisce 200 con { "status": "ok" } quando il worker API è attivo.
/activityFlusso live delle attività per il globo della home. Memorizzato nella cache ai margini di Cloudflare.
/bandwidth/status60/minUtilizzo attuale della quota di upload per il chiamante: usato dalla CLI e dall’app desktop per mostrare la capacità residua. La struttura della risposta cambia per gli utenti autenticati. Nonostante il nome dell’URL, tiene traccia solo dei byte upload; i download non vengono conteggiati.
/app-analytics120/minInvia un evento di utilizzo dalla CLI o dall’app desktop.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
app | string · required | desktop, cli o web. |
version | string · optional | Versione del client. |
event | string · required | Nome dell’evento, ad es. upload_complete. |
context | object · optional | Metadati extra. |
/app-errors60/minInvia una segnalazione di errore dalla CLI o dall’app desktop. Deduplicata lato server: massimo 10 dello stesso errore per ora.
Corpo della richiesta
| Campo | Tipo | Descrizione |
|---|---|---|
app | string · required | desktop, cli o web. |
type | string · required | Classe/tipo di errore. |
message | string · required | Messaggio di errore. |
stack | string · optional | Stack trace. |
version, os, os_version, arch, context | various · optional | Metadati diagnostici. |