Skip to main content
Webhooks let your application react to BoothZen events in real time — a new booking, a payment received, a quote accepted. BoothZen signs every delivery so you can prove the payload came from us and hasn’t been tampered with.

Subscribe

Webhook subscriptions are created and managed in the admin UI. Each subscription has a target URL, an event filter (* or an explicit list), and its own signing secret.

Manage webhook subscriptions

Create endpoints, choose events, copy the signing secret. The full whsec_* secret is shown once on creation — store it somewhere safe.
Signing secrets have the format whsec_<56-hex-chars> (62 characters total). Each subscription has its own secret; rotating a secret is a destructive action that invalidates the previous one.

Events

Thirteen events fan out from the BoothZen observer chain. Every event delivers a JSON body with a top-level id, type, created, and data.object (the resource snapshot at the moment of the event). The canonical list is the platform’s App\Services\Webhooks\WebhookEventCatalog. The Laravel SDK exposes typed constants — BoothZen\Laravel\Webhooks\Events::BOOKING_CREATED etc. — that mirror this catalog 1:1.
There is no payment.succeeded or payment.failed event — payment.received is the only success signal. There is no booking.status_changed or booking.completed — use booking.confirmed / booking.cancelled for status transitions. There are no *.updated events for customer, lead, or invoice; only *.created / invoice.sent / invoice.paid fire for those resources. Availability does not emit events — derive from booking events instead.
The exact shape of data.object for each resource is part of the OpenAPI contract. Browse it in the API Reference tab — the webhook resource shape matches the corresponding GET /api/v1/{resource}/{id} response.

Signature verification

Every delivery carries a BoothZen-Signature header in Stripe’s signature format:
  • t — Unix timestamp (seconds) when the signature was computed.
  • v1 — HMAC-SHA256 of the signed payload string, encoded as lowercase hex.
The signed payload string is:
That is: the timestamp, a literal ., then the raw request body bytes (do NOT parse and re-serialise — verify against the bytes you received).

Tolerance window

Reject deliveries where t is more than 5 minutes in the past or future (the same default Stripe uses). This stops replay attacks where an attacker re-POSTs an old signed body.

Code

Verify against the raw request body. Frameworks that auto-parse JSON (Express, Laravel) reorder keys and strip whitespace — the resulting bytes will not match the signature. Capture the raw body in middleware before any parsing.

Retries

BoothZen retries failed deliveries (non-2xx response or connection error) with exponential backoff: After 20 consecutive failures the subscription is auto-disabled and the operator receives an email with a link to re-enable it. Successful deliveries reset the failure counter to zero. Aim for a sub-3-second response time. Return 2xx as soon as you’ve persisted the event; do the heavy work in a background job.

SDK helper

The official Laravel SDK ships a SignatureVerifier helper so you don’t have to copy-paste the snippets above into every project.

boothzen/laravel-sdk on Packagist

composer require boothzen/laravel-sdk — includes BoothZen\Sdk\Webhooks\SignatureVerifier and a Laravel middleware (boothzen.webhook) that verifies and rejects invalid deliveries before they reach your controller.