Skip to content
DocsGo to Dashboard
Signed webhooks

X-Weboptiva-Signature holds an HMAC-SHA256 of the raw JSON body, keyed with your webhook secret

Every outbound CRM delivery carries a signature header so your receiver can prove the payload was produced by WebOptiva — not merely delivered over a URL anyone knows.

What arrives#

POST with Content-Type: application/json and three headers:

  • X-Weboptiva-Signature — HMAC-SHA256(secret, rawBody), hex-encoded (lowercase, no prefix).
  • X-Weboptiva-Event — the event name, currently lead.captured.
  • X-Weboptiva-Delivery — the delivery id, identical to the payload's deliveryId and idempotencyKey, stable across every retry of the same delivery.

The JSON body is { event, deliveryId, idempotencyKey, lead }, where lead carries your lead fields after the connection's field mapping (at most 50 mapping entries) is applied.

How to verify#

Read the raw request bytes before any JSON parsing or re-serialization — a recomputed body with different key order produces a different digest. Compute the hex HMAC-SHA256 of those bytes with the connection's webhook secret and compare against the header using a constant-time comparison (timingSafeEqual in Node, hmac.compare_digest in Python). Reject on mismatch. Then deduplicate: retries reuse the same deliveryId, so treat repeats as the same event and respond 2xx idempotently.

The secret#

The signing secret is generated when the connection is first saved (32 random bytes, base64url) and preserved across every subsequent save, while API responses expose only the URL and field mapping — never the key itself. The endpoint must be a public https URL (Webhook URL must use https.), which is also what the connection test exercises before you go live.

Back to Signed webhooks