{"contractVersion":"1.0.0","asyncapi":"3.0.0","developerDocsUrl":"/docs/developers/webhooks","payloadFamilies":["canonicalOrder","legacyOfferableBooking","genericOfferableTest","legacyOfferableQuota","canonicalContact","legacyRecordChange","canonicalSegmentMembership","canonicalScan"],"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":"event-specific","note":"Scan tests use the integration delivery route and bypass filters for the selected endpoint. Other Test button events create a sample WebhookEvent through the legacy delivery route, even when their production 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"]},"ticket.validation.checked":{"production":[{"pipeline":"integration","family":"canonicalScan"}],"testSendFamily":"canonicalScan","publishers":["app/services/integration_events/publish_scan_event.rb"]},"ticket.entry.committed":{"production":[{"pipeline":"integration","family":"canonicalScan"}],"testSendFamily":"canonicalScan","publishers":["app/services/integration_events/publish_scan_event.rb"]},"ticket.exit.committed":{"production":[{"pipeline":"integration","family":"canonicalScan"}],"testSendFamily":"canonicalScan","publishers":["app/services/integration_events/publish_scan_event.rb"]},"ticket.commitment.recorded":{"production":[{"pipeline":"integration","family":"canonicalScan"}],"testSendFamily":"canonicalScan","publishers":["app/services/integration_events/publish_scan_event.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"}},"canonicalScan":{"id":"123","key":"ticket.entry.committed","version":1,"occurred_at":"2026-10-01T10:00:00Z","tenant":{"id":"42","slug":"museum"},"data":{"scan":{"source":"korona_entry","source_event_id":"korona-entry:source-digest","account_id":"entry-account","phase":"commitment","result":"SUCCESS","outcome":"accepted","direction":"access","gate_number":"MAIN","gate_name":"Main entrance","occurred_at":"2026-10-01T10:00:00Z","received_at":"2026-10-01T10:00:05Z","number_of_uses":3,"resolved":false,"external_ticket_id":"remote-ticket","ticket_product_ids":[],"linked_event_ids":[]}}}}}