Skip to main content

Webhooks

Webhooks let Elivaas push you a notification the moment catalogue data changes — a listing, property, inventory or rates — so you can keep your copy in sync without polling.

Each webhook is a thin notification: it tells you what changed (an entity type and id, plus an affected date window for inventory/rate changes), not the changed values themselves. When you receive one, re-fetch the current state from the read endpoints. This keeps you authoritative against live data and means you don't have to worry about deliveries arriving out of order.

Managing endpoints

Register and manage your webhook endpoints yourself via the API — no email required. Every call is scoped to the partner your API key authenticates as, so you only ever see and change your own endpoints. See the Webhooks API reference for full schemas.

ActionRequest
List your endpointsGET /api/webhooks/endpoints
Create an endpointPOST /api/webhooks/endpoints
Get oneGET /api/webhooks/endpoints/{id}
Update / rotate secretPUT /api/webhooks/endpoints/{id}
DeleteDELETE /api/webhooks/endpoints/{id}
List subscribable event typesGET /api/webhooks/event-types

A new endpoint is active immediately. Specify eventTypes to subscribe to specific events, or omit it to receive all of them.

curl -u 'dk_live_xxxxxxxxxxxxxxxxxxxxxxxx:' \
-X POST https://partner-api.elivaas.com/api/webhooks/endpoints \
-H 'Content-Type: application/json' \
-d '{
"url": "https://hooks.example.com/elivaas",
"authType": "HMAC",
"signingSecret": "your-shared-secret",
"eventTypes": ["inventory.changed", "rate.changed"]
}'

The response echoes the endpoint without the secret — secrets are write-only. The signingSecretConfigured / authSecretConfigured flags tell you whether a secret is set.

Rotating a secret

On PUT, omit signingSecret/authSecret to keep the stored value, or send a new value to rotate it. You never need to re-send a secret just to change other fields.

Event types

eventTypeentityTypeSent whenDate window
listing.updatedlistingA listing's catalogue data changes
property.updatedpropertyA property's data changes
inventory.changedinventoryA sync changed availability for a propertyfromDate..toDate
rate.changedrateA sync changed a property's ratesfromDate..toDate

inventory.changed and rate.changed are sent only when data actually changed — inventory and rates are re-synced on a schedule, and a re-sync that produces identical values sends no webhook. These events carry the affected date window so you can re-fetch just those dates instead of the whole calendar.

Payload

Every webhook is an HTTP POST with this JSON body:

{
"eventType": "inventory.changed",
"entityType": "inventory",
"entityId": "prop_8fQ2zK",
"fromDate": "2026-07-01",
"toDate": "2026-07-09",
"occurredAt": "2026-06-18T11:04:22Z",
"dedupKey": "0f3c1e9a-8d52-4f7b-9b1a-2c6f0a5d44e1"
}
FieldTypeNotes
eventTypestringOne of the types above.
entityTypestringEntity class, e.g. inventory.
entityIdstringId of the changed entity. For inventory.changed / rate.changed this is the property id.
fromDatestring | nullISO-8601 date, inclusive — first affected date. null for listing.updated / property.updated.
toDatestring | nullISO-8601 date, inclusive — last affected date. null for listing.updated / property.updated.
occurredAtstringISO-8601 UTC timestamp of the change.
dedupKeystringUnique per event — dedupe on this.
Re-fetch the affected dates

On inventory.changed / rate.changed, call GET /api/inventory or GET /api/rates for entityId over fromDate..toDate to pull the new values. On listing.updated, re-fetch the listing via GET /api/listings.

Delivery & retries

  • Delivery is asynchronous and at-least-once — you may occasionally receive the same event twice.
  • Respond 2xx as soon as you've safely accepted the event; do the re-fetch afterwards so you don't time out.
  • 4xx is treated as a permanent contract error and is not retried. Fix the endpoint and ask us to replay if needed.
  • 5xx, timeouts and connection errors are retried with exponential backoff up to the maximum attempts configured for your endpoint.

Security

You choose how your endpoint is authenticated when you register it:

AuthWhat we send
None
BasicAuthorization: Basic …
BearerAuthorization: Bearer <token>
HMAC (recommended)X-Webhook-Signature: <base64(HMAC-SHA256(body, your secret))>

With HMAC, recompute the signature over the raw request body with your shared secret and compare it (constant-time) before trusting the payload:

import crypto from 'node:crypto';

function verify(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody) // the raw bytes, before JSON.parse
.digest('base64');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader),
);
}

Any static custom headers you register are sent on every call.

Idempotency

Because delivery is at-least-once, store recently-seen dedupKeys and ignore repeats. Processing should be idempotent anyway — re-fetching current state for the same entity twice is always safe.