Working with Webhooks
Overview
Webhooks are a quick and easy way of getting automatically notified of events occurring in your system. The webhook workflow is automated, so if you subscribe to one, you will notified of any change that are happening against that event, without you having to poll the API.
In this guide, you will learn how to:
- Register, update and delete a webhook
- Test webhooks in the sandbox environment
Prerequisites
Before you start, ensure you’ve created an access token to access the Remote API. Please refer to the guide on obtaining an access token for customers/partners.
ℹ️ Managing webhooks: Managing webhooks requires a company-scoped access token, as webhooks are always tied to individual companies. There is currently no support for global or partner-level webhooks outside of a specific company context.
Registering a webhook
If you want to listen to one or more changes happening internally in your system, first you need to register a webhook callback for those events.
The payload of these subscription requests consists of the subscribed_events
you want to listen to and the URL
our system will call and send the identifier of the resource related to the event. Please note that this URL
must be unique, so if you want to listen to multiple webhook event types, we suggest registering them all at once.
ℹ️ For each callback, the URL needs to be unique, but an event can be listened to on multiple URLs. For example, you can create two different callbacks with different URLs and include the same event in both and you will be able to listen to that event on both those URLs.
To see the list of available webhook event types, please refer to the available webhooks document.
Let's say you want to get notified whenever a new hire completes their onboarding tasks so you could send them a welcome email. And, later you would want to know when an employee's payslip was released so you can automate sending employees a notification about their pay being on the way. You can achieve both tasks in one simple call with the Create a Webhook Callback endpoint by subscribing to the right webhooks.
{
"subscribed_events": [
"employment.onboarding_task.completed",
"payslip.released"
],
"url": "https://example.com/callback"
}
Now, you can listen to both these events on the https://example.com/callback
url.
In case your use case requires you to listen to one of these events on more than one url, you can make another call with the same event and the second url:
{
"subscribed_events": [
"payslip.released"
],
"url": "https://example.com/payroll_callback"
}
This functionality comes in handy if you have multiple teams that need to be notified of the change on different channels.
The response to this request will include an id
. Make sure you save this ID, as you will need it to update or delete the webhook callback you just registered.
Updating a webhook
Once you have created a webhook callback and later you want to modify the subscription, you can use the Update a Webhook Callback endpoint. This endpoint can be used to add or remove subscribed events from your webhook callback, or change the URL if needed. To update a webhook, you need to provide the webhook ID returned when you created the webhook in the request body. There's no need to provide the URL again unless you want to update the previously set URL.
{
"data": {
"webhook_callback": {
"id": "0073fcb5-b669-4e4a-b963-2a47744e75a1",
"subscribed_events": [
"employment.onboarding_task.completed",
"timeoff.requested"
]
}
}
}
In this request, you added a new event and removed an already registered event from the callback.
ℹ️ This call will override the list of events previously registered. So, please make sure to provide all events you want to register for again in this call, otherwise those events will be removed from the list.
List all subscribed events
The List Webhook Events endpoint will return a list of all webhook events that you have subscribed to. You can customize the results by filtering by their event type, company ID, by date, or whether the event was successfully delivered or not. The response will look something like this:
{
"current_page": 1,
"total_count": 1,
"total_pages": 1,
"webhook_events": [
{
"company_id": "123e4567-e89b-12d3-a456-426614174000",
"event_type": "timeoff.requested",
"first_triggered_at": "2025-01-01T00:00:00Z",
"id": "0073fcb5-b669-4e4a-b963-2a47744e75a1",
"last_triggered_at": "2025-01-02T00:00:00Z",
"successfully_delivered": true
}
]
...
}
This endpoint helps you in not just listing the subscribed webhook events, but monitor them as well. For example, if a new time off request came in but you were not notified, you can call this endpoint to check whether the webhook was triggered for that event or not and troubleshoot accordingly.
Replay webhooks
The webhooks API provides an option to replay previously triggered webhooks at any time. This features specially comes in handy if you notice failed webhook deliveries. You can use the list webhook events feature to identify which events need to be retriggered and then use the Replay Webhook Events endpoint to bulk trigger them at once.
You can directly specify the webhook event IDs for all events you want to replay in the header body:
{
"ids": [
"0073fcb5-b669-4e4a-b963-2a47744e75a1",
"0093kcb8-b669-4e4c-b463-2b52664c75w3",
...
]
}
Or, you can specify timestamp filters to specify a date range for which webhooks need to be replayed.
{
"after": "2025-06-01T00:00:00Z",
"before": "2025-06-30T00:00:00Z"
}
You can also filter the webhook events to be triggered by their company ID, event type, and delivery status.
{
"company_id": "123e4567-e89b-12d3-a456-426614174000",
"event_type": "timesheet.created",
"successfully_delivered": false
}
This endpoint replays webhooks with the same payload as originally registered.
Deleting a webhook
You can also delete a webhook callback if that subscription is not needed anymore. The delete a webhook callback endpoint will take the webhook callback ID and respond with an ok
message if the deletion was a success.
Please note that deleting a callback will remove subscription to all webhook events that were registered in that callback. So, if your requirement is to modify rather than delete, please use update webhook callback instead.
Testing webhooks in Sandbox
ℹ️ This endpoint is not available in production.
To test a webhook in sandbox, you can use the Trigger a Webhook endpoint to simulate triggering one of the event types.
When developing your integration, you’ll usually be working with a locally running server. Your local server will accept connections with localhost likehttp://localhost:xxxx
. Please note that our servers can’t send webhooks directly to your local server since your local server is not exposed to the Internet. Which is why we recommend using a reverse proxy or a tunneling service such as ngrok to forward requests to your local server.
🔴 We only recommend using ngrok when testing in the Sandbox environment. Do not use the free version of ngrok in production, as ngrok assigns URLs randomly. So, if you forget to delete a registered webhook callback after shutting down the ngrok service, your randomly-assigned ngrok URL may get assigned to another free ngrok user, in which case your webhook data would get sent there! 😱
Example: Testing payslip.released
webhook event type
payslip.released
webhook event typeLet's say you want to be notified when an employee's payslip is released. After registering the subscribed_events
and the webhook callback URL
, send a POST request to the /webhook-callbacks/trigger
endpoint with the required parameters as shown below:
{
"employment_id": "5e9e8861-9ead-4a2a-a402-c130bcfac5d6",
"event_type": "payslip.released"
}
You'll receive the following response in the registered URL.
{
"employment_id": "aab0f8c2-bef6-4b22-b61f-f3fc7357e5ca",
"event_type": "payslip.released",
"payslip_id": "a87c2792-sandbox-sample-payslip-693312ee2bee"
}
With this identifier, you can query the Remote API to get the most recent version of the resource. Specifically for the payslip.released
event type, if the payslip exists, its identifier will be returned. Otherwise, the Remote API will return the identifier of a sample payslip file. Then, they can be checked using the Download payslip PDF file endpoint.
⚠️ The sample payslip file is only displayed for testing purposes since it can take some time to have payslips in the test environment. It does not reflect an actual payslip, as actual payslips may have different formats and information depending on each country.
When you’re ready to release your integration, replace the domain with https://gateway.remote.com
.
You can find the API documentation for the /v1/webhook-callbacks
.
Updated 3 days ago