Cheaper Veo

API v1

Documentação da API Cheaper Veo

Gere vídeos com Veo 3.1 via HTTP. Pay as you go, sem mensalidade, créditos pré-pagos. Esta referência cobre autenticação, geração, polling de status, modelos disponíveis e tratamento de erros.

Integração via LLM

Cole no Claude / ChatGPT / Cursor e integre em segundos

Copie o prompt abaixo, cole no seu LLM de código e ele vai scaffoldar o cliente, escrever a integração e wire up no seu stack — Node ou Python — automaticamente.

prompt para LLM
Integrate Cheaper Veo into this project. The full API spec, types, error handling, and drop-in clients (Node.js + Python) are at:

https://cheapervideo.com/llms.txt

Fetch that file, follow the integration agent instructions, and wire up at least one working example using my existing stack. Add CHEAPER_VEO_API_KEY to .env. After you're done, tell me where to get an API key.
Ver llms.txt completoConvenção llmstxt.org — funciona com qualquer LLM moderno.

Introdução

A API Cheaper Veo é uma camada HTTP fina sobre o Google Veo 3.1. Você envia um prompt (e opcionalmente imagens de referência), recebe um taskId imediato e faz polling até o vídeo ficar pronto. Em três passos:

  1. Autenticar: envie sua chave no header Authorization: Bearer veo_live_….
  2. Gerar: POST /api/v1/generate com o body do tipo desejado (text-to-video, image-to-video ou references). A resposta contém o taskId e o custo em créditos já debitado.
  3. Aguardar: GET /api/v1/status/{taskId} a cada 5–10 segundos até o status virar succeeded. O campo videoUrl aponta para o MP4 final.

Base URL

Produção: https://api.geraew.com
Desenvolvimento: http://localhost:3000

Quickstart

Do zero ao primeiro vídeo em 3 passos. Total: ~2 minutos.

  1. 1

    Crie uma API key

    Acesse Painel → API Keys e clique em Gerar nova chave. A chave (formato veo_live_…) é exibida apenas uma vez — copie pra um cofre de segredos.

  2. 2

    Teste o saldo

    Confirma que a chave tá funcionando antes de gerar nada (não consome crédito):

    bash
    curl https://api.geraew.com/api/v1/account \
      -H "Authorization: Bearer veo_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"

    Resposta deve mostrar seu email e balance em créditos. Se receber 401, a chave está errada ou foi revogada.

  3. 3

    Gere e aguarde

    Vídeo barato pra testar (Lite 720p sem áudio, 4s = 5 créditos = US$0,05):

    bash
    # Inicia geração — retorna taskId imediato
    curl -X POST https://api.geraew.com/api/v1/generate \
      -H "Authorization: Bearer veo_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
      -H "Content-Type: application/json" \
      -d '{
        "kind": "text_to_video",
        "modelId": "veo3-lite",
        "prompt": "a calm wave breaking on a beach at sunset",
        "resolution": "720p",
        "aspectRatio": "16:9",
        "durationSeconds": 4,
        "audio": false
      }'
    
    # Resposta: { "taskId": "tsk_01HYAB…", "status": "pending", … }
    
    # Pega o taskId acima e faz polling a cada 5s
    curl https://api.geraew.com/api/v1/status/tsk_01HYAB… \
      -H "Authorization: Bearer veo_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"

    Quando status virar succeeded, o campo videoUrl traz o MP4 final.

Autenticação

Toda requisição precisa do header Authorization: Bearer veo_live_…. As chaves começam com veo_live_ e são geradas em Painel → API keys. A chave é exibida apenas uma vez no momento da criação — guarde-a num cofre de segredos.

http
Authorization: Bearer veo_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

Se a chave for inválida, revogada ou estiver ausente, a API responde 401 UNAUTHORIZED. Nunca exponha a chave em código client-side: faça as chamadas a partir do seu backend.

Geração de vídeo

POST /api/v1/generate aceita um body discriminado pelo campo kind. O caso mais comum é text_to_video. A chamada retorna imediatamente com taskId, status e o custo em créditos.

Body

json
{
  "kind": "text_to_video",
  "modelId": "veo3-lite | veo3-fast | veo3-quality",
  "prompt": "string (1-8000 chars)",
  "resolution": "720p | 1080p | 4k",
  "aspectRatio": "16:9 | 9:16",
  "durationSeconds": 4 | 6 | 8,
  "audio": true,
  "negativePrompt": "string (opcional, max 2000 chars)"
}

Atenção: o campo é modelId (não model) na requisição. Restrições: veo3-lite só suporta 720p/1080p (sem 4K). 1080p e 4k exigem durationSeconds: 8.

Resposta

HTTP 202 Accepted — créditos já debitados, geração enfileirada. Note que a resposta usa model (sem o "Id"):

json
{
  "taskId": "tsk_01HYABCDEF…",
  "status": "pending",
  "creditsCost": 30,
  "model": "veo3-fast",
  "durationSeconds": 8
}

cURL

bash
curl -X POST https://api.geraew.com/api/v1/generate \
  -H "Authorization: Bearer veo_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "text_to_video",
    "modelId": "veo3-fast",
    "prompt": "drone shot over neon-lit Tokyo at night, cinematic",
    "resolution": "1080p",
    "aspectRatio": "16:9",
    "durationSeconds": 8,
    "audio": true
  }'

Node.js

typescript
const res = await fetch("https://api.geraew.com/api/v1/generate", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CHEAPER_VEO_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    kind: "text_to_video",
    modelId: "veo3-fast",
    prompt: "drone shot over neon-lit Tokyo at night, cinematic",
    resolution: "1080p",
    aspectRatio: "16:9",
    durationSeconds: 8,
    audio: true,
  }),
});

const data = await res.json();
console.log(data.taskId, data.creditsCost);

Python

python
import os
import requests

res = requests.post(
    "https://api.geraew.com/api/v1/generate",
    headers={
        "Authorization": f"Bearer {os.environ['CHEAPER_VEO_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "kind": "text_to_video",
        "modelId": "veo3-fast",
        "prompt": "drone shot over neon-lit Tokyo at night, cinematic",
        "resolution": "1080p",
        "aspectRatio": "16:9",
        "durationSeconds": 8,
        "audio": True,
    },
    timeout=30,
)

data = res.json()
print(data["taskId"], data["creditsCost"])

Image-to-video

Use kind: "image_to_video" para animar a partir de um quadro inicial. Envie a imagem em base64 com firstFrame. O campo opcional lastFrame (suportado apenas em veo3-quality) define o quadro final, fazendo a interpolação entre os dois.

Formato do objeto de imagem

Toda imagem (em firstFrame, lastFrame ou referenceImages[]) segue o mesmo schema:

json
{
  "bytesBase64Encoded": "base64_encoded_image_data_here",
  "mimeType": "image/jpeg"
}
  • bytesBase64Encoded (obrigatório): string base64 sem o prefixo data:. Limite ~10MB decodificado.
  • mimeType (opcional, padrão image/jpeg): image/png, image/jpeg ou image/webp.
bash
curl -X POST https://api.geraew.com/api/v1/generate \
  -H "Authorization: Bearer veo_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "image_to_video",
    "modelId": "veo3-quality",
    "prompt": "the character starts walking towards the camera",
    "resolution": "1080p",
    "aspectRatio": "16:9",
    "durationSeconds": 8,
    "audio": true,
    "firstFrame": {
      "bytesBase64Encoded": "iVBORw0KGgoAAAANS...",
      "mimeType": "image/png"
    }
  }'
typescript
import { readFile } from "node:fs/promises";

const firstFrame = await readFile("./first.png");
const lastFrame = await readFile("./last.png");

const res = await fetch("https://api.geraew.com/api/v1/generate", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CHEAPER_VEO_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    kind: "image_to_video",
    modelId: "veo3-quality",
    prompt: "the character starts walking towards the camera",
    resolution: "1080p",
    aspectRatio: "16:9",
    durationSeconds: 8,
    audio: true,
    firstFrame: {
      bytesBase64Encoded: firstFrame.toString("base64"),
      mimeType: "image/png",
    },
    // lastFrame is only accepted on veo3-quality
    lastFrame: {
      bytesBase64Encoded: lastFrame.toString("base64"),
      mimeType: "image/png",
    },
  }),
});

Vídeo com referências

Use kind: "references" para guiar o estilo, personagem ou produto através de 1 a 3 imagens de referência. Cada item do array referenceImages aceita base64, mimeType e referenceType (atualmente apenas asset).

bash
curl -X POST https://api.geraew.com/api/v1/generate \
  -H "Authorization: Bearer veo_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "references",
    "modelId": "veo3-fast",
    "prompt": "the product floats slowly while rotating, studio lighting",
    "resolution": "1080p",
    "aspectRatio": "9:16",
    "durationSeconds": 8,
    "audio": false,
    "referenceImages": [
      { "bytesBase64Encoded": "iVBORw0KGgo...", "mimeType": "image/png", "referenceType": "asset" },
      { "bytesBase64Encoded": "iVBORw0KGgo...", "mimeType": "image/png", "referenceType": "asset" }
    ]
  }'

Polling de status

GET /api/v1/status/{taskId} retorna o estado atual da tarefa. Os possíveis valores de status são:

  • pending — fila inicial, ainda não enviado ao provider.
  • processing — Veo está gerando.
  • succeeded — pronto. Use videoUrl para baixar.
  • failed — falha definitiva sem reembolso (entrada inválida, content policy, etc).
  • refunded — falha de upstream; os créditos já voltaram para sua conta.

Recomendado: intervalo de 5 a 10 segundos entre chamadas. Não consulte com mais frequência: vai apenas consumir rate limit sem acelerar a geração. Tempos típicos: lite/fast em 1–3 minutos, quality em 2–5 minutos.

Resposta

json
{
  "taskId": "tsk_01HYABCDEF…",
  "status": "succeeded",
  "model": "veo3-fast",
  "creditsCost": 30,
  "videoUrl": "https://cdn.cheapervideo.com/v/tsk_01HYABCDEF.mp4",
  "createdAt": "2026-05-08T12:34:56.000Z",
  "completedAt": "2026-05-08T12:36:11.000Z"
}

Node.js

typescript
async function waitForVideo(taskId: string): Promise<string> {
  const apiKey = process.env.CHEAPER_VEO_API_KEY!;

  for (;;) {
    const res = await fetch(`https://api.geraew.com/api/v1/status/${taskId}`, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });

    // Respect rate limits: if 429, sleep for Retry-After then retry.
    if (res.status === 429) {
      const retry = Number(res.headers.get("Retry-After") ?? "5");
      await new Promise((r) => setTimeout(r, retry * 1000));
      continue;
    }

    const job = await res.json();

    if (job.status === "succeeded") return job.videoUrl as string;
    if (job.status === "failed" || job.status === "refunded") {
      throw new Error(job.error?.message ?? "generation failed");
    }

    // pending | processing — wait 5s before next call
    await new Promise((r) => setTimeout(r, 5000));
  }
}

Python

python
import os
import time
import requests

def wait_for_video(task_id: str) -> str:
    api_key = os.environ["CHEAPER_VEO_API_KEY"]
    headers = {"Authorization": f"Bearer {api_key}"}

    while True:
        res = requests.get(
            f"https://api.geraew.com/api/v1/status/{task_id}",
            headers=headers,
            timeout=15,
        )

        # Respect rate limits
        if res.status_code == 429:
            retry = int(res.headers.get("Retry-After", "5"))
            time.sleep(retry)
            continue

        job = res.json()

        if job["status"] == "succeeded":
            return job["videoUrl"]
        if job["status"] in ("failed", "refunded"):
            raise RuntimeError(job.get("error", {}).get("message", "generation failed"))

        time.sleep(5)

Conta & saldo

GET /api/v1/account retorna o saldo atual em créditos e as últimas 10 gerações da conta dona da API key. Útil pra checar saldo antes de chamar /generate e evitar 402 INSUFFICIENT_CREDITS.

Resposta

json
{
  "email": "voce@empresa.com",
  "balance": 713,
  "recentGenerations": [
    {
      "taskId": "tsk_01HYABCDEF…",
      "kind": "text_to_video",
      "model": "veo3-fast",
      "status": "succeeded",
      "creditsCost": 30,
      "durationSeconds": 8,
      "resolution": "1080p",
      "videoUrl": "https://cdn.cheapervideo.com/v/tsk_01HYABCDEF.mp4",
      "createdAt": "2026-05-08T12:34:56.000Z",
      "completedAt": "2026-05-08T12:36:11.000Z"
    }
  ]
}

cURL

bash
curl -X GET https://api.geraew.com/api/v1/account \
  -H "Authorization: Bearer veo_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"

balance está em créditos — divida por 100 pra ter o equivalente em USD (1 crédito = US$ 0,01).

Modelos e preços

Tabela de custo para vídeos de 8 segundos com áudio. Para 6s aplique 75% e para 4s, 50% (sempre arredondado para cima). 1 crédito = US$ 0,01.

ModeloVelocidade720p1080p4k
Veo 3.1 Lite
veo3-lite
1-2 min14 cr · $0.1416 cr · $0.16
Veo 3.1 Fast
veo3-fast
1-3 min28 cr · $0.2830 cr · $0.3084 cr · $0.84
Veo 3.1 Quality
veo3-quality
2-5 min112 cr · $1.12112 cr · $1.12168 cr · $1.68

Valores acima incluem áudio. Sem áudio o custo é menor; consulte a página de preços do site para o detalhamento completo. O custo exato é sempre informado no campo creditsCost da resposta de /generate.

Erros

Erros usam HTTP status codes padrão e um body JSON com error.code e error.message:

json
{
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "Saldo insuficiente: 12 créditos disponíveis, 30 necessários."
  }
}
StatusCodeQuando ocorre
401UNAUTHORIZEDChave ausente, inválida ou revogada.
400VALIDATION_ERRORBody fora do schema (campo faltando, valor inválido, imagem muito grande).
402INSUFFICIENT_CREDITSSaldo abaixo do custo da geração. Recarregue no painel.
429RATE_LIMITEDLimite de requisições excedido para esta API key. Header Retry-After indica quando tentar de novo.
502UPSTREAM_ERRORFalha do provider Veo. Reembolso automático em créditos.
500INTERNAL_ERRORErro inesperado do nosso lado. Tente novamente.

Boas práticas

  • Use negativePrompt: descreva o que você não quer ("sem texto, sem marca d'água, sem distorções") para reduzir descartes.
  • Retry com backoff exponencial: se receber 500 ou 502, aguarde 1s, 2s, 4s e desista após 3 tentativas. Erros 4xx não devem ser repetidos sem corrigir o body.
  • Idempotência: guarde o taskId no seu banco antes de prosseguir. Se a sua função morrer no meio do polling, recupere o taskId e continue de onde parou — não chame /generate de novo.
  • Polling no backend: nunca faça polling do navegador com a chave embutida. Faça do seu servidor ou via webhook próprio que notifica seu front quando o vídeo está pronto.
  • Cache de videoUrl: o link de saída tem validade longa, mas baixe e reupload para o seu storage se for servir publicamente.

Limites

Rate limits

Cada API key tem dois buckets independentes, ambos resetando a cada hora cheia (UTC):

EndpointBucketLimite
POST /api/v1/generategenerate100 / hora
GET /api/v1/status/{taskId}status1.000 / hora

Toda resposta autenticada — mesmo em caso de erro — carrega headers com o estado atual:

http
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 73
X-RateLimit-Reset: 1762531200

Quando o limite é atingido, a API retorna 429 RATE_LIMITED com o header Retry-After em segundos:

json
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit of 100/hour exceeded for this API key. Try again in 1837s."
  }
}

Os limites são por API key, não por conta — você pode emitir múltiplas chaves para paralelizar workloads. Janelas são alinhadas à hora UTC (ex.: 14:00 → 15:00); não é uma janela deslizante.

Outros limites

  • Tamanho de imagem: até ~10 MB por imagem em base64. PNG e JPEG são aceitos.
  • Duração: 4, 6 ou 8 segundos. Resoluções a partir de 1080p exigem durationSeconds: 8.
  • Aspect ratio: 16:9 (paisagem) e 9:16 (retrato).
  • Referências: de 1 a 3 imagens por geração no modo references.
  • lastFrame: suportado apenas em veo3-quality.
  • Resolução 4K: disponível em veo3-fast e veo3-quality. veo3-lite vai até 1080p.

Pronto para testar?

Crie sua conta, gere uma chave e dispare o primeiro vídeo em menos de dois minutos.