Webhooks

Webhooks allow you to receive real-time notifications when your dashboard generation completes, eliminating the need to poll the status endpoint.

Overview

If a webhook is configured (one per user) and the request used the API key, Alloy will POST a dashboard.ready event to your webhook URL when processing completes.

Configuration

Configure your webhook URL in the Alloy dashboard. Only one webhook URL can be configured per user account.

Security: Signature Verification

All webhook requests include a signature header that you must verify to ensure the request is authentic and hasn't been tampered with.

Signature Header

The request always includes:

  • X-Alloy-Signature: HMAC SHA256 signature of the raw JSON body, using the SHA256 hash of your API key as the secret.

The secret is calculated as:

secret = sha256(b"alloy_<your_key>").hexdigest()

Webhook Payload

The webhook payload includes the following fields:

  • generation_id - The ID of the generation request

  • dashboard_id - The ID of the generated dashboard

  • dataset_id - The ID of the uploaded dataset

  • title - The dashboard title

  • share_link_id - The ID of the share link

  • share_url - The URL to view the dashboard

Example Webhook Payload

{
  "event": "dashboard.ready",
  "timestamp": "2025-01-08T10:16:12.456Z",
  "data": {
    "generation_id": "af52d214-...",
    "dashboard_id": "d6ad65c0-...",
    "dataset_id": "1b0b7d3e-...",
    "title": "Q3 Sales Overview",
    "share_link_id": "4a5b...",
    "share_url": "https://api.example.com/share/4a5b.../view/"
  }
}

Verifying the Signature

Python Example

import hashlib, hmac, json

payload_bytes = request.body  # raw bytes
signature = request.headers.get("X-Alloy-Signature")

# Derive the secret Alloy used: sha256 of your API key string
api_key_hash = hashlib.sha256(b"alloy_yourapikey").hexdigest()

expected = hmac.new(
    api_key_hash.encode("utf-8"),
    payload_bytes,
    hashlib.sha256
).hexdigest()

if not hmac.compare_digest(signature, expected):
    raise ValueError("Invalid webhook signature")

Node.js Example

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, apiKey) {
  // Derive the secret: SHA256 hash of the API key
  const secret = crypto
    .createHash('sha256')
    .update(`alloy_${apiKey}`)
    .digest('hex');
  
  // Calculate expected signature
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  // Use timing-safe comparison
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Usage
const isValid = verifyWebhookSignature(
  request.body,
  request.headers['x-alloy-signature'],
  'yourapikey'
);

if (!isValid) {
  throw new Error('Invalid webhook signature');
}

Best Practices

1

Always verify the signature

Never process webhook requests without verifying the signature.

2

Use raw request body

Make sure you're using the raw bytes/string of the request body, not a parsed JSON object.

3

Handle errors gracefully

Return appropriate HTTP status codes (200 for success, 4xx for errors).

4

Idempotency

Your webhook handler should be idempotent, as webhooks may be retried.

5

Timeout

Respond quickly (within 5 seconds) to avoid timeouts.

Testing Webhooks

You can test your webhook endpoint using tools like:

  • https://ngrok.com/ (ngrok) - Expose local server to the internet

  • https://webhook.site/ (webhook.site) - Temporary webhook testing service

  • https://www.postman.com/ (Postman) - API testing tool

Last updated