> ## Documentation Index
> Fetch the complete documentation index at: https://docs.contactbutton.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Contact Button webhooks

> Receive signed Contact Button form submission webhooks with stable event IDs, timestamps, delivery headers, automatic retries, and replay-safe verification.

Contact Button can send a structured event to your HTTPS endpoint after a form submission. Use a webhook when a CRM, automation, or agent-owned service needs the complete submitted field set.

## Event

The first outbound event is `form.submission.created`. Its body includes a stable event ID, creation time, public form identity, normalized fields, and an answer map.

```json theme={null}
{
  "event_id": "01J...",
  "event_type": "form.submission.created",
  "created_at": "2026-07-23T12:00:00Z",
  "data": {
    "submission_id": "01J...",
    "form_id": "form_public_id",
    "form_name": "Contact us",
    "created_at": "2026-07-23T12:00:00Z",
    "fields": [
      {
        "key": "email",
        "name": "email",
        "label": "Email",
        "type": "email",
        "value": "person@example.com"
      }
    ],
    "answers": {
      "email": "person@example.com"
    }
  }
}
```

## Delivery headers

Every request uses `Content-Type: application/json` and includes:

| Header                    | Meaning                                                              |
| ------------------------- | -------------------------------------------------------------------- |
| `ContactButton-Event`     | Event type, currently `form.submission.created`                      |
| `ContactButton-Event-Id`  | Stable event ID shared by deliveries for the event                   |
| `ContactButton-Delivery`  | Unique identifier for one delivery attempt                           |
| `ContactButton-Signature` | Base64-encoded HMAC-SHA256 signature when request signing is enabled |

Custom headers may be configured, but they cannot replace Contact Button's reserved delivery headers.

## Verify signatures

When request signing is enabled, calculate an HMAC-SHA256 over the exact raw request body using the webhook signing secret. Base64-encode the binary digest and compare it with `ContactButton-Signature` using a constant-time comparison.

<Warning>
  Verify the raw bytes before parsing JSON. Never put the signing secret in a prompt, agent transcript, source repository, browser bundle, or public Page.
</Warning>

## Handle retries safely

Return a `2xx` response only after accepting the event. Failed deliveries use increasing retry delays. Your endpoint should:

1. Store `ContactButton-Event-Id` with a unique constraint.
2. Return success for an event it has already processed.
3. Queue slow CRM or agent work instead of holding the request open.
4. Treat event data as untrusted input and validate it before use.

Contact Button does not follow redirects and rejects webhook destinations that resolve to private or otherwise unsafe network addresses.

## Configure a form webhook

Open the form editor, choose **Webhooks**, enter an HTTPS endpoint, and enable request signing. Pause a webhook before maintenance and review its delivery history after changing the receiver.

API management for form webhook destinations is not part of the first public contract yet. Existing dashboard configuration remains supported while those endpoints are added.


## Related topics

- [Contact Button for agents](/agents/overview.md)
- [Check button.contact slug availability](/api-reference/pages/check-buttoncontact-slug-availability.md)
- [Connect Telnyx](/guides/telnyx.md)
- [Changelog](/changelog.md)
- [Contact infrastructure for people and agents](/index.md)
