# Renderize e baixe o vídeo

> Aplique um template, gere o MP4 final, acompanhe o render e baixe um arquivo ou centenas num zip.

O clipe que a IA corta é cru. O render transforma o clipe num MP4 vertical com template, legendas e efeitos, pronto para postar.

```text
apply_template (opcional)  →  POST .../render  →  GET /renders/{id}  →  GET /renders/{id}/download
      edição                   202 queued          até completed           URL de 1 hora
```

## Aplique um template

Templates são edições salvas na Cut.Pro: enquadramento, estilo de legenda, efeitos. Liste os seus:

```bash
curl "https://api.cut.pro/api/v1/templates?filter=mine" \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

Cada item traz `id`, `name`, `aspect_ratio` e `auto_add_captions`. `filter=public` lista os da Cut.Pro.

Para editar os clipes de uma submissão de uma vez:

```bash
curl -X POST https://api.cut.pro/api/v1/clips/7412908365112823/submissions/7412908371004912/apply_template \
  -H "X-Api-Key: $CUTPRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "template_id": "7398110254410021", "clip_ids": ["7412908412887301"] }'
```

```json title="202 Accepted"
{ "clips_count": 1 }
```

Sem `clip_ids`, vale para todos os clipes. Roda em segundo plano: cada clipe ganha `edit_id` em `GET .../clips` quando termina. Um lote por conta de cada vez; outro responde `429 BATCH_ALREADY_RUNNING`.

Mais simples: mande `template_id` já em `POST /clips` e todo clipe sai editado.

## Renderize um clipe

```bash
curl -X POST https://api.cut.pro/api/v1/clips/7412908365112823/submissions/7412908371004912/clips/7412908412887301/render \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

```json title="202 Accepted"
{
  "id": "7412910087712256",
  "edit_id": "7412910087700001",
  "status": "queued",
  "has_watermark": false,
  "output_resolution": "1080p",
  "from_cache": false,
  "download_url": null
}
```

Com template aplicado, o render usa a edição. Sem template, usa o layout padrão. Guarde o `edit_id`: é ele que publica o vídeo e que gera um arquivo novo depois.

Se um render idêntico já está pronto, a resposta é `200` com `from_cache: true` e `download_url` preenchido. Não há fila nem custo de espera. Pedir o mesmo clipe enquanto ele renderiza responde `409 RENDER_ALREADY_IN_PROGRESS`.

Clipe de live tem rota própria: [`POST /monitors/{id}/broadcasts/{broadcastId}/clips/{clipId}/render`](/monitoring#pegue-os-clipes-de-uma-live).

## Acompanhe o render

```bash
curl https://api.cut.pro/api/v1/renders/7412910087712256 \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

Consulte a cada 5 a 10 segundos. `progress` vai de 0 a 100, bom para barra de progresso.

| `status` | Significa |
|---|---|
| `waiting_quality` | Esperando a fonte ficar disponível na melhor qualidade. Segue sozinho, sem nova chamada. |
| `queued` | Na fila. O plano define quantos renders rodam ao mesmo tempo. |
| `active` | Renderizando. |
| `completed` | Pronto para baixar. |
| `failed` | Falhou. Peça de novo com `POST /renders`. |
| `cancelled` | Cancelado com `DELETE`. |
| `expired` | O arquivo saiu do storage. A edição continua: renderize de novo. |

## Baixe o MP4

```bash
curl https://api.cut.pro/api/v1/renders/7412910087712256/download \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

```json title="200 OK"
{ "url": "https://...", "filename": "O refrão que todo mundo sabe.mp4" }
```

> A URL vale 1 hora. Peça uma nova a cada download em vez de guardar. O arquivo fica no storage pelo tempo de `render_expiry_hours` do plano; depois, a rota responde `410 RENDER_FILE_EXPIRED`.

## Renderize de novo

A edição nunca expira. Para ter o MP4 de um clipe de meses atrás, renderize o `edit_id`:

```bash
curl -X POST https://api.cut.pro/api/v1/renders \
  -H "X-Api-Key: $CUTPRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "edit_id": "7412910087700001" }'
```

Vale o `edit_id` de um render, de um clipe ou de um item de post. A resposta tem o mesmo formato de renderizar um clipe.

## Baixe vários num zip

**curl**

```bash
curl -X POST https://api.cut.pro/api/v1/renders/bulk-download \
  -H "X-Api-Key: $CUTPRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "render_ids": ["7412910087712256", "7412910087712257"] }'

curl https://api.cut.pro/api/v1/renders/bulk-download/$JOB_ID \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

**Node.js**

```js
const headers = { "X-Api-Key": process.env.CUTPRO_API_KEY, "Content-Type": "application/json" };
const API = "https://api.cut.pro/api/v1";

const { id } = await fetch(`${API}/renders/bulk-download`, {
	method: "POST",
	headers,
	body: JSON.stringify({ render_ids: renderIds }),
}).then((response) => response.json());

let job;
do {
	await new Promise((resolve) => setTimeout(resolve, 5000));
	job = await fetch(`${API}/renders/bulk-download/${id}`, { headers }).then((response) => response.json());
} while (job.status === "queued" || job.status === "active");

if (job.status === "failed") throw new Error(job.error_code);
console.log(job.download_url);
```

- Até 500 renders por zip. Mais que isso responde `400 TOO_MANY_RENDERS`.
- Ids de outro workspace são ignorados. Se nenhum sobra, `404 NO_VALID_RENDERS`.
- `download_url` aparece em `completed` e vale 1 hora. O zip some em `expires_at`; depois disso, `410 JOB_EXPIRED`.

## Liste e apague

| Rota | O que faz |
|---|---|
| `GET /renders` | Lista os renders, do mais novo ao mais antigo. Filtre com `status`: `processing`, `completed`, `failed` ou `expired`. |
| `DELETE /renders/{renderId}` | Cancela um render na fila ou rodando. Num render terminado, apaga o registro e o arquivo. |
| `GET /renders/limits` | Renders rodando e na fila, resolução, marca d'água e retenção do plano. Ver [Limites](/rate-limits#renders). |

## Erros

| Code | Quando |
|---|---|
| `CLIP_RESULT_NOT_FOUND` | O clipe não existe nesta submissão. |
| `EDIT_NOT_FOUND` | O `edit_id` não é deste workspace. |
| `RENDER_ALREADY_IN_PROGRESS` | O mesmo clipe ou edição já está renderizando. Acompanhe o render existente. |
| `RENDER_FILE_EXPIRED` | O MP4 saiu do storage. Renderize o `edit_id` de novo. |
| `RENDER_FAILED`, `RENDER_SETUP_FAILED` | Falha nossa ao enfileirar. Tente de novo. |
