destinationlab
Developer Guide

Webhook Integration

Receive real-time notifications when events happen in your destinationlab workspace. Subscribe to events, verify signatures, and process payloads securely.

Overview

Built for reliability

HMAC-SHA256 Signing

Every webhook payload is signed with your secret key. Verify the signature to ensure the request is authentic.

Automatic Retries

Failed deliveries are retried up to 3 times with exponential backoff. Monitor delivery status in your dashboard.

Delivery Logs

Full history of every delivery attempt including response codes, timestamps, and payloads via the deliveries endpoint.

Configurable Events

Subscribe to only the events your integration needs. Add or remove events at any time via the API or dashboard.

Getting Started

Create a webhook subscription

Register an endpoint URL and specify which events you want to receive. Requires the webhooks:write scope.

1. Register your endpoint

curl -X POST https://api.destinationlab.io/v1/webhooks \
  -H "Authorization: Bearer uk_live_a1b2c3d4..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/destinationlab",
    "events": ["order.created", "payment.received"],
    "secret": "whsec_your_signing_secret",
    "headers": {
      "X-Custom-Header": "my-value"
    }
  }'

2. Successful response

HTTP/1.1 201 Created
{
  "data": {
    "id": "wh_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "url": "https://your-app.com/webhooks/destinationlab",
    "events": ["order.created", "payment.received"],
    "active": true,
    "retry_count": 3,
    "created_at": "2026-01-15T12:00:00.000Z"
  }
}
Security

Verify webhook signatures

Every webhook request includes a X-Webhook-Signature header containing an HMAC-SHA256 hash of the request body, signed with your webhook secret.

Node.js

import crypto from "crypto";

function verifySignature(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(payload)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler:
app.post("/webhooks", (req, res) => {
  const sig = req.headers["x-webhook-signature"];
  const body = JSON.stringify(req.body);

  if (!verifySignature(body, sig, SECRET)) {
    return res.status(401).send("Invalid");
  }

  // Process the event
  const { event, data } = req.body;
  console.log(`Received: ${event}`);
  res.status(200).send("OK");
});

Python

import hmac
import hashlib

def verify_signature(
    payload: bytes,
    signature: str,
    secret: str
) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(
        signature, expected
    )

# In your webhook handler:
@app.route("/webhooks", methods=["POST"])
def handle_webhook():
    sig = request.headers.get(
        "X-Webhook-Signature"
    )
    body = request.get_data()

    if not verify_signature(body, sig, SECRET):
        abort(401)

    event = request.json
    print(f"Received: {event['event']}")
    return "OK", 200
Payload Format

Webhook payload structure

Example: order.created

POST /webhooks/destinationlab HTTP/1.1
Host: your-app.com
Content-Type: application/json
X-Webhook-Signature: sha256=a1b2c3d4e5f6...
X-Webhook-ID: evt_9a8b7c6d-5e4f-3a2b-1c0d
X-Webhook-Timestamp: 2026-01-15T12:05:00.000Z

{
  "event": "order.created",
  "timestamp": "2026-01-15T12:05:00.000Z",
  "tenant_id": "a7d6ae99-9485-447d-...",
  "data": {
    "id": "ord_abc123",
    "orderNumber": "ORD-2026-0042",
    "status": "pending",
    "customer": {
      "firstName": "Sarah",
      "lastName": "Chen",
      "email": "sarah@example.com"
    },
    "total": 4850.00,
    "currency": "USD",
    "items": [...]
  }
}

Respond within 30 seconds. If your endpoint does not return a 2xx status within 30 seconds, the delivery is marked as failed and queued for retry. Return a 200 immediately and process the event asynchronously.

Event Reference

Available webhook events

Orders

order.created

A new order is created

order.updated

An order is modified

order.confirmed

An order is confirmed

order.cancelled

An order is cancelled

Payments

payment.received

A payment is recorded

payment.refunded

A payment is refunded

invoice.created

An invoice is generated

invoice.paid

An invoice is marked as paid

Customers

customer.created

A new customer is added

customer.updated

A customer record is updated

inquiry.created

A new inquiry is submitted

Products

product.created

A new product or tour is added

product.updated

A product is modified

itinerary.created

An itinerary is generated

Monitoring

Delivery logs and retries

View the full delivery history for your webhook subscriptions, including response codes, timestamps, and payloads.

GET /v1/webhooks/deliveries?webhook_id=wh_8f3a...
Authorization: Bearer uk_live_a1b2c3d4...

{
  "data": [
    {
      "id": "del_001",
      "webhook_id": "wh_8f3a...",
      "event": "order.created",
      "status": "delivered",
      "response_code": 200,
      "attempts": 1,
      "delivered_at": "2026-01-15T12:05:01.234Z"
    },
    {
      "id": "del_002",
      "webhook_id": "wh_8f3a...",
      "event": "payment.received",
      "status": "failed",
      "response_code": 500,
      "attempts": 3,
      "last_attempt_at": "2026-01-15T13:15:00.000Z",
      "next_retry_at": "2026-01-15T14:15:00.000Z"
    }
  ]
}
3 retries
Retry attempts
Exponential
Backoff strategy
24 hours
Max retry window
Get started today

Ready to streamline your travel operations?

Start your 14-day free trial today. No credit card required. Full access to all features.

Webhook Integration — API Documentation