Webhooks
Webhooks let your own systems receive a POST request from RecSphere whenever something interesting happens, without you having to poll the API. Use them for real-time syncing, alerting and automation.
How webhooks work​
A webhook is a URL you control. When a relevant event happens in RecSphere, RecSphere sends a POST request to that URL with a JSON body describing the event. Your server reads the body and does whatever it needs to do.
This is push, not pull. You do not need to repeatedly call /v1/vacancies/get-filtered to find new vacancies; you can subscribe to vacancy.created and RecSphere will notify you the moment one is created.
Supported events​
| Event | Fires when |
|---|---|
vacancy.created | A new vacancy is created |
vacancy.updated | A vacancy's details change |
vacancy.closed | A vacancy is marked filled or closed |
application.created | A candidate applies to a vacancy |
candidate.created | A new candidate record is added |
candidate.placed | A candidate is marked as placed against a vacancy |
contract.activated | A contract is activated |
timesheet.submitted | A timesheet is submitted by a candidate |
timesheet.approved | A timesheet is approved |
invoice.issued | An invoice is issued to a client |
payroll.completed | A payroll run completes |
More events are added regularly. See the Webhooks page in your workspace settings for the up-to-date list and the full payload schema per event.
Subscribing to events​
- Open Settings > Integrations > Webhooks.
- Click Add webhook.
- Enter the URL RecSphere should POST to. It must be HTTPS.
- Select one or more events to subscribe to.
- Save.
RecSphere immediately sends a test event to your URL. If your endpoint responds with a 2xx status, the subscription is active.
Payload format​
Every webhook POST has this shape:
{
"event": "application.created",
"timestamp": "2026-05-24T10:23:00Z",
"workspaceId": "rs_w_8a1c",
"data": {
"applicationId": 87,
"vacancyRefNo": "RS-1045",
"candidateId": 4521,
"submittedAt": "2026-05-24T10:22:58Z"
}
}
The shape of the data object varies per event. Treat the event field as the discriminator and dispatch to the appropriate handler in your code.
Verifying the signature​
Every webhook POST includes an X-RecSphere-Signature header containing an HMAC-SHA256 signature of the raw request body, computed using your webhook's secret. Verify this on your end before trusting the payload.
import crypto from 'crypto';
function verifyWebhook(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader),
);
}
Without signature verification, anyone who guesses your URL can fire events into your system. Treat the webhook secret like an API key: never commit it, rotate it if exposed.
Retries​
If your endpoint returns a non-2xx status or does not respond within 10 seconds, RecSphere retries with exponential backoff: 1 minute, 5 minutes, 15 minutes, 1 hour, 6 hours. After 5 failures the delivery is marked failed and shown in your webhook delivery log.
Each retry includes the same payload and an incremented X-RecSphere-Delivery-Attempt header.
Idempotency​
RecSphere generates a stable X-RecSphere-Delivery-Id header for each delivery. If you receive the same delivery ID twice (because of a retry), it is the same event. Use the ID as an idempotency key to avoid double-processing.
Testing locally​
To receive webhooks during development, expose your local server with a tunnelling tool such as ngrok or Cloudflare Tunnel, then point your webhook URL at the public address. The test event from the Webhooks page is the fastest way to confirm your handler works.
Disabling a webhook​
Toggle a webhook off from Settings > Integrations > Webhooks. Disabled webhooks stop receiving deliveries but keep their delivery history for audit.