Skip to main content

Webhooks

Webhooks provide real-time notifications when your video generation tasks complete. Instead of polling the API, your server receives an HTTP POST request when the task finishes.

Setting Up Webhooks

Include a webhook_url in your slideshow request:
curl -X POST https://api.vibepeak.ai/v1/real-estate/narrated-slideshow \
  -H "Authorization: Bearer vpk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "images": [
      "https://example.com/living-room.jpg",
      "https://example.com/kitchen.jpg",
      "https://example.com/bedroom.jpg",
      "https://example.com/bathroom.jpg",
      "https://example.com/backyard.jpg"
    ],
    "webhook_url": "https://yourserver.com/webhooks/vibepeak"
  }'

Webhook Payload

When a task completes (successfully or with an error), VibePeak sends a POST request to your webhook URL:

Successful Completion

{
  "event": "task.completed",
  "task_id": "task_abc123xyz",
  "status": "completed",
  "created_at": "2026-01-04T12:00:00Z",
  "completed_at": "2026-01-04T12:15:00Z",
  "result": {
    "video_url": "https://storage.vibepeak.ai/videos/task_abc123xyz.mp4",
    "cover_image_url": "https://storage.googleapis.com/vibepeak-audio/covers/task_abc123xyz.jpg",
    "duration_seconds": 45,
    "resolution": "1080p",
    "expires_at": "2026-01-11T12:15:00Z"
  }
}

Failed Task

{
  "event": "task.failed",
  "task_id": "task_abc123xyz",
  "status": "failed",
  "created_at": "2026-01-04T12:00:00Z",
  "completed_at": "2026-01-04T12:06:00Z",
  "error": {
    "code": "IMAGE_PROCESSING_FAILED",
    "message": "Failed to process image at index 2: Invalid image format"
  }
}

Webhook Headers

Each webhook request includes the following headers:
HeaderDescription
Content-Typeapplication/json
X-VibePeak-SignatureHMAC-SHA256 signature for verification
X-VibePeak-TimestampUnix timestamp when the webhook was sent
X-VibePeak-EventEvent type (task.completed or task.failed)

Webhook Secret

Each API key has an associated webhook secret used for signing webhook payloads. You can find your webhook secret in the VibePeak Dashboard under your API key settings.
Your webhook secret is displayed only once when you create an API key. Store it securely - if you lose it, you’ll need to regenerate your API key.

Verifying Webhooks

Always verify webhook signatures to ensure requests are from VibePeak.
Webhooks are signed using HMAC-SHA256 with your webhook secret. Verify the signature before processing:
const crypto = require('crypto');

function verifyWebhook(payload, signature, timestamp, secret) {
  const signedPayload = `${timestamp}.${JSON.stringify(payload)}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// Express.js example
app.post('/webhooks/vibepeak', express.json(), (req, res) => {
  const signature = req.headers['x-vibepeak-signature'];
  const timestamp = req.headers['x-vibepeak-timestamp'];

  if (!verifyWebhook(req.body, signature, timestamp, process.env.WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process the webhook
  const { event, task_id, result, error } = req.body;

  if (event === 'task.completed') {
    console.log(`Video ready: ${result.video_url}`);
    console.log(`Cover image: ${result.cover_image_url}`);
  } else if (event === 'task.failed') {
    console.log(`Task failed: ${error.message}`);
  }

  res.status(200).json({ received: true });
});

Webhook Requirements

Your webhook endpoint must:

HTTPS Only

Webhook URLs must use HTTPS for security

Respond Quickly

Return a 2xx response within 30 seconds

Be Idempotent

Handle duplicate deliveries gracefully

Publicly Accessible

Be reachable from the internet

Retry Policy

If your webhook endpoint fails to respond with a 2xx status code, VibePeak will retry the delivery with exponential backoff:
AttemptDelay
1st retry1 second
2nd retry2 seconds
3rd retry4 seconds
After 3 failed attempts, the webhook is marked as failed. You can still retrieve the task status via the API by polling /v1/tasks/{taskId}.

Testing Webhooks

For local development, use a tunneling service like ngrok:
# Start ngrok
ngrok http 3000

# Use the ngrok URL in your request
curl -X POST https://api.vibepeak.ai/v1/real-estate/narrated-slideshow \
  -H "Authorization: Bearer vpk_test_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "images": ["..."],
    "webhook_url": "https://abc123.ngrok.io/webhooks/vibepeak"
  }'

Best Practices

Process webhooks asynchronously. Return a 200 response immediately, then process the payload in a background job.
  1. Return quickly - Acknowledge receipt with a 200 response before processing
  2. Use a queue - Process webhook payloads asynchronously
  3. Store the task_id - Always log the task_id for debugging
  4. Handle duplicates - Use the task_id to deduplicate events
  5. Verify signatures - Always validate the webhook signature
  6. Download promptly - Video URLs expire after 7 days