Webhooks
Webhooks provide real-time event subscriptions, allowing your application to send data to external services, such as email systems or third-party APIs, as events happen. They can also be used to trigger custom logic within your application, enabling smooth integration with external workflows and automating event-driven processes.
Creating a webhook
Webhooks are directly related to applications so if you haven't already, please follow this guide to create an application.
Once your application is set up, let's proceed with creating a webhook. From the main application page, find "Webhooks" in the left-hand navigation menu and click on it to access the webhooks dashboard. Next, click on "+ Create Webhook" to go to the webhook creation page.
In the steps outlined above, we created a named webhook and configured it to point to http://localhost:4000/webhook. This webhook will be triggered whenever a user signs in or publishes a message.
Webhook events
Currently, the following webhook events are supported:
Event Name | Description |
---|---|
auth:signup | Successful user registration. |
auth:verify | Successful user verification. |
auth:signin | Successful user sign-in. |
auth:session:initialize | Session initialization event. |
presence:join | User joined a presence set. |
presence:leave | User left a presence set. |
presence:update | User updated presence data. |
room:create | The first user entered a room, in turn creating the room. |
room:join | Room is joined by a user. |
room:publish | A message is published to a room. |
room:leave | User left a room. |
room:destroy | The last user left a Room |
user:status:update | User updated status |
The webhook request
When a webhook is triggered, a request will be sent to the specified endpoint, carrying a JSON payload with the relevant event data. For instance, when a user publishes a message, a POST request with the following body will be delivered to the webhook endpoint.
{
id: '123',
event: 'room:publish',
data: {
message: 'asd',
roomId: 'chat:one:test',
event: 'custom'
},
session: {
appPid: 'RF6lWPaGHHHR',
keyId: 'j0SkOl15fgtT',
clientId: 'P0nEJBOKTZaj',
connectionId: 'RF6lWPaGHHHR:b_CZfSVSEyG7',
socketId: '6f12c9d6-dae4-49b0-b911-659020fa212d',
timestamp: '2024-10-22T13:14:49.823Z',
exp: 1729603189,
user: {
id: '123',
clientId: 'P0nEJBOKTZaj',
createdAt: '2024-10-22T10:10:22.755Z',
updatedAt: '2024-10-22T10:10:22.755Z',
username: 'MarxistPinniped997',
orgId: '841447d5-f696-405f-b7a9-3eecc2f82c36',
appId: '73070aee-7f8b-40c2-9eba-8216e4c86654',
isOnline: false,
lastOnline: '2024-10-22T12:49:58.897Z',
blockedAt: null,
firstName: null,
lastName: null
}
},
timestamp: '2024-10-22T13:15:08.913Z'
}
The request body will always follow this structure, regardless of the event type. The only variations will be in the value of data, which will hold the event-specific information, and session.user, which may be null if the session does not have an associated user object.
Read more about authentication and session data by viewing the Authentication section of this documentation.
In the example above, the publish event triggered the webhook. As a result, the data field contains the message content, the ID of the room where the message was published, and the name of the event.
Verifying a webhook request
By default, every request dispatched from the webhook service also includes two additional headers.
- X-Relaybox-Webhook-Signature
- X-Relaybox-Webhook-Id
These headers can be used to identify and verify the authenticity of the request—essentially confirming whether it originated from RelayBox. To verify the request signature, you can use a helper method provided by the REST SDK library.
If you haven't already, please install the REST SDK library.
After installing the library, you can easily verify the webhook signature by calling verifyWebhookSignature. Pass the request body as the first argument, the request signature as the second, and the webhook signing key as the third argument.
The webhook signing key can be found with the webhook data in the dashboard under the "Basic Information" section.
import Relaybox from '@relaybox/rest';
const relayBox = new RelayBox({
apiKey: '123.456.78910'
});
const webhookSigningKey = '21d45d1d4dff46f13cd4478ba08395d9'; // The webhook signing key
const webhookSignature = req.headers['X-Relaybox-Webhook-Signature'];
const isValidSignature = relayBox.verifyWebhookSignature(
req.body,
webhookSignature,
webhookSigningKey
); // boolean
In the example above, if the return value of relayBox.verifyWebhookSignature is true, the request is valid and can be processed. If the return value is false, it indicates the request has been tampered with and should be rejected.
Webhook replay attacks
A replay attack occurs when an attacker intercepts a legitimate HTTP request and resends (or "replays") the same request to the server, often aiming to execute the action multiple times.
To prevent this type of attack, you can utilize the timestamp field (e.g., 2024-10-22T16:59:04.987Z) in the payload to enforce a time-based validity window. Upon receiving the request, the server should first verify the request signatire then compare the provided timestamp with the current time.
If the request is older than a predefined threshold (e.g., 30 seconds or 1 minute), it can be rejected as a likely replay attempt.
Working with webhooks offline
Webhooks are also available when working offline via the relaybox CLI toolkit. Please refer to the relaybox CLI documentation for more details.