RentalTideRentalTideDocs
Dashboard

Webhooks

Receive signed, retried event notifications from RentalTide — the event catalog, payload shape, and signature verification.

Webhooks push what happens in an account — bookings, payments, waivers, carts, POS sales — to a URL you control, the moment it happens, with no polling. RentalTide signs every delivery and retries failures with exponential backoff.

There are two ways to receive them:

  • Your own endpoint (Settings → Webhooks). Any merchant can register a URL, tick the events they want, and point it at Zapier, Make, n8n, a CRM or their own server. No app, no scopes, no code on our side.
  • A marketplace app. An installed app with the webhooks:receive scope gets the same deliveries at the app's registered webhook URL.

Both use the same payload, the same signature scheme and the same retry ladder.

Setup — your own endpoint

  1. Go to Settings → Webhooks and click Add endpoint.
  2. Paste the URL. It must be reachable from the public internet — localhost and private/internal addresses are rejected when you save, not silently later.
  3. Tick the events: individual names, a whole domain (All bookings), or Everything — which also covers events added in future releases.
  4. Copy the signing secret. It is shown in full when the endpoint is created and whenever you rotate it, and can be re-shown from the endpoint's panel.
  5. Hit Send test to fire a signed sample payload and see exactly what your server answered.

Each endpoint gets its own secret; rotating one never affects another. Rotating takes effect immediately — update your consumer first, or the next delivery fails signature verification.

Setup — marketplace app

  1. Register a Webhook URL and a Webhook secret on your app in the partner portal.
  2. Request the webhooks:receive scope.
  3. Verify the signature on every request before trusting it.

Use the Test webhook button in the developer portal to send a signed sample delivery to your endpoint at any time.

Event catalog

Subscribe to an exact name (booking.created), a whole domain (booking.*), or everything (*).

EventWhen
booking.createdA booking was created — online, walk-up, internal or agent.
booking.updatedA booking changed with no more specific event.
booking.status_changedA booking moved to a new status.
booking.checked_inA booking was checked in.
booking.completedThe rental finished / the asset came back.
booking.cancelledA booking was cancelled.
booking.rescheduledA booking was rescheduled.
booking.note_addedStaff added a note to a booking.
payment.receivedA payment was recorded against a booking.
payment.refundedA refund was issued.
payment.charge_addedAn extra charge (fuel, damage, add-on) was posted to a booking.
cart.abandonedA customer started a booking online and did not finish.
cart.recoveredAn abandoned cart converted into a booking.
customer.createdA new customer was created.
customer.updatedA customer record was updated.
waiver.completedA participant signed a waiver — one per signer, not one per booking.
membership.createdA membership was sold or started.
membership.status_changedA membership changed status.
membership.cancelledA membership was cancelled or expired.
giftcard.issuedA gift card was purchased or issued.
giftcard.redeemedGift card balance was spent.
pos.sale_completedA POS sale was completed.
pos.refund_issuedA POS sale was refunded.
asset.launch_detectedA tracked asset crossed its launch zone (direction: out / in).
tour.status_changedA tour departure changed status.
tour.cancelledA tour departure was cancelled.
staff.clocked_inA staff member clocked in.
staff.clocked_outA staff member clocked out.
app.installedYour app was installed by a merchant (provision here).
app.uninstalledYour app was uninstalled (deprovision / clean up here).

app.installed / app.uninstalled go to marketplace apps only.

The live list is always available at GET /webhooks/events, and the same catalog ships as WEBHOOK_EVENT_CATALOG in @rentaltide/app-sdk.

Payload

Every delivery is a JSON POST:

HTTP
POST /your-webhook-endpoint
Content-Type: application/json
X-RentalTide-Event: booking.created
X-RentalTide-Signature: v1=<hmac-sha256-hex>
X-RentalTide-Timestamp: 2026-05-22T18:04:11.000Z

{
  "event": "booking.created",
  "timestamp": "2026-05-22T18:04:11.000Z",
  "data": { "rentalId": "bkg_…", "...": "..." }
}

Verify the signature

The signature is v1= + HMAC_SHA256(secret, "{X-RentalTide-Timestamp}.{rawBody}") in hex. Compute it over the raw request body and compare in constant time. Reject deliveries whose timestamp is more than 5 minutes old (replay protection).

JavaScript

A complete runnable receiver is in the with-backend example.

Delivery & retries

  • Respond 2xx quickly to acknowledge. Do slow work asynchronously.
  • Non-2xx (or a timeout) is retried with exponential backoff — 1m → 5m → 15m → 1h → 6h — up to 6 attempts, then the delivery is marked dead.
  • Deliveries can arrive more than once; make your handler idempotent (e.g. dedupe on the data ids). We collapse repeat emits of a single change, but network-level retries can still duplicate a delivery your server already processed but failed to acknowledge in time.
  • Every request carries X-RentalTide-Delivery, a stable id for that delivery — the simplest key to dedupe on.

When your endpoint is down

Each failed delivery is retried through the full ladder before it dies. Ten consecutive dead deliveries auto-disables the endpoint — we stop sending, the Webhooks page shows it as Auto-disabled with the last error, and you turn it back on once the endpoint is fixed. A single success resets the counter.

Delivery log

Every endpoint keeps a log of what we sent, what your server answered, how many attempts it took, and the exact payload. Any delivery can be replayed from there — useful after fixing a handler bug, without waiting for the event to happen again.

Was this page helpful?
Need help? Contact Support.See what’s new. Check out changelog.Questions? Book a video chat.
Ask AI
Responses are generated using AI and may contain mistakes.
Ask questions about RentalTide and get help with your integration.