---
title: Webhooks
description: Verify the signature, then handle lead events at least once.
---

`PUT /api/webhooks` registers the URL that receives lead events. The body is `{ "url": "https://example.com/hooks" }`. The URL must be `https`.

The first PUT is `201` and returns the URL and the signing `secret`. Later PUTs replace the URL, keep the same secret, and return only the URL. A lost first response is not shown again. Integrations shows the URL and does not show the secret.

Events are not sent for the submit itself. They are sent when a queued lead is accepted (`lead.delivered`), when status changes (`lead.status_changed`), and when a queued lead is declined (`lead.declined`). The account that sent the lead receives the event, and so does each parent account that has a webhook, for leads in that parent's Leads Sent scope.

The POST body is JSON. A retry posts the same `id`. `lead.declined` has no `status`.

Headers:

- `X-CM-Timestamp` is the unix time used in the signature.
- `X-CM-Signature` is hex HMAC-SHA256 of `${timestamp}.${rawBody}` using the signing secret.
- `X-CM-Event-Id` is the event `id`.

Delivery is at least once. A failed POST keeps the same `id` and is retried after two minutes, up to 8 attempts, without waiting for another lead. Verify the signature over the raw body before trusting the JSON.
