Skip to Content

Webhooks

Passez un callback_url lorsque vous créez une tâche et ofox livre le résultat par webhook au lieu que vous l’interrogiez. Lorsque la tâche atteint un état terminal, ofox envoie un POST à votre URL avec l’objet complet de la tâche dans le corps (une livraison échouée est relancée — voir la section Relances ci-dessous).

callback_url doit être en HTTPS et passer la validation SSRF (les adresses privées, loopback et de métadonnées cloud sont rejetées). Une URL invalide est rejetée à la création avec 400 invalid_callback_url — voir Créer une vidéo.

Événements

Un événement est livré par tâche, correspondant au statut terminal sur lequel elle s’est stabilisée (la même valeur apparaît dans data.status).

ÉvénementDéclenché quand
video.generation.completedLa tâche a réussi
video.generation.failedLa tâche a échoué
video.generation.cancelledLa tâche a été annulée
video.generation.expiredLa tâche a expiré

Payload de livraison

Chaque livraison est un POST vers votre callback_url avec ces Headers :

POST https://your-app.example/webhooks/ofox-video Content-Type: application/json X-Ofox-Idempotency-Key: 9bcf3c60-7db2-4e1a-a1b2-c3d4e5f60718-completed X-Ofox-Signature: <HMAC-SHA256, base64url>

Le corps est une enveloppe. Son champ data est identique au corps de réponse Obtenir le statut vidéo pour la même tâche :

{ "event": "video.generation.completed", "id": "9bcf3c60-7db2-4e1a-a1b2-c3d4e5f60718", "created_at": 1776211400, "data": { "id": "9bcf3c60-7db2-4e1a-a1b2-c3d4e5f60718", "status": "completed", "model": "google/veo-3.1", "prompt": "A golden retriever running on the beach at sunset", "unsigned_urls": ["https://upstream.example/out.mp4"], "mirror_urls": ["https://cdn.ofox.ai/videos/vgen_xxx.mp4?sig=..."], "usage": { "video_seconds": 5, "video_cost": "0.4000000000" }, "created_at": 1776211362, "updated_at": 1776211400 } }
ChampTypeDescription
eventstringL’un des types d’événements ci-dessus
idstringId de tâche (UUID)
created_atintegerHorodatage de l’événement, secondes Unix
dataobjectL’objet complet de la tâche — même forme que GET /v1/videos/{id}

Idempotence

Le même événement peut être livré plusieurs fois — une relance peut se produire après que votre endpoint a déjà traité la première livraison. Dédupliquez sur le Header X-Ofox-Idempotency-Key, qui vaut <id>-<status> (par exemple 9bcf3c60-7db2-4e1a-a1b2-c3d4e5f60718-completed), et traitez chaque clé au plus une fois.

Répondez avec n’importe quel statut 2xx pour accuser réception. Une réponse non-2xx ou un timeout est traité comme une livraison échouée et déclenche une relance ; renvoyez donc 2xx rapidement et effectuez tout traitement lourd de façon asynchrone.

Vérification de signature

Chaque livraison porte un Header X-Ofox-Signature : HMAC-SHA256(raw request body, your webhook secret), encodé en base64url. Recalculez-le avec votre secret et comparez en temps constant avant de faire confiance au payload.

verify-webhook.js
import crypto from 'node:crypto' // X-Ofox-Signature = HMAC-SHA256(raw request body, your webhook secret), // base64url-encoded. function verifyOfoxSignature(rawBody, signatureHeader, secret) { if (typeof signatureHeader !== 'string') return false const expected = crypto .createHmac('sha256', secret) .update(rawBody) .digest('base64url') const a = Buffer.from(expected) const b = Buffer.from(signatureHeader) // Constant-time compare; guard length first (timingSafeEqual throws on mismatch). return a.length === b.length && crypto.timingSafeEqual(a, b) }

Calculez le HMAC sur les octets bruts exactement tels que reçus, avant tout parsing JSON ou toute re-sérialisation — sinon la signature ne correspondra pas. Dans Express, capturez le corps avec express.raw({ type: 'application/json' }).

Relances

Une livraison échouée (non-2xx ou timeout) est relancée automatiquement avec un backoff exponentiel plafonné plus jitter — jusqu’à 10 relances sur une fenêtre d’environ 40 minutes. Le délai avant la relance n est min(5·2^(n-1), 600) secondes, plus un jitter aléatoire.

RelanceDélaiCumul
15s5s
210s15s
320s35s
440s1m15s
580s2m35s
6160s5m15s
7320s10m35s
8600s (capped)20m35s
9600s30m35s
10600s40m35s

Fallback

Si toutes les relances sont épuisées, ofox cesse les tentatives de livraison. Le résultat de la tâche n’est jamais perdu — vous pouvez toujours interroger GET /v1/videos/{id} pour récupérer l’état final (sous réserve de la limite de débit de cet endpoint).

Last updated on