📢 Overview

To receive webhook events, your server must expose a publicly accessible HTTPS endpoint. This endpoint will handle webhook requests securely and validate them. Webhooks are sent as asynchronous HTTP POST requests containing event-related data. These requests must be handled in near real-time, as they will not wait for a response before continuing execution.

🔗 Webhook URL Format

Your server should expose a publicly accessible HTTPS endpoint to receive webhook notifications.

Example:

POST https://your-domain.com/webhook-handler

🔐 Security & Validation

Each webhook request includes an HMAC SHA-256 signature in the X-Webhook-Signature header. This signature is generated using a pre-shared secret token and the exact request payload.

What is the Secret Token?

The secret token is a unique, private key that only you and our system know. It is used to sign webhook requests and allows your server to verify that they are authentic and untampered.

  • How is it generated? You generate the secret token and provide it to our system when configuring the webhook.
  • How should it be stored? It must be stored securely on your server and never shared or exposed publicly.
  • How is it used? It is used to compute a signature that validates the authenticity of incoming webhooks.

How Signature Verification Works

The recipient must verify this signature to ensure:

  • The request originated from a trusted source (authentication).
  • The request was not altered in transit (integrity).

Example Header:

X-Webhook-Signature: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

Validation Steps:

  1. Extract the X-Webhook-Signature from headers.
  2. Recompute the signature using your secret token and the request payload.
  3. Use hmac.compare_digest() to compare the expected vs. received signature.
  4. If they do not match, reject the request with HTTP 403 Forbidden.

📥 Webhook Handling Example (Python)

This is an example implementation of a webhook receiver with validation:

from fastapi import FastAPI, Request, HTTPException, Header
import hmac
import hashlib
import json
import logging

app = FastAPI()
logger = logging.getLogger(__name__)

# Replace with your actual secret key
WEBHOOK_SECRET = "your-secret-token"

@app.post("/webhook-handler")
async def webhook_handler(
    request: Request,
    x_webhook_signature: str = Header(None)
):
    """
    Webhook receiver with security validation.
    Ensures message integrity using HMAC.
    """
    payload = await request.json()
    headers = dict(request.headers)

    # Validate HMAC Signature
    if not x_webhook_signature:
        logger.error("❌ Missing X-Webhook-Signature header.")
        raise HTTPException(status_code=400, detail="Bad Request: Missing signature header.")
    
    # Normalize JSON to ensure signature consistency across different implementations
    normalized_payload = json.dumps(payload, separators=(',', ':'), sort_keys=True).encode()

    # Recompute the expected signature
    expected_signature = hmac.new(
        WEBHOOK_SECRET.encode(),
        normalized_payload,
        hashlib.sha256
    ).hexdigest()
    
    if not hmac.compare_digest(expected_signature, x_webhook_signature):
        logger.error("❌ Signature mismatch. Potential tampering detected.")
        raise HTTPException(status_code=403, detail="Forbidden: Signature verification failed.")
    
    logger.info("✅ Webhook validation successful.")
    return {"message": "Webhook received"}

✅ Response Codes

Status CodeMeaning
200 OKWebhook received and validated successfully.
400 Bad RequestMalformed request (e.g., missing JSON body, missing headers).
403 ForbiddenSignature verification failed (invalid or missing signature).

🔄 Retry Logic

If your server returns any 4xx or 5xx errors, we will retry the webhook.

Webhook retries follow exponential backoff:

1 min → 5 min → 15 min → 1h → 2h → Max retries: 5 times.

If all retries fail, the event will not be resent.

❓ FAQs

How do I update my webhook URL?
You can provide a new webhook URL via your account settings or by contacting support.

Can I receive multiple webhook events?
Yes. Webhooks are event-driven. You can subscribe to different events.

What happens if my server is down?
We will retry delivery as per our retry policy above.