Docs/Webhooks/Reservation

reservation.created

A new reservation arrived from any connected channel or direct booking.

When it fires

Fires once when a new reservation lands in Repull from a channel sync (Airbnb, Booking.com, VRBO, Plumguide), an OAuth-linked PMS push, a direct-booking website, or a manual API call. It will not fire again on subsequent edits — those raise reservation.updated.

Payload

Every delivery uses the same outer envelope (type, deliveryId, createdAt, data). Dedupe on deliveryId — retries reuse the same id.

{
  "type": "reservation.created",
  "deliveryId": "evt_01HX5XPQ2K",
  "createdAt": "2026-05-01T12:34:56.000Z",
  "data": {
    "id": 215906,
    "confirmationCode": "HMA1234567",
    "listingId": 6250,
    "platform": "airbnb",
    "status": "confirmed",
    "checkIn": "2026-06-01",
    "checkOut": "2026-06-05",
    "nights": 4,
    "guests": { "adults": 2, "children": 0, "infants": 0 },
    "primaryGuest": {
      "firstName": "Alex",
      "lastName": "Morgan",
      "email": "alex@example.com"
    },
    "pricing": {
      "subtotal": "1200.00",
      "taxes": "120.00",
      "total": "1320.00",
      "currency": "USD"
    },
    "createdAt": "2026-05-01T12:34:56.000Z"
  }
}

Verifying signatures

Every delivery includes an X-Repull-Signature header containing an HMAC-SHA256 of the raw request body computed with your subscription's signing secret. Verify it before processing — see Verify Signatures for full Node.js and Python examples.

Use the raw body

Verify the HMAC against the raw request body, not a re-stringified JSON object. Re-serialisation can reorder keys or change whitespace and break the signature.

Example handler

// Express handler — verify signature, then route on type
app.post('/webhooks/repull', express.raw({ type: 'application/json' }), (req, res) => {
  if (!verifyRepullSignature(req)) return res.sendStatus(401)
  const { type, deliveryId, data } = JSON.parse(req.body.toString())

  if (type === 'reservation.created') {
    // Idempotent on deliveryId — retries reuse the same id
    if (alreadyProcessed(deliveryId)) return res.sendStatus(200)
    onNewReservation(data) // sync to your CRM, notify the cleaner, etc.
  }

  res.sendStatus(200)
})

Common patterns

  • Treat the payload as a hint, not the source of truth. Always re-fetch the full reservation via GET /v1/reservations/{id} before charging cards or sending guest comms — the canonical record may have additional fields the payload trims.
  • Dedupe on deliveryId. Retries reuse the same id, so a simple seen-set or unique index on deliveryId is enough to make your handler idempotent.
  • Subscribe to reservation.created together with reservation.updated and reservation.cancelled. The three events form the full lifecycle — alone, reservation.created leaves you blind to date shifts and cancellations.

Tip: Acknowledge with a 2xx status within 5 seconds. Failed deliveries are retried up to 5 times with exponential backoff.Webhook reliability →

AI