---
updatedAt: 2026-08-01T20:05:20.000Z
---

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

# Webhooks

**Lodgestory CRM › Settings → Webhooks**

`Added On Request `

# Webhooks

> **Get real-time notifications in your own systems the moment something happens in Lodgestory — a message sent or received, a ticket created, a campaign finished, a channel connected.**

> **TL;DR**
>
> * **What it is —** you register an HTTPS endpoint, choose which events you care about, and Lodgestory sends a signed notification to that endpoint whenever one of those events happens, across every channel.
> * **Who it's for —** developers and technical teams who want to sync Lodgestory activity into a CRM, data warehouse, helpdesk, or any internal tool.
> * **Top outcome —** no polling. Your systems learn about messages, tickets, contacts, campaigns, and channel changes within seconds of them happening.

## At a glance

|                      |                                                                                                       |
| -------------------- | ----------------------------------------------------------------------------------------------------- |
| **Plan tiers**       | All paid tiers.                                                                                       |
| **Who can use it**   | Admins and Account Owners create and manage endpoints.                                                |
| **Channels covered** | All — WhatsApp, Instagram, Messenger, Email, and Web Chat.                                            |
| **Events**           | 14 event types across messages, templates, tickets, contacts, chat workflow, campaigns, and channels. |
| **Top limits**       | Up to 3 endpoints per organisation. Up to 30 custom headers per endpoint.                             |
| **Delivery**         | Signed (HMAC-SHA256), automatically retried, with a delivery log you can inspect and replay.          |
| **API**              | Yes — manage endpoints and view deliveries via the admin API; receive events at your own endpoint.    |

## How to find it

**Sidebar: Settings → Webhooks.**

**Direct URL:** `https://lodgestory.com/crm/settings/webhooks`

\[SCREENSHOT: webhooks-landing.png — list of configured endpoints with status, events, and actions]

## What is Webhooks?

### The problem it solves

Most teams that want Lodgestory data in another system end up polling our API on a timer — asking "anything new?" over and over. That's slow, wasteful, and always a little behind. Webhooks flip it around: instead of you asking, Lodgestory tells you the instant something happens, so your CRM, data warehouse, or internal dashboard stays in sync in near real time.

### What you get

* **Real-time event delivery** — events reach your endpoint within seconds of happening.
* **Full coverage** — one place to subscribe to messages, delivery statuses, templates, tickets, contacts, chat-workflow transitions, campaigns, and channel connect/disconnect, across every channel.
* **The whole record, not just an ID** — each notification carries the full object (the message, the ticket, the contact), so you usually don't need a follow-up API call.
* **Signed and verifiable** — every delivery is signed with a secret only you and Lodgestory know, so you can confirm it really came from us.
* **Reliable delivery** — failed deliveries are retried automatically with increasing delays; a delivery log lets you see exactly what happened and replay anything.

### How it's different

You subscribe once and receive a single, consistent notification format for every event type — the same envelope whether it's a WhatsApp message, an email, a ticket assignment, or a campaign completion. The event type tells you what happened; the payload always carries the full object. That uniformity makes it fast to build one handler that routes everything.

### Customer scenarios

* **A hotel group syncing to their PMS** — every inbound guest message and ticket is pushed into their property-management system the moment it arrives, so front-desk staff see context without opening Lodgestory.
* **An agency with a data warehouse** — campaign completions and message delivery statuses stream into their warehouse for reporting, with no nightly export job.
* **A team with a custom on-call tool** — `ticket.created` and `ticket.assigned` events page the right person instantly.

### How it fits with the rest of Lodgestory

Webhooks observe the rest of the platform — the [Unified Inbox](../workspace/home-unified-inbox.md), [Tickets](../workspace/tickets.md), [Campaigns](../workspace/campaigns.md), [Contacts](../workspace/contacts.md), [WhatsApp Templates](whatsapp-templates.md), [Workflow Lifecycle Stages](workflow-lifecycle-stages.md), and [Connections](connections.md) — and forward those events to you.

\[SCREENSHOT: webhooks-create.png — the add-endpoint form with URL field and event checkboxes grouped by category]

## Core concepts

* **Endpoint** — an HTTPS URL you own that receives event notifications. You can have up to 3 per organisation.
* **Event** — something that happened in Lodgestory (for example, `message.received`). You choose which events each endpoint receives.
* **Signing secret** — a unique secret generated for each endpoint. Lodgestory uses it to sign every delivery so you can verify authenticity. You can view or rotate it at any time.
* **Delivery** — a single attempt (with retries) to send one event to one endpoint. Every delivery is recorded in the log.
* **Delivery log** — the recent history of deliveries for an endpoint, including status, response code, and number of attempts. You can resend any past delivery.

## Quick Start — receive your first event in 5 minutes

### Step 1 — Open Webhooks

Go to **Settings → Webhooks** and click **Add Endpoint**.

\[SCREENSHOT: webhooks-addbutton.png]

### Step 2 — Enter your endpoint URL

Paste the HTTPS URL that will receive events (for example, `https://example.com/webhooks/lodgestory`). Add an optional description so your team knows what it's for.

### Step 3 — Choose your events

Tick the events you want this endpoint to receive, or use **Select all**. You can change this later.

\[SCREENSHOT: webhooks-events.png — event checkboxes grouped by Messages, Templates, Tickets, Contacts & Campaigns, Chat Workflow, Channels]

### Step 4 — Save and copy your signing secret

When you create the endpoint, Lodgestory shows your signing secret once. Copy it and store it securely — you'll use it to verify deliveries. You can always copy or rotate it later from the endpoint's row.

\[SCREENSHOT: webhooks-secret.png — the signing-secret reveal dialog with a copy button]

### Step 5 — Send a test event

Click **Send test** on the endpoint to fire a sample notification at your URL, then check it arrived and that your signature check passes.

### Step 6 — Verify and go live

Once your endpoint returns a success response (any 2xx) to the test, you're live. Real events will start flowing as they happen.

## How it works

1. Something happens in Lodgestory — a message is sent or received, a ticket changes, a campaign finishes.
2. Lodgestory checks which of your endpoints subscribe to that event.
3. For each matching endpoint, Lodgestory builds a standard notification, signs it with that endpoint's secret, and delivers it to your URL.
4. If your endpoint doesn't respond with a success code, Lodgestory automatically retries with increasing delays — up to 6 attempts. Each delivery is recorded in the log.
5. If an endpoint keeps failing over many events, Lodgestory pauses it automatically so it isn't hammered. You can re-enable it once it's fixed.

Behind the scenes Lodgestory does all of this asynchronously, so sending events never slows down your messaging or your team's inbox.

## Features in depth

### Choose exactly what you receive

Each endpoint subscribes to its own set of events. Point one endpoint at your CRM for messages and contacts, and another at your on-call tool for tickets only.

### One consistent notification format

Every event uses the same envelope. The `event` field tells you what happened; `data.object` tells you the type of record; and `data` carries the full object. Update-type events (statuses, assignments, workflow transitions) also include a `previous_attributes` block showing what changed.

### Signed deliveries

Every request includes a signature header computed from your endpoint's secret. Verifying it confirms the request genuinely came from Lodgestory and wasn't altered in transit. (See **API → Verifying deliveries**.)

### Automatic retries and auto-pause

Temporary outages on your side are handled for you: failed deliveries are retried automatically with growing delays. If an endpoint fails consistently across many events, it's paused so it stops receiving traffic until you re-enable it.

### Delivery log, test, and replay

Open any endpoint's delivery log to see recent attempts with their status, response code, and attempt count. **Send test** fires a sample event on demand. **Redeliver** re-sends any past delivery — useful after you fix a bug on your side.

### Rotate the secret

Rotate an endpoint's signing secret at any time (for example, if it may have leaked). Update your verification code with the new secret to continue accepting deliveries.

## Roles & permissions

| Role                      | Can do                                                                                                                                |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **Account Owner / Admin** | Create, edit, enable/disable, and delete endpoints; view and rotate secrets; view delivery logs; send test events; replay deliveries. |
| **Team member / Agent**   | No access to webhook settings.                                                                                                        |

## Connections

* **[Unified Inbox](../workspace/home-unified-inbox.md)** — `message.sent` and `message.received` fire for every channel that lands in the inbox.
* **[Tickets](../workspace/tickets.md)** — `ticket.created`, `ticket.status_changed`, and `ticket.assigned` keep an external helpdesk or on-call tool in sync.
* **[Campaigns](../workspace/campaigns.md)** — `campaign.created` and `campaign.completed` let you track broadcast progress in your own reporting.
* **[Contacts](../workspace/contacts.md)** — `contact.created` notifies you when a new contact is added from a conversation or the create-contact action.
* **[WhatsApp Templates](whatsapp-templates.md)** — `template.created` and `template.status_updated` tell you when a template is submitted and when Meta approves or rejects it.
* **[Workflow Lifecycle Stages](workflow-lifecycle-stages.md)** — `chat.state_changed` fires when a conversation moves between workflow stages.
* **[Connections](connections.md)** — `channel.connected` and `channel.disconnected` notify you when a channel is added or removed.

## Limits a user will run into

* **3 endpoints per organisation.** Delete one before adding another if you hit the limit.
* **Custom headers:** up to 30 per endpoint; names and values must be plain text with no line breaks.
* **Endpoint URL:** must be a reachable HTTPS URL; it can't point at the Lodgestory API itself.
* **Delivery history** is retained for 30 days.
* **Bulk operations** (such as a large contact import) don't fire per-record events, to avoid flooding your endpoint.

## Errors & FAQ

**My endpoint isn't receiving events.** Check that the endpoint is enabled, that it's subscribed to the event you expect, and that your URL returns a 2xx response. Use **Send test** and the delivery log to diagnose.

**My endpoint was disabled automatically.** That happens after many consecutive failed deliveries. Fix your endpoint, then re-enable it from its row — re-enabling clears the failure count.

**Signature verification fails.** Make sure you're computing the signature over the exact raw request body (not a re-serialized version) together with the timestamp header, using the current secret. If you recently rotated the secret, update your verification code.

**I received the same event twice.** Treat deliveries as at-least-once. Use the delivery ID (the `id` field, also in the `X-Webhook-Id` header) to make your handler idempotent.

**Do campaign sends fire a&#x20;**`message.sent`**&#x20;per recipient?** Yes — each outbound message is a real send. Subscribe to `message.sent` only if you want that volume.

## API

Webhooks are a developer feature. There are two surfaces: the **admin API** to manage endpoints, and the **delivery contract** for the events you receive.

### Events you can subscribe to

| Event                     | Fires when                                                              |
| ------------------------- | ----------------------------------------------------------------------- |
| `message.sent`            | An outbound message is sent on any channel.                             |
| `message.received`        | An inbound message arrives on any channel.                              |
| `message.status_updated`  | A message's delivery status changes (sent / delivered / read / failed). |
| `template.created`        | A WhatsApp template is created and submitted.                           |
| `template.status_updated` | A template is approved, rejected, or otherwise updated.                 |
| `ticket.created`          | A ticket is created.                                                    |
| `ticket.status_changed`   | A ticket is resolved or reopened.                                       |
| `ticket.assigned`         | A ticket's assignee changes.                                            |
| `contact.created`         | A contact is created.                                                   |
| `chat.state_changed`      | A conversation moves between workflow lifecycle stages.                 |
| `campaign.created`        | A campaign is created.                                                  |
| `campaign.completed`      | A campaign finishes sending.                                            |
| `channel.connected`       | A channel is connected.                                                 |
| `channel.disconnected`    | A channel is disconnected or removed.                                   |

### The notification format

Every delivery is an HTTP `POST` with this JSON body:

```json
{
  "id": "f1c2…",
  "event": "message.received",
  "api_version": "2026-05-01",
  "occurred_at": "2026-05-25T10:14:02.000Z",
  "organisation_id": "550e8400-e29b-41d4-a716-446655440000",
  "data": {
    "object": "message",
    "message": {
      "id": "wamid.HBgL…",
      "chat_id": "919999999999@c.us",
      "channel_id": "…",
      "channel_type": "whatsapp",
      "direction": "inbound",
      "type": "text",
      "text": "Is breakfast included?",
      "media_uri": null,
      "status": "DELIVERED",
      "from_name": "John Doe",
      "from_number": "+919999999999",
      "timestamp": "2026-05-25T10:14:02.000Z"
    }
  }
}
```

Update-type events also include `previous_attributes`. For example, `ticket.status_changed`:

```json
{
  "event": "ticket.status_changed",
  "api_version": "2026-05-01",
  "occurred_at": "2026-05-25T11:02:00.000Z",
  "organisation_id": "550e8400-…",
  "data": {
    "object": "ticket",
    "ticket": {
      "id": "…",
      "chat_id": "…",
      "status": "resolved",
      "priority": "HIGH_PRIORITY",
      "assigned_to_user_id": "…",
      "created_at": "2026-05-24T09:00:00.000Z",
      "updated_at": "2026-05-25T11:02:00.000Z"
    },
    "previous_attributes": { "status": "open" }
  }
}
```

`data.object` is one of `message`, `message_status`, `template`, `ticket`, `contact`, `chat_state`, `campaign`, or `channel`, and the object's full payload is under the matching key.

### Headers on every delivery

| Header                | Purpose                                       |
| --------------------- | --------------------------------------------- |
| `X-Webhook-Id`        | Unique delivery ID — use it for idempotency.  |
| `X-Webhook-Event`     | The event type (matches `event` in the body). |
| `X-Webhook-Timestamp` | When the delivery was signed (Unix seconds).  |
| `X-Webhook-Signature` | `sha256=<hmac>` — see below.                  |

### Verifying deliveries

The signature is an HMAC-SHA256, using your endpoint's signing secret, computed over the timestamp and the **raw** request body joined by a dot: `{timestamp}.{body}`. To verify, recompute it and compare:

```js
import crypto from 'crypto';

function isValid(req, secret) {
  const timestamp = req.headers['x-webhook-timestamp'];
  const signature = req.headers['x-webhook-signature']; // "sha256=…"
  const expected =
    'sha256=' +
    crypto
      .createHmac('sha256', secret)
      .update(`${timestamp}.${req.rawBody}`) // the exact bytes you received
      .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
```

Always use the raw, unparsed body — re-serializing the JSON will change the bytes and break the check.

### Responding

Return any `2xx` status to acknowledge a delivery. Any other status (or a timeout — each attempt waits up to 10 seconds) is treated as a failure and retried automatically, up to 6 attempts with increasing delays. Endpoints that fail consistently across many events are paused automatically.

### Managing endpoints

Admins can create, list, update, enable/disable, and delete endpoints, rotate secrets, list deliveries, send test events, and replay a delivery through the admin API under `/api/wp-crm/webhooks` (all scoped to your organisation). The same actions are available in the UI.

## Changelog

* **2026-01-12** — Webhooks launched: 14 event types across all channels, signed delivery with automatic retries, a delivery log with test and replay, and per-endpoint custom headers.

## Related modules & next steps

* [Connections](connections.md) — connect the channels whose events you'll receive.
* [Tickets](../workspace/tickets.md) and [Campaigns](../workspace/campaigns.md) — common event sources.
* [WhatsApp Templates](whatsapp-templates.md) — track template approval via `template.status_updated`.

<br />