Webhooks
Receive real-time notifications when generations complete or fail.
Overview
Instead of polling GET /generations/{id}, you can configure a webhook URL to receive notifications when generations complete or fail.
Setup
Configure your webhook URL in the dashboard at Settings > API Keys. Click "Edit webhook" on any API key to set the URL. Each API key can have its own webhook URL.
A webhook secret is generated when you create the API key. Store it securely -- it's used to verify webhook signatures.
Webhook Payload
When a generation completes or fails, Adsumo sends a POST request to your webhook URL:
{
"event": "generation.completed",
"generation_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "ai-video",
"status": "completed",
"result_url": "https://cdn.adsumo.ai/...",
"created_at": "2026-01-15T12:00:00Z",
"completed_at": "2026-01-15T12:02:30Z"
}For failed generations:
{
"event": "generation.failed",
"generation_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "ai-video",
"status": "failed",
"error_message": "Video generation failed due to content policy violation",
"created_at": "2026-01-15T12:00:00Z",
"completed_at": "2026-01-15T12:02:30Z"
}Events
| Event | Description |
|---|---|
generation.completed | Generation finished successfully. result_url is available. |
generation.failed | Generation failed. error_message describes the failure. |
Signature Verification
Every webhook request includes an X-Adsumo-Signature header containing an HMAC-SHA256 signature of the request body, signed with your webhook secret.
Always verify signatures to ensure the webhook is from Adsumo.
import crypto from 'crypto';
function verifyWebhook(body: string, signature: string, secret: string): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected),
);
}
// In your webhook handler:
const body = await request.text();
const signature = request.headers.get('x-adsumo-signature');
if (!verifyWebhook(body, signature, process.env.WEBHOOK_SECRET)) {
return new Response('Invalid signature', { status: 401 });
}
const event = JSON.parse(body);Delivery
- Webhooks are sent once (single delivery attempt)
- Your endpoint should return a 2xx status within 10 seconds
- If your endpoint is down, the webhook is dropped
Best Practices
- Always verify the signature before processing
- Respond with 200 quickly, then process the event asynchronously
- Use the
generation_idto look up the full generation details viaGET /generations/{id} - Store the webhook secret securely (environment variable, not in code)