# Webhooks

> Receive events — new messages, replies, account status changes, accepted invitations.

Webhooks push events to your server as they happen, so you don't have to poll. Register an HTTPS endpoint and CorrectInbox `POST`s a JSON body for each event.

## Register an endpoint

```http
POST /v1/webhooks
```

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `url` | string | yes | Your HTTPS endpoint. |
| `events` | string[] | no | Events to receive. Omit for all. |

```bash
curl -X POST https://api.correctinbox.com/v1/webhooks \
  -H "X-API-KEY: $CORRECTINBOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://yourapp.com/hooks/correctinbox", "events": ["message.received", "account.disconnected"] }'
```

```js
await fetch("https://api.correctinbox.com/v1/webhooks", {
  method: "POST",
  headers: {
    "X-API-KEY": process.env.CORRECTINBOX_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://yourapp.com/hooks/correctinbox",
    events: ["message.received", "account.disconnected"],
  }),
});
```

```python
requests.post(
    "https://api.correctinbox.com/v1/webhooks",
    headers={"X-API-KEY": os.environ["CORRECTINBOX_API_KEY"]},
    json={"url": "https://yourapp.com/hooks/correctinbox", "events": ["message.received", "account.disconnected"]},
)
```

## Event types

| Event | Fires when |
| --- | --- |
| `account.connected` | An account finishes linking and is operational. |
| `account.disconnected` | An account's session becomes invalid. |
| `message.received` | A new inbound message arrives in any chat. |
| `campaign.reply` | A lead replies to a campaign. |
| `invitation.accepted` | Someone accepts a connection request you sent. |

## Delivery payload

Every delivery is an HTTPS `POST` with this envelope:

```json
{
  "id": "evt_6h2k",
  "type": "message.received",
  "created_at": "2026-02-01T18:02:11Z",
  "data": {
    "account_id": "acc_8f21c0",
    "chat_id": "cht_19ab",
    "message": { "id": "msg_09", "from_me": false, "text": "Thursday works!" }
  }
}
```

## Verify deliveries

Each request carries an `X-CorrectInbox-Signature` header — an HMAC‑SHA256 of the raw body using your webhook's signing secret (shown once when you create the webhook). Recompute it and compare before trusting a payload.

```js
import crypto from "node:crypto";

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

Respond `2xx` within a few seconds. CorrectInbox retries failed deliveries with exponential backoff.
