Webhooks

In this guide, we'll walk you through the process of integrating webhooks from Start Booking.

Registering Webhooks

To register a new webhook, you need to provide us with a webhook URL that Start Booking can call. You can configure a new webhook URL directly within your Start Booking account > Integrations > Webhooks.

Now, whenever specific events occur within your Start Booking account, we'll send a POST request to your webhook URL. In the next section, we'll look at how to consume webhooks.

Consuming Webhooks

When your app receives a webhook request from Start Booking, check the action attribute to see what event caused it.

Example Customer Created Webhook

{
  "action": "customer.created",
  "changes": null,
  "data": {
    "url_string": "74f62f7a-044f-4647-8ca8-fff5557a95a9",
    "first_name": "John",
    "last_name": "Doe",
    // ...
  }
}

In the example above, a Customer was Created, and the payload data is a Customer. It's worth noting that the payload data will vary depending on the event action. For example, if the event action is customer.created, the payload data will be a Customer. If the event action is appointment.created, the payload data will be an Appointment. Below is an example of a webhook payload for an appointment.created event.

Example Appointment Created Webhook

{
  "action": "appointment.created",
  "changes": null,
  "data": {
    "url_string": "74f62f7a-044f-4647-8ca8-fff5557a87yj",
    "customer_tz": null,
    "status": "active",
    "start_date": "2023-05-10 13:00:00",
    "end_date": "2023-05-10 13:30:00",
    "buffer": 0,
    "account_tz": "America/Denver",
    "booking_origin": "create_appointment",
    "type": "appointment",
    "hash_group": "13c96a0dbf62bc37c009536e9371b05c",
    "updated_at": "2023-05-10T12:49:49.000000Z",
    "created_at": "2023-05-10T12:49:49.000000Z",
    "customer": {
      "url_string": "74f62f7a-044f-4647-8ca8-fff5557a95a9",
      "account_url_string": "p5ni2f7a-044f-4647-8ca8-fff5557a87yj",
      "first_name": "John",
      "last_name": "Doe",
      "email": "[email protected]",
      "image_url": null,
      "is_valid_email": false,
      "home_phone": null,
      "mobile_phone": null,
      "work_phone": null,
      "preferred_contact_method": "mobile",
      "is_valid_mobile_phone": false,
      "country_code": null,
      "timezone": "America/Denver",
      "language": "english",
      "birthday": null,
      "occupation": null,
      "gender": null,
      "receive_emails": true,
      "receive_sms": true,
      "emergency_contact": null,
      "emergency_phone": null,
      "is_guest": false,
      "created_at": "2021-07-22T23:37:47.000000Z",
      "updated_at": "2022-06-09T01:06:29.000000Z",
      "deleted_at": null,
    },
    "user": {
      "url_string": "74f62f7a-044f-4647-8ca8-fff555724kb7",
      "sort_order": null,
      "status": "active",
      "first_name": "Rick",
      "last_name": "Smith",
      "email": "[email protected]",
      "is_valid_email": true,
      "home_phone": null,
      "mobile_phone": "+18018082909",
      "work_phone": null,
      "is_valid_mobile_phone": true,
      "color": "#8ed1fc",
      "country_code": "US",
      "language": null,
      "bio": null,
      "created_at": "2018-04-16T06:42:04.000000Z",
      "updated_at": "2022-12-18T22:16:11.000000Z",
      "deleted_at": null,
      "media": [
        {
          "url_string": null,
          "url": "https://www....com",
          "file_type": null,
          "created_at": null,
          "updated_at": null,
          "deleted_at": null
        }
      ],
      "image_url": "https://www....com"
    }
  }
}

Event Actions

  • Name
    appointment.created
    Type
    Description

    A new appointment was created.

  • Name
    appointment.updated
    Type
    Description

    An existing appointment was updated.

  • Name
    appointment.cancelled
    Type
    Description

    An existing appointment was cancelled.

  • Name
    appointment.service.changed
    Type
    Description

    An existing appointment's service was changed.

  • Name
    service.created
    Type
    Description

    A new service was created.

  • Name
    service.updated
    Type
    Description

    An existing service was updated.

  • Name
    service.deleted
    Type
    Description

    An existing service was deleted.

  • Name
    customer.created
    Type
    Description

    A new customer was created.

  • Name
    customer.updated
    Type
    Description

    An existing customer was updated.

  • Name
    customer.deleted
    Type
    Description

    An existing customer was deleted.

  • Name
    customer.joined.class
    Type
    Description

    A customer joined a class.

  • Name
    customer.removed.from.class
    Type
    Description

    A customer was removed from a class.

  • Name
    class.created
    Type
    Description

    A new class was created.

  • Name
    class.updated
    Type
    Description

    An existing class was updated.

  • Name
    class.deleted
    Type
    Description

    An existing class was deleted.

  • Name
    class.schedule.created
    Type
    Description

    A new class schedule was created.

  • Name
    class.schedule.updated
    Type
    Description

    An existing class schedule was updated.

  • Name
    class.schedule.deleted
    Type
    Description

    An existing class schedule was deleted.

  • Name
    user.created
    Type
    Description

    A new user was created.

  • Name
    user.updated
    Type
    Description

    An existing user was updated.

  • Name
    user.deleted
    Type
    Description

    An existing user was deleted.


Security

To know for sure that a webhook was, in fact, sent by Start Booking instead of a malicious actor, you can verify the request signature. Each webhook request contains a header named x-startbooking-signature, and you can verify this signature by using your signing secret key located in your webhooks settings of your Start Booking account.

The signature is an HMAC hash of the request payload hashed using your signing secret key. Here is an example of how to verify the signature in your app:

Verifying a request

const signature = req.headers['x-startbooking-signature']
const hash = crypto.createHmac('sha256', secret).update(payload).digest('hex')

if (hash === signature) {
  // Request is verified
} else {
  // Request could not be verified
}

If your generated signature matches the x-startbooking-signature header, you can be sure that the request was truly coming from Start Booking. It's essential to keep your secret webhook signing secret key safe — otherwise, you can no longer be sure that a given webhook was sent by Start Booking. Don't commit your secret webhook key to GitHub!

If you feel your secret webhook key has been compromised, you can refresh it in your Webhook settings. This will immediately invalidate the previous key, and you will need to use the new key to verify any subsequent webhook requests.