Skip to content

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:

HTTP
POST /webhook-endpoint
Content-Type: application/json
X-Signature: abcdef

{
  "id": "evt_qwerty",
  "event": "event.type",
  "data": {
    "...": "..."
  }
}

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.

JavaScript
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

JSON
{
    "type": "users",
    "id": String
}
  • id will be the ID as provided by your SSO; even if it is numerical, we store it as a string

Events

JSON
{
  "type": "events",
  "id": Number,
  "title": String,
  "url": String|Null,
  "isVip": Boolean
}
  • url is the external URL set by your admins when creating the event on our platform.
  • isVip indicates whether the event is a VIP-only event

Event Attendees

JSON
{
  "type": "event-attendees",
  "id": Number,
  "isCheckedIn": Boolean,
  "user": User,
  "event": Event
}

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:

JSON
{
  "id": "evt_...",
  "event": "event.attendees.created",
  "data": {
    "id": 1,
    "isCheckedIn": false,
    "user": {
      "type": "users",
      "id": "your_sso_id"
    },
    "event": {
      "type": "events",
      "id": 1,
      "url": null,
      "isVip": true
    }
  }
}

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.