Webhooks
The webhooks for events allow you to synchronise mutations in our system with yours, e.g. to track attendance, for table planning, etcetera.
Mechanism
When we enable the webhooks for you, you will be provided with an identifier for your channel, as well as a webhook secret. Both of these MUST be kept secret, as they are sensitive credentials.
With these two values, you can verify that the incoming request did indeed come from our systems.
Webhooks have a header X-Signature, which contains a string that is generated by our systems, using your credentials.
Bodies will always be JSON. Generally speaking, a webhook looks as follows:
Verifying the incoming webhook
SDK availability
We can provide SDKs for PHP and JavaScript upon request, which will make it very quick to implement this.
Any code in this section is pseudocode. You will need adapt this pseudocode to the programming language of your choice.
The signature header consists of 2 parts: a timestamp (as nanoseconds since UNIX epoch) and a hash (a string).
These 2 parts are joined by a slash (/).
The timestamp indicates when the webhook was generated on our systems;
you may use this to make sure the webhook was executed in a timely fashion.
const identifier = env['PLATFORM_IDENTIFIER']
const secret = env['WEBHOOK_SECRET']
// This MUST be the raw string from the body.
const body = request.body
const header = request.headers['X-Signature']
// Split the header, as per our spec
const parts = header.split('/')
// Must be exactly 2 non-empty parts to it.
if (parts.length !== 2 || parts[0] is empty || parts[1] is empty) {
fail 'Invalid Header'
}
const timestamp = parts[0] as number
const signature = parts[1] as string
// Optional: you can check for a discrepancy between the timestamp and current time.
if (timestamp === 0 || timestamp < time.now.minusMinutes(5).nanoseconds) {
fail 'Timestamp is out of range'
}
// Generate the message to verify.
// You MUST use the body exactly as we sent it in order to verify.
const message = identifier + '/' + timestamp + '/' + body
const expectedSignature = HMAC('SHA256', message, secret)
if (signature !== expectedSignature) {
fail 'Invalid signature'
}
// Proceed to parse the body as you see fit.
Request Body
| Attribute | Type | Description |
|---|---|---|
id |
string | A unique identifier for this particular webhook. May be used to ensure every webhook is handled only once. |
event |
string | The type of this webhook. See the individual webhooks below for details. |
data |
object | The data for this particular webhook. See the individual webhooks below for details. |
Data Types
Data is represented in consistent structures across all webhooks.
At their core, each data structure will have a type and an id field.
type is a lowercase, dash-separated plural data type; e.g. users rather than user,
or event-attendees as opposed to event-attendee.
The id will typically be a unique, generated ID from our platform.
The exception is with users, where only an external ID is returned.
Users
idwill be the ID as provided by your SSO; even if it is numerical, we store it as a string
Events
externalIdis the external ID if it was set during cross-postingurlis the external URL set by your admins when creating the event on our platform.isVipindicates whether the event is a VIP-only eventisPaidindicates whether the event is a paid eventisTicketedindicates whether the event is an on-platform, ticketed event
Event Attendees
useris a nested user data structureeventis a nested event data structureisCheckedInindicates whether the attendee has been checked in
Event Ticket Types
eventis a nested event data structureexternalIdis the external ID if it was set during cross-postingpriceis the price of this ticket type in the smallest denomination possible (cents, pence)quantityis total inventory available of this ticket typepurchaseLimitis the maximum number of tickets that may be purchased of this type per customerisVipindicates whether this ticket type is limited to VIP members only
Event Tickets
useris a nested user data structure, indicating the user who purchased this ticket.eventis a nested event data structuregivenNameis the given name for this ticket as provided during the order processfamilyNameis the family name for this ticket as provided during the order processisPrimaryGuestindicates whether this ticket is for the primary guest, e.g. the user who placed the order.isCheckedInindicates whether the guest registered on this ticket has been checked in
Webhooks
Note
All webhooks below only detail the structure of the data field in the full request body, not the entire body.
As an example, here's an example of event.attendees.created:
Event Mutations
There are 3 webhooks for event mutations:
- events.created When an event is created
- events.updated When an event is updated
- events.deleted When an event is deleted
The data field is of type events.
Event Ticket Type Mutations (ticketed events only)
There are 3 webhooks for event mutations:
- ticket-types.created When a ticket type is created
- ticket-types.updated When a ticket type is updated
- ticket-types.deleted When a ticket type is deleted
The data field is of type event-ticket-types.
Event Attendee Mutations
There are 4 webhooks for attendee mutations:
- event.attendees.created When someone RSVP's to an event
- event.attendees.deleted When someone retracts their RSVP for an event
- event.attendees.checked-in An attendee has been checked in
- event.attendees.checked-out An attendee has been checked out
The data field is of type event-attendees.
Note
These webhooks also fire for ticketed events, but only for the member who booked.
For ticketed events, we recommend listening to the event.tickets.* webhooks.
Event Ticket Mutations
There are 4 webhooks for ticket mutations:
- event.tickets.created When an order is placed for a ticketed event (e.g. a member RSVPing, optionally with guests)
- event.tickets.deleted Occurs only when an order is cancelled or refunded
- event.tickets.checked-in An attendee or guest has been checked in
- event.tickets.checked-out An attendee or guest has been checked out
The data field is of type event-tickets.
Note
These webhooks only fire for ticketed events.