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 2xx response quickly.
  • The subscription_type for 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

FieldTypeRequiredDescription
subscription_typestringYesThe event to subscribe to, e.g. timeoff/leave/reject.
target_urlstringYesYour publicly accessible HTTPS endpoint.
company_idintegerYesThe ID of the company the subscription belongs to.
namestringNoA human-readable label to help you identify the subscription.
challengestringNoA secret you define. Returned on every delivery in the x-factorial-wh-challenge header so you can verify the request.
enabledbooleanNoDefaults to true.
api_versionstringNoThe 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 automatically

If your endpoint keeps failing, Factorial disables the subscription after the retry window is exhausted. See Webhooks Policies.

⚠️

Subscription permissions are inherited from the token

A 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 disable

If 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.


Did this page help you?