# Arquivos

Armazenamento de arquivos por conteúdo, com envio em partes para arquivos grandes.

URL base: `https://data.inovacc.dev`

## Visão geral

Arquivos armazena o conteúdo binário da sua aplicação (imagens, documentos, exportações, gravações) em `https://data.inovacc.dev`, com envios em partes para tudo o que for grande. Ele oferece duas formas de endereçar um arquivo:

- **por caminho, na pasta da sua aplicação**: `PUT /v1/files/users/123/avatar.png`, do jeito que um bucket de armazenamento na nuvem nomeia arquivos, com listagens por pasta, metadados do usuário e pastas compartilhadas com outras aplicações do seu espaço de trabalho;
- **por conteúdo, dentro de um banco de dados**: `PUT /v1/databases/{db}/blobs/{sha256}`, em que o próprio SHA-256 do arquivo é o seu nome, de modo que um registro de [Dados](/pt-br/products/data/) pode apontar para ele com um campo `blob`.

O problema que ele resolve é manter arquivos junto dos seus dados sem operar armazenamento: a Inovacc escolhe onde os bytes vivem, verifica-os contra o hash, remove duplicatas dentro da sua pasta e os devolve com cabeçalhos que impedem que um arquivo baixado seja executado em um navegador.

Use Arquivos para tudo o que for bytes em vez de campos. Mantenha a descrição estruturada de um arquivo (proprietário, título, status) como um registro em [Dados](/pt-br/products/data/). Para tornar um arquivo pesquisável por significado, adicione-o a uma coleção de [Conhecimento e busca vetorial](/pt-br/products/knowledge/).

## Conceitos

**A pasta da sua aplicação.** Cada aplicação tem a sua própria pasta. A pasta é escolhida a partir da credencial, nunca da requisição: uma credencial vinculada a uma aplicação usa a pasta dessa aplicação, e uma credencial não vinculada a nenhuma aplicação recebe `403 application_required` em toda rota de caminho. Os caminhos são UTF-8, de 1 a 1.024 bytes, separados por `/`, diferenciam maiúsculas de minúsculas, sem segmentos vazios, `.` ou `..`; um caminho que ainda não esteja nessa forma é recusado, nunca reescrito silenciosamente.

**Metadados.** Uma escrita pode levar um `Content-Type` e cabeçalhos `X-File-Meta-<name>` próprios (2 KiB no total). Ambos voltam em toda leitura. Uma escrita substitui por inteiro o conteúdo, o tipo e os metadados do arquivo.

**Hashes.** Todo arquivo é identificado pelo seu SHA-256. Envie `X-File-Sha256` com uma escrita e os bytes são conferidos contra ele (`400 hash_mismatch`, nada é armazenado). Dentro da pasta de uma aplicação, dois caminhos com os mesmos bytes compartilham uma única cópia armazenada; a cópia é mantida até que o último caminho seja removido. A deduplicação nunca atravessa aplicações ou organizações.

**Blobs de banco de dados.** Um blob é endereçado pelo SHA-256 em seu caminho dentro de um banco de dados. Enviá-lo de novo responde `200` em vez de `201`. Qualquer pessoa com permissão de leitura no banco de dados que conheça o hash pode lê-lo: as regras de registros não se aplicam a blobs.

**Pastas compartilhadas.** Uma aplicação pode criar uma pasta `team` que aparece para toda aplicação com acesso como `shared/team/...`. Quem a criou é o proprietário e concede a outras aplicações do mesmo espaço de trabalho `read` ou `read_write`. Uma aplicação sem acesso não consegue saber que a pasta existe: toda operação responde `404`.

**Arquivos grandes.** Até 100 MiB vão em uma única requisição. Acima disso, até 5 GiB, você envia em partes e depois vincula o resultado a um caminho (ou ele se torna o blob).

## Como funciona

Toda chamada leva `Authorization: Bearer <credential>`; não há cabeçalho de organização, porque a sua organização e a aplicação vêm da credencial. A permissão verificada é de leitura, escrita ou exclusão de blobs. Uma página web pode usar essas rotas com uma chave publicável a partir de uma origem que a sua aplicação lista.

**Escrita por caminho.** `PUT /v1/files/{path}` com os bytes e um `Content-Length` (obrigatório). A resposta é `201` para um caminho novo ou `200` para uma substituição: `{"path","size","sha256","content_type","updated_at","metadata"}` e `ETag: "<sha256>"`.

**Leitura.** `GET /v1/files/{path}` devolve o arquivo inteiro (intervalos não são suportados) com `Content-Type`, `ETag`, `X-File-Sha256`, `X-File-Updated-At` e os seus cabeçalhos `X-File-Meta-*`. Todo download também traz `X-Content-Type-Options: nosniff`, um `Content-Security-Policy` que o isola e `Cache-Control: no-store`, de modo que uma página HTML enviada nunca possa ser executada como se fosse o seu site. `HEAD` devolve apenas os cabeçalhos.

**Listagem.** `GET /v1/files?prefix=photos/&delimiter=/` lista os arquivos diretamente sob uma pasta como `items` e cada subpasta uma única vez em `prefixes`. Siga `next_cursor` até que seja `null`: uma página pode ser menor que `limit` e ainda assim ter uma próxima.

**Em partes.** `POST /v1/files-uploads/{sha256}` inicia um envio (ou responde `200` com `exists: true` quando a sua pasta já contém esses bytes). Envie as partes de 1 a 10.000 com `PUT .../{upload_id}/parts/{n}`, cada uma entre 5 MiB e 100 MiB, exceto a última, e depois `POST .../complete` com a lista de partes e seus `etag`s. A Inovacc lê o objeto inteiro de volta e confere o seu SHA-256 e o tamanho. Por fim, `PUT /v1/files/{path}` com `X-File-Sha256` e corpo vazio dá a ele um caminho. Os blobs de banco de dados usam as mesmas quatro etapas em `/v1/databases/{db}/blobs/{sha256}/uploads`.

Envios, downloads e exclusões são registrados no [Registro de atividade](/pt-br/products/activity/) com o hash e o tamanho do arquivo.

## Primeiros passos

Você precisa de uma chave secreta vinculada a uma aplicação, com permissões de blobs ([Autenticação](/pt-br/guides/authentication/)).

1. **Envie um arquivo.** `PUT /v1/files/reports/2026-10.csv` com o arquivo como corpo e `Content-Type: text/csv` (veja [os exemplos](#example)). A resposta é `201` com o seu `sha256`.
2. **Leia-o de volta.** `GET /v1/files/reports/2026-10.csv`. Os bytes chegam com `ETag` igual ao hash do passo 1.
3. **Liste a pasta.** `GET /v1/files?prefix=reports/&delimiter=/`. O seu arquivo está em `items`.
4. **Substitua-o.** Faça `PUT` no mesmo caminho com bytes novos. A resposta é `200`, com um novo `sha256`.
5. **Exclua-o.** `DELETE /v1/files/reports/2026-10.csv` responde `204`; um segundo `GET` resulta em `404 file_not_found`.

## Casos de uso

**Fotos de perfil a partir do navegador.** Um aplicativo web envia cada avatar para `users/<id>/avatar.png` com uma chave publicável e guarda o `sha256` devolvido no registro do usuário, para que uma página perceba quando a imagem mudou.

**Exportações compartilhadas com um aplicativo parceiro.** Uma aplicação de relatórios cria a pasta compartilhada `exports`, concede `read` à aplicação de faturamento e grava arquivos mensais em `shared/exports/`. A aplicação de faturamento os lista e baixa; revogar a concessão tem efeito já na requisição seguinte dela.

**Mídia grande com integridade.** Uma ferramenta de vídeo calcula o hash de uma gravação de 2 GiB no cliente, envia-a em partes de 100 MiB e a conclui. A Inovacc só a armazena se o SHA-256 coincidir, de modo que uma transferência corrompida nunca se torna um arquivo.

## Limites e preços

| Limite | Valor |
|---|---|
| Arquivo ou blob em uma requisição | 100 MiB, `Content-Length` obrigatório |
| Arquivo ou blob enviado em partes | 5 GiB; partes de 5 MiB a 100 MiB (exceto a última), numeradas de 1 a 10.000 |
| Caminho | 1.024 bytes |
| Prefixo de listagem | 256 bytes |
| Metadados por arquivo | 2 KiB |
| Página de listagem | 1 a 200 (padrão 50) |
| Nome da pasta compartilhada | 1 a 64 letras, dígitos, `_` ou `-` |
| Taxa | 600 requisições por minuto por titular de credencial, por localização |

**Preços:** sob consulta.

## Erros

| Status | Código | O que significa e o que fazer |
|---|---|---|
| 400 | `invalid_path`, `invalid_prefix` | O caminho ou prefixo não está na forma canônica; corrija do seu lado. |
| 400 | `invalid_metadata` | `Content-Type` ou `X-File-Meta-*` viola as regras ou excede 2 KiB. |
| 400 | `hash_mismatch` | Os bytes não correspondem ao SHA-256 que você enviou; nada foi armazenado. |
| 400 | `invalid_part`, `invalid_limit`, `invalid_cursor`, `invalid_grantee` | Corrija as partes do envio, a listagem ou a concessão. |
| 401 | `invalid_credentials` | Envie uma credencial válida. |
| 403 | `application_required` | As rotas de caminho exigem uma credencial vinculada a uma aplicação. |
| 403 | `forbidden` | Falta permissão, ou um beneficiário com `read` tentou escrever. |
| 404 | `file_not_found`, `blob_not_found`, `share_not_found`, `upload_not_found` | Não existe, ou você não tem acesso a ele. |
| 409 | `already_exists`, `not_empty` | O nome da pasta compartilhada já está em uso; esvazie a pasta antes de excluí-la. |
| 411 | `length_required` | Envie `Content-Length`. |
| 413 | `payload_too_large` | Mais de 100 MiB em uma requisição (use partes) ou mais de 5 GiB. |
| 429 | `rate_limited` | Diminua o ritmo. |
| 503 | `service_unavailable` | Tente novamente mais tarde. |

## Boas práticas

- **Envie `X-File-Sha256` em toda escrita** para que um envio danificado seja recusado em vez de armazenado.
- **Use partes acima de 100 MiB** e comece com `POST .../uploads`: ele responde `exists: true` quando os bytes já estão lá.
- **Guarde o `sha256`, não apenas o caminho**, nos seus registros; ele diz exatamente a que conteúdo um registro se refere.
- **Siga `next_cursor` até o fim** ao listar; páginas curtas são normais.
- **Conceda `read`, a menos que um parceiro precise escrever**, e revogue as concessões de que não precisa mais.
- **Não conte com blobs serem privados por regra**: qualquer pessoa que possa ler o banco de dados e conheça o hash pode ler um blob.

## Relacionados

- [Dados](/pt-br/products/data/): registros que apontam para arquivos com campos `blob`
- [Registro de atividade](/pt-br/products/activity/): envios e downloads com seus hashes
- [Conhecimento e busca vetorial](/pt-br/products/knowledge/): torne documentos pesquisáveis
- [Autenticação](/pt-br/guides/authentication/), [Erros](/pt-br/guides/errors/), [Limites](/pt-br/guides/limits/)

## Endpoints

- PUT /v1/databases/{database}/blobs/{sha256}
- GET /v1/databases/{database}/blobs/{sha256}
- DELETE /v1/databases/{database}/blobs/{sha256}
- POST /v1/databases/{database}/blobs/{sha256}/uploads

## Exemplo

```sh
curl -X PUT "https://data.inovacc.dev/v1/databases/{database}/blobs/{sha256}" -H "Authorization: Bearer $INOVACC_API_KEY" -H "Content-Type: application/json" -d '{}'
```
