Empfio Docs

Custom Webhooks

Receive real-time event notifications in your own system.

Overview

Register any HTTPS URL and Empfio will POST a JSON payload every time a selected event occurs — no polling needed. This is the most flexible integration option, suitable for custom backends, internal tools, or any system that can receive HTTP requests.

Setup

  1. Go to Settings → Integrations → Webhooks
  2. Click Add webhook
  3. Enter your HTTPS endpoint URL
  4. Select which events to subscribe to
  5. Save — Empfio will immediately send a test ping to verify the URL is reachable

Payload format

All webhook payloads share this envelope:

{
  "event": "booking.created",
  "timestamp": "2026-03-07T10:30:00Z",
  "organization_id": "550e8400-...",
  "data": { ... }
}

The data object shape depends on the event type — see Webhook Events for the full reference.

Available events

EventWhen it fires
lead.createdA new lead is captured
lead.status_changedLead status updated
booking.createdAn appointment is confirmed
booking.cancelledAn appointment is cancelled
conversation.escalatedAI agent escalated to a human

Security

Each webhook request includes an X-Empfio-Signature header — an HMAC-SHA256 signature of the raw request body, signed with your webhook secret.

Verifying signatures

To verify that a webhook came from Empfio:

Python:

import hmac
import hashlib

def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        key=secret.encode("utf-8"),
        msg=body,
        digestmod=hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

Node.js:

const crypto = require("crypto");

function verifySignature(body, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Retries

If your endpoint returns a non-2xx response or times out (10 seconds), Empfio retries with exponential backoff:

AttemptDelay
1st retry~1 minute
2nd retry~5 minutes
3rd retry~30 minutes

After all retries fail, the event is logged as failed.

Best practices

  • Return 200 quickly — process the event asynchronously if your logic takes time
  • Handle duplicates — use the timestamp and event data to deduplicate if your endpoint receives the same event twice
  • Verify signatures — always validate the X-Empfio-Signature header in production
  • Use HTTPS — webhook URLs must use HTTPS for security

On this page