APIMaster Webhooks para Tarefas Assíncronas
Receba notificações assinadas de conclusão e falha para tarefas Seedance, vídeo e imagem assíncronas, com retentativas, histórico de entrega e fallback de polling.
Webhooks para tarefas assíncronas do APIMaster
Use webhooks como o mecanismo principal de notificação para geração assíncrona, e mantenha o polling como fallback. O APIMaster envia um POST HTTPS assinado quando uma tarefa rastreada é concluída ou falha. As notificações são independentes do provedor de geração e usam seu ID de tarefa do APIMaster.
Modelos e endpoints suportados
O Seedance inclui todos os quatro modelos: seedance-2.0, seedance-2.5, seedance-2.0-fast e seedance-2.0-mini. Use POST /v1/videos/generations ou o POST /v1/video/generations compatível.
As notificações de tarefas de vídeo também suportam MiniMax-H3, Kling Omni / Motion Control, Grok Imagine Video e Sora. Os fluxos de trabalho de imagem GPT 2 / 2.5 e Gemini suportados usam /v1/images/generations/async ou /v1/images/edits/async suportado; Midjourney v8.2 / Niji 7 usam /v1/midjourney/generations. A disponibilidade de rota e os parâmetros de geração ainda seguem o guia de cada modelo. A geração síncrona Seedream e Grok, streaming de chat e revisão de ativos Seedance não fazem parte deste contrato de webhook de geração.
Verifique GET /v1/webhook-capabilities?model=seedance-2.0-fast para elegibilidade do modelo. Use um endpoint de submissão assíncrono suportado; elegibilidade não significa que toda operação de imagem ou todo alias de modelo suporta geração assíncrona.
Registrar e verificar um endpoint
Use sua chave de API em Authorization: Bearer YOUR_API_KEY. Uma chave de API pode gerenciar endpoints e eventos pertencentes à sua conta. Mantenha-a no seu servidor.
curl --fail-with-body "https://apimaster.ai/v1/webhook-endpoints" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://your-server.example/webhooks/apimaster"}'
A resposta contém endpoint.id, endpoint.key_id e signing_secret. Salve o segredo de assinatura com segurança: ele é retornado apenas uma vez. É separado da sua chave de API e não pode autorizar geração ou downloads. A URL deve ser um endpoint HTTPS publicamente acessível na porta 443. Endereços privados e redirecionamentos são rejeitados. Até 20 endpoints são permitidos por conta; as URLs são imutáveis, portanto crie e verifique um novo endpoint ao mudar o destino.
Após configurar seu receptor, verifique a propriedade:
curl --fail-with-body -X POST "https://apimaster.ai/v1/webhook-endpoints/whep_example/verify" \
-H "Authorization: Bearer YOUR_API_KEY"
O APIMaster envia um evento webhook.endpoint_verification assinado contendo data.challenge. Retorne HTTP 200 com {"challenge":"THE_RECEIVED_CHALLENGE"} dentro de 10 segundos. Uma solicitação de geração que referencia um endpoint não verificado, pausado ou de outra conta é rejeitada antes da submissão.
O tempo limite total da solicitação HTTP é de 10 segundos, incluindo DNS, conexão e TLS. Os cabeçalhos da resposta devem chegar em até 8 segundos após o envio. Grave o evento de forma persistente e confirme imediatamente.
Submeter uma tarefa com notificações
curl --fail-with-body "https://apimaster.ai/v1/videos/generations" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model":"seedance-2.5",
"prompt":"A paper boat floating on a calm pond, slow camera movement.",
"duration":4,
"resolution":"480p",
"aspect_ratio":"16:9",
"notifications":{
"webhook":{
"endpoint_id":"whep_example",
"events":["task.completed","task.failed"]
}
},
"client_reference_id":"order_123"
}'
Substitua o ID do modelo por qualquer um dos quatro IDs do Seedance mantendo seus próprios parâmetros suportados. Salve o ID da tarefa da resposta normal de criação. client_reference_id é uma referência de negócio opcional de no máximo 128 bytes; não é uma chave de idempotência de submissão. Não combine notifications com os parâmetros de provedor legados webhook ou callback_url.
Para edições de imagem multiparte suportadas, envie notifications como um campo de formulário de string JSON e client_reference_id como um campo de formulário separado:
curl --fail-with-body "https://apimaster.ai/v1/images/edits/async" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "model=gpt-image-2" \
-F "prompt=Turn the reference into a watercolor illustration" \
-F "image=@reference.png" \
-F 'notifications={"webhook":{"endpoint_id":"whep_example","events":["task.completed","task.failed"]}}' \
-F "client_reference_id=image_order_123"
Não há um endpoint padrão em nível de conta nesta versão: referencie um endpoint em cada solicitação de tarefa. Webhooks podem chegar antes da resposta da sua submissão. Persista-os mesmo que sua aplicação ainda não tenha salvo o ID da tarefa retornado. Alguns fluxos de imagem assíncronos encapsulam geração upstream síncrona, portanto a própria submissão ainda pode levar tempo.
Payloads de sucesso e falha
Uma notificação de sucesso contém o ID público da tarefa e um link de vídeo autenticado:
{
"id":"evt_example",
"type":"task.completed",
"api_version":"2026-10-03",
"created_at":1791014400,
"data":{
"task_id":"task_example",
"model":"seedance-2.5",
"kind":"video",
"status":"completed",
"client_reference_id":"order_123",
"completed_at":1791014400,
"task_url":"https://apimaster.ai/v1/videos/task_example",
"result":{
"outputs":[{
"output_id":"0",
"type":"video",
"url":"https://apimaster.ai/v1/videos/task_example/content",
"authentication":"bearer",
"expires_at":null
}]
},
"error":null
}
}
A falha usa o mesmo envelope com type: "task.failed", data.status: "failed", data.result: null e um objeto de erro:
{
"code":"generation_failed",
"message":"The generation task failed. Query the task for details."
}
Tanto falhas confirmadas pelo provedor quanto timeouts de tarefa no gateway podem gerar eventos de falha. Uma solicitação de criação rejeitada antes que uma tarefa seja aceita não gera um evento de tarefa. Falha na entrega da notificação não altera o status da geração ou executa novamente a geração. Eventos não confirmam que a reconciliação de cobrança foi concluída.
Para imagens, kind é image e outputs contém todas as saídas de imagem disponíveis. Eventos de tarefas filhas do Midjourney incluem batch_id; você pode adicionalmente se inscrever em batch.completed para receber um resumo de lote após todas as filhas terminarem. Seu status é completed, partial_failure ou failed, com contagens em data.summary. Conclusão do lote nem sempre significa que toda filha teve sucesso.
Baixe URLs de saída com uma chave de API pertencente à conta da tarefa. Salve a mídia gerada prontamente. expires_at: null significa que nenhum tempo de expiração garantido é fornecido, não armazenamento permanente; um download posterior pode retornar HTTP 410. Reproduzir um evento não estende a disponibilidade da mídia.
Autenticar callbacks e reconhecer prontamente
Cada POST contém:
X-APIMaster-Event-ID: evt_example
X-APIMaster-Delivery-ID: dlv_example
X-APIMaster-Timestamp: 1791014400
X-APIMaster-Signature: v1=<hex-hmac>,kid=<key-id>
Verifique o HMAC-SHA256 sobre o timestamp, um ponto literal e os bytes brutos do corpo da requisição usando o segredo de assinatura do endpoint. Use comparação de tempo constante, permita no máximo cinco minutos de diferença de relógio e verifique se o cabeçalho Event-ID corresponde ao ID do corpo. As retentativas mantêm o mesmo ID de evento e corpo, mas recebem um novo ID de entrega, timestamp e assinatura.
O seguinte receptor Python usa Flask e SQLite. Ele persiste um evento atomicamente antes de reconhecê-lo. Seu worker de aplicação deve consumir as linhas salvas, baixar arquivos e executar a lógica de negócios separadamente.
import hashlib, hmac, json, os, sqlite3, time
from flask import Flask, request, jsonify, abort
app = Flask(__name__)
# During key rotation, configure both active and previous kid/secret pairs.
SECRETS = json.loads(os.environ["APIMASTER_WEBHOOK_SECRETS_JSON"])
DB_PATH = os.environ.get("WEBHOOK_DB_PATH", "webhook-events.sqlite3")
with sqlite3.connect(DB_PATH) as db:
db.execute("CREATE TABLE IF NOT EXISTS events (id TEXT PRIMARY KEY, body BLOB NOT NULL)")
@app.post("/webhooks/apimaster")
def receive():
raw = request.get_data()
try:
timestamp = request.headers["X-APIMaster-Timestamp"]
if abs(time.time() - int(timestamp)) > 300:
abort(401)
fields = dict(part.split("=", 1) for part in
request.headers["X-APIMaster-Signature"].split(","))
secret = SECRETS[fields["kid"]]
expected = hmac.new(secret.encode(), timestamp.encode() + b"." + raw,
hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, fields["v1"]):
abort(401)
event = json.loads(raw)
if event["id"] != request.headers["X-APIMaster-Event-ID"]:
abort(401)
except (KeyError, ValueError, TypeError):
abort(401)
if event["type"] == "webhook.endpoint_verification":
return jsonify(challenge=event["data"]["challenge"])
with sqlite3.connect(DB_PATH) as db:
db.execute("INSERT OR IGNORE INTO events(id, body) VALUES (?, ?)",
(event["id"], raw))
return "", 204
Retorne qualquer status 2xx dentro de 10 segundos para eventos de geração. Reconheça após o armazenamento durável, sem aguardar os downloads de mídia. A entrega é pelo menos uma vez: eventos duplicados são possíveis, especialmente se um reconhecimento for perdido, então faça deduplicação por id. Não há garantia de ordenação entre tarefas.
Retentativas, histórico de entrega e replay
O APIMaster retenta falhas de rede, timeouts de reconhecimento e respostas não 2xx por até 72 horas a partir da criação do evento. Os atrasos iniciais são de 1, 2, 5, 15 e 30 minutos, depois 1, 2, 4 e 8 horas, seguidos por intervalos de 12 horas, com até 20% de jitter. Um Retry-After válido em 429/503 é respeitado dentro da janela de retentativa. Redirecionamentos não são seguidos. HTTP 410 pausa o endpoint; outras respostas 4xx são retentadas para permitir correções de configuração.
curl --fail-with-body "https://apimaster.ai/v1/webhook-events?task_id=task_example" \
-H "Authorization: Bearer YOUR_API_KEY"
curl --fail-with-body "https://apimaster.ai/v1/webhook-events/evt_example/deliveries" \
-H "Authorization: Bearer YOUR_API_KEY"
curl --fail-with-body -X POST "https://apimaster.ai/v1/webhook-events/evt_example/redeliver" \
-H "Authorization: Bearer YOUR_API_KEY"
Os status incluem pending, in_flight, retrying, delivered, paused e exhausted. Os registros de evento e tentativa são retidos por 30 dias. O replay preserva o ID de evento original e o payload e abre uma nova janela de entrega de 72 horas; ele não regenera mídia nem cobra novamente. Até cinco replays manuais por evento por dia UTC são permitidos. Um evento atualmente alugado para entrega não pode ser reproduzido até que essa tentativa termine ou seu aluguel expire.
Pause ou retome um endpoint com PATCH /v1/webhook-endpoints/{id} e {"enabled":false} ou {"enabled":true}. Retomar continua eventos pausados cujo prazo original não passou. Gire os segredos com POST /v1/webhook-endpoints/{id}/rotate-secret; salve o novo segredo e kid, e mantenha o par anterior pelo período de transição de 24 horas retornado.
Fallback de polling
Para tarefas sem um evento terminal recebido, consulte /v1/videos/{task_id} ou a consulta de tarefa de imagem documentada do modelo a cada 60–120 segundos. Use a API de tarefa como fonte da verdade e verifique o histórico de entrega se a geração terminou, mas a notificação está faltando. A falta de um webhook não é motivo para reenviar uma requisição de geração faturada. Um tempo de inatividade persistente do endpoint pode esgotar as retentativas automáticas; restaure o receptor e reproduza os eventos retidos.
