Fini le polling. Flixly envoie un POST signé à votre URL à l'instant où une génération aboutit — que la requête ait été synchrone (modèles d'image) ou asynchrone (modèles vidéo, files d'attente lentes).
Chaque livraison porte une signature calculée sur `${timestamp}.${body}`, ce qui vous permet de vérifier qu'elle vient bien de nous et qu'elle n'a pas été altérée.
L'en-tête X-Flixly-Timestamp vous permet de rejeter les signatures de plus de 5 minutes environ — une défense contre les rejeux de requêtes capturées.
3 tentatives avec backoff exponentiel (immédiat, +2s, +6s). Délai d'attente de 5 secondes par tentative. Interroger /generations/{id} reste votre solution de repli.
Chaque clé API a son propre secret de webhook. Vous pouvez le renouveler à tout moment depuis le tableau de bord : les anciennes signatures échouent immédiatement à la vérification.
Deux façons d'indiquer à Flixly où envoyer vos événements en POST :
Définissez une URL de webhook par défaut et générez un secret de signature sur chaque clé API. Toute génération soumise avec cette clé est livrée à cette URL.
Remplacez la valeur par défaut de la clé requête par requête en renseignant webhook_url dans le corps du POST. Pratique pour des destinations ponctuelles ou pour router selon l'environnement.
POST /api/v1/generate
{
"model": "veo-3-fast",
"prompt": "...",
"webhook_url": "https://you/hook"
}Un POST par génération terminée (ou échouée). Corps JSON, en-têtes signés.
POST https://your-server.example.com/flixly-webhook
Content-Type: application/json
User-Agent: Flixly-Webhook/1.0
X-Flixly-Event: generation.completed
X-Flixly-Timestamp: 1781085600
X-Flixly-Signature: sha256=abc123...
X-Flixly-Delivery-Id: wh_a1b2c3d4e5f6g7h8{
"event": "generation.completed",
"id": "j5h2k9...",
"status": "completed",
"type": "TEXT_TO_IMAGE",
"model": "flux-dev",
"output_url": "https://cdn.flixly.ai/outputs/...",
"credits_charged": 1,
"error": null,
"created_at": "2026-06-06T12:00:00Z",
"completed_at": "2026-06-06T12:00:05Z"
}generation.completed ou generation.failed.POST /api/v1/generate et que vous utilisez avec GET /api/v1/generations/{id}.completed ou failed au moment de la livraison.null en cas d'échec.null en cas de succès. Déjà nettoyé — vous pouvez l'afficher tel quel à vos utilisateurs.Nous signons chaque livraison en HMAC-SHA256 sur `${timestamp}.${body}`. Vous recalculez le HMAC sur votre serveur avec le secret affiché lors de sa génération, puis vous comparez en temps constant.
JSON.parse → JSON.stringify modifie les espaces et l'ordre des champs, ce qui casse la signature. Sous Express, utilisez un middleware de raw body. Dans l'App Router de Next.js, appelez await req.text() avant await req.json().
import { Flixly } from "@flixly/sdk";
// In your webhook handler — Express, Hono, Next.js, etc.
export async function POST(req) {
const rawBody = await req.text(); // MUST be raw — re-stringifying breaks the signature
const signature = req.headers.get("x-flixly-signature");
const timestamp = req.headers.get("x-flixly-timestamp");
const valid = await Flixly.verifyWebhookSignature({
secret: process.env.FLIXLY_WEBHOOK_SECRET,
timestamp,
signature,
body: rawBody,
tolerance: 300, // optional — defaults to 300s replay window
});
if (!valid) {
return new Response("invalid signature", { status: 401 });
}
const event = JSON.parse(rawBody);
// event.event === "generation.completed" | "generation.failed"
// event.id, event.status, event.output_url, event.credits_charged, ...
await handleGenerationEvent(event);
return new Response("ok");
}Chaque livraison suit le même schéma, en synchrone comme en asynchrone :
2xx. Renvoyez 200 OK avec un corps vide si vous n'avez rien à dire.301, 302 et les autres réponses 3xx comme des échecs : elles supprimeraient silencieusement l'en-tête X-Flixly-Signature au saut suivant.Chaque livraison porte un en-tête X-Flixly-Delivery-Id unique. Si des réessais vous font recevoir deux fois le même événement (par exemple, notre réessai est parti alors que votre première réponse mettait trop de temps à nous parvenir), servez-vous de cet en-tête pour dédoublonner de votre côté.
Le champ id de l'événement est l'id de la génération — identique d'un réessai à l'autre pour une même livraison. Le X-Flixly-Delivery-Id ne change d'une tentative à l'autre que si nous reconstruisons le payload (ce que nous ne faisons pas aujourd'hui).