Gareth Wilson Gareth Wilson

Guide to Lodgix Webhooks: Features and Best Practices

Published


Lodgix webhooks tell your systems when a guest sends a message about a booking. If you run vacation rentals on Lodgix and want guest messages in a shared inbox, a Slack channel, a CRM or an AI assistant, a webhook gets each message to you as it arrives instead of on a polling schedule.

This guide covers how to create a Lodgix webhook, how deliveries are signed and retried, and how to build a receiver that keeps up.

What are Lodgix webhooks?

Lodgix webhooks are signed HTTP POST requests that Lodgix sends to an HTTPS endpoint you register in your account. There's one event today, message.received, and Lodgix says more event types may be added later.

Each endpoint has its own secret. Lodgix signs every request with HMAC-SHA256 over the X-Lodgix-Timestamp value, a period and the raw body, and sends the result as X-Lodgix-Signature: sha256=<hex>.

Lodgix webhook features

FeatureDetails
ConfigurationModules > Integrations > Webhooks in Lodgix
Endpoint URLMust start with https://
Eventsmessage.received
Signature headerX-Lodgix-Signature, in the form sha256=<hex>
Timestamp headerX-Lodgix-Timestamp, Unix seconds when the request was signed
Signed content<timestamp>.<raw body>
SecretOne per endpoint
Event headerX-Lodgix-Event
Delivery IDX-Lodgix-Delivery
Success responseAny 2xx
Retries5 retries, at 30 seconds, 5 minutes, 30 minutes, 2 hours and 6 hours
Delivery logEach delivery records its last HTTP status and error
Auto-disableAn endpoint that keeps failing can be disabled. Re-enable is on the endpoint card

Common events

EventFires when
message.receivedA guest message is received

Read the event name from X-Lodgix-Event so your receiver is ready for new event types. Lodgix doesn't publish the body of a message.received delivery, so log the first few real deliveries before you map fields.

Setting up Lodgix webhooks

  1. In Lodgix, go to Modules > Integrations > Webhooks.
  2. Click Create Webhook, or Add Endpoint if you already have one.
  3. Give the endpoint a name you'll recognise later.
  4. Enter the endpoint URL. It must start with https://.
  5. Select Message Received (message.received).
  6. Click Create Endpoint, then copy the endpoint's secret and store it server-side, for example as LODGIX_WEBHOOK_SECRET.

If you receive Lodgix webhooks through Hookdeck, use the Hookdeck source URL as the endpoint URL, create a source with the Lodgix type and paste the endpoint's secret. The Lodgix source accepts POST only, which is how Lodgix delivers webhooks.

Securing Lodgix webhooks

Read X-Lodgix-Timestamp and X-Lodgix-Signature. Build the message from the timestamp, a period and the raw body bytes, compute an HMAC-SHA256 with the endpoint secret, and compare the hex digest with the value after sha256= in constant time.

const crypto = require('crypto');
const express = require('express');

function verifyLodgixSignature(rawBody, signatureHeader, timestampHeader, secret, toleranceSeconds = 0) {
  if (!signatureHeader || !timestampHeader || !secret) return false;

  const hex = signatureHeader.startsWith('sha256=') ? signatureHeader.slice(7) : signatureHeader;
  if (!/^[0-9a-fA-F]{64}$/.test(hex)) return false;

  // Optional replay window. Off by default (see below).
  if (toleranceSeconds > 0) {
    const timestamp = Number(timestampHeader);
    if (!Number.isFinite(timestamp)) return false;
    if (Math.abs(Date.now() / 1000 - timestamp) > toleranceSeconds) return false;
  }

  const message = Buffer.concat([Buffer.from(timestampHeader, 'latin1'), Buffer.from('.'), rawBody]);
  const expected = crypto.createHmac('sha256', secret).update(message).digest();
  const received = Buffer.from(hex, 'hex');
  return received.length === expected.length && crypto.timingSafeEqual(received, expected);
}

const app = express();

app.post('/webhooks/lodgix', express.raw({ type: '*/*' }), (req, res) => {
  const secret = process.env.LODGIX_WEBHOOK_SECRET;
  if (!secret) return res.sendStatus(500); // fail closed

  const valid = verifyLodgixSignature(
    req.body,
    req.get('x-lodgix-signature'),
    req.get('x-lodgix-timestamp'),
    secret
  );
  if (!valid) return res.sendStatus(401);

  const eventType = req.get('x-lodgix-event');
  // Deduplicate on the X-Lodgix-Delivery header, route on eventType, then process asynchronously.
  res.sendStatus(200);
});

The same check in Python:

import hashlib
import hmac
import re
import time


def verify_lodgix_signature(raw_body: bytes, signature_header, timestamp_header, secret: str,
                            tolerance_seconds: int = 0) -> bool:
    if not signature_header or not timestamp_header or not secret:
        return False
    digest = signature_header[7:] if signature_header.startswith("sha256=") else signature_header
    if not re.fullmatch(r"[0-9a-fA-F]{64}", digest):
        return False
    # Optional replay window. Off by default (see below).
    if tolerance_seconds > 0:
        try:
            timestamp = float(timestamp_header)
        except ValueError:
            return False
        if abs(time.time() - timestamp) > tolerance_seconds:
            return False
    message = timestamp_header.encode("latin-1") + b"." + raw_body
    expected = hmac.new(secret.encode("utf-8"), message, hashlib.sha256).digest()
    return hmac.compare_digest(bytes.fromhex(digest), expected)


# In FastAPI: raw_body = await request.body()
# verify_lodgix_signature(raw_body, request.headers.get("x-lodgix-signature"),
#                         request.headers.get("x-lodgix-timestamp"),
#                         os.environ["LODGIX_WEBHOOK_SECRET"])

Lodgix tells you to reject a request whose timestamp is more than five minutes old. The samples above make that check optional and leave it off by default. Hookdeck applies no timestamp tolerance, and its retries and replays resend Lodgix's original headers, so a five-minute window on your endpoint would reject any delivery Hookdeck retries later than that. If your endpoint receives directly from Lodgix, pass toleranceSeconds = 300 to follow Lodgix's advice.

Lodgix also documents an n8n recipe: turn on Raw Body in the Webhook trigger node, extract the body as text, and compute the HMAC with a Crypto node over {{ $('Webhook').item.json.headers['x-lodgix-timestamp'] }}.{{ $json.body_text }}, output as hex, before comparing sha256= plus that value with the header.

To check your verifier, use the secret lodgix-guide-secret, an X-Lodgix-Timestamp of 1761480000 and this exact body:

{"event":"message.received"}

The header should be:

X-Lodgix-Signature: sha256=4be0339d1f0afc0d5a6aae977527f5c71ae44ed0be2fee0db20fbd02c01af576

Make Lodgix webhooks production-ready. Hookdeck Event Gateway verifies the X-Lodgix-Signature header on every delivery, returns a 2xx straight away, and queues each guest message until your service has processed it.

Lodgix webhook limitations and pain points

A short retry schedule and auto-disable

The Problem: Guest messages stop arriving after an outage, and the endpoint shows as disabled.

Why It Happens: Lodgix retries a failed delivery five times over about eight and a half hours, then marks it Exhausted. An endpoint that keeps failing can be disabled automatically and stays off until someone re-enables it.

Workarounds:

  • Return 2xx as soon as the request is verified and stored, and do the work asynchronously.
  • Check the delivery log on the endpoint after an incident. It records the last status code and error.
  • Use Re-enable on the endpoint card once your endpoint is fixed.

How Hookdeck Can Help: Hookdeck acknowledges each delivery as soon as it arrives and stores it, then delivers to your service with retries you configure, so your own downtime doesn't count towards Lodgix's failures.

A five-minute window that fights retries

The Problem: Following Lodgix's advice to reject old timestamps makes late retries and replays fail.

Why It Happens: X-Lodgix-Timestamp is when the request was signed. A delivery replayed or retried by something between Lodgix and your code keeps the original header.

Workarounds:

  • Apply the window only where requests come straight from Lodgix.
  • Rely on the delivery ID for duplicate protection behind a proxy.

How Hookdeck Can Help: Hookdeck verifies the signature when the request first arrives and applies no timestamp tolerance, so a late retry isn't marked as failed. If your service keeps its own window behind Hookdeck, make it wide enough for Hookdeck's retries, or leave it off.

An undocumented body

The Problem: You can't build a parser for guest messages from the docs alone.

Why It Happens: Lodgix documents the headers and signature but not the message.received body.

Workarounds:

  • Point a test endpoint at a request inspector and send yourself a guest message.
  • Route on X-Lodgix-Event, not on a body field, until you know the body's shape.

How Hookdeck Can Help: Hookdeck stores every request, headers and body, so the first real delivery becomes the reference for your parser.

Best practices

Verify against the raw body

Lodgix warns that re-serialising the JSON changes the signature. In Express, use express.raw({ type: '*/*' }). In Next.js, use Buffer.from(await request.arrayBuffer()). In FastAPI, use await request.body().

Deduplicate deliveries

Store each X-Lodgix-Delivery value you've processed and skip repeats. Lodgix calls it a unique ID for the delivery. Check one retried request to confirm the ID stays the same across attempts. See our guide to webhook idempotency and Hookdeck's deduplication.

Plan for new event types

Lodgix expects to add events. Route on X-Lodgix-Event, return 2xx for types you don't handle yet, and log them.

Conclusion

Lodgix webhooks are simple to set up: one event, an HTTPS endpoint and a sha256= signature over the timestamp and raw body. The parts to plan for are the short retry schedule, automatic disabling, and a five-minute timestamp rule that only suits requests coming straight from Lodgix.

Hookdeck Event Gateway sits in front of your receiver, checks every Lodgix signature, and holds each guest message until your service has processed it.

Get started with Hookdeck for free and handle Lodgix webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.