Webhooks

The Wellhub webhooks will notify you when specific events are triggered. This notification is an HTTP POST request to your registered URL.

This document describes both the events that are triggered along with the data they send and the API resources available for the webhooks.

General Information

Data format

Every API resource and push event uses JSON as its standard data format.

Security

When Wellhub sends an event notification to a registered webhook, we include a signature header so you know the request was sent from our servers. The header name is X-Gympass-Signature. We strongly recommend that you verify this signature when you receive a request at your webhook endpoint. This allows you to verify that the events were sent by Wellhub, not by a third party.

Before you can verify signatures, you need to provide your secret key to Wellhub Tech Sales.

Please note that the secret key has a max character limit of 100 characters

  • Wellhub generates the signature by encoding the HTTP request body using your secret key.
  • The encryption is done by HMAC-SHA-1 algorithm, and the body of the request will need to be stringified.
  • Compare the signature string with the Wellhub header value. If they match, the message came from Wellhub servers.
  • The signature string will always be Upper.

Below you will find several templates you can use to generate the hash script.

JavaScript || Java || C# || GO || PHP || Python

Retry

The response time is 1s. After that, if we have no response, we retry 3 times immediately after the missed response.

Booking Events

POST - booking.Requested

localhost:8080/gym-webhook-url/booking/requested

Triggered whenever a new booking request is made.

Request example
1curl --location --request POST 'localhost:8080/gym-webhook-url/booking/requested' \
2--header 'Content-Type: application/json' \
3--header 'X-Gympass-Signature: 0XFBDB1D1B18AA6C08324B7D64B71FB76370690E1D' \
4--data-raw '{
5 "event_type": "booking-requested",
6 "event_data": {
7 "user": {
8 "unique_token": "123456789012",
9 "name": "Firstname Lastname",
10 "email": "user@email.com"
11 },
12 "slot": {
13 "id": 01234567,
14 "gym_id": 012345,
15 "class_id": 654321,
16 "booking_number": "BK_A1B2C3"
17 },
18 "timestamp": 1560983373378,
19 "event_id": "7e8cbb0f-9681-4d3e-8c36-2b3dd6ecbadb"
20 }
21}'

Request Params

NameTypeDescription
event_typeStringType of the event. For a booking request event, it defaults to "booking-requested"
event_data.user.unique_tokenStringThe Wellhub ID for the user
event_data.user.nameStringName of the user who has originated the booking request.
event_data.user.emailStringEmail of the user who has originated the booking request.
event_data.slot.idIntId for the slot.
event_data.slot.gym_idIntID for the gym in which the booking is requested to.
event_data.slot.booking_numberStringIdentifier for the booking event.
event_data._event_timeLongTime when the event was generated.
_event_idStringID for the event.

Headers

FieldDescription
Content-Typeapplication/json
X-Gympass-Signature0XFBDB1D1B18AA6C08324B7D64B71FB76370690E1D - This is an example

Response

Response example
1{
2 "event_type": "booking-requested",
3 "event_data": {
4 "user": {
5 "unique_token": "123456789012",
6 "name": "Firstname Lastname",
7 "email": "user@email.com"
8 },
9 "slot": {
10 "id": 01234567,
11 "gym_id": 012345,
12 "class_id": 654321,
13 "booking_number": "BK_A1B2C3"
14 },
15 "timestamp": 1560983373378,
16 "event_id": "7e8cbb0f-9681-4d3e-8c36-2b3dd6ecbadb"
17 }
18}

POST - booking.Cancelation

localhost:8080/gym-webhook-url/booking/cancelation

Triggered whenever a user cancels a previously booked class.

Request Example
1curl --location --request POST 'localhost:8080/gym-webhook-url/booking/cancelation' \
2--header 'Content-Type: application/json' \
3--header 'X-Gympass-Signature: 0XFBDB1D1B18AA6C08324B7D64B71FB76370690E1D' \
4--data-raw '{
5 "event_type": "booking-canceled",
6 "event_data": {
7 "user": {
8 "unique_token": "123456789012"
9 },
10 "slot": {
11 "id": 01234567,
12 "gym_id": 012345,
13 "class_id": 654321,
14 "booking_number": "BK_A1B2C3"
15 },
16 "timestamp": 1560983373378,
17 "event_id": "7e8cab0f-9981-4d3e-8c36-2b3dd6ecbadb"
18 }
19}'

Event payload:

NameTypeDescription
event_typeStringType of the event. For a booking cancellation event, it defaults to "booking-canceled"
event_data.user.unique_tokenStringThe Wellhub ID for the user
event_data.slot.idIntId for the slot.
event_data.slot.gym_idIntID for the gym to which the booking is requested.
event_data.slot.booking_numberStringIdentifier for the booking event.
_event_id StringIDfor the event.

Headers

FieldDescription
Content-Typeapplication/json
X-Gympass-Signature0XFBDB1D1B18AA6C08324B7D64B71FB76370690E1D - This is an example

Response

Response example
1{
2 "event_type": "booking-canceled",
3 "event_data": {
4 "user": {
5 "unique_token": "123456789012"
6 },
7 "slot": {
8 "id": 01234567,
9 "gym_id": 012345,
10 "class_id": 654321,
11 "booking_number": "BK_A1B2C3"
12 },
13 "timestamp": 1560983373378,
14 "event_id": "7e8cab0f-9981-4d3e-8c36-2b3dd6ecbadb"
15 }
16}

POST - booking.LateCancelation

localhost:8080/gym-webhook-url/booking/lateCancelation

Triggered whenever a user cancels a previously booked class.

Request example
1curl --location --request POST 'localhost:8080/gym-webhook-url/booking/lateCancelation' \
2--header 'Content-Type: application/json' \
3--header 'X-Gympass-Signature: 0XFBDB1D1B18AA6C08324B7D64B71FB76370690E1D' \
4--data-raw '{
5 "event_type": "booking-late-canceled",
6 "event_data": {
7 "user": {
8 "unique_token": "123456789012"
9 },
10 "slot": {
11 "id": 01234567,
12 "gym_id": 012345,
13 "class_id": 654321,
14 "booking_number": "BK_A1B2C3"
15 },
16 "timestamp": 1560983373378,
17 "event_id": "7e8cab0f-9981-4d3e-8c36-2b3dd6ecbadb"
18 }
19}'

Event payload:

NameTypeDescription
event_typeStringType of the event. For a booking cancellation event, it defaults to "booking-late-cancelled"
event_data.user.unique_tokenStringThe Wellhub ID for the user
event_data.slot.idIntId for the slot.
event_data.slot.gym_idIntID for the gym to which the booking is requested.
event_data.slot.booking_numberStringIdentifier for the booking event.
_event_idStringID for the event.

Headers

FieldDescription
Content-Typeapplication/json
X-Gympass-Signature0XFBDB1D1B18AA6C08324B7D64B71FB76370690E1D - This is an example

Response

Response example
1{
2 "event_type": "booking-late-canceled",
3 "event_data": {
4 "user": {
5 "unique_token": "123456789012"
6 },
7 "slot": {
8 "id": 01234567,
9 "gym_id": 012345,
10 "class_id": 654321,
11 "booking_number": "BK_A1B2C3"
12 },
13 "timestamp": 1560983373378,
14 "event_id": "7e8cab0f-9981-4d3e-8c36-2b3dd6ecbadb"
15 }
16}

POST - checkin-booking-occurred

localhost:8080/gym-webhook-url/booking/checkin-booking-occurred

Triggered whenever a user checks in to a gym partner with a pending booked class.

Request example
1curl --location --request POST 'localhost:8080/gym-webhook-url/booking/checkin-booking-occurred \
2--header 'Content-Type: application/json' \
3--header 'X-Gympass-Signature: 0XFBDB1D1B18AA6C08324B7D64B71FB76370690E1D' \
4--data-raw {
5 "event_data": {
6 "booking": {
7 "booking_number": "BK_LRNLABC"
8 },
9 "user": {
10 "unique_token": "1234567890123"
11 },
12 "location": {
13 "lat": 33.9976708,
14 "lon": -118.4597197
15 },
16 "gym": {
17 "id": 123456,
18 "title": "Gym Name",
19 "product": {
20 "description": "Classes - Unlimited",
21 "pass_type_number": 1
22 }
23 },
24 "timestamp": 1668090666,
25 "expires_at": 1668096066
26 },
27 "event_type": "checkin-booking-occurred"
28}

Event payload:

NameTypeDescription
event_data.booking.booking_numberStringIdentifier for the booking event.
event_data.user.unique_tokenStringThe Wellhub ID for the user
event_data.coordinatesObjectContains the lat and long information for the gym where the check-in is being made.
event_data.coordinates.latDoubleLatitude for the gym where the check-in has taken place.
event_data.coordinates.lonDoubleLongitude for the gym where the check-in has taken place.
event_data.gym.idIntThe gym ID for which the check-in refers.
event_data.gym.titleStringThe gym name for which the check-in refers.
event_data.productObjectProduct details for which the check-in refers
event_data.product.descriptionStringProduct description
pass_type_numberIntSpecifies what product the check-in is for
timestampLongTimestamp for the creation date of the event
event_typeStringType of the event. For check-ins with a corresponding booking.

Headers

FieldDescription
Content-Typeapplication/json
X-Gympass-Signature0XFBDB1D1B18AA6C08324B7D64B71FB76370690E1D - This is an example

Response

Response example
1{
2 "event_type": "booking-late-canceled",
3 "event_data": {
4 "user": {
5 "unique_token": "123456789012"
6 },
7 "slot": {
8 "id": 01234567,
9 "gym_id": 012345,
10 "class_id": 654321,
11 "booking_number": "BK_A1B2C3"
12 },
13 "timestamp": 1560983373378,
14 "event_id": "7e8cab0f-9981-4d3e-8c36-2b3dd6ecbadb"
15 }
16}

X-Gympass-Signature Scripts

JavaScript

SHA 1 HASH
1const crypto = require('crypto');
2
3// Your secret key provided by you
4const secretKey = '*Secret Key*';
5
6// Function to generate the x-gympass-signature
7function generateGympassSignature(requestBody) {
8 const hmac = crypto.createHmac('sha1', secretKey);
9 hmac.update(requestBody);
10 const signature = hmac.digest('hex');
11 return signature.toUpperCase();
12}
13
14// Example usage
15const requestBody = JSON.stringify({ **Webhook event Body Payload** });
16
17const gympassSignature = generateGympassSignature(requestBody);
18
19console.log('Generated x-gympass-signature:', gympassSignature);

Java

SHA1 HASH
1import javax.crypto.Mac;
2import javax.crypto.spec.SecretKeySpec;
3import java.nio.charset.StandardCharsets;
4import java.security.InvalidKeyException;
5import java.security.NoSuchAlgorithmException;
6
7public class GympassSignatureGenerator {
8 public static void main(String[] args) {
9 // Your secret key provided by you
10 String secretKey = "";
11
12 // Example request body
13 String requestBody = "Webhook request body";
14
15 String gympassSignature = generateGympassSignature(requestBody, secretKey);
16
17 System.out.println("Generated x-gympass-signature: " + gympassSignature);
18 }
19
20 public static String generateGympassSignature(String requestBody, String secretKey) {
21 try {
22 Mac hmacSha1 = Mac.getInstance("HmacSHA1");
23 SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
24 hmacSha1.init(keySpec);
25 byte[] hash = hmacSha1.doFinal(requestBody.getBytes(StandardCharsets.UTF_8));
26 StringBuilder hexString = new StringBuilder();
27 for (byte b : hash) {
28 String hex = Integer.toHexString(0xFF & b);
29 if (hex.length() == 1) {
30 hexString.append('0');
31 }
32 hexString.append(hex);
33 }
34 return hexString.toString().toUpperCase();
35 } catch (NoSuchAlgorithmException | InvalidKeyException e) {
36 e.printStackTrace();
37 }
38 return null;
39 }
40}

C#

SHA 1 HASH
1using System;
2using System.Security.Cryptography;
3using System.Text;
4
5class Program
6{
7 static string GenerateGympassSignature(string requestBody, string secretKey)
8 {
9 using (var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(secretKey)))
10 {
11 byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(requestBody));
12 return BitConverter.ToString(hash).Replace("-", "").ToUpper();
13 }
14 }
15
16 static void Main()
17 {
18 string secretKey = "*Secret Key*";
19 string requestBody = "{**Webhook event Body Payload** }";
20
21 string gympassSignature = GenerateGympassSignature(requestBody, secretKey);
22
23 Console.WriteLine("Generated x-gympass-signature: " + gympassSignature);
24 }
25}

Go

SHA 1 HASH
1package main
2
3import (
4 "crypto/hmac"
5 "crypto/sha1"
6 "encoding/hex"
7 "fmt"
8)
9
10func generateGympassSignature(requestBody string, secretKey string) string {
11 hmacSha1 := hmac.New(sha1.New, []byte(secretKey))
12 hmacSha1.Write([]byte(requestBody))
13 signature := hex.EncodeToString(hmacSha1.Sum(nil))
14 return fmt.Sprintf("%s", signature)
15}
16
17func main() {
18 secretKey := "*Secret Key*"
19 requestBody := `{**Webhook event Body Payload** }`
20
21 gympassSignature := generateGympassSignature(requestBody, secretKey)
22
23 fmt.Println("Generated x-gympass-signature:", gympassSignature)
24}

PHP

SHA 1 HASH
1<?php
2
3function generateGympassSignature($requestBody, $secretKey) {
4 $signature = hash_hmac('sha1', $requestBody, $secretKey);
5 return strtoupper($signature);
6}
7
8$secretKey = '*Secret Key*';
9$requestBody = '{**Webhook event Body Payload** }';
10
11$gympassSignature = generateGympassSignature($requestBody, $secretKey);
12
13echo 'Generated x-gympass-signature: ' . $gympassSignature;
14?>

Python

SHA 1 HASH
1import hmac
2import hashlib
3
4def generate_gympass_signature(request_body, secret_key):
5 signature = hmac.new(secret_key.encode('utf-8'), request_body.encode('utf-8'), hashlib.sha1).hexdigest()
6 return signature.upper()
7
8secret_key = '*Secret Key*'
9request_body = '{**Webhook event Body Payload** }'
10
11gympass_signature = generate_gympass_signature(request_body, secret_key)
12
13print('Generated x-gympass-signature:', gympass_signature)