Documentaçãoda chave ao primeiro clipe
Tudo o que você precisa para uma primeira geração: uma chave, uma requisição, a tarefa e o webhook.
O acesso à API para desenvolvedores é por solicitação.
Visão geral
REST sobre HTTPS, com JSON na entrada e na saída. Toda geração é assíncrona.
- URL base
https://api.pershot.app/v1- Autenticação
- Authorization: Bearer seguido da sua chave. As chaves começam com sk_test_ ou sk_live_ e são exibidas uma única vez; armazenamos apenas um hash.
- Permissões da chave
- Cada chave tem escopos e, se você configurar no estúdio, uma lista de permissões de modelos e ferramentas. Uma chave com lista de permissões só pode usar o que está nela, inclusive as ferramentas: aumento de resolução de imagens, remoção de fundo, Aprimorar, sincronização labial, expansão de imagens e o editor de imagens. Qualquer outra coisa retorna 403 forbidden_model. 1080p ou 4K com Aprimorar exige tanto o modelo de vídeo quanto o Aprimorar.
- Formato do erro
{ "error": { "code", "message", "param", "request_id" } }- IDs
- Com prefixo conforme o tipo: job_, qt_, key_, up_.
- OpenAPI
- /api/v1/openapi.json
- Para agentes de IA
- Texto simples para agentes de IA: entradas, valores aceitos, cada preço e um exemplo de requisição
seedance-2.0-fastseedance-2.0-miniqwen-image-2512-lightningqwen-image-2512qwen-image-edit-2511-lightningqwen-image-edit-2511
As gerações reais ainda não estão disponíveis. Deixe seu e-mail na página de um modelo e avisaremos uma única vez, quando estiverem disponíveis.
Início rápido
Quatro etapas, cada uma com a resposta que você deve ver.
- 01
Obtenha uma chave
O acesso à API para desenvolvedores é por solicitação: peça no estúdio, em Chaves de API. Quando estiver liberado, crie uma chave ali e copie: a chave completa é exibida uma única vez.
export API_KEY="sk_test_…" - 02
Envie uma requisição
Envie a tomada por POST com um Idempotency-Key e um limite max_credits. Você recebe 202 e uma tarefa na fila na hora, e os créditos ficam reservados.
curl https://api.pershot.app/v1/videos/generations \ -H "Authorization: Bearer $API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "model": "seedance-2.0-fast", "prompt": "Perfume mist in hard side light. Slow push-in, black background, grain.", "duration": 5, "resolution": "720p", "aspect_ratio": "16:9", "generate_audio": true, "max_credits": 34 }'{ "id": "job_01J9ZK4T8W", "object": "job", "kind": "video", "status": "queued", "money_status": "reserved", "queue_position": 2, "requested_model": "seedance-2.0-fast", "credits_quoted": 34, "credits_charged": null } - 03
Consulte a tarefa
Consulte a tarefa com GET até o status ser succeeded. A URL de saída é assinada e expira; baixe o que quiser guardar.
curl https://api.pershot.app/v1/jobs/job_01J9ZK4T8W \ -H "Authorization: Bearer $API_KEY"{ "id": "job_01J9ZK4T8W", "object": "job", "kind": "video", "status": "succeeded", "money_status": "settled", "requested_model": "seedance-2.0-fast", "resolved_model": "seedance-2.0-fast", "credits_quoted": 34, "credits_charged": 34, "outputs": [ { "kind": "video", "url": "https://…/job_01J9ZK4T8W.mp4?sig=…", "width": 1280, "height": 720, "duration_s": 5 } ], "error": null } - 04
Receba o webhook
Passe webhook_url e enviaremos cada mudança de estado por POST para ele, assinada com um carimbo de data/hora. Responda 2xx; entregas com falha são repetidas com intervalos crescentes.
{ "id": "evt_01J9ZKB1QX", "type": "job.succeeded", "created_at": "2026-09-29T14:02:31Z", "data": { "job": { "id": "job_01J9ZK4T8W", "object": "job", "status": "succeeded", "money_status": "settled", "credits_charged": 34, "outputs": [ { "kind": "video", "url": "https://…/job_01J9ZK4T8W.mp4?sig=…", "width": 1280, "height": 720, "duration_s": 5 } ] } } }
Endpoints
Todos os caminhos são relativos à URL base.
| Método | Caminho | O que faz |
|---|---|---|
| GET | /v1/models | Modelos, recursos e status disponíveis para a sua conta |
| GET | /v1/pricing | Preços públicos; com autenticação, os preços da sua conta |
| POST | /v1/quotes | Plano, itens da cotação, cobrança máxima e validade (10 minutos) |
| POST | /v1/videos/generations | Gerar um vídeo; 202 e uma tarefa |
| POST | /v1/images/generations | Gerar ou editar uma imagem; 202 e uma tarefa |
| GET | /v1/jobs/{id} | Status, saídas como links assinados, custo real |
| GET | /v1/jobs | Suas tarefas, mais recentes primeiro |
| POST | /v1/jobs/{id}/cancel | Pedir o cancelamento; os créditos reservados são reembolsados, a menos que o modelo já tenha aceitado a tarefa |
| GET | /v1/balance | Créditos disponíveis e reservados, por categoria |
| GET | /v1/usage | Uso por dia ou modelo, em JSON ou CSV |
| POST | /v1/uploads | Enviar um JPEG, PNG ou WebP de até 10 MB |
Cotações e limites de gastos
Toda geração precisa de um quote_id ou de um limite max_credits, nunca dos dois. Com um quote_id, a tarefa é executada por aquela cotação; com max_credits, ela só é executada se o preço for igual ou menor que o limite.
model: "auto" sempre exige max_credits. Uma cotação vale por 10 minutos; depois disso, você recebe quote_expired.
Idempotência
Envie um cabeçalho Idempotency-Key (de 1 a 255 caracteres ASCII visíveis) em toda requisição de geração.
A mesma chave dentro de 24 horas retorna a mesma tarefa com HTTP 200 em vez de 202, então tentar de novo após um timeout nunca cria nem cobra uma segunda tarefa.
Webhooks
Passe webhook_url em uma geração (ou em um lote) para receber as mudanças de estado dela. Cada evento é um POST cujo corpo JSON tem id, type, created_at e data: data.job para eventos de tarefa, data.batch para batch.completed.
Eventos
job.queuedjob.processingjob.succeededjob.failedjob.cancelledbatch.completed
- Cada entrega tem um ID de evento, um carimbo de data/hora e uma assinatura. Verifique a assinatura antes de confiar no corpo.
- Uma entrega conta quando o seu endpoint responde 2xx em até 10 segundos. Caso contrário, ela é tentada de novo após 1 min, 5 min, 30 min, 2 h e 6 h e depois marcada como falha; o suporte pode reenviá-la. Redirecionamentos não são seguidos.
- As URLs de webhook precisam ser https. Hosts em endereços privados, de loopback ou reservados são recusados, tanto no envio quanto quando nos conectamos.
Cabeçalhos
X-Signaturet=<unix>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>X-Event-Id- O ID do evento, que também vem no corpo. Novas tentativas e reenvios mantêm o mesmo ID, então guarde-o e ignore um ID que você já processou.
- Segredo de assinatura
- Um segredo whsec_… por conta, no estúdio, em Chaves de API. A chave do HMAC é o segredo inteiro, com o prefixo.
- Rotação
- Depois da rotação, o segredo antigo continua assinando por 24 horas como uma segunda entrada v1. Aceite a entrega se qualquer v1 corresponder.
Calcule o HMAC sobre o corpo bruto, e não sobre uma cópia serializada de novo, compare em tempo constante e recuse carimbos de data/hora com mais de cinco minutos.
import { createHmac, timingSafeEqual } from "node:crypto";
// rawBody: the request body exactly as received, before any JSON parsing.
export function verifyWebhook(header, rawBody, secret, toleranceSec = 300) {
let t = null;
const signatures = [];
for (const item of (header ?? "").split(",")) {
const [key, value] = item.split("=", 2);
if (key === "t") t = Number(value);
if (key === "v1") signatures.push(Buffer.from(value, "hex"));
}
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest();
return signatures.some((s) => s.length === expected.length && timingSafeEqual(s, expected));
}
// verifyWebhook(req.headers["x-signature"], rawBody, process.env.WEBHOOK_SECRET)
// Answer 2xx quickly, and skip an X-Event-Id you have already handled.Erros
Os códigos e os status HTTP são fixos; a mensagem é feita para pessoas.
| Código | HTTP | Quando |
|---|---|---|
invalid_request | 400 | Um campo está faltando ou fora do intervalo |
unauthorized | 401 | Sem chave, chave revogada ou assinatura inválida |
insufficient_credits | 402 | O saldo não cobre a reserva |
forbidden_model | 403 | A lista de permissões da chave não inclui este modelo ou ferramenta |
region_not_supported | 403 | O modelo não é oferecido na sua região |
developer_api_closed | 403 | Uma chave de desenvolvedor enquanto a API para desenvolvedores está fechada; o acesso é por solicitação |
member_connections_paused | 403 | Um login de membro (MCP, código de conexão ou linha de comando) enquanto a conexão do seu próprio agente de IA está pausada |
not_found | 404 | Essa tarefa, cotação ou arquivo enviado não existe na sua conta |
quote_expired | 409 | A cotação tem mais de 10 minutos |
price_changed | 409 | O preço subiu acima do seu limite |
content_rejected | 422 | O conteúdo foi recusado; nada é cobrado |
rate_limited | 429 | Requisições demais para esta chave |
concurrency_limited | 429 | Tarefas demais em execução nesta conta |
internal_error | 500 | Algo falhou do nosso lado |
upstream_unavailable | 503 | O modelo está indisponível; tente de novo mais tarde |
Um resultado incerto do modelo não é um erro: a tarefa informa o status unknown e é verificada antes de qualquer reenvio.
Limites
- Requisições
- 60 por minuto por chave, por padrão.
- Simultaneidade
- 3 tarefas ao mesmo tempo por conta, por padrão; peça para aumentar.
- Teto
- A capacidade do modelo é um teto rígido. Mais chaves não aumentam a simultaneidade.
Imagens
POST /v1/images/generations aceita os mesmos cabeçalhos. Escolha um ID de modelo por nível e operação; os modelos de edição também precisam de image_url, e os modelos de geração o rejeitam.
| Nível | gerar | editar |
|---|---|---|
| Image MiniEconômico · rascunho | qwen-image-2512-lightning | qwen-image-edit-2511-lightning |
| Image FastRecomendado | qwen-image-2512 | qwen-image-edit-2511 |
Limites por modelo
A página da API de cada modelo tem a tabela completa: o valor, a unidade, quem verifica e o que acontece acima do limite. GET /v1/models retorna os mesmos limites em JSON.
- Validado por nósVerificamos e respondemos 400 antes de qualquer cotação ou reserva.
- Validado pelo fornecedorO fornecedor verifica. Uma tarefa recusada por ele falha, e nada é cobrado.
- RecomendadoNinguém verifica. Ficar dentro do limite dá resultados melhores.
| Modelo | Principais limites | Tabela completa |
|---|---|---|
seedance-2.0-fastSeedance 2.0 Fast | Prompt de 2 a 2.000 caracteres · 4 a 15 s · até 9 imagens de referência · imagens de 300 a 6.000 px por lado | Abrir a tabela |
seedance-2.0-miniSeedance 2.0 Mini | Prompt de 2 a 2.000 caracteres · 4 a 15 s · até 9 imagens de referência · imagens de 300 a 6.000 px por lado | Abrir a tabela |
qwen-image-2512Qwen-Image-2512 | Prompt de 2 a 2.000 caracteres · 1K ou 2K · sem imagem de origem | Abrir a tabela |
qwen-image-2512-lightningQwen-Image-2512 · Lightning 4-step | Prompt de 2 a 2.000 caracteres · 1K ou 2K · sem imagem de origem | Abrir a tabela |
qwen-image-edit-2511Qwen-Image-Edit-2511 | Prompt de 2 a 2.000 caracteres · 1K ou 2K · uma imagem de origem, JPEG, PNG ou WebP de até 10 MB | Abrir a tabela |
qwen-image-edit-2511-lightningQwen-Image-Edit-2511 · Lightning | Prompt de 2 a 2.000 caracteres · 1K ou 2K · uma imagem de origem, JPEG, PNG ou WebP de até 10 MB | Abrir a tabela |
Envios
POST /v1/uploads identifica o tipo pelo próprio arquivo. Os links de envio duram 7 dias.
| Arquivo | Formatos | Tamanho máximo | Duração máxima |
|---|---|---|---|
| Imagem: primeiro quadro, referência ou imagem a editar | JPEG, PNG, WebP | 10 MB | – |
| Vídeo: sincronização labial | MP4 | 50 MB | 60 s |
| Áudio: sincronização labial | MP3, WAV, M4A | 10 MB | 60 s |
Nunca buscamos imagens em outros sites, então, nesses links, quem verifica o tamanho é o fornecedor, e uma tarefa que ele recusa não é cobrada. Os mesmos limites também vêm em JSON: GET /v1/models retorna um objeto limits para cada modelo.
Vindo do fal, do Replicate ou do WaveSpeed
Trocar a URL base e a chave não basta: toda requisição também precisa do ID do modelo no corpo, de um cabeçalho Idempotency-Key e de um limite de preço (max_credits ou um quote_id). O guia de migração mapeia cada campo do Seedance 2.0 e do Qwen-Image e lista o que não se transfere.