# Webhooks

> SmartChat calls your web address when something happens. Headers, payload, delivery rules and how to respond.

Last updated: 2026-10-30. Source: https://docs.smartchat.marketing/en/webhooks/overview/

A webhook lets SmartChat tell your software that something happened, for example a new contact or a message that was delivered. You register an **endpoint** (an https address) and choose the **events** you want. SmartChat sends each event to the endpoint as a `POST` with a JSON body.

Set one up in [Set up a webhook](https://docs.smartchat.marketing/en/guides/set-up-a-webhook/). The list of events is on the [events page](https://docs.smartchat.marketing/en/webhooks/events/).

## What you receive

Headers:

| Header | Meaning |
|---|---|
| `SmartChat-Signature` | `t=<unix seconds>,v1=<hex>`. Proves the delivery is from SmartChat. [How to check it](https://docs.smartchat.marketing/en/webhooks/signature-verification/). |
| `SmartChat-Event-Id` | ID of the event (`evt_...`). Same for every endpoint. |
| `SmartChat-Event-Type` | The event name, for example `contact.created`. |
| `SmartChat-Delivery-Id` | ID of this delivery (`whd_...`). |
| `SmartChat-Delivery-Attempt` | Number of this try, starting at 1. |
| `User-Agent` | `SmartChat-Webhooks/2` |
| `Content-Type` | `application/json` |

Body:

```json
{
  "id": "evt_0f8c1a2e4b7d4c3e9a5b6d7e8f901234",
  "object": "event",
  "type": "contact.opted_out",
  "api_version": "2026-10-25",
  "created_at": "2026-10-25T09:41:07.412Z",
  "sequence": 128734,
  "account_id": "acc_0f8c1a2e4b7d4c3e9a5b6d7e8f901234",
  "livemode": true,
  "request_id": "req_01JAB9C3X7K2M4N5P6Q7R8S9T0",
  "data": {
    "object": { "object": "contact", "id": "con_0f8c1a2e4b7d4c3e9a5b6d7e8f901234", "optin_whatsapp": "opted_out" },
    "previous_attributes": { "optin_whatsapp": "confirmed" }
  }
}
```

| Field | Meaning |
|---|---|
| `id` | Event ID. Use it to find duplicates. |
| `type` | Event name. |
| `created_at` | When the event happened, with milliseconds, in UTC. |
| `sequence` | A counter to sort events. |
| `request_id` | The ID of the API call that caused the event, if there was one. |
| `data.object` | The object the event is about. |
| `data.previous_attributes` | For changes: the old values of the changed fields. |

The body is at most 256 KB. If it would be larger, `data.object` is cut to `object` and `id` and the body gets `"truncated": true`. Read the full object with the API.

## What you must do

1. **Check the signature** with the raw body. [Code in shell, Python and TypeScript](https://docs.smartchat.marketing/en/webhooks/signature-verification/).
2. **Answer fast** with any 2xx status. SmartChat waits 10 seconds. Do the real work after you answered.
3. **Expect duplicates.** Delivery is *at least once*. Keep the `id` of events you handled and skip repeats.
4. **Do not rely on order.** Events can arrive out of order. Use `sequence` or `created_at` to sort.
5. **Use https.** Only https on port 443 is allowed, without a user name or password in the address, and without redirects. Internal and private addresses are refused ([`webhook_url_invalid`](https://docs.smartchat.marketing/en/errors/#webhook_url_invalid)). SmartChat checks the address when you save it and again at every connection.

An account can have up to 20 endpoints. The same address twice in one account is a conflict. Endpoints belong to the account, not to a key: revoking the key that created an endpoint does not stop it.

## Failures

If your endpoint does not answer with 2xx, SmartChat tries again later. The schedule, the health states of an endpoint and what happens at the end are on [Retries and health](https://docs.smartchat.marketing/en/webhooks/retries/).

