Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developer.boothzen.com/llms.txt

Use this file to discover all available pages before exploring further.

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).
EventFires whenPayload root
booking.createdA new booking is inserted, by any path (admin, widget, API)data.object = full Booking
booking.updatedA booking’s mutable fields change (notes, dates, services)data.object = full Booking
booking.status_changedA booking’s status transitions (e.g. pending to confirmed)data.object = Booking, data.previous_attributes.status = prior value
EventFires when
payment.receivedPayment recorded against an invoice or booking
payment.refundedRefund issued (full or partial)
EventFires when
lead.createdNew lead captured (widget, manual, API, embed)
lead.updatedLead status, owner, or notes change
EventFires when
customer.createdFirst time a customer record is created
EventFires when
quote.createdA new quote is generated and saved
quote.acceptedCustomer accepts a quote
quote.declinedCustomer declines a quote (or it expires)
EventFires when
invoice.sentInvoice issued to customer
invoice.paidInvoice marked fully paid
The exact shape of data.object for each resource is part of the OpenAPI contract. Browse it in the API Reference — 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:
BoothZen-Signature: t=1778530000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
  • 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:
<t>.<raw-body>
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

<?php
function verify_boothzen_webhook(string $rawBody, string $header, string $secret, int $tolerance = 300): bool {
    if (!preg_match('/t=(\d+),v1=([a-f0-9]+)/', $header, $m)) return false;
    [, $t, $v1] = $m;
    if (abs(time() - (int) $t) > $tolerance) return false;
    $expected = hash_hmac('sha256', $t . '.' . $rawBody, $secret);
    return hash_equals($expected, $v1);
}
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:
AttemptDelay after previous
1immediate
21 minute
35 minutes
430 minutes
52 hours
612 hours
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.