REST API

Przesyłaj pliki, twórz kolekcje i zarządzaj udostępnieniami przez HTTP. Wszystkie odpowiedzi są w formacie JSON; do anonimowego przesyłania nie jest wymagany klucz API.

Wprowadzenie

API storage.to napędza nasze CLI, aplikacja desktopowa, web uploader oraz dowolnego klienta zewnętrznego, którego chcesz stworzyć.

Proces przesyłania składa się z trzech kroków:

  1. Inicjalizacja — powiedz nam, że chcesz przesłać plik. Zwracamy jeden lub więcej podpisanych URL-i wskazujących na Cloudflare R2.
  2. Prześlij do R2PUT swoje bajty bezpośrednio na presigned URL(e). Bajty nie przechodzą przez nasze serwery.
  3. Potwierdź — powiedz nam, że przesyłanie zakończyło się. Tworzymy rekord File i przekazujemy Ci udostępnialny URL.

Podstawowy URL

https://storage.to/api

Wszystkie poniższe endpointy są względem tego podstawowego URL. Przykład: POST /upload/init oznacza POST https://storage.to/api/upload/init.

Uwierzytelnianie

Większość endpointów nie wymaga uwierzytelniania. Anonimowe przesyłanie to podstawowa funkcja.

Uwierzytelnianie jest opcjonalne i odblokowuje:

  • Przesyłania powiązane z Twoim kontem (widoczne w /dashboard)
  • Funkcje premium (trwałe pliki, większa przestrzeń)
  • Operacje na własności (usuwanie, ustawianie hasła, zmiana daty ważności) bez konieczności dopasowania tokena odwiedzającego

Używamy tokenów typu bearer Laravel Sanctum. Wygeneruj token przez desktopowy OAuth lub logowanie webowe, a następnie wyślij go jako:

Authorization: Bearer <token>

Token odwiedzającego

Anonimowi klienci potrzebują sposobu na potwierdzenie własności swoich przesłań bez konta. Używamy token odwiedzającego — losowego ciągu znaków generowanego raz i używanego ponownie. Wyślij go z każdym żądaniem:

X-Visitor-Token: <random-string>

W sieci token jest automatycznie przechowywany w ciasteczku visitor_token. CLI zapisuje go w ~/.config/storageto/token (zobacz Dokumentacja CLI).

Dla endpointów mutujących (usuń, ustaw hasło, zmień datę ważności) własność potwierdzana jest, jeśli lub token odwiedzającego się zgadza albo żądanie pochodzi z tego samego IP, które utworzyło plik.

Błędy

Błędy mają spójną strukturę:

{
  "success": false,
  "error": "Human-readable message"
}

Typowe kody statusu HTTP:

KodZnaczenie
200OK.
201Utworzono.
400Błędne żądanie (np. przekroczono limit rozmiaru kolekcji).
401Wymagane hasło lub nieprawidłowe.
403Brak autoryzacji (nie jesteś właścicielem zasobu).
404Zasób nie znaleziony lub wygasł.
422Niepowodzenie walidacji lub ograniczenie planu/kwoty.
429Przekroczono limit szybkości lub kwotę przesyłania.
500Błąd serwera. Sprawdź status.

Limity szybkości

Wszystkie limity szybkości są na IP. Odpowiedź 429 zawiera standardowe nagłówki Retry-After, X-RateLimit-Limit i X-RateLimit-Remaining.

ZakresLimit
Inicjacja / potwierdzenie / anulowanie przesyłania60 / minuta
Zakończenie przesyłania wieloczęściowego500 / minuta
URL-e części wieloczęściowych120 / minuta
Inicjacja / potwierdzenie wsadowe500 / minuta
Zapytania o status (plik i kolekcja)120 / minuta
Ustawienia (hasło, wygaśnięcie, max pobrań)30 / minuta
Weryfikacja hasła10 / minuta
Utwórz kolekcję30 / minuta
Zarządzaj (gotowe, usuń)60 / minuta
Przesyłanie miniatury120 / minuta
Przesyłanie ShareX20 / dzień
Analizy aplikacji / błędy120 i 60 / minuta

Limit przesyłania: Anonimowi klienci mają dwie limity działające równolegle — 100 GB / 24 h na token odwiedzającego i 500 GB / 24 h na IP (limit IP obejmuje ruch bez tokena i sieci współdzielone). Po przekroczeniu któregokolwiek otrzymasz 429 ze szczegółami. To jest tylko limit przesyłanie — pobrania są nieograniczone i bez ograniczeń prędkości (serwowane bezpośrednio z podpisanych URL-i R2).

Prześlij

Trzystopniowy proces przesyłania dowolnego pliku, w tym plików powyżej 5 GB (automatycznie wieloczęściowy). Jeśli potrzebujesz tylko szybkiego przesłania w stylu zrzutu ekranu, zobacz zamiast tego ShareX.

POST /upload/init 60/min

Rozpocznij przesyłanie. Dla plików >50 MB odpowiedź zawiera part_urls dla przesyłania wieloczęściowego; w przeciwnym razie pojedynczy url.

Treść żądania

PoleTypOpis
filenamestring · requiredOryginalna nazwa pliku. Maks. 255 znaków.
content_typestring · requiredTyp MIME.
sizeinteger · requiredRozmiar pliku w bajtach. 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, "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

Poproś o dodatkowe URL-e części dla trwającego przesyłania wieloczęściowego. Używane, gdy /init zwrócił mniej URL-i niż masz części (lub wygasły).

Treść żądania

PoleTypOpis
upload_idstring · requiredupload_id z /init.
part_numbersarray<int> · requiredNumery części, dla których pobrać URL-e.
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

Zakończ przesyłanie wieloczęściowe na R2 po przesłaniu wszystkich części.

Treść żądania

PoleTypOpis
upload_idstring · requiredupload_id z /init.
partsarray · requiredKażdy wpis: { partNumber, etag } z odpowiedzi R2.
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

Anuluj przesyłanie wieloczęściowe i usuń częściowe dane na R2.

Treść żądania

PoleTypOpis
upload_idstring · requiredPrzesyłanie do anulowania.
Request
curl -X POST https://storage.to/api/upload/abort \ -H "Content-Type: application/json" \ -d '{ "upload_id": "01HXYZ..." }'
POST /upload/confirm 60/min

Potwierdź zakończenie przesyłania. Wtedy tworzymy rekord File i zwracamy link do udostępniania.

Treść żądania

PoleTypOpis
filenamestring · requiredOryginalna nazwa pliku.
sizeinteger · requiredRozmiar pliku w bajtach.
content_typestring · requiredTyp MIME.
r2_keystring · requiredr2_key z /init.
collection_idstring · optionalDołącz do kolekcji.
crc32integer · optionalSuma kontrolna CRC32 do weryfikacji integralności.
file_idstring(9) · optionalZrealizuj wcześniej zarezerwowane ID pliku.
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

Zarezerwuj ID pliku i link do udostępniania przed zanim bajty będą gotowe. Przydatne, gdy najpierw musisz udostępnić link, a przesyłanie wykonać później. Własność jest powiązana z Twoim tokenem odwiedzającego + IP. Dokończ przesyłanie później za pomocą /upload/init + /upload/confirm, przekazując file_id do potwierdzenia.

Treść żądania

PoleTypOpis
filenamestring · optionalNazwa pliku zastępczego. Domyślnie "Pending".
content_typestring · optionalTyp MIME zastępczy.
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

Odpowiednik wsadowy /upload/init, zoptymalizowany pod kątem webowego uploadera. Inicjuje do 250 plików w jednej rundzie.

Używane wewnętrznie przez webowego uploadera. Większość klientów powinna preferować pojedyncze /upload/init.

POST /upload/confirm-batch 500/min

Odpowiednik wsadowy /upload/confirm. Potwierdza wiele plików w jednej rundzie.

Kolekcje

Kolekcja grupuje wiele plików pod jednym adresem URL do udostępniania (/c/{id}). Do 10 000 plików i łącznie 25 GB.

POST /collection 30/min

Utwórz nową kolekcję. Dołącz pliki później, przekazując collection_id na /upload/confirm.

Treść żądania

PoleTypOpis
expected_file_countinteger · optionalPodpowiedź do automatycznego oznaczenia kolekcji jako gotowej, gdy wszystkie oczekiwane pliki zostaną potwierdzone.
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

Sprawdź stan kolekcji. Automatycznie oznacza kolekcję jako gotową, jeśli wszystkie oczekiwane pliki zostały potwierdzone.

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

Oznacz kolekcję jako gotową do pobrania. Zazwyczaj niepotrzebne — kolekcje automatycznie stają się gotowe po osiągnięciu expected_file_count.

DELETE /collection/{id} Owner only 60/min

Usuń kolekcję i wszystkie jej pliki.

POST /collection/{id}/password Owner only 30/min

Ustaw hasło dla kolekcji. Wymagane 4–100 znaków.

Treść żądania

PoleTypOpis
passwordstring · required4–100 znaków.
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

Usuń hasło z kolekcji.

POST /collection/{id}/verify-password 10/min

Sprawdź hasło. Zwraca 200 przy sukcesie, 401 przy błędnym haśle.

Treść żądania

PoleTypOpis
passwordstring · required
POST /collection/{id}/expiry Owner only 30/min

Zmień wygaśnięcie kolekcji.

Treść żądania

PoleTypOpis
daysinteger · optional1–7 dni od teraz. Pomiń lub null dla stałego (tylko premium).
POST /collection/{id}/max-downloads Owner only 30/min

Ustaw limit pobrań (usuń po N pobraniach). Kolekcja usuwa się automatycznie po osiągnięciu limitu.

Treść żądania

PoleTypOpis
max_downloadsinteger · optional1–1000. Musi przekraczać aktualną liczbę pobrań. null usuwa limit.

Pliki

Wszystkie ustawienia na poziomie pliku (hasło, wygaśnięcie, max pobrań) odzwierciedlają ustawienia kolekcji. Tylko dla właściciela.

GET /file/{id}/status 120/min

Sprawdź, czy plik nadal oczekuje na przesłanie.

Response
{ "pending": false }
DELETE /file/{id} Owner only 60/min

Usuń plik natychmiast.

POST /file/{id}/thumbnail Owner only 120/min

Prześlij miniaturę dla pliku wideo lub obrazu (używana na stronie pobierania). Maks. 2 MB.

Treść żądania

PoleTypOpis
thumbnailimage · requiredUpload wieloczęściowy. Maks. 2 MB.
Response
{ "success": true, "thumbnail_url": "https://..." }
POST /file/{id}/password Owner only 30/min

Ustaw hasło dla pliku. Wymagane 4–100 znaków.

DELETE /file/{id}/password Owner only 30/min

Usuń hasło pliku.

POST /file/{id}/verify-password 10/min

Zweryfikuj hasło pliku.

POST /file/{id}/expiry Owner only 30/min

Zmień wygaśnięcie pliku.

Treść żądania

PoleTypOpis
daysinteger · optional1–7 dni od teraz. Pomiń lub null dla stałego (tylko premium).
POST /file/{id}/max-downloads Owner only 30/min

Ustaw limit pobrań pliku. Usuwa się automatycznie po osiągnięciu limitu.

Przesyłanie ShareX

Endpoint do jednorazowego uploadu — wyślij plik wieloczęściowy, otrzymaj link do udostępniania. Bez faz init/confirm. Idealne dla narzędzi do zrzutów ekranu. Pełny przewodnik na /pl/docs/sharex.

POST /sharex/upload 20/day

Prześlij obraz lub plik bezpośrednio (formularz wieloczęściowy, pole file). Maks. 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" }

Uwierzytelnianie na pulpicie

Dla uwierzytelnionych klientów (np. aplikacja desktopowa) posiadających token Sanctum.

GET /user Bearer token

Zwróć uwierzytelnionego użytkownika.

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

Unieważnij bieżący token dostępu.

Różne

GET /health

Sprawdzenie stanu. Ping bazy danych, magazynu R2 i pamięci podręcznej Redis. Zwraca 200 jeśli wszystko działa, 503 w przeciwnym razie.

Response
{ "status": "healthy", "checks": { "database": "ok", "storage": "ok", "cache": "ok" }, "timestamp": "2026-04-12T12:00:00Z" }
GET /activity

Na żywo strumień aktywności dla globu na stronie głównej. Buforowane na krawędzi Cloudflare.

GET /bandwidth/status 60/min

Aktualne wykorzystanie limitu uploadu dla wywołującego — używane przez CLI i aplikację desktopową do pokazania pozostałej pojemności. Kształt odpowiedzi różni się dla uwierzytelnionych użytkowników. Pomimo nazwy URL, śledzi tylko przesyłanie bajtów; pobrania nie są liczone.

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

Prześlij zdarzenie użycia z CLI lub aplikacji desktopowej.

Treść żądania

PoleTypOpis
appstring · requireddesktop, cli lub web.
versionstring · optionalWersja klienta.
eventstring · requiredNazwa zdarzenia, np. upload_complete.
contextobject · optionalDodatkowe metadane.
POST /app-errors 60/min

Prześlij raport błędu z CLI lub aplikacji desktopowej. Usuwanie duplikatów po stronie serwera — max 10 takich samych błędów na godzinę.

Treść żądania

PoleTypOpis
appstring · requireddesktop, cli lub web.
typestring · requiredKlasa/typ błędu.
messagestring · requiredKomunikat błędu.
stackstring · optionalŚlad stosu.
version, os, os_version, arch, contextvarious · optionalMetadane diagnostyczne.