UploadCenter

Introdução

De uma conta vazia até o seu primeiro arquivo enviado, em cinco etapas.

Instale o SDK
SDKs oficiais e totalmente tipados para TypeScript/JavaScript (Node.js e navegador) e Python. Cada etapa abaixo também mostra a solicitação cURL equivalente, caso você prefira chamar a API diretamente.
bash
npm install @uploadcenter/sdk-js
typescript
import { createClient } from "@uploadcenter/sdk-js";

const client = createClient({
  baseUrl: "https://api.uploadscenter.com",
  token: process.env.UPLOADCENTER_API_KEY, // an API key from your project settings
});

Todos os métodos são gerados a partir do esquema OpenAPI do UploadCenter; portanto, o preenchimento automático abrange toda a superfície da API — visualizar o pacote JS no npm ou o pacote Python no PyPI.

1
Criar uma conta
Um espaço de trabalho (organização) é criado automaticamente para você no momento da inscrição.
2
Crie um projeto e uma chave de API
No seu painel: crie um projeto e, em seguida, gere uma chave de API com escopo específico para ele — a chave completa é exibida apenas uma vez, portanto, copie-a imediatamente.
3
Assinar previamente um upload
Solicite à API uma URL pré-assinada — os arquivos nunca passam pelo seu próprio backend.
bash
curl -X POST https://api.uploadscenter.com/v1/uploads/presign \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "project_id": "project_...",
    "filename": "photo.jpg",
    "size_bytes": 128000,
    "mime_type": "image/jpeg",
    "visibility": "private"
  }'
4
Faça o upload do arquivo
COLOQUE o arquivo diretamente no `upload_url` retornado — é isso que torna os uploads rápidos, independentemente do tamanho.
bash
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg
5
Confirme o envio
É isso que aciona a verificação e o processamento pelo antivírus — o arquivo só é marcado como pronto depois de passar por essa verificação.
bash
curl -X POST https://api.uploadscenter.com/v1/uploads/complete \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"file_id": "file_..."}'

Lendo um arquivo novamente — GET /v1/files/{file_id}/url — sempre exige uma chave de API ou sessão válida para arquivos privados. Os arquivos públicos funcionam de maneira diferente — veja abaixo.

URLs públicas
Faça o upload com visibilidade: “pública” e, assim que o arquivo estiver pronto, o campo de URL dele será um link permanente e sem necessidade de autenticação — seguro para ser incorporado diretamente, armazenado em cache na borda da rede e que nunca expira.
json
GET /v1/files/{file_id}

{
  "id": "file_...",
  "visibility": "public",
  "status": "ready",
  "url": "https://cdn.uploadscenter.com/o/…/photo.jpg"
}

Arquivos privados (por padrão) não possuem um campo de URL — em vez disso, chame GET /v1/files/{id}/url, o que retorna um novo link assinado, válido por um período limitado.

Reagir a eventos
Adicione um webhook nas configurações do seu projeto para receber notificações sobre eventos de envio, processamento e cota. Cada entrega é assinada — verifique a assinatura antes de confiar no conteúdo.
http
POST <your webhook URL>
Content-Type: application/json
X-Signature: sha256=<hex-encoded HMAC-SHA256>
X-Timestamp: <unix timestamp, seconds>

{"event":"file.processed","created_at":"2026-01-01T12:00:00Z","data":{"id":"file_...","project_id":"project_...","status":"ready", ...}}

Eventos: file.uploaded, file.processed, file.failed, file.quarantined, file.flagged, storage.limit_reached. São permitidas até 3 tentativas de entrega (com intervalos de 30 s, 2 min e 10 min) antes que a entrega seja considerada falha.

typescript
import crypto from "node:crypto";

// Sign over "${timestamp}.${rawBody}" — rawBody must be the exact bytes
// received, not a re-serialized JSON.stringify(JSON.parse(rawBody)).
function verifyWebhook(rawBody: string, timestamp: string, signatureHeader: string, secret: string): boolean {
  const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
  const provided = signatureHeader.replace(/^sha256=/, "");
  return crypto.timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(provided, "hex"));
}

// signatureHeader = req.headers["x-signature"]
// timestamp       = req.headers["x-timestamp"]
Transforme imagens em tempo real
Redimensione, recorte e converta o formato com parâmetros de consulta — o resultado é armazenado em cache após a primeira solicitação, não sendo recalculado a cada acesso.
http
GET /v1/files/{file_id}/transform?w=480&h=320&format=auto&fit=cover

# fit: "cover" (crop to fill) or "inside" (contain)
# format: auto (default) | webp | jpeg | png
# quality: auto (default) | 1-100
#
# format=auto picks WebP or JPEG based on the request's Accept header —
# no more branching client-side for older browsers. quality=auto applies
# a sensible per-format default (80 for WebP, 82 for JPEG). Pass explicit
# values any time you want full control instead.
Coloque uma marca d’água nas suas imagens
Sobreponha o logotipo do seu projeto em qualquer transformação — a posição, a opacidade e o tamanho são totalmente configuráveis, e o resultado é armazenado em cache como qualquer outra transformação.
http
PUT /v1/projects/{project_id}/watermark
{"file_id": "file_..."}   # any image already uploaded to the project

GET /v1/files/{file_id}/transform?w=1200&watermark=true&gravity=south_east&opacity=60&overlay_scale=0.2

# gravity: north_west | north_east | south_west | south_east | center
# opacity: 1-100 (default 60)
# overlay_scale: 0.05-1.0 (default 0.2, fraction of the output image's width)
Domínios personalizados
Hospede arquivos públicos a partir do seu próprio domínio, em vez de usar a CDN compartilhada, assim que a propriedade for verificada por meio do DNS.
http
POST /v1/domains
{"project_id": "project_...", "hostname": "cdn.yourapp.com"}

# Add the returned TXT record at your DNS provider, then:
POST /v1/domains/{domain_id}/verify

# Once verified, point cdn.yourapp.com at UploadCenter (A/CNAME — shown in
# the dashboard) and a TLS certificate is issued automatically. From then
# on, every public file's url uses your domain instead of the shared CDN.
Moderação de conteúdo
As imagens enviadas passam por uma triagem automática para detectar conteúdo explícito — trata-se apenas de detecção; nada é bloqueado ou excluído em seu nome.
json
GET /v1/files/{file_id}

{
  "id": "file_...",
  "status": "ready",
  "moderation_status": "flagged",  // null (not evaluated) | "clean" | "flagged" | "error"
  "moderation_score": 0.87
}

Um arquivo marcado permanece exatamente como foi enviado — seu aplicativo decide o que “marcado” significa para o seu produto. Disponível nos planos pagos; consulte a página de recursos.

Miniaturas de vídeo e arquivos derivados
Cada vídeo enviado recebe automaticamente uma miniatura em JPEG; os vídeos menores também passam por uma transcodificação para MP4 em 720p. A URL de cada variante já está pronta para uso imediato — sem necessidade de autenticação adicional.
json
GET /v1/files/{file_id}/variants

[
  { "variant": "thumbnail", "format": "jpg", "width": 640, "height": 360, "url": "https://…" },
  { "variant": "720p", "format": "mp4", "width": 1280, "height": 720, "url": "https://…" }
]
Geração de imagens e vídeos por IA
Gere, edite, remova planos de fundo, aumente a resolução ou crie variações de uma imagem; gere um vídeo a partir de texto ou de uma imagem existente. Todas as chamadas são assíncronas — 202 com um ID de geração; em seguida, verifique o status ou aguarde o webhook ai.generation.completed / ai.generation.failed.
typescript
const generation = await client.ai.generateImageEndpointV1AiImagesGeneratePost({
  project_id: projectId,
  prompt: "a minimalist logo of a fox, flat vector style",
  use_brand_kit: true, // pulls in this org's brand kit colors/fonts
});

// 202 Accepted — poll until it settles (or listen for the webhook below).
const result = await client.ai.getGenerationEndpointV1AiGenerationsGenerationIdGet(
  generation.id,
  projectId,
);
// result.file_ids — the new file(s), same shape as anything you upload

O resultado é um arquivo comum — chamado “file_ids” após a geração — com sua própria visibilidade, entrega e ciclo de vida, exatamente como qualquer arquivo que você envie diretamente.

Confiabilidade, sinceramente
O UploadCenter é uma plataforma jovem e em desenvolvimento ativo — não temos um histórico de anos de disponibilidade para apresentar e não vamos inventar um número. O que está em vigor hoje: todos os arquivos passam por uma verificação antivírus antes mesmo de serem disponibilizados, os uploads são processados de forma atômica (nada fica pela metade se uma etapa falhar) e a entrega ocorre pela rede da Cloudflare. Ainda não há um SLA formal — se o seu caso de uso precisar de garantias contratuais, entre em contato conosco e conversaremos sobre o que é viável.

Quer ter uma visão completa?

Confira todos os recursos — controle de versões, domínios personalizados, funções da equipe e muito mais — na página de recursos.