Webhooks Subscriptions
Create, list, enable, disable and delete webhook subscriptions through the API.
A webhook subscription is the object that connects one Factorial event type to one of your endpoints. Everything about webhooks is configured through subscriptions — there is no separate dashboard to set up.
Each subscription registers a target_url for a specific subscription_type within a company_id. Once it is enabled, Factorial sends an HTTP POST to that URL every time the associated event occurs.
Before you start
You need:
- An API key or an OAuth2 access token with access to the company. See Authentication.
- A publicly reachable HTTPS endpoint that returns a
2xxresponse quickly. - The
subscription_typefor the event you want. All available types are listed in the Webhooks section of the API Reference, and the most common ones in Payloads & Event Types.
Base URL
https://api.factorialhr.com/api/2026-10-01/resources/api_public/webhook_subscriptions
Subscriptions are versioned. The api_version you set on a subscription determines the payload shape Factorial sends to your endpoint, so it stays stable even as newer API versions ship.
Create a subscription
POST /api/2026-10-01/resources/api_public/webhook_subscriptions
Request body
| Field | Type | Required | Description |
|---|---|---|---|
subscription_type | string | Yes | The event to subscribe to, e.g. timeoff/leave/reject. |
target_url | string | Yes | Your publicly accessible HTTPS endpoint. |
company_id | integer | Yes | The ID of the company the subscription belongs to. |
name | string | No | A human-readable label to help you identify the subscription. |
challenge | string | No | A secret you define. Returned on every delivery in the x-factorial-wh-challenge header so you can verify the request. |
enabled | boolean | No | Defaults to true. |
api_version | string | No | The API version used to build the payload. Defaults to the version of the request. |
Example request
curl --request POST \
--url https://api.factorialhr.com/api/2026-10-01/resources/api_public/webhook_subscriptions \
--header 'x-api-key: YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'accept: application/json' \
--data '{
"company_id": 157412,
"subscription_type": "timeoff/leave/reject",
"target_url": "https://yourapp.com/webhooks/factorial",
"name": "Time off rejections",
"challenge": "2zal4e6d",
"enabled": true,
"api_version": "2026-10-01"
}'curl --request POST \
--url https://api.factorialhr.com/api/2026-10-01/resources/api_public/webhook_subscriptions \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'content-type: application/json' \
--header 'accept: application/json' \
--data '{
"company_id": 157412,
"subscription_type": "timeoff/leave/reject",
"target_url": "https://yourapp.com/webhooks/factorial",
"name": "Time off rejections",
"challenge": "2zal4e6d",
"enabled": true,
"api_version": "2026-10-01"
}'Example response
{
"id": 18395,
"company_id": 157412,
"type": "timeoff/leave/reject",
"target_url": "https://yourapp.com/webhooks/factorial",
"name": "Time off rejections",
"challenge": "2zal4e6d",
"enabled": true,
"api_version": "2026-10-01"
}Store the returned id — you need it to enable, disable or delete the subscription later.
Subscriptions can be disabled automaticallyIf your endpoint keeps failing, Factorial disables the subscription after the retry window is exhausted. See Webhooks Policies.
Subscription permissions are inherited from the tokenA subscription created with a user token only receives payloads that user is allowed to see in Factorial. Use a company token or an API key to avoid these restrictions. See Webhooks Policies.
Verify deliveries with a challenge
If you set a challenge when creating the subscription, Factorial returns that same value on every delivery in the x-factorial-wh-challenge request header.
Compare the header against the value you stored for that subscription and reject the request if it does not match. This confirms the request originates from the subscription you created, rather than from an arbitrary caller that discovered your URL.
app.post("/webhooks/factorial", (req, res) => {
if (req.get("x-factorial-wh-challenge") !== process.env.FACTORIAL_WH_CHALLENGE) {
return res.sendStatus(401);
}
// Acknowledge first, process later
res.sendStatus(200);
queue.enqueue(req.body);
});List subscriptions
Returns every subscription configured for your credentials — useful for auditing what is currently active.
GET /api/2026-10-01/resources/api_public/webhook_subscriptions
curl --request GET \
--url https://api.factorialhr.com/api/2026-10-01/resources/api_public/webhook_subscriptions \
--header 'x-api-key: YOUR_API_KEY' \
--header 'accept: application/json'curl --request GET \
--url https://api.factorialhr.com/api/2026-10-01/resources/api_public/webhook_subscriptions \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'accept: application/json'Enable or disable a subscription
Send a PUT with the subscription {id} and enabled: true or false. Subscriptions are created enabled by default.
PUT /api/2026-10-01/resources/api_public/webhook_subscriptions/{id}
curl --request PUT \
--url https://api.factorialhr.com/api/2026-10-01/resources/api_public/webhook_subscriptions/18395 \
--header 'x-api-key: YOUR_API_KEY' \
--header 'content-type: application/json' \
--header 'accept: application/json' \
--data '{"enabled": false}'curl --request PUT \
--url https://api.factorialhr.com/api/2026-10-01/resources/api_public/webhook_subscriptions/18395 \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'content-type: application/json' \
--header 'accept: application/json' \
--data '{"enabled": false}'
Recovering from an automatic disableIf a subscription was disabled because of failed deliveries, you do not need to recreate it. Fix your endpoint, then re-enable the same subscription with
{"enabled": true}.
Disabling is also the right tool for planned maintenance on your side: turn the subscription off before the window and back on afterwards, rather than letting deliveries fail and burn through retries.
Delete a subscription
Permanently removes the subscription. Use this when you no longer want the events at all — for a temporary pause, disable it instead.
DELETE /api/2026-10-01/resources/api_public/webhook_subscriptions/{id}
curl --request DELETE \
--url https://api.factorialhr.com/api/2026-10-01/resources/api_public/webhook_subscriptions/18395 \
--header 'x-api-key: YOUR_API_KEY' \
--header 'accept: application/json'curl --request DELETE \
--url https://api.factorialhr.com/api/2026-10-01/resources/api_public/webhook_subscriptions/18395 \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'accept: application/json'Next step
Now that you have a subscription, see Payloads & Event Types for what Factorial will send to your endpoint.
Updated 9 days ago

