Back to Blog
ProductJune 1, 20266 min read

Webhooks for Errors and Duplicates — Stop Polling

If you operate a hotel mapping pipeline, you probably already have a workflow for reporting bad matches. A row is mapped to the wrong reference hotel, your ops team files a mismatch, our team investigates, and eventually the mapping is corrected.

Today, you find out it was fixed by polling. You scan our API, you scan our admin UI, you wait for an email. None of that scales when you have hundreds of in-flight reports.

Starting today, Pro and above customers can subscribe to two new webhook events:

  • mapping.error.resolved — fires when a mismatch report you filed is closed.
  • inventory.duplicate.resolved — fires when a duplicate report is closed on a reference hotel any of your mappings point to, even if you didn't report it.

The Shape of an Event

Every webhook delivery is a JSON envelope:

{
  "id": "9a2c0f0a-…",
  "eventId": "5e1b…",
  "type": "mapping.error.resolved",
  "apiVersion": "2026-06-01",
  "occurredAt": "2026-06-01T12:34:56Z",
  "organizationId": "org_…",
  "data": {
    "reportId": "…",
    "partnerInventoryId": "…",
    "partnerHotelId": "EXP-12345",
    "referenceHotelId": "ref_…",
    "resolution": "FIXED",
    "resolvedAt": "2026-06-01T12:34:56Z"
  }
}

The id field is the delivery attempt — it changes on every retry. The eventId is stable across retries and is your idempotency key.

Signing

Every request carries three headers:

X-Webhook-Signature: t=1717250400,v1=<hex_hmac_sha256(secret, "1717250400." + body)>
X-Webhook-Event:     mapping.error.resolved
X-Webhook-Delivery:  <delivery uuid>

Verify in your handler with HMAC-SHA256 against the secret we showed you exactly once at create time. If the timestamp is more than five minutes from your server clock, reject — it's a replay.

Retries

If your endpoint returns a non-2xx response, we retry 3 more times at 1 minute, 5 minutes, and 30 minutes. After the fourth failure the delivery is marked DEAD and recorded in audit. No silent failures.

You can inspect every delivery — including the response code and body of failures — in the new Developers → Webhooks → Deliveries drawer in the app.

Duplicate Fan-out

The interesting one is inventory.duplicate.resolved. Duplicates aren't a property of your organization; they're a property of our reference dataset. When we close a duplicate report on hotel X, every Pro+ org with a mapping touching X gets notified — even if they had no idea the duplicate existed.

If your downstream system has cached that hotel ID, you now know to invalidate it.

How to Set It Up

  1. Open Developers → Webhooks in the app.
  2. Click New webhook, choose your event types, and paste your HTTPS endpoint.
  3. Copy the signing secret shown once — store it where you keep your other API secrets.
  4. Use the Test event button to send a synthetic payload through the real delivery pipeline.

That's the whole flow. No polling, no inboxes, no daily exports.

What's Next

The new delivery pipeline (signing + retries + idempotency) is shipped as shared infrastructure. The existing mapping.completed export webhook will migrate onto it in a follow-up release — same payload, just with signing and retries layered on. Existing customers don't need to change anything.

If you want this earlier, ping us. We're staged behind a feature flag and rolling out one canary org at a time.