Webhook event types

The full list of events Zillo emits today. Adding a new event is a code change, not a migration — check back here when integrating.

EventWhen
order.completedFires after fulfillOrder() flips the order to `fulfilled`. Payload is the full order object.
order.refundedFires after a charge.refunded webhook reconciles. Payload includes the updated order with `partially_refunded` / `refunded` status.
gift_card.issuedFires the first time a gift card row is created for an order item. Webhook re-deliveries from Stripe don't double-fire.
gift_card.redeemedFires every time the balance is decremented. Payload includes the updated gift card and the `redeemed_amount_cents`.
ticket.issuedOne event per ticket on first issuance. Payload includes `qr_token` and `max_uses` (1 for single-entry tickets; >1 for multi-day or multi-entry passes — e.g. a 3-day festival pass).
ticket.redeemedFires on EVERY scan, not just the first — multi-entry tickets (`max_uses > 1`) emit one event per scan. Payload includes the updated ticket (with live `uses_after` / `remaining`) plus `was_first: true|false` so subscribers can distinguish opening scans from subsequent re-entries.
booking.confirmedFires after a booking is issued (post-fulfillment). For slot-based bookings, payload's `experience_slot_id` is set; for multi-pass walk-in bookings (`max_uses > 1`) it's `null` — no slot was reserved at purchase.
booking.redeemedFires on EVERY scan, not just the first — multi-pass walk-in bookings (`max_uses > 1`, e.g. 10-class yoga pack) emit one event per visit. Payload includes the updated booking (with live `uses_after` / `remaining`) plus `was_first: true|false` so subscribers can distinguish first scans from subsequent punches.
voucher.issuedFires the first time a voucher row is created for an order item. Payload includes `max_uses` (1 for single-use; >1 for prepaid packs like a 5-class yoga pass).
voucher.redeemedFires on EVERY scan, not just the first — multi-use packs (`max_uses > 1`) emit one event per redemption. Payload includes the updated voucher (with live `uses_after` / `remaining`), the new `redemption` event row, and `was_first: true|false` so subscribers can distinguish opening scans from subsequent ones.
membership.activatedFires on first activation (status transitioned to `active` or `trialing`). Renewals don't re-fire.
membership.cancelledFires when the membership transitions to `canceled`.
membership.checkin.createdFires every time a check-in is recorded (append-only, not idempotent). On plans with a per-period cap (`max_checkins_per_period` — e.g. '5 classes a month'), payload includes a `usage` block with the live count, remaining allowance, and refill date. Capped plans reject scans beyond the allowance at the API layer (409 `exhausted`), so this event only fires for successful check-ins.
order.shippedFires when a merchant marks an order's physical-product lines shipped from the dashboard. Payload is the full order object plus the `tracking_number` and `carrier` entered at ship time (either may be null). Re-marking an already-shipped order is a no-op and doesn't re-fire.
digital_product.issuedFires the first time download tokens are minted for a digital-product order line (at fulfillment). Payload includes `order_id`, `order_item_id`, `product_id`, and `file_count`. Re-deliveries don't re-fire. The buyer separately receives secure, expiring download links by email.