Files API
Visão geral
A Files API hospeda arquivos no qr3 e fornece uma URL estável para eles. O código QR aponta para essa URL — você pode substituir o arquivo por trás dela a qualquer momento, sem precisar reimprimir o código.
URL base: https://qr3.app/v1/files
Opcionalmente, você pode vincular um arquivo a um código usando code_id. Essa é a base para a landing page por código, que lista todos os arquivos públicos de um código.
Os tipos suportados são verificados por magic byte, não pela extensão do arquivo: PDF, PNG, JPEG, WebP, MP4, glTF/GLB, JSON. Um arquivo .pdf que não seja um PDF real será rejeitado.
Funções
| Operação | Necessário | Recebe 403 |
|---|---|---|
Todos os GET | Qualquer função | — |
POST /upload, PUT /:id | Função de escrita | viewer |
DELETE /:id | Função de exclusão | viewer, contributor |
A regra especial é para o contributor: esta função pode criar e modificar, mas não pode remover nada.
Fazer upload de arquivo
POST /v1/files/upload
Espera multipart/form-data.
| Campo | Obrigatório | Descrição |
|---|---|---|
file | Sim | O arquivo |
code_id | Não | Vincular a um código (deve pertencer ao workspace) |
visibility | Não | private (padrão) ou public |
curl -X POST https://qr3.app/v1/files/upload \ -H "Authorization: Bearer qr3_sk_..." \ -F "code_id=qr_a1b2c3d4" \ -F "visibility=public"const form = new FormData();form.append('file', fileInput.files[0]);form.append('code_id', 'qr_a1b2c3d4');form.append('visibility', 'public');
const res = await fetch('https://qr3.app/v1/files/upload', { method: 'POST', headers: { Authorization: 'Bearer qr3_sk_...' }, body: form, // Content-Type NICHT selbst setzen — der Boundary fehlt sonst});Resposta (HTTP 201):
{ "data": { "id": "file_a1b2c3d4", "code_id": "qr_a1b2c3d4", "filename": "datenblatt.pdf", "mime_type": "application/pdf", "size_bytes": 284913, "hash_sha256": "9f86d081884c7d65…", "visibility": "public", "status": "active", "created_at": "2026-03-14T12:00:00.000Z", "download_url": "https://qr3.app/v1/files/file_a1b2c3d4/download", "public_url": "https://qr3.app/f/file_a1b2c3d4" }, "meta": { "request_id": "req_abc123" }}public_url é definida apenas quando visibility: "public" e status: "active". O endereço não requer autenticação e é adequado diretamente como URL de destino de um código QR.
Listar arquivos
GET /v1/files
Query: code_id e visibility, ambos opcionais. Retorna os arquivos ativos do workspace, os mais recentes primeiro.
curl "https://qr3.app/v1/files?code_id=qr_a1b2c3d4" \ -H "Authorization: Bearer qr3_sk_..."Resposta (HTTP 200):
{ "data": [ { "id": "file_a1b2c3d4", "…": "…" } ], "meta": { "request_id": "req_abc123", "file_count": 3, "total_size_bytes": 812004 }}Obter informações do arquivo
GET /v1/files/:id
Retorna os metadados, incluindo download_url (e public_url para arquivos públicos). Legível por todas as funções.
Baixar arquivo
GET /v1/files/:id/download
Transmite o conteúdo como Content-Disposition: attachment com Cache-Control: private, no-store — portanto, a resposta é sempre o estado mais recente, ao contrário da URL pública /f/:id armazenada em cache.
O erro 404 ocorre de duas formas: o arquivo não existe no workspace (ou foi excluído) ou ele existe, mas o objeto armazenado está ausente.
Substituir arquivo
PUT /v1/files/:id
Substitui o conteúdo e mantém o id — e, consequentemente, o endereço público /f/:id e a download_url. Um código QR já impresso permanece válido.
curl -X PUT https://qr3.app/v1/files/file_a1b2c3d4 \ -H "Authorization: Bearer qr3_sk_..." \visibility, code_id e created_at são mantidos; filename, mime_type, size_bytes e hash_sha256 são atualizados. O limite do plano por arquivo se aplica da mesma forma que no upload, e o limite de armazenamento do workspace é verificado em relação à diferença. O limite de “arquivos por código” não se aplica, pois nenhum arquivo novo é adicionado.
Excluir arquivo
DELETE /v1/files/:id
Exclusão lógica (soft-delete): o arquivo desaparece imediatamente da lista, não pode mais ser acessado e — se for público — deixa de ser servido em /f/:id.
Resposta (HTTP 200):
{ "data": { "id": "file_a1b2c3d4", "deleted": true }, "meta": { "request_id": "req_abc123" }}Limites
| Plano | Máx. por arquivo |
|---|---|
| Free | 5 MB |
| Pro | 25 MB |
| Business | 100 MB |
| Agency | 100 MB |
| Enterprise | 250 MB |
Adicionalmente, aplicam-se por plano um número máximo de arquivos por código e um limite de armazenamento total por workspace. O limite de taxa de upload é de 100 uploads por hora por workspace.
Erros
| Status | Quando |
|---|---|
| 400 | Assinatura de arquivo desconhecida ou incompatível, corpo multipart inválido |
| 401 | API Key ausente ou inválida |
| 403 | A função não tem permissão para gravar ou excluir |
| 404 | code_id ou arquivo não encontrado no workspace; no download também: objeto ausente no armazenamento |
| 413 | Arquivo maior que o limite do plano |
| 422 | Arquivo ausente, visibility inválida, limite de “arquivos por código” atingido, limite de armazenamento do workspace excedido |
| 429 | Limite de taxa de upload (100/hora/workspace) ou limite de taxa geral |
Relacionado
- Arquivos e Fichas Técnicas — o caminho pelo painel
- Landing page por código