لا حاجة إلى الاستطلاع المتكرر. يرسل Flixly طلب POST بحدث موقَّع إلى عنوانك في اللحظة التي تكتمل فيها عملية التوليد، سواء كان الطلب متزامنًا (نماذج الصور) أو غير متزامن (نماذج الفيديو وقوائم الانتظار البطيئة).
يحمل كل تسليم توقيعًا محسوبًا على `${timestamp}.${body}`، فتستطيع التأكد من أنه صادر عنا فعلًا وأنه لم يُعبث به.
يتيح لك ترويسة X-Flixly-Timestamp رفض أي توقيع أقدم من 5 دقيقة تقريبًا، وهو دفاع ضد إعادة إرسال الطلبات الملتقطة.
3 محاولات مع تباعد أُسّي (فوري، +2s، +6s). مهلة 5 ثانية لكل محاولة. ويبقى استطلاع /generations/{id} خيارك البديل.
لكل مفتاح API سرّ webhook خاص به. يمكنك تدويره في أي وقت من لوحة التحكم، وعندها تفشل التواقيع القديمة في التحقق فورًا.
طريقتان لإخبار Flixly بالوجهة التي يرسل إليها أحداثك عبر POST:
اضبط عنوان webhook افتراضيًا وأنشئ سرًّا للتوقيع على كل مفتاح API. عندها تُسلَّم كل عملية توليد أُرسلت بذلك المفتاح إلى ذلك العنوان.
تجاوز القيمة الافتراضية للمفتاح في كل طلب بتعيين webhook_url في جسم طلب الـ POST. مفيد للوجهات العابرة أو للتوجيه حسب البيئة.
POST /api/v1/generate
{
"model": "veo-3-fast",
"prompt": "...",
"webhook_url": "https://you/hook"
}طلب POST واحد لكل عملية توليد مكتملة (أو فاشلة). جسم بصيغة JSON وترويسات موقَّعة.
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 أو generation.failed.POST /api/v1/generate وتستخدمه مع GET /api/v1/generations/{id}.completed أو failed بحلول وقت التسليم.null عند الفشل.null عند النجاح. وهي منقّحة مسبقًا، فيمكن عرضها لمستخدميك بأمان.نوقّع كل تسليم بخوارزمية HMAC-SHA256 على `${timestamp}.${body}`. وأنت تعيد حساب الـ HMAC على خادمك بالسرّ الذي عرضناه لك عند إنشائه، ثم تقارن في زمن ثابت.
إن JSON.parse ثم JSON.stringify يغيّران المسافات وترتيب الحقول، وهو ما يُبطل التوقيع. في Express استخدم وسيطًا برمجيًا للجسم الخام، وفي App Router الخاص بـ Next.js استدعِ await req.text() قبل 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");
}يتبع كل تسليم النمط نفسه، متزامنًا كان أم غير متزامن:
2xx. أعد 200 OK بجسم فارغ إن لم يكن لديك ما تقوله.301 و302 وسائر استجابات 3xx على أنها إخفاقات، لأنها ستُسقط ترويسة X-Flixly-Signature بصمت عند القفزة التالية.يحمل كل تسليم ترويسة X-Flixly-Delivery-Id فريدة. فإن أدّت إعادة المحاولة إلى استقبالك الحدث نفسه مرتين (مثلًا انطلقت إعادة محاولتنا بينما تأخّرت استجابتك الأولى في الوصول إلينا)، فاستعمل تلك الترويسة لإزالة التكرار من جهتك.
حقل id في الحدث هو معرّف عملية التوليد، وهو ثابت عبر كل محاولات التسليم الواحد. أما X-Flixly-Delivery-Id فلا يتغير بين المحاولات إلا إذا أعدنا بناء الحمولة (وهو ما لا نفعله حاليًا).