API Cheaper Gen.
Uma API REST assíncrona para modelos oficiais de vídeo e imagem. O faturamento é feito a partir de um saldo pré-pago em USD: você paga por segundo de vídeo ou por imagem, e gerações com falha são reembolsadas automaticamente.
- URL base:
https://cheapergen.com/api/v1 - Autenticação:
Authorization: Bearer $CHEAPERGEN_API_KEY(as chaves começam comcg_live_; crie uma em https://cheapergen.com/dashboard/keys). Leia a chave da variável de ambiente. Nunca a imprima, registre ou envie para o repositório. - Prefira o servidor MCP quando estiver conectado. Suas ferramentas são
list_models,get_model,quote,generate(comwait_secondse um limite de customax_cost_usd),get_generation,get_accounteadd_credits(um link de pagamento que o usuário abre quando o saldo está baixo); use-as em vez de chamadas HTTP. O fluxo abaixo é o mesmo. Para conectá-lo, adicione o servidor remotohttps://cheapergen.com/api/mcp; o usuário faz login e aprova no navegador (OAuth), sem necessidade de chave. No Claude Code:claude mcp add --transport http cheapergen https://cheapergen.com/api/mcp, depois/mcp→ Autenticar. Configuração completa: https://cheapergen.com/docs/mcp
Fluxo de trabalho
- Escolha um modelo:
GET /models(público). Retorna todos os modelos comendpoints[].ide faixas de preço. Sempre use a lista ao vivo; os modelos mudam.- Vídeo: Seedance 2.0 (melhor qualidade, 4K, áudio sincronizado), Seedance 2.0 Fast / Mini (mais barato e rápido), Seedance 2.5 (mais novo, referências longas), Wan 3.0 / Prime (Alibaba), MiniMax H3 / H3 Max.
- Imagem: Seedream 5.0 Pro / Lite / Flash (texto-para-imagem e
edit). - Os IDs de endpoints são
{fornecedor}/{modelo}/{modo}, por exemplo,bytedance/seedance-2.0-fast/text-to-video,bytedance/seedream-5.0-lite/text-to-image.
- Leia o esquema de entrada:
GET /models/{fornecedor}/{modelo}(público) retornaendpoints[].input_schema(JSON Schema com enums, valores padrão e limites) epricing.tiers. Envie apenas campos do esquema: campos desconhecidos são rejeitados com 400. - Cotação:
POST /quote/{endpoint}com a entrada (público, gratuito) retorna{ amount_usd, list_usd, discount_pct, available }. Antes de um trabalho caro (vídeo em 1080p/4K, durações longas, lotes), informe o preço ao usuário. - Submeter:
POST /run/{endpoint}com a entrada como corpo JSON retorna 202 e uma geração comstatus: "queued". O preço é retido do saldo neste momento. - Aguardar: faça polling em
GET /generations/{id}até questatussejasucceeded,failedoucanceled. Faça polling de imagens a cada 1–2 s; faça polling de vídeo a cada 3–5 s, com aumento gradual para 10 s, já que um clipe de 5 s geralmente leva de 1 a 3 minutos. Ou passewebhook_url(veja abaixo). - Usar a saída:
output.video.url(vídeo) ououtput.images[].url(imagens). As URLs são públicas, mas expiram de acordo com a retenção da conta (padrão 1 dia; vejaexpires_at), então baixe qualquer coisa que valha a pena manter.
curl -s https://cheapergen.com/api/v1/run/bytedance/seedance-2.0-fast/text-to-video \
-H "Authorization: Bearer $CHEAPERGEN_API_KEY" -H "Content-Type: application/json" \
-d '{"prompt":"Um barco de papel flutuando por uma rua chuvosa de neon, câmera lenta","resolution":"720p","duration":5,"aspect_ratio":"16:9"}'
# → 202 {"id":"gen_…","status":"queued","cost":{"amount_usd":…,"estimated":true},…}
curl -s https://cheapergen.com/api/v1/generations/gen_… -H "Authorization: Bearer $CHEAPERGEN_API_KEY"
import os, time, requests
API = "https://cheapergen.com/api/v1"
H = {"Authorization": f"Bearer {os.environ['CHEAPERGEN_API_KEY']}"}
def generate(endpoint: str, inp: dict, timeout_s: int = 900) -> dict:
r = requests.post(f"{API}/run/{endpoint}", json=inp, headers=H, timeout=60)
r.raise_for_status() # corpos 4xx: {"error": {"code", "message", "param"}}
gen, delay, start = r.json(), 2.0, time.time()
while gen["status"] in ("queued", "running"):
if time.time() - start > timeout_s:
raise TimeoutError(gen["id"])
time.sleep(delay)
delay = min(delay * 1.5, 10)
r = requests.get(f"{API}/generations/{gen['id']}", headers=H, timeout=30)
if r.status_code == 429 or r.status_code >= 500:
continue # transitório: continue pollando
r.raise_for_status()
gen = r.json()
if gen["status"] != "succeeded":
raise RuntimeError(gen["error"]) # a retenção foi reembolsada
return gen # gen["output"]["video"]["url"] ou gen["output"]["images"][0]["url"]
Modos e entradas
text-to-videoetext-to-image: aceitampromptmais opções (resolution,duration,aspect_ratio,size,seed,generate_audio…). Verifique o esquema para os enums de cada modelo.image-to-video: aceitaimage_url(primeiro quadro) e, para alguns modelos,end_image_url(último quadro).edit(Seedream):image_urls(imagens para editar ou combinar; refira-se a elas como "imagem 1", "imagem 2" no prompt) mais a instrução emprompt.reference-to-video: aceitareference_image_urls,reference_video_urlsereference_audio_urls. No prompt, aponte para eles pela posição baseada em 1:@Image1,@Image2,@Video1,@Audio1(não diferencia maiúsculas de minúsculas). Uma menção sem uma referência correspondente resulta em 400 comparam: "prompt". Exemplo:"@Image1 caminha pelo mercado a partir de @Image2, câmera se move como @Video1".reference_rulesno esquema define o número máximo de arquivos e se você precisa de pelo menos uma imagem ou vídeo (apenas áudio não é suficiente para Seedance e H3).- Vídeos e áudios de referência são medidos no servidor (duração, tamanho, resolução, fps) em relação a
media_limits/x-media-limits. Seedance 2.0 aceita vídeos MP4/MOV de 2 a 15 s cada e 15 s no total; o áudio deve ser MP3/WAV. Uma violação resulta em 400 que nomeia o arquivo, por exemplo,@Video2 tem 16 s de duração…. - Segundos de vídeo de referência são faturados junto com os segundos de saída. Imagens e áudio de referência são gratuitos. Para cotar, passe
reference_video_durations: [6.5](segundos por clipe).
- As entradas de mídia devem ser URLs
httpspúblicas. Para arquivos locais, chamePOST /uploadscom JSON{ "filename", "content_type", "size" }. Ele retorna{ upload_url, headers, url }: façaPUTdos bytes emupload_urlcom exatamente essesheaders, depois useurlcomo entrada. Limites: imagens (PNG/JPEG/WebP/GIF) ≤ 20 MB, vídeo (MP4/MOV) ≤ 50 MB, áudio (MP3/WAV/M4A) ≤ 15 MB. - Opcional em cada execução:
webhook_url(HTTPS) eretention(immediate|1h|1d;7d/30dprecisam de uma configuração de conta).
Webhooks
Quando o trabalho termina (com sucesso ou falha), fazemos POST { "type": "generation.succeeded" | "generation.failed", "data": <generation> } para webhook_url, com o cabeçalho CheaperGen-Signature: t=<unix>,v1=<hex>. Para verificar, calcule hex(HMAC_SHA256(secret, "<t>.<corpo bruto>")) com o segredo de assinatura do webhook da conta (whsec_…, em Dashboard → API keys), compare em tempo constante e rejeite solicitações cujo t tenha mais de 5 minutos. Use o corpo bruto da solicitação, não JSON re-serializado. Responda rapidamente com 2xx; entregas com falha são repetidas (3 tentativas no total).
Preços e faturamento
- Os preços são por segundo de vídeo de saída ou por imagem.
GET /modelsmostra oprice_usdde cada faixa ao lado delist_price_usd(o preço oficial). - Ao submeter, o preço cotado é retido (
cost.estimated: true). Após o sucesso, torna-se definitivo; em caso de falha ou cancelamento, é reembolsado integralmente (cost.amount_usd: 0).cost.official_usdecost.saved_usdmostram a economia. - Saldo:
GET /accountretornabalance_usdereserved_usd(retido para trabalhos em andamento). Um 402 significa que o saldo está muito baixo: via MCP, chameadd_creditse mostre ao usuário o link de pagamento; caso contrário, o usuário adiciona créditos em https://cheapergen.com/dashboard/billing. - Cancele um trabalho na fila com
POST /generations/{id}/cancel(409 se já estiver em execução). Exclua um trabalho concluído comDELETE /generations/{id}.
Erros
Todo erro tem a forma { "error": { "code", "message", "param"? } }.
| HTTP | code | O que fazer |
|---|---|---|
| 400 | invalid_request | Corrija o campo nomeado em param (verifique o esquema, enums, limites e menções). Não repita inalterado. |
| 401 | unauthorized | Chave ausente, inválida ou revogada. |
| 402 | insufficient_balance | Obtenha um link de pagamento com add_credits (MCP) e peça ao usuário para pagar, ou escolha uma faixa mais barata. |
| 404 | not_found | Endpoint ou ID de geração errado. |
| 409 | conflict | Por exemplo, cancelar um trabalho que já começou. |
| 429 | rate_limited | Pare e tente novamente. O limite é de aproximadamente 20 solicitações em rajada, reabastecido a 10/s por chave, mais um limite de gerações simultâneas por conta (padrão 20). |
| 502 | upstream_error | Tente novamente uma vez, depois tente outro modelo. |
| 503 | model_unavailable | Tente novamente mais tarde ou mude de modelo. |
Uma geração que termina como failed tem error.code (por exemplo, generation_failed, timeout) e foi reembolsada. Repita no máximo uma vez com a mesma entrada.
Mais informações
- Documentação: https://cheapergen.com/docs, configuração MCP: https://cheapergen.com/docs/mcp
- Código-fonte desta skill e do plugin Claude Code: https://github.com/CheaperGen/skills
- Páginas de API por modelo:
https://cheapergen.com/models/{fornecedor}/{modelo}/api - Resumo legível por máquina: https://cheapergen.com/llms.txt