{"contractVersion":"1.0.0","asyncapi":"3.0.0","developerDocsUrl":"/docs/developers/webhooks","payloadFamilies":["canonicalOrder","legacyOfferableBooking","genericOfferableTest","legacyOfferableQuota","canonicalContact","legacyRecordChange","canonicalSegmentMembership"],"signature":{"algorithm":"HMAC-SHA256","signedContent":"<unix-seconds>.<raw-json-body>","headerValue":"t=<unix-seconds>,v1=<hex-hmac>"},"headers":{"common":["Content-Type","X-Webhook-Signature","X-Webhook-Event-Id","X-Webhook-Event-Type","X-Webhook-Timestamp"],"integration":["X-ToucanTix-Event-Id","X-ToucanTix-Event-Key","X-ToucanTix-Event-Version","X-ToucanTix-Occurred-At","X-ToucanTix-Delivery-Id","X-ToucanTix-Signature"],"legacy":["X-Toucantix-Webhook-Signature","X-Toucantix-Webhook-Timestamp","X-Toucantix-Webhook-Sample"]},"delivery":{"totalAttempts":5,"connectionTimeoutSeconds":5,"readTimeoutSeconds":10,"retryDelaysSeconds":[30,60,300,900],"integrationRetryable":["HTTP 408","HTTP 425","HTTP 429","HTTP 5xx","connection and timeout failures"],"legacyRetryable":["HTTP 408","HTTP 429","HTTP 499","HTTP 5xx","connection and timeout failures"],"receiverGuidance":"Verify the signature, enqueue durable processing, and return a 2xx response within the response/read deadline. Do not perform long-running work before acknowledging the delivery."},"testSend":{"pipeline":"legacy","note":"The Test button always creates a sample WebhookEvent and uses the legacy delivery route, even when production delivery for the selected event uses the integration route."},"events":{"order.settled":{"production":[{"pipeline":"integration","family":"canonicalOrder"}],"testSendFamily":"canonicalOrder","publishers":["app/models/request.rb"]},"offerable.booking.created":{"production":[{"pipeline":"integration","family":"legacyOfferableBooking"}],"testSendFamily":"genericOfferableTest","publishers":["app/services/webhook/booking_change_detector.rb"]},"offerable.booking.updated":{"production":[{"pipeline":"integration","family":"legacyOfferableBooking"}],"testSendFamily":"genericOfferableTest","publishers":["app/services/webhook/booking_change_detector.rb"]},"offerable.booking.cancelled":{"production":[{"pipeline":"integration","family":"legacyOfferableBooking"}],"testSendFamily":"genericOfferableTest","publishers":["app/services/webhook/booking_change_detector.rb"]},"offerable.quota.updated":{"production":[{"pipeline":"integration","family":"legacyOfferableQuota"}],"testSendFamily":"legacyOfferableQuota","publishers":["app/workers/webhook/quota_update_support.rb"]},"contact.created":{"production":[{"pipeline":"integration","family":"canonicalContact"},{"pipeline":"legacy","family":"legacyRecordChange","note":"Service writes can publish both variants when both subscription paths are active."}],"testSendFamily":"legacyRecordChange","publishers":["app/services/contact/create.rb","app/models/contact.rb"]},"contact.updated":{"production":[{"pipeline":"integration","family":"canonicalContact"},{"pipeline":"legacy","family":"legacyRecordChange","note":"Service writes can publish both variants when both subscription paths are active."}],"testSendFamily":"legacyRecordChange","publishers":["app/services/contact/update.rb","app/models/contact.rb"]},"contact.deleted":{"production":[{"pipeline":"legacy","family":"legacyRecordChange"}],"testSendFamily":"legacyRecordChange","publishers":["app/models/contact.rb"]},"contact.newsletter_consent.changed":{"production":[{"pipeline":"integration","family":"canonicalContact"}],"testSendFamily":"legacyRecordChange","publishers":["app/services/contact/update.rb"]},"contact.subscription.added":{"production":[{"pipeline":"integration","family":"canonicalContact"}],"testSendFamily":"legacyRecordChange","publishers":["app/services/contact/create.rb","app/services/contact/update.rb"]},"contact.subscription.removed":{"production":[{"pipeline":"integration","family":"canonicalContact"}],"testSendFamily":"legacyRecordChange","publishers":["app/services/contact/update.rb"]},"segment.created":{"production":[{"pipeline":"legacy","family":"legacyRecordChange"}],"testSendFamily":"legacyRecordChange","publishers":["app/models/saved_filter.rb"]},"segment.updated":{"production":[{"pipeline":"legacy","family":"legacyRecordChange"}],"testSendFamily":"legacyRecordChange","publishers":["app/models/saved_filter.rb"]},"segment.deleted":{"production":[{"pipeline":"legacy","family":"legacyRecordChange"}],"testSendFamily":"legacyRecordChange","publishers":["app/models/saved_filter.rb"]},"segment.membership.added":{"production":[{"pipeline":"integration","family":"canonicalSegmentMembership"}],"testSendFamily":"canonicalSegmentMembership","publishers":["app/services/saved_filter_watches/evaluate_resource.rb"]}},"examples":{"canonicalOrder":{"id":"evt_123","key":"order.settled","type":"order.settled","version":1,"occurred_at":"2026-08-29T12:00:00Z","tenant":{"id":"42","slug":"museum"},"data":{"order":{"id":"100","number":"OR1001","payment_state":"settled"},"line_items":[]}},"legacyOfferableBooking":{"id":"whevt_123","type":"offerable.booking.created","created_at":"2026-08-29T12:00:00Z","tenant_id":"42","tenant_slug":"museum","data":{"offerable_id":"200","offerable_type":"EVENT","booking":{"id":"300","quantity":2},"current_attributes":{"remaining_quota":18},"previous_attributes":{"remaining_quota":20}}},"genericOfferableTest":{"id":"whevt_sample123","type":"offerable.booking.created","created_at":"2026-08-29T12:00:00Z","tenant_id":"42","tenant_slug":"museum","data":{"sample":true,"offerable_id":"sample-offerable-id","offerable_type":"EVENT","offerable_name":"Sample event","current_attributes":{"max_quota":100,"booked_quota":10,"remaining_quota":90,"max_participants":100},"previous_attributes":{"max_quota":100,"booked_quota":9,"remaining_quota":91,"max_participants":100}}},"legacyOfferableQuota":{"id":"whevt_124","type":"offerable.quota.updated","created_at":"2026-08-29T12:00:00Z","tenant_id":"42","tenant_slug":"museum","data":{"offerable_id":"200","offerable_type":"EVENT","current_attributes":{"max_quota":100,"booked_quota":12,"remaining_quota":88},"previous_attributes":{"max_quota":100,"remaining_quota":89}}},"canonicalContact":{"id":"evt_125","key":"contact.updated","version":1,"occurred_at":"2026-08-29T12:00:00Z","tenant":{"id":"42","slug":"museum"},"data":{"contact":{"id":"400","email":"alex@example.com","newsletter_accepted":true}}},"legacyRecordChange":{"id":"whevt_126","type":"segment.updated","created_at":"2026-08-29T12:00:00Z","tenant_id":"42","tenant_slug":"museum","data":{"resource":{"id":"500","name":"Members"},"changes":{"name":["Guests","Members"]}}},"canonicalSegmentMembership":{"id":"evt_127","key":"segment.membership.added","type":"segment.membership.added","version":1,"occurred_at":"2026-08-29T12:00:00Z","tenant":{"id":"42","slug":"museum"},"data":{"segment":{"id":"500","name":"Members"},"matched_resource":{"type":"Request","id":"600"},"matched_at":"2026-08-29T12:00:00Z"}}}}