Generated reference

Outbound webhook contract

This English reference is generated from the reviewed, tracked implementation contract.

Contract sha256:6ca4835ad0f5cd8c5890b3a281e92efd417607d0c8b41d26d481164b4f912ca7

There is no universal webhook envelope. Select the payload family for the event and production delivery path you consume.

Verification and delivery

Signatures use HMAC-SHA256 over <unix-seconds>.<raw-json-body> and are sent as t=<unix-seconds>,v1=<hex-hmac>. Verify the signature against the exact request bytes before parsing JSON.

A delivery has 5 total attempts. After a failed initial attempt, retries wait 30, 60, 300, 900 seconds.

The connection deadline is 5 seconds and the response/read deadline is 10 seconds. 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.

Integration delivery retries: HTTP 408; HTTP 425; HTTP 429; HTTP 5xx; connection and timeout failures.

Legacy delivery retries: HTTP 408; HTTP 429; HTTP 499; HTTP 5xx; connection and timeout failures.

Test send: 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.

Headers

Common: Content-Type, X-Webhook-Signature, X-Webhook-Event-Id, X-Webhook-Event-Type, X-Webhook-Timestamp.

Integration aliases: X-ToucanTix-Event-Id, X-ToucanTix-Event-Key, X-ToucanTix-Event-Version, X-ToucanTix-Occurred-At, X-ToucanTix-Delivery-Id, X-ToucanTix-Signature.

Legacy aliases: X-Toucantix-Webhook-Signature, X-Toucantix-Webhook-Timestamp, X-Toucantix-Webhook-Sample.

Custom headers cannot replace these authoritative headers. Authorization is allowed.

Event matrix

order.settled

Production: integration: canonicalOrder.

Test send: canonicalOrder via legacy delivery.

offerable.booking.created

Production: integration: legacyOfferableBooking.

Test send: genericOfferableTest via legacy delivery.

offerable.booking.updated

Production: integration: legacyOfferableBooking.

Test send: genericOfferableTest via legacy delivery.

offerable.booking.cancelled

Production: integration: legacyOfferableBooking.

Test send: genericOfferableTest via legacy delivery.

offerable.quota.updated

Production: integration: legacyOfferableQuota.

Test send: legacyOfferableQuota via legacy delivery.

contact.created

Production: integration: canonicalContact; legacy: legacyRecordChange (Service writes can publish both variants when both subscription paths are active.).

Test send: legacyRecordChange via legacy delivery.

contact.updated

Production: integration: canonicalContact; legacy: legacyRecordChange (Service writes can publish both variants when both subscription paths are active.).

Test send: legacyRecordChange via legacy delivery.

contact.deleted

Production: legacy: legacyRecordChange.

Test send: legacyRecordChange via legacy delivery.

Production: integration: canonicalContact.

Test send: legacyRecordChange via legacy delivery.

contact.subscription.added

Production: integration: canonicalContact.

Test send: legacyRecordChange via legacy delivery.

contact.subscription.removed

Production: integration: canonicalContact.

Test send: legacyRecordChange via legacy delivery.

segment.created

Production: legacy: legacyRecordChange.

Test send: legacyRecordChange via legacy delivery.

segment.updated

Production: legacy: legacyRecordChange.

Test send: legacyRecordChange via legacy delivery.

segment.deleted

Production: legacy: legacyRecordChange.

Test send: legacyRecordChange via legacy delivery.

segment.membership.added

Production: integration: canonicalSegmentMembership.

Test send: canonicalSegmentMembership via legacy delivery.

Payload families

Canonical order event

json
{
  "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": []
  }
}

Offerable booking event

json
{
  "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
    }
  }
}

Generic offerable test-send event

json
{
  "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
    }
  }
}

Offerable quota event

json
{
  "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
    }
  }
}

Canonical contact event

json
{
  "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": "[email protected]",
      "newsletter_accepted": true
    }
  }
}

Legacy record-change event

json
{
  "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"]
    }
  }
}

Canonical segment membership event

json
{
  "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"
  }
}

Ready to Get Started?

Book a free demo or reach out — we’d love to hear from you.