# Envio de arquivos

> Envie imagens, vídeo e áudio ao Nodaro com POST /v1/upload, copie de URLs, importe vídeos de redes sociais, corte mídia salva grátis e liste a biblioteca.

Source: https://nodaro.ai/pt-BR/docs/developers/api/uploads

O **envio de arquivos** coloca as suas próprias imagens, vídeos e áudios no armazenamento do Nodaro, para que qualquer nó possa usá-los pela URL. `POST /v1/upload` armazena um arquivo e retorna a URL dele. Outras rotas copiam um arquivo de uma URL, importam um vídeo de uma rede social, cortam um arquivo armazenado de graça ou listam a mídia que você armazenou.

## Endpoints
| Método | Caminho | O que faz |
| --- | --- | --- |
| `POST` | `/v1/upload` | Envia um arquivo, como multipart form data. |
| `POST` | `/v1/save-to-storage` | Copia um arquivo de uma URL para o seu armazenamento, como um job. |
| `POST` | `/v1/download-video` | Importa um vídeo de uma rede social ou de um link direto de vídeo. |
| `GET` | `/v1/download-video/progress/:downloadId` | O progresso da importação, como server-sent events. |
| `POST` | `/v1/video-metadata` | Lê a duração, o tamanho e o título de um vídeo sem baixá-lo. |
| `POST` | `/v1/media/process` | Corta ou recorta um arquivo de vídeo ou de áudio armazenado. Grátis e síncrono. |
| `GET` | `/v1/library` | A sua mídia armazenada, com um resumo do armazenamento. |

## Enviar um arquivo
Envie o arquivo como multipart form data, no campo `file`. Você também pode enviar `type`, com o valor `image`, `video` ou `audio`.

**curl**

```bash
curl -s -X POST https://app.nodaro.ai/v1/upload \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -F "file=@portrait.png;type=image/png" \
  -F "type=image"
```

```json
{
"data": {
"url": "https://…/portrait.png",
"assetId": "5d6e7f80-91a2-4b3c-8d4e-5f60718293a4",
"thumbnailUrl": "https://…/portrait-thumb.webp",
"category": "image",
"filename": "portrait.png",
"mimeType": "image/png",
"sizeBytes": 1482233,
"r2Key": "…/portrait.png"
}
}
```

**TypeScript SDK**

```ts
// In a browser, file comes from an <input type="file">.
// In Node 20 or newer, build it from bytes:

const file = new File([await readFile('portrait.png')], 'portrait.png', { type: 'image/png' })
const upload = await client.uploads.upload(file)
console.log(upload.url) // pass it as imageUrl, videoUrl or audioUrl
```

| Campo | Significado |
| --- | --- |
| `url` | A URL pública do arquivo armazenado. Use-a em qualquer nó. |
| `assetId` | O ID do arquivo no seu armazenamento. |
| `thumbnailUrl` | Uma miniatura para imagens e vídeo, ou `null` para áudio. |
| `category` | `image`, `video` ou `audio`, conforme o servidor classificou o arquivo. |
| `filename` | O nome de exibição do arquivo. |
| `mimeType` | O tipo de arquivo que o servidor definiu. Veja abaixo. |
| `sizeBytes` | O tamanho armazenado, em bytes. |
| `r2Key` | A chave do arquivo no armazenamento. |

A CLI não tem comando de upload. Para copiar pelo terminal um arquivo que já está on-line para o seu armazenamento, use `nodaro media save <url>`.

### Formatos e tipos de arquivo
| Mídia | Formatos |
| --- | --- |
| Imagem | PNG, JPEG, WebP |
| Vídeo | MP4, MOV, WebM |
| Áudio | MP3, WAV, M4A e AAC, OGG, WebM, FLAC. Até 50 MB. |

Cada tipo de mídia tem um limite de tamanho próprio. O tipo que o seu cliente declara não precisa ser o padrão, porque o servidor descobre o tipo real antes de verificar o arquivo:

- **Os parâmetros são removidos.** `audio/webm;codecs=opus` vira `audio/webm`.
- **As grafias alternativas comuns são convertidas.** `audio/vnd.dlna.adts`, que o Windows usa para um arquivo `.aac` comum, vira `audio/aac`, `image/jpg` vira `image/jpeg`, e `video/mov` vira `video/quicktime`.
- **Um tipo pouco informativo é deduzido do nome do arquivo.** Com `application/octet-stream`, ou sem tipo nenhum, a extensão decide: `clip.mp4` é armazenado como `video/mp4`.

Um tipo que ainda assim não corresponde a nenhum formato aceito retorna `400 validation_error`, com a lista de formatos aceitos. O tipo que o servidor definiu volta como `mimeType`, e o arquivo é servido com ele.

### Quando um envio é recusado
| Status | Código | Significado |
| --- | --- | --- |
| 400 | `validation_error` | O arquivo não está em um formato aceito. |
| 413 | | O seu armazenamento está cheio. O SDK lança `StorageExceededError`, com o seu limite em `limitBytes`. |
| 422 | `upload_blocked` | A política de envio da implantação recusou o arquivo antes de armazená-lo. Mostre a `message` ao seu usuário como ela é. Só em implantações com essa política. |

## Usar uma URL no lugar
A maioria das rotas recebe mídia por URL, como `imageUrl`, `videoUrl`, `audioUrl` e `referenceImageUrls`, então um arquivo que já está on-line não precisa ser enviado. A URL precisa ser um endereço público `http` ou `https`: uma URL que aponta para um endereço de rede privada, ou que usa outro esquema, é recusada.

Copie o arquivo para o armazenamento do Nodaro quando a URL for temporária, como um link assinado que expira, ou quando você quiser que o arquivo continue disponível:

**curl**

```bash
curl -s -X POST https://app.nodaro.ai/v1/save-to-storage \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"mediaUrl": "https://example.com/clip.mp4", "filename": "clip.mp4", "mediaType": "video"}'
# {"jobId":"…"}  poll the job; its output carries the stored file
```

**TypeScript SDK**

```ts
const { jobId } = await client.media.saveToStorage({
mediaUrl: 'https://example.com/clip.mp4',
filename: 'clip.mp4',
mediaType: 'video',
})
```

**CLI**

```bash
nodaro media save https://example.com/clip.mp4 --filename clip.mp4 --type video --watch
```

Em um workflow, passe a URL de um arquivo enviado para um nó [**Enviar imagem** (Upload Image)](https://nodaro.ai/docs/nodes/image/upload-image), [**Enviar vídeo** (Upload Video)](https://nodaro.ai/docs/nodes/video/upload-video) ou [**Enviar áudio** (Upload Audio)](https://nodaro.ai/docs/nodes/audio/upload-audio) pelas entradas da execução. Os campos `url` de mídia dos nós de entrada sempre podem ser substituídos por uma execução. Veja [Executar um workflow com novos valores de entrada](https://nodaro.ai/docs/developers/api/workflows#run-a-workflow-with-new-input-values).

## Importar um vídeo de uma rede social
`POST /v1/download-video` importa para o seu armazenamento um vídeo do YouTube, TikTok, Instagram, X ou Facebook, ou de um link direto para um arquivo de vídeo. A rota responde com um `downloadId`, não com um ID de job:

```json
{ "url": "https://youtu.be/XXXX", "maxHeight": 720, "sectionStartSec": 30, "sectionEndSec": 90 }
```

- `maxHeight` limita a resolução; omita o campo para obter a melhor disponível. `sectionStartSec` e `sectionEndSec` baixam só esse trecho do vídeo, com cerca de 3 segundos a mais em cada ponta, porque o corte cai nos quadros-chave. Envie os dois ou nenhum, e corte o resultado quando precisar de um corte exato.
- Um vídeo sem faixa de som falha, a menos que você envie `requireAudio: false`.
- Cada conta pode fazer 4 importações ao mesmo tempo. Uma quinta retorna `429 too_many_downloads`.
- `GET /v1/download-video/progress/:downloadId` transmite o progresso como server-sent events, cerca de duas vezes por segundo: `{ phase, percent, videoUrl?, thumbnailUrl?, error? }`. A transmissão termina quando a importação fica `completed`, com o `videoUrl` armazenado, ou `failed`, com um `error`. O progresso só fica guardado por pouco tempo depois que a importação termina, então comece a lê-lo logo.
- O vídeo pronto é salvo na sua biblioteca.

Para verificar um vídeo antes de importá-lo, `POST /v1/video-metadata` com `{ url }` lê a duração, o tamanho e o título dele sem baixá-lo. No terminal: `nodaro media download <url> --max-height 720 --watch` e `nodaro media metadata <url>`. As outras ferramentas de mídia estão em [Voz e mídia](https://nodaro.ai/docs/developers/api/voice-and-media).

## Cortar ou recortar um arquivo armazenado
`POST /v1/media/process` corta ou recorta um arquivo de vídeo ou de áudio armazenado. A rota é gratuita e responde na hora, sem job:

```json
{
"sourceUrl": "https://…/interview.mp4",
"type": "video",
"trim": { "startTime": 12.5, "endTime": 48 },
"crop": { "x": 0, "y": 0, "width": 1080, "height": 1080 }
}
```

A resposta é `{ "data": { url, thumbnailUrl, assetId, sizeBytes, mimeType, metadata } }`. `format` define o formato de saída: `mp4` ou `webm` para vídeo, `mp3`, `wav`, `m4a` ou `aac` para áudio. Com `deleteSource: true`, o arquivo de origem é removido depois, quando ele é seu e nada mais o usa, e assim o corte substitui o original. No SDK, chame `client.media.process(input)`. Para cortar dentro de um workflow, use o nó [**Cortar vídeo** (Trim Video)](https://nodaro.ai/docs/nodes/video/trim-video), que custa créditos.

## Listar a sua mídia armazenada
`GET /v1/library` retorna as suas imagens, vídeos e áudios armazenados, com um resumo do seu armazenamento. Filtre com `type` (`image`, `video` ou `audio`) e pagine com `limit` e `cursor`. No SDK, chame `client.library.list({ type: 'image' })`.

## Enviar arquivos a partir de um assistente de IA
O [servidor MCP](https://nodaro.ai/docs/mcp/tools) oferece três jeitos de enviar arquivos, cada um para imagens, áudio e vídeo. Todos exigem o escopo `assets:write`.

| Jeito | Ferramentas | Funciona em |
| --- | --- | --- |
| Seletor de arquivos no chat | `upload_image_widget`, `upload_audio_widget`, `upload_video_widget` | Claude.ai na web. O seletor de imagens aceita até 10 arquivos. |
| Página de envio no navegador | `request_image_upload`, `request_audio_upload`, `request_video_upload` | Todos os clientes MCP. A ferramenta retorna uma página para abrir em um navegador e a URL pública final do arquivo. |
| URL de upload pré-assinada | `prepare_image_upload`, `prepare_audio_upload`, `prepare_video_upload` | Clientes que conseguem executar comandos de shell, como Claude Code, Cursor ou Cline. Envie o arquivo com `curl -X PUT --data-binary @file`. Não funciona no Claude.ai web nem no Android. |

## Frequently asked questions

### Como envio um arquivo para o Nodaro pela API?

Envie POST /v1/upload como multipart form data, com o arquivo no campo file. A resposta traz a url do arquivo armazenado, que você pode passar para qualquer nó como imageUrl, videoUrl ou audioUrl.

### Quais formatos de arquivo posso enviar?

Imagens em PNG, JPEG ou WebP, vídeo em MP4, MOV ou WebM e áudio em MP3, WAV, M4A ou AAC, OGG, WebM ou FLAC. Os arquivos de áudio podem ter até 50 MB.

### Preciso enviar um arquivo antes que um nó possa usá-lo?

Não. A maioria das rotas aceita diretamente uma URL pública http ou https. Envie o arquivo, ou copie-o com POST /v1/save-to-storage, quando a URL for privada ou temporária, ou quando você quiser que o Nodaro guarde uma cópia própria.

### O que acontece quando o meu armazenamento está cheio?

O envio retorna 413, e o SDK lança StorageExceededError com o seu limite em limitBytes. Exclua os arquivos de que você não precisa mais, ou libere espaço, e envie de novo.

### Como os assistentes de IA enviam arquivos pelo MCP?

O servidor MCP oferece três jeitos: um seletor de arquivos no chat, uma página de envio no navegador e uma URL de upload pré-assinada para clientes que conseguem executar comandos de shell. Cada um existe para imagens, áudio e vídeo.
