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:

JSON
{
  "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:

JSON
{
  "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

EventDescription
generation.completedGeneration finished successfully. result_url is available.
generation.failedGeneration 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_id to look up the full generation details via GET /generations/{id}
  • Store the webhook secret securely (environment variable, not in code)