Skip to content
Rate Extra

Webhooks and signature verification

Both APIs push events to your endpoint. Verify every delivery before you process it: check the signature with a constant-time comparison, reject stale timestamps, and deduplicate by delivery id.

TravelDistro webhooks

X-TD-Webhook-Signature
sha256=<hex>, HMAC-SHA256 of {TIMESTAMP}.{RAW_BODY} keyed by the endpoint secret
X-TD-Webhook-Timestamp
Unix seconds; reject if older than 300 s
X-TD-Webhook-Event
Event type, e.g. transfer.confirmed
X-TD-Webhook-Id
Delivery id, stable across retries; deduplicate by it
Retries
2 retries with exponential backoff, then dead-lettered

Transfer events

  • transfer.confirmed
  • transfer.updated
  • transfer.driver_assigned (driver details arrive here)
  • transfer.driver_unassigned
  • transfer.cancelled

Verification in Node.js

import crypto from "node:crypto";

// TravelDistro webhook: X-TD-Webhook-Signature = "sha256=" + HMAC-SHA256(`${timestamp}.${rawBody}`, endpointSecret)
export function verifyTravelDistroWebhook(headers: Record<string, string>, rawBody: string, endpointSecret: string): boolean {
  const timestamp = headers["x-td-webhook-timestamp"];
  const signature = headers["x-td-webhook-signature"] ?? "";
  if (!timestamp || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false; // stale or replayed

  const expected = "sha256=" + crypto.createHmac("sha256", endpointSecret).update(`${timestamp}.${rawBody}`).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signature);
  return a.length === b.length && crypto.timingSafeEqual(a, b); // constant-time compare
}

// Deduplicate by X-TD-Webhook-Id: the same id is reused on every retry of one delivery.

Hotel API by Safaryar Holidays

X-Webhook-Signature
HMAC signature of the delivery
Events
booking.created, booking.cancelled, booking.prebook_confirmed, booking.prebook_rejected
Retries
None; respond within 10 seconds

Endpoint checklist

  • Read the raw body before any JSON parsing; the signature covers the exact bytes.
  • Return 2xx quickly and process asynchronously.
  • Store processed delivery ids for at least the retry window.
  • Treat the endpoint secret like the API secret: server-side only.

Licensed travel agency? Apply for API access.

Get API access