Webhook Documentation

When a subscribed event occurs, a POST request is sent to your endpoint URL within a few minutes. The request body is a JSON object with an event_type field that identifies what happened, so a single URL can receive all event types and route them internally.

Request format

Every delivery sends the following HTTP headers:

HeaderValue
Content-Typeapplication/json
X-Webhook-EventThe event type string, e.g. ticket.purchased
X-Webhook-Signaturesha256=<HMAC-SHA256 hex digest>

Verifying the signature

Each subscription has a signing secret shown on its edit page. Compute HMAC-SHA256 of the raw request body using that secret and compare it to the value in X-Webhook-Signature (after stripping the sha256= prefix). Always use a constant-time comparison to prevent timing attacks.

PHP

$secret  = 'your_signing_secret';
$payload = file_get_contents('php://input');
$sig     = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$expect  = 'sha256=' . hash_hmac('sha256', $payload, $secret);

if (! hash_equals($expect, $sig)) {
    http_response_code(401);
    exit;
}

Node.js

const crypto = require('crypto');
const secret = 'your_signing_secret';
const sig    = req.headers['x-webhook-signature'];
const digest = 'sha256=' +
  crypto.createHmac('sha256', secret)
        .update(req.rawBody)
        .digest('hex');

if (!crypto.timingSafeEqual(
      Buffer.from(digest),
      Buffer.from(sig))) {
  return res.status(401).end();
}

Envelope

Every payload shares the same top-level envelope. The data object varies by event type.

{
  "event_type": "ticket.purchased",   // string — one of the event types below
  "event_id":   42,                   // integer — the event this subscription belongs to
  "webhook_id": "550e8400-...",       // string — UUID v4, unique per delivery attempt
  "created_at": "2026-06-23T10:30:00-06:00",  // ISO-8601 with the event timezone offset
  "data": { ... }
}

Event types

TypeTriggerdata shape
ticket.purchased A ticket order was completed and payment collected. order + attendee
ticket.exchanged A ticket was exchanged for a different event time or type. order + attendee
ticket.transferred A ticket was transferred to a new holder. order + attendee
ticket.canceled A ticket was canceled. order + attendee
ticket.refunded A refund was issued for a ticket order. order + attendee
attendee.checked_in A ticket holder was scanned in at the gate. order + attendee
registration.created A new registration was confirmed. order + registration
registration.updated An existing registration was modified. order + registration
registration.canceled A registration was canceled. Also triggers alongside registration.refunded when a refund includes a cancellation. order + registration
registration.refunded A refund was issued for a registration. order + registration
registration.checked_in A participant was checked in at the event. order + registration
registration.transferred A registration was transferred to a different category. order + registration
registration.deferred A registration was deferred to a future year. order + registration
waiver.signed A participant signed a waiver, either during registration checkout or per-attendee for a ticket order after purchase. registration + waiver
product.purchased A merchandise order was completed and payment collected. order + product
product.fulfilled A purchased product was marked as fulfilled (picked up or shipped). order + product
donation.made A donation to a charity was completed as part of an order. order + donation
sponsorship.purchased A sponsorship was purchased for an event. order + sponsorship

Payload reference

The ticket and registration words are fixed for API consistency, event customizations to display text are ignored here.

Ticket events (ticket.* and attendee.checked_in) include an order and an attendee object. Registration events (registration.*) include an order and a registration object. The order object is the same shape in both cases. The waiver.signed event includes a registration and a waiver object (no order). product.purchased and product.fulfilled include an order and a product object. donation.made includes an order and a donation object. sponsorship.purchased includes an order and a sponsorship object.

Order object

FieldTypeNotes
idintegerInternal order ID
finish_dateISO-8601 stringWhen payment was collected and the order completed
billing_namestring
billing_emailstring
billing_addressstring
billing_citystring
billing_statestringTwo-letter state code
billing_provincestring|nullNon-US province, if applicable
billing_zipstring
billing_countrystringTwo-letter country code
order_typestringHuman-readable order type name
payment_typestringe.g. Credit Card, Free
ccnumberstringMasked card number, e.g. xxxx-xxxx-xxxx-4242
transaction_idstring|nullProcessor transaction reference
ticket_totaldecimal stringSum of ticket prices
registration_totaldecimal stringSum of registration prices (ticket events only)
merchandise_totaldecimal stringTicket events only
tax_totaldecimal string
marketplace_tax_totaldecimal string
discount_totaldecimal stringPromo codes and referral discounts
fee_totaldecimal stringProcessing fees
bonus_fee_totaldecimal stringEvent-specific bonus fees (subset of fee_total)
gift_card_paymentdecimal stringAmount paid with a gift card
order_totaldecimal stringGrand total charged

Ticket event payload

Used by: ticket.purchased, ticket.exchanged, ticket.transferred, ticket.canceled, ticket.refunded, attendee.checked_in

{
  "event_type": "ticket.purchased",
  "event_id":   42,
  "webhook_id": "550e8400-e29b-41d4-a716-446655440000",
  "created_at": "2026-06-23T10:30:00-06:00",
  "data": {
    "order": {
      "id":            456,
      "finish_date":   "2026-06-23T10:30:00-06:00",
      "billing_name":  "Jane Smith",
      "billing_email": "jane@example.com",
      "order_type":    "Ticket Order",
      "payment_type":  "Credit Card",
      "ccnumber":      "xxxx-xxxx-xxxx-4242",
      "ticket_total":  "75.00",
      "fee_total":     "6.50",
      "order_total":   "81.50",
      ...
    },
    "attendee": {
      "id":            789,
      "order_id":      456,
      "name":          "Jane Smith",
      "email":         "jane@example.com",
      "phone":         "5551234567",
      "status":        "Active",
      "billing_name":  "Jane Smith",
      "billing_email": "jane@example.com",
      "order_date":    "2026-06-23T10:30:00-06:00",
      "tickets": [
        {
          "id":               101,
          "order_id":         456,
          "event_time_name":  "5K Run",
          "event_time_start": "2026-07-04T08:00:00-06:00",
          "section_name":     "General Admission",
          "row_name":         null,
          "seat_name":        null,
          "price_label":      "Adult",
          "price":            "35.00",
          "tax":              "0.00",
          "fee":              "3.25"
        }
      ]
    }
  }
}

Attendee fields

FieldTypeNotes
idintegerTicket group ID — uniquely identifies this attendee record
order_idintegerThe order this attendee belongs to
namestringAttendee name as entered during checkout
emailstringAttendee email
phonestring|null
statusstringTicket group status name
billing_namestringName on the order (may differ from attendee name)
billing_emailstringEmail on the order
order_dateISO-8601 stringWhen the order was completed
ticketsarrayOne entry per ticket in this group — see below

Ticket fields (within attendee.tickets[])

FieldTypeNotes
idintegerUnique ticket ID — use this to identify an individual ticket
order_idintegerThe parent order — ties this ticket to its group and billing record
event_time_namestringName of the event time group, e.g. 5K Run
event_time_startISO-8601|nullStart time of the event time; null for reserved-seat tickets with a custom reservation window
section_namestring|nullVenue section, if assigned
row_namestring|nullSeat row, if assigned
seat_namestring|nullSpecific seat, if assigned
price_labelstring|nullTicket tier label, e.g. Adult, VIP
pricedecimal stringFace value of the ticket
taxdecimal string
feedecimal stringProcessing fee for this ticket

Registration event payload

Used by: registration.created, registration.updated, registration.canceled, registration.refunded, registration.checked_in, registration.transferred, registration.deferred

{
  "event_type": "registration.created",
  "event_id":   42,
  "webhook_id": "550e8400-e29b-41d4-a716-446655440001",
  "created_at": "2026-06-23T11:00:00-06:00",
  "data": {
    "order": {
      "id":            457,
      "finish_date":   "2026-06-23T11:00:00-06:00",
      "billing_name":  "John Doe",
      "billing_email": "john@example.com",
      "order_type":    "Registration",
      "payment_type":  "Credit Card",
      "ccnumber":      "xxxx-xxxx-xxxx-1234",
      "registration_total": "45.00",
      "fee_total":     "4.00",
      "order_total":   "49.00",
      ...
    },
    "registration": {
      "id":                  123,
      "order_id":            457,
      "first_name":          "John",
      "last_name":           "Doe",
      "email":               "john@example.com",
      "phone":               "5559876543",
      "address":             "123 Main St",
      "city":                "Boulder",
      "state":               "Colorado",
      "province":            null,
      "zip":                 "80301",
      "country_code":        "US",
      "gender":              "M",
      "birthdate":           "1988-04-15",
      "bib_number":          "1042",
      "category":            "5K Adult",
      "registration_date":   "2026-06-23T11:00:00-06:00",
      "checked_in_datetime": null
    }
  }
}

Registration fields

FieldTypeNotes
idintegerUnique registration ID
order_idintegerThe order this registration belongs to
first_namestring
last_namestring
emailstring
phonestring|null
addressstring|null
citystring|null
statestring|nullFull state name
provincestring|nullNon-US province
zipstring|null
country_codestringTwo-letter ISO country code
genderstring|nullM or F
birthdatedate|nullYYYY-MM-DD
bib_numberstring|nullAssigned race bib; null until assigned
categorystring|nullRegistration category/division name
registration_dateISO-8601 stringWhen the registration was created
checked_in_datetimeISO-8601|nullSet when the participant checks in on race day; null otherwise

Waiver event payload

Used by: waiver.signed

This event does not include an order object. It fires once per waiver per registration at the moment of signing.

{
  "event_type": "waiver.signed",
  "event_id":   42,
  "webhook_id": "550e8400-e29b-41d4-a716-446655440002",
  "created_at": "2026-06-23T11:00:00-06:00",
  "data": {
    "registration": {
      "id":                123,
      "order_id":          457,
      "first_name":        "John",
      "last_name":         "Doe",
      "email":             "john@example.com",
      "registration_date": "2026-06-23T11:00:00-06:00"
    },
    "waiver": {
      "waiver_id":         7,
      "waiver_version_id": 12,
      "waiver_name":       "General Liability Waiver",
      "signed_at":         "2026-06-23T11:00:05-06:00"
    }
  }
}

Waiver fields

FieldTypeNotes
waiver_idintegerID of the waiver template
waiver_version_idintegerID of the specific version that was signed; versions are created when the waiver text is edited
waiver_namestringName of the waiver
signed_atISO-8601 stringTimestamp when the signature was recorded

Product event payload

Used by: product.purchased, product.fulfilled

{
  "event_type": "product.purchased",
  "event_id":   42,
  "webhook_id": "550e8400-e29b-41d4-a716-446655440003",
  "created_at": "2026-06-23T11:00:00-06:00",
  "data": {
    "order": {
      "id":            458,
      "finish_date":   "2026-06-23T11:00:00-06:00",
      "billing_name":  "Jane Smith",
      "billing_email": "jane@example.com",
      "order_type":    "Merchandise Order",
      "payment_type":  "Credit Card",
      "ccnumber":      "xxxx-xxxx-xxxx-4242",
      "merchandise_total": "25.00",
      "fee_total":     "2.00",
      "order_total":   "27.00",
      ...
    },
    "product": {
      "id":                 321,
      "order_id":           458,
      "product_name":       "Event T-Shirt",
      "size":               "Large",
      "quantity":           1,
      "price":              "25.00",
      "shipping":           "0.00",
      "tax":                "0.00",
      "fee":                "2.00",
      "total":              "27.00",
      "fulfillment_status": "Unfulfilled"
    }
  }
}

Product fields

FieldTypeNotes
idintegerUnique product purchase ID
order_idintegerThe order this product purchase belongs to
product_namestring
sizestring|nullSelected size, if the product has sizes
quantityinteger
pricedecimal stringUnit price
shippingdecimal string
taxdecimal string
feedecimal stringProcessing fee
totaldecimal stringPrice, shipping, tax, and fee combined
fulfillment_statusstringUnfulfilled, Fulfilled, or Cancelled

Donation event payload

Used by: donation.made

{
  "event_type": "donation.made",
  "event_id":   42,
  "webhook_id": "550e8400-e29b-41d4-a716-446655440004",
  "created_at": "2026-06-23T11:00:00-06:00",
  "data": {
    "order": {
      "id":            459,
      "finish_date":   "2026-06-23T11:00:00-06:00",
      "billing_name":  "Jane Smith",
      "billing_email": "jane@example.com",
      "order_type":    "Ticket Order",
      "payment_type":  "Credit Card",
      "ccnumber":      "xxxx-xxxx-xxxx-4242",
      "order_total":   "35.00",
      ...
    },
    "donation": {
      "id":           654,
      "order_id":      459,
      "charity_name": "Local Food Bank",
      "donor_name":   "Jane Smith",
      "amount":       "25.00",
      "fee":          "2.00",
      "total":        "27.00",
      "comment":      "Keep up the great work!"
    }
  }
}

Donation fields

FieldTypeNotes
idintegerUnique donation ID
order_idintegerThe order this donation belongs to
charity_namestring
donor_namestring|null
amountdecimal stringDonation amount before fee
feedecimal string
totaldecimal stringAmount plus fee, if the donor covered the fee
commentstring|nullOptional message left by the donor

Sponsorship event payload

Used by: sponsorship.purchased

{
  "event_type": "sponsorship.purchased",
  "event_id":   42,
  "webhook_id": "550e8400-e29b-41d4-a716-446655440005",
  "created_at": "2026-06-23T11:00:00-06:00",
  "data": {
    "order": {
      "id":            460,
      "finish_date":   "2026-06-23T11:00:00-06:00",
      "billing_name":  "Acme Co.",
      "billing_email": "sponsor@acme.example.com",
      "order_type":    "Sponsorship",
      "payment_type":  "Credit Card",
      "ccnumber":      "xxxx-xxxx-xxxx-4242",
      "order_total":   "500.00",
      ...
    },
    "sponsorship": {
      "sponsor_id":      88,
      "order_id":        460,
      "sponsor_name":    "Acme Co.",
      "category_name":   "Gold Sponsor",
      "price":           "475.00",
      "tax":             "0.00",
      "marketplace_tax": "0.00",
      "fee":             "25.00"
    }
  }
}

Sponsorship fields

FieldTypeNotes
sponsor_idintegerUnique sponsor ID
order_idintegerThe order this sponsorship belongs to
sponsor_namestring
category_namestringSponsorship tier/category name
pricedecimal string
taxdecimal string
marketplace_taxdecimal string
feedecimal stringProcessing fee