Skip to main content
Everything Maat pushes to you — the booking lifecycle, live holds, reviews, listing publication and pricing changes — arrives as a signed HTTPS POST to one endpoint you register with PUT /v1/webhooks/endpoint. Get verification right and every delivery you act on is provably ours; get it wrong and anyone who finds your endpoint URL can feed your system fake bookings — see Webhook signatures before you rely on anything this page delivers.

Registering your endpoint

Send the URL and the events you want:
  • Every event is available to every key. See The event catalogue. Asking for one that is not on the list answers 400 validation_failed and names the event, so the fix is never a guess.
  • https only, on port 443 or 8443, on a publicly resolvable DNS name. We check the address the name actually resolves to at the moment we connect — not just at registration — and we never follow redirects. A refused URL gets one generic validation_failed; we do not report which check failed.
  • One endpoint per workspace. Registering again replaces the URL and the event list. A PUT on an endpoint that is already active takes it back to pending_verification first, and the challenge decides whether it comes back. So do not re-register while your handler is down or mid-deploy: a re-registration that fails its challenge leaves you subscribed to nothing until you send another one that passes. events must name at least one event: an empty array is refused, because every registration re-arms the challenge and an empty one would leave your endpoint pending_verification and subscribed to nothing. DELETE /v1/webhooks/endpoint is the operation that means stop, and it keeps your secret and your history — see Managing your endpoint yourself.
  • The signing secret is returned once, in the response to your first registration, and never again — we cannot read it back. Store it in a secret manager immediately. Re-registering (a corrected path, a new event list) does not mint a new secret, so your existing verification keeps working.

The challenge round-trip

Nothing real is delivered until your endpoint proves it is yours. During the registration call we POST a signed endpoint.challenge delivery to your URL, and your handler must answer 2xx with a JSON body echoing the same string back:
Echo it and the endpoint becomes active. Anything else leaves it pending_verification and nothing is ever sent to it — call the registration endpoint again to retry. The challenge is signed exactly like a real delivery, so your verification code is exercised before your first real payload rather than after it. Respond within five seconds; the challenge happens inside your own registration request. And expect it on every registration call, including one that does not change the URL.

Acknowledge within the deadline

Every delivery gives you ten seconds to answer, and any 2xx acknowledges it. Past that we retry on a fixed ladder — what to do about retries, ordering and a delivery that never lands is the rest of the story: Webhook delivery.

Where the rest lives

  • Verifying a delivery is genuinely ours — the header scheme, the exact bytes to sign, two offline test vectors, and verifiers in Node, Python and Go: Webhook signatures.
  • Everything about a delivery’s lifecycle — retries, ordering, what a booking payload carries, the full event catalogue, running your endpoint’s own lifecycle, the delivery log, redriving a delivery, and sending yourself a test event: Webhook delivery.
  • What each event actually carries, field by field with a live example: its own reference page under API Reference → Booking notifications (and → Reviews, Listings, Pricing, Calendar for the rest), or browse the closed set as WebhookEventType.
  • The seven booking.* events as one state machine — which fires when, what never fires, and how to apply them in order: Booking notifications lifecycle.