REST API
Sube archivos, crea colecciones y gestiona compartidos mediante HTTP. Todas las respuestas son JSON; no se requiere una clave de API para subidas anónimas.
Cómo funcionan las subidas
La API de storage.to impulsa nuestro CLI, app de escritorio, cargador web y cualquier cliente de terceros que quieras crear. El flujo de subida tiene tres pasos:
PUT tus bytes directamente a las URL(s) prefirmadas. Los bytes no pasan por nuestros servidores.File y te damos una URL compartible.Todos los endpoints de abajo son relativos a esta base. Ejemplo: POST /upload/init significa POST https://storage.to/api/upload/init.
Autenticación
Las subidas anónimas funcionan sin autenticación, pero con límites estrictos. Las llamadas sin clave están limitadas a 50 archivos por cada 24 horas por dispositivo o IP, más las cuotas de ancho de banda de abajo, y los archivos caducan a los 3 días.
Autenticarse con una cuenta gratuita desbloquea:
- Sin límite diario de archivos
- Sin cuota de ancho de banda de subida
- Subidas vinculadas a tu cuenta (visibles en /dashboard)
- Funciones premium (archivos permanentes, más almacenamiento)
- Mutaciones basadas en la propiedad (eliminar, establecer contraseña, cambiar caducidad) sin necesidad de que coincida el visitor-token
Límites de un vistazo
expiry_daysexpiry_daysNo hay cuotas mensuales: todos los límites son ventanas móviles de 24 horas o límites por minuto. El plan gratuito no tiene un espacio de almacenamiento fijo: cada archivo caduca por sí solo, así que nada se acumula contra una cuota.
Demostrar la propiedad
/upload/init multipart, /upload/confirm, /file/reserve, /collection) devuelve un owner_token en su respuesta. El token es una prueba firmada de propiedad vinculada a ese recurso específico, independiente de tu IP o del token del visitante. Los tokens viven mientras viva el recurso, son seguros para persistir y no caducan de forma independiente. Perder un token significa perder el control de ese recurso (archivo/colección/subida): trátalos como contraseñas locales.# o, junto con una sesión Bearer
X-Owner-Token: <token>
visitor_token. La CLI lo guarda en ~/.config/storageto/token (ver Documentación de la CLI).Para los endpoints de mutación (borrar, establecer contraseña, cambiar la caducidad), la propiedad se confirma si o el token del visitante coincide o la solicitud proviene de la misma IP que creó el archivo. Ambas cosas pueden perderse (cookies borradas, cambios de red). El token del propietario es la prueba preferida a partir de ahora.
Errores
Los errores siguen una estructura consistente: { "success": false, "error": "…" }
Límites de velocidad
Todos los límites de velocidad son por IP. Una respuesta 429 incluye los encabezados estándar Retry-After, X-RateLimit-Limit y X-RateLimit-Remaining.
Cuota de subida: Los clientes anónimos tienen dos límites en paralelo: 100 GB / 24 h por visitor token y 500 GB / 24 h por IP (el límite de IP detecta el tráfico sin token y redes compartidas). Cuando se supera cualquiera, recibirás un 429 con detalles. Esto es solo una cuota de subida: las descargas son ilimitadas y sin limitación.
Subir
8 endpointsEl flujo de subida en tres pasos para cualquier archivo, incluidos los de más de 5 GB (multipart automáticamente). Si solo necesitas una subida rápida tipo captura de pantalla, mira ShareX.
Inicia una subida. Para archivos >50 MB, la respuesta es una subida multipart (campo type: "multipart"); de lo contrario, un único PUT prefirmado.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
filename | string · required | Nombre de archivo original. Máx. 255 caracteres. |
content_type | string · required | Tipo MIME. |
size | integer · required | Tamaño del archivo en bytes. Mín. 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_..." }
Solicita URLs adicionales de partes para una carga multipart en progreso. Se usa cuando /init devolvió menos URLs de las que tienes partes (o cuando expiraron).
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
upload_id | string · required | El upload_id de /init. |
part_numbers | array<int> · required | Números de partes para los que obtener URLs. |
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://..." } ] }
Finaliza una carga multipart una vez que todas las partes estén subidas.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
upload_id | string · required | El upload_id de /init. |
parts | array · required | Cada entrada: { partNumber, etag } de la respuesta de la carga de la parte. |
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 }
Cancela una carga multipart y limpia cualquier dato parcial.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
upload_id | string · required | La carga que se debe cancelar. |
curl -X POST https://storage.to/api/upload/abort \ -H "Content-Type: application/json" \ -d '{ "upload_id": "01HXYZ..." }'
Confirma que la carga está completa. Es cuando creamos el registro File y devolvemos la URL compartible.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
filename | string · required | Nombre de archivo original. |
size | integer · required | Tamaño del archivo en bytes. |
content_type | string · required | Tipo MIME. |
r2_key | string · required | El r2_key de /init. |
collection_id | string · optional | Adjuntar a una colección. |
crc32 | integer · optional | Suma de verificación CRC32 para la verificación de integridad. |
file_id | string(9) · optional | Completa un ID de archivo previamente reservado. |
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_..." }
Reserva un ID de archivo y una URL compartible antes de que los bytes estén listos. Útil cuando necesitas entregar un enlace primero y completar la carga después. La propiedad está vinculada a tu token de visitante + IP. Termina la carga más tarde con /upload/init + /upload/confirm, pasando file_id para confirmar.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
filename | string · optional | Nombre de archivo de ejemplo. Por defecto es "Pending". |
content_type | string · optional | Tipo MIME de ejemplo. |
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_..." }
Equivalente en lote de /upload/init, optimizado para el cargador web. Inicia hasta 250 archivos en un solo viaje.
Usado internamente por el cargador web. La mayoría de los clientes deberían preferir /upload/init para un solo archivo.
Equivalente en lote de /upload/confirm. Confirma muchos archivos en un solo viaje.
Colecciones
9 endpointsUna colección agrupa varios archivos bajo una única URL de compartición (/c/{id}). Hasta 10.000 archivos y 25 GB en total.
Crea una nueva colección. Adjunta archivos después pasando collection_id en /upload/confirm.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
expected_file_count | integer · optional | Pista para marcar automáticamente la colección como lista una vez que todos los archivos esperados hayan confirmado. |
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_..." }
Consulta el estado de una colección. También la marca automáticamente como lista si todos los archivos esperados han confirmado.
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" }
Marca la colección como lista para descargar. Normalmente no hace falta: las colecciones se vuelven automáticamente listas cuando se alcanza expected_file_count.
Elimina una colección y todos sus archivos.
Establece una contraseña en la colección. Requiere 4–100 caracteres.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
password | string · required | 4–100 caracteres. |
curl -X POST https://storage.to/api/collection/ABC123xyz/password \ -H "X-Visitor-Token: abc123" \ -d '{ "password": "hunter22" }'
Quita la contraseña de una colección.
Comprueba una contraseña. Devuelve 200 si es correcta y 401 si es incorrecta.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
password | string · required |
Cambia la caducidad de una colección.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
days | integer · optional | De 1 a 7 días desde ahora, pero nunca más de 7 días después de la subida (o la caducidad actual, si es posterior). Omite o null para permanente (solo premium). |
Establece un límite de descargas (burn-after-N-downloads). La colección se elimina automáticamente cuando se alcanza.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
max_downloads | integer · optional | 1–1000. Debe superar el número actual de descargas. null para quitar el límite. |
Archivos
8 endpointsTodas las configuraciones a nivel de archivo (contraseña, caducidad, max-downloads) reflejan los endpoints de la colección. Solo el propietario.
Comprueba si un archivo aún está pendiente de su carga.
{ "pending": false }
Elimina un archivo inmediatamente.
Sube una imagen de miniatura para un archivo de video o imagen (se usa en la página de descarga). Máx. 2 MB.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
thumbnail | image · required | Carga multipart. Máx. 2 MB. |
{ "success": true, "thumbnail_url": "https://..." }
Establece una contraseña en un archivo. Requiere 4–100 caracteres.
Quita la contraseña de un archivo.
Verifica la contraseña de un archivo.
Cambia la caducidad de un archivo.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
days | integer · optional | De 1 a 7 días desde ahora, pero nunca más de 7 días después de la subida (o la caducidad actual, si es posterior). Omite o null para permanente (solo premium). |
Limita el número total de descargas de un archivo. Se elimina automáticamente cuando se alcanza el límite.
Autenticación de escritorio
2 endpointsPara clientes con sesión iniciada, como la app de escritorio, que tienen un token Bearer.
Devuelve el usuario autenticado.
curl https://storage.to/api/user \ -H "Authorization: Bearer <token>"
{ "id": 42, "name": "Ada", "email": "ada@example.com", "is_premium": true }
Revoca el token de acceso actual.
Varios
5 endpointsEstado, cuotas y telemetría de clientes.
Comprobación de disponibilidad. Devuelve 200 con { "status": "ok" } cuando el worker de la API está sirviendo.
{ "status": "ok" }
Flujo de actividad en vivo para el globo de la portada. Se guarda en caché en el borde.
Uso actual de la cuota de subida para quien llama: lo usan la CLI y la app de escritorio para mostrar la capacidad restante. La forma de la respuesta cambia para usuarios autenticados. A pesar del nombre de la URL, esto solo registra bytes de subida; las descargas no se cuentan.
{ "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" }
Envía un evento de uso desde la CLI o la app de escritorio.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
app | string · required | desktop, cli o web. |
version | string · optional | Versión del cliente. |
event | string · required | Nombre del evento, por ejemplo upload_complete. |
context | object · optional | Metadatos adicionales. |
Envía un informe de error desde la CLI o la app de escritorio. Dedupe en el servidor: máximo 10 del mismo error por hora.
Cuerpo de la solicitud
| Campo | Tipo | Descripción |
|---|---|---|
app | string · required | desktop, cli o web. |
type | string · required | Clase/tipo de error. |
message | string · required | Mensaje de error. |
stack | string · optional | Traza de la pila. |
version, os, os_version, arch, context | various · optional | Metadatos de diagnóstico. |