Plataforma
Callbacks (webhooks)
Em vez de consultar o estado periodicamente, inclua um callback_url no pedido de imagem ou vídeo. Quando estiver pronto, ou se falhar, a Zurelay envia o resultado para esse URL por POST, com uma assinatura que permite confirmar que veio de nós.
Pedir um callback
Adicione callback_url a qualquer um destes pedidos. Tem de ser um URL https acessível na Internet pública.
curl https://api.zurelay.com/v1/videos \ -H "Authorization: Bearer $ZURELAY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "seedance-2.0", "prompt": "A fox running through fresh snow at dawn", "seconds": 5, "callback_url": "https://example.com/hooks/zurelay" }'Pedidos de imagem com callback
Sem callback_url, um pedido de imagem espera e responde com as imagens, tal como a API da OpenAI. Com este campo, o pedido é aceite de imediato e a resposta contém a tarefa. Só há cobrança se forem geradas imagens:
HTTP/1.1 202 Acceptedx-request-id: req_6fJd0kQ3pW9xT2mB7cZ1hR4u{ "id": "req_6fJd0kQ3pW9xT2mB7cZ1hR4u", "object": "image.generation", "model": "nano-banana-pro", "status": "in_progress", "created_at": 1791000000, "completed_at": null, "data": [], "url_expires_at": null, "cost": null, "error": null, "callback_url": "https://example.com/hooks/zurelay"}/v1/images/{id}Também pode consultar o estado periodicamente: GET /v1/images/{id} devolve o mesmo objeto, com novas ligações em data assim que o seu status for completed. Os callbacks incluem sempre ligações, nunca base64, independentemente do valor de response_format.
O que enviamos
Um POST por evento, com um corpo JSON: type, timestamp e data, a tarefa exatamente como a API a devolve (o objeto de vídeo ou o pedido de imagem acima), com ligações de transferência válidas durante 24 horas.
POST /hooks/zurelay HTTP/1.1content-type: application/jsonuser-agent: Zurelay-Webhooks/1.0 (+https://zurelay.com/docs/webhooks)webhook-id: msg_2c1f9e0b7a4d4f6e8b3a91c05d7e6f42webhook-timestamp: 1791000094webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4={ "type": "video.completed", "timestamp": "2026-10-03T03:21:34.000Z", "data": { "id": "video_Qm3v8Rk2Lx7Pa1Zt9Ws4Yn6B", "object": "video", "model": "seedance-2.0", "status": "completed", "progress": 100, "created_at": 1791000000, "completed_at": 1791000093, "expires_at": 1793592000, "seconds": 5, "resolution": "720p", "aspect_ratio": "16:9", "size": "1280x720", "generate_audio": true, "url": "https://…/video_Qm3v8Rk2Lx7Pa1Zt9Ws4Yn6B.mp4?token=…", "url_expires_at": 1791086494, "cost": 0.45, "error": null, "callback_url": "https://example.com/hooks/zurelay" }}{ "type": "image.completed", "timestamp": "2026-10-03T03:20:41.000Z", "data": { "id": "req_6fJd0kQ3pW9xT2mB7cZ1hR4u", "object": "image.generation", "model": "nano-banana-pro", "status": "completed", "created_at": 1791000000, "completed_at": 1791000041, "data": [{ "url": "https://…/req_6fJd0kQ3pW9xT2mB7cZ1hR4u-1.png?token=…" }], "url_expires_at": 1791086441, "cost": 0.07, "error": null, "callback_url": "https://example.com/hooks/zurelay" }}Verificar a assinatura
Os callbacks seguem o formato Standard Webhooks, o mesmo que os webhooks da OpenAI usam. A assinatura é um HMAC-SHA256 de <webhook-id>.<webhook-timestamp>.<body>, em base64, calculado com o segredo de assinatura do seu espaço de trabalho como chave. Encontre o segredo (começa por whsec_) na página API Chaves de do painel e guarde-o apenas no seu servidor.
import osfrom fastapi import FastAPI, HTTPException, Requestfrom standardwebhooks.webhooks import Webhook # pip install standardwebhookswebhook = Webhook(os.environ["ZURELAY_WEBHOOK_SECRET"]) # whsec_…app = FastAPI()@app.post("/hooks/zurelay")async def zurelay_hook(request: Request): body = await request.body() # the raw bytes: the signature covers exactly these try: event = webhook.verify(body, dict(request.headers)) except Exception: raise HTTPException(status_code=400) handle(event) # event["type"], event["data"]; keep it quick, or queue it return {"ok": True}- Verifique o corpo em bruto: interpretar e voltar a serializar o JSON altera os bytes e, com eles, a assinatura.
- Rejeite um
webhook-timestampcom mais de cinco minutos: isto impede a reutilização de um callback intercetado. As bibliotecas fazem esta verificação por si. - A rotação do segredo (disponível para proprietários e administradores na página Chaves de API) cria um novo de imediato. O antigo continua a ser usado para assinar em paralelo durante 24 horas, por isso configure o seu servidor para usar o novo dentro desse prazo.
Responder primeiro, processar depois
Responda com qualquer 2xx no prazo de 15 segundos para que o callback seja considerado entregue. Guarde o evento e responda primeiro; descarregue o vídeo ou as imagens depois. Um callback pode chegar mais de uma vez (por exemplo, se a sua resposta se perder pelo caminho), por isso use webhook-id para processar cada um apenas uma vez.
Novas tentativas
Qualquer outro resultado (um estado de erro, um redirecionamento, ausência de resposta no prazo de 15 segundos ou um servidor inacessível) leva a uma nova tentativa, até um total de seis:
Cada callback aparece junto do respetivo pedido em Pedidos no painel: o destino, a resposta de cada tentativa e a data da próxima. A opção Repetir callback envia-o de novo imediatamente, tenha sido entregue ou não. Os links incluídos são renovados a cada tentativa.
Tem dúvidas ou falta alguma coisa? Contacte a nossa equipa de apoio e responderemos por email, normalmente num minuto.