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,
except in cases where an external ID is available.
Users
idwill be the ID as provided by your SSO; even if it is numerical, we store it as a string
Events
urlis the external URL set by your admins when creating the event on our platform.isVipindicates whether the event is a VIP-only event
Event Attendees
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 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.