Referência

REST API

Envie arquivos, crie coleções e gerencie compartilhamentos via HTTP. Todas as respostas são em JSON; não é necessária uma chave de API para uploads anônimos.

URL basehttps://storage.to/api
33 endpoints · JSON

Como funcionam os carregamentos

A API do storage.to alimenta nosso CLI, app de desktop, enviador web e qualquer cliente de terceiros que você queira criar. O fluxo de envio tem três etapas:

01 · POST /upload/init
Iniciar
diga que você quer enviar um arquivo. Nós retornamos uma ou mais URLs presignadas apontando para o nosso edge de armazenamento.
02 · PUT {upload_url}
Upload
PUT seus bytes diretamente na(s) URL(s) pré-assinada(s). Os bytes não passam pelos nossos servidores.
03 · POST /upload/confirm
Confirmar
diga que o envio foi concluído. Criamos um registro File e entregamos uma URL compartilhável.

Todos os endpoints abaixo são relativos a esta base. Exemplo: POST /upload/init significa POST https://storage.to/api/upload/init.

Autenticação

Uploads anônimos funcionam sem autenticação, mas com limites rígidos. Chamadas sem chave são limitadas a 50 arquivos por 24 horas por dispositivo ou IP, além das cotas de banda abaixo, e os arquivos expiram após 3 dias.

Autenticar com uma conta gratuita desbloqueia:

  • Sem limite diário de arquivos
  • Sem quota de largura de banda de envio
  • Uploads vinculados à sua conta (visível em /dashboard)
  • Recursos premium (arquivos permanentes, mais armazenamento)
  • Mutations baseadas em propriedade (excluir, definir senha, alterar validade) sem precisar do match do visitor-token

Limites num relance

Sem token (anónimo)
Token de conta gratuita
Token de conta paga
Ficheiros por dia
50 / 24 horas
Ilimitado
Ilimitado
Largura de banda de envio
100 GB / 24 horas (500 GB por IP)
Ilimitado
Ilimitado
Tamanho máximo do arquivo
25 GB
25 GB
100 GB
Expiração do ficheiro
3 dias por predefinição, até 7 via expiry_days
3 dias por predefinição, até 7 via expiry_days
Nunca (os ficheiros são permanentes)
Espaço de armazenamento
Nenhum (os ficheiros expiram)
Nenhum (os ficheiros expiram)
100 GB - 1 TB permanente, conforme o plano
Ver planos →

Não há quotas mensais: todos os limites são janelas móveis de 24 horas ou limites por minuto. O plano gratuito não tem espaço de armazenamento fixo: cada ficheiro expira por si só, pelo que nada se acumula contra uma quota.

Para autenticar, gere um token de API pessoal na sua conta e envie-o como um bearer token em todas as requisições: Você precisa estar conectado. O token completo é exibido apenas uma vez no momento da criação, então copie-o em algum lugar seguro. Você pode revogar um token a qualquer momento na mesma página. Gerar token de API →
Authorization: Bearer <token>

Provar a propriedade

Token do proprietárioRecomendado
Todo endpoint que cria recursos (/upload/init multipart, /upload/confirm, /file/reserve, /collection) retorna um owner_token na resposta. O token é uma prova de propriedade assinada, vinculada a esse recurso específico, independente do seu IP ou do token do visitante. Os tokens duram enquanto o recurso existir, são seguros para persistir e não expiram de forma independente. Um token perdido significa perder o controle desse recurso (arquivo/coleção/envio) - trate-os como senhas locais.
Authorization: Owner <token>
# ou, juntamente com uma sessão Bearer
X-Owner-Token: <token>
Token de visitante
Clientes anônimos precisam de uma forma de provar que são donos dos próprios envios sem ter uma conta. Usamos um visitor token - uma string aleatória que o cliente gera uma vez e reutiliza. Envie isso em toda requisição: No web, o token é armazenado automaticamente no cookie visitor_token. O CLI o armazena em ~/.config/storageto/token (veja Documentação da CLI).
X-Visitor-Token: <random-string>

Para endpoints de mutação (delete, definir senha, alterar validade), a propriedade é confirmada se ou o token do visitante corresponder a ou a requisição vier do mesmo IP que criou o arquivo. Ambos podem ser perdidos (cookies apagados, mudanças de rede). O token do proprietário é a prova preferida daqui pra frente.

Erros

Os erros seguem um formato consistente: { "success": false, "error": "…" }

200OK.
201Criado.
400Requisição inválida (por exemplo, limite de tamanho da coleção excedido).
401Senha necessária ou incorreta.
403Não autorizado (não é o proprietário do recurso).
404Recurso não encontrado ou expirado.
422Falha na validação ou restrição de plano/quota.
429Limite de taxa atingido ou cota de upload excedida.
500Erro no servidor. Verifique status.

Limites de taxa

Todos os limites de taxa são por IP. Uma resposta 429 inclui os cabeçalhos padrão Retry-After, X-RateLimit-Limit e X-RateLimit-Remaining.

Upload init / confirm / abort60 / minuto
Conclusão multipart500 / minuto
URLs das partes multipart120 / minuto
Batch init / confirm500 / minuto
Consultas de status (arquivo e coleção)120 / minuto
Configurações (senha, validade, max-downloads)30 / minuto
Verificação de senha10 / minuto
Criação de coleção30 / minuto
Gerenciar (ready, delete)60 / minuto
Upload de miniatura120 / minuto
Upload pelo ShareX20 / dia
Analytics do app / erros120 e 60 / minuto

Cota de upload: clientes anônimos têm dois limites em paralelo - 100 GB / 24 h por visitor token e 500 GB / 24 h por IP (o limite de IP captura tráfego sem token e redes compartilhadas). Quando qualquer um for excedido, você recebe um 429 com detalhes. Isso é apenas uma cota de upload - downloads são ilimitados e sem limitação.

Upload

8 endpoints

O fluxo de upload em três etapas para qualquer arquivo, incluindo arquivos acima de 5 GB (multipart automático). Se você só precisa de um upload rápido no estilo de captura de tela, veja ShareX.

POST/upload/init60/min

Inicie um upload. Para arquivos >50 MB, a resposta é um upload multipart (campo type: "multipart"); caso contrário, um único PUT presignado.

Corpo da requisição

CampoTipoDescrição
filenamestring · requiredNome original do arquivo. Máx. 255 caracteres.
content_typestring · requiredTipo MIME.
sizeinteger · requiredTamanho do arquivo em bytes. Mín. 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/partsApenas o proprietário120/min

Solicita URLs adicionais das partes para um upload multipart em andamento. Usado quando /init retornou menos URLs do que você tem partes (ou elas expiraram).

Corpo da requisição

CampoTipoDescrição
upload_idstring · requiredO upload_id de /init.
part_numbersarray<int> · requiredNúmeros das partes para obter URLs.
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-multipartApenas o proprietário500/min

Finaliza um upload multipart assim que todas as partes forem enviadas.

Corpo da requisição

CampoTipoDescrição
upload_idstring · requiredO upload_id de /init.
partsarray · requiredCada entrada: { partNumber, etag } da resposta do envio da parte.
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/abortApenas o proprietário60/min

Cancele um upload multipart e limpe qualquer dado parcial.

Corpo da requisição

CampoTipoDescrição
upload_idstring · requiredO upload a ser interrompido.
Request
curl -X POST https://storage.to/api/upload/abort \
  -H "Content-Type: application/json" \
  -d '{ "upload_id": "01HXYZ..." }'
POST/upload/confirm60/min

Confirme que o upload foi concluído. É quando criamos o registro File e retornamos a URL compartilhável.

Corpo da requisição

CampoTipoDescrição
filenamestring · requiredNome original do arquivo.
sizeinteger · requiredTamanho do arquivo em bytes.
content_typestring · requiredTipo MIME.
r2_keystring · requiredO r2_key de /init.
collection_idstring · optionalAnexar a uma coleção.
crc32integer · optionalSoma de verificação CRC32 para verificação de integridade.
file_idstring(9) · optionalConcluir um ID de arquivo reservado previamente.
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

Reserve um ID de arquivo e uma URL compartilhável antes os bytes ficarem prontos. Útil quando você precisa entregar um link primeiro e concluir o upload depois. A propriedade fica vinculada ao seu token de visitante + IP. Finalize o upload mais tarde com /upload/init + /upload/confirm, passando file_id para confirmar.

Corpo da requisição

CampoTipoDescrição
filenamestring · optionalNome de arquivo de exemplo. Padrão: "Pending".
content_typestring · optionalTipo MIME de exemplo.
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_..."
}

Equivalente em lote de /upload/init, otimizado para o uploader web. Inicia até 250 arquivos em uma única ida e volta.

Usado internamente pelo uploader web. A maioria dos clientes deve preferir o /upload/init de arquivo único.

Equivalente em lote de /upload/confirm. Confirma muitos arquivos em uma única ida e volta.

Coleções

9 endpoints

Uma coleção agrupa vários arquivos sob uma única URL de compartilhamento (/c/{id}). Até 10.000 arquivos e 25 GB no total.

POST/collection30/min

Crie uma nova coleção. Anexe arquivos depois passando collection_id em /upload/confirm.

Corpo da requisição

CampoTipoDescrição
expected_file_countinteger · optionalDica para marcar automaticamente a coleção como pronta assim que todos os arquivos esperados forem confirmados.
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_..."
}

Verifica o estado de uma coleção. Também marca automaticamente a coleção como pronta se todos os arquivos esperados tiverem sido confirmados.

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}/readyApenas o proprietário60/min

Marque a coleção como pronta para download. Normalmente não é necessário - as coleções ficam automaticamente prontas quando expected_file_count é atingido.

DELETE/collection/{id}Apenas o proprietário60/min

Exclua uma coleção e todos os seus arquivos.

POST/collection/{id}/passwordApenas o proprietário30/min

Defina uma senha na coleção. Requer 4–100 caracteres.

Corpo da requisição

CampoTipoDescrição
passwordstring · required4–100 caracteres.
Request
curl -X POST https://storage.to/api/collection/ABC123xyz/password \
  -H "X-Visitor-Token: abc123" \
  -d '{ "password": "hunter22" }'
DELETE/collection/{id}/passwordApenas o proprietário30/min

Remover a senha de uma coleção.

Verifique uma senha. Retorna 200 em caso de sucesso, 401 em caso de senha incorreta.

Corpo da requisição

CampoTipoDescrição
passwordstring · required
POST/collection/{id}/expiryApenas o proprietárioPermanente: pago30/min

Altere a expiração de uma coleção.

Corpo da requisição

CampoTipoDescrição
daysinteger · optionalDe 1 a 7 dias a partir de agora, mas nunca mais de 7 dias após o envio (ou a expiração atual, se for posterior). Omita ou null para permanente (apenas premium).
POST/collection/{id}/max-downloadsApenas o proprietário30/min

Defina um limite de downloads (burn-after-N-downloads). A coleção é excluída automaticamente quando atingir o limite.

Corpo da requisição

CampoTipoDescrição
max_downloadsinteger · optional1–1000. Deve exceder a contagem atual de downloads. null para remover o limite.

Arquivos

8 endpoints

Todas as configurações no nível do arquivo (senha, expiração, max-downloads) espelham os endpoints da coleção. Apenas o proprietário.

Verifique se um arquivo ainda está aguardando o upload.

Response
{ "pending": false }
DELETE/file/{id}Apenas o proprietário60/min

Exclua um arquivo imediatamente.

POST/file/{id}/thumbnailApenas o proprietário120/min

Envie uma imagem de miniatura para um arquivo de vídeo ou imagem (usada na página de download). Máx. 2 MB.

Corpo da requisição

CampoTipoDescrição
thumbnailimage · requiredUpload multipart. Máx. 2 MB.
Response
{
  "success": true,
  "thumbnail_url": "https://..."
}
POST/file/{id}/passwordApenas o proprietário30/min

Defina uma senha em um arquivo. Requer 4–100 caracteres.

DELETE/file/{id}/passwordApenas o proprietário30/min

Remova a senha de um arquivo.

Verifique a senha de um arquivo.

POST/file/{id}/expiryApenas o proprietárioPermanente: pago30/min

Altere a expiração de um arquivo.

Corpo da requisição

CampoTipoDescrição
daysinteger · optionalDe 1 a 7 dias a partir de agora, mas nunca mais de 7 dias após o envio (ou a expiração atual, se for posterior). Omita ou null para permanente (apenas premium).
POST/file/{id}/max-downloadsApenas o proprietário30/min

Limite o total de downloads de um arquivo. Apaga automaticamente quando atingir o limite.

Upload pelo ShareX

1 endpoint

Endpoint de envio em uma única etapa - envie um arquivo multipart e receba uma URL compartilhável de volta. Sem aquela dança de init/confirm. Ideal para ferramentas de captura de tela. Guia completo de configuração em /docs/sharex.

POST/sharex/upload20/day

Envie uma imagem ou arquivo diretamente (formulário multipart, campo file). Máx. 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"
}

Autenticação no desktop

2 endpoints

Para clientes com sessão iniciada, como a aplicação de ambiente de trabalho, que têm um token Bearer.

GET/userToken Bearer

Retorne o usuário autenticado.

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/logoutToken Bearer

Revogue o token de acesso atual.

Diversos

5 endpoints

Estado, quotas e telemetria de clientes.

Verificação de disponibilidade. Devolve 200 com { "status": "ok" } quando o worker da API está a responder.

Response
{ "status": "ok" }

Stream ao vivo de atividades para o globo da página inicial. Armazenado em cache na borda.

Uso atual da cota de upload do solicitante - usado pela CLI e pelo app de desktop para mostrar a capacidade restante. A estrutura da resposta muda para usuários autenticados. Apesar do nome da URL, isso rastreia apenas bytes de upload; downloads não são contabilizados.

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

Envie um evento de uso pela CLI ou pelo app de desktop.

Corpo da requisição

CampoTipoDescrição
appstring · requireddesktop, cli ou web.
versionstring · optionalVersão do cliente.
eventstring · requiredNome do evento, por exemplo upload_complete.
contextobject · optionalMetadados extras.
POST/app-errors60/min

Envie um relatório de erro pela CLI ou pelo app de desktop. Deduplicado no servidor - no máximo 10 do mesmo erro por hora.

Corpo da requisição

CampoTipoDescrição
appstring · requireddesktop, cli ou web.
typestring · requiredClasse/tipo do erro.
messagestring · requiredMensagem do erro.
stackstring · optionalRastreamento (stack trace).
version, os, os_version, arch, contextvarious · optionalMetadados de diagnóstico.