Last Updated: October 15, 2025
Webhooks let you react to assignment activity in real time. Whenever a resource is scheduled, updated, or removed, ResourcePlanner sends an HTTP POST to your URL.
You can rotate the URL or secret any time. Updates take effect immediately.
| Event | Triggered when… |
| ----- | --------------- |
| `assignment.created` | A new assignment is created via the UI or REST API. |
| `assignment.updated` | An existing assignment changes (dates, hours, note, project/resource reassignment). |
| `assignment.deleted` | An assignment is removed. |All events include the full assignment payload so you can mirror the ResourcePlanner state without another API call.
Every webhook POST has the following headers:
| Header | Description |
| ------ | ----------- |
| `Content-Type` | Always `application/json`. |
| `X-ResourcePlanner-Event` | Event name (e.g. `assignment.updated`). |
| `X-ResourcePlanner-Signature` | Hex-encoded HMAC SHA-256 signature (present only when a webhook secret is configured). |The JSON body looks like this:
{
"event": "assignment.created",
"workspaceId": "64f1088d4f3c2c0012b12345",
"timestamp": "2025-10-15T09:21:34.512Z",
"data": {
"id": "6717a347e1577b0b4e9fd200",
"project": { "id": "6702ac44e1577b0b4e9fd100", "title": "Website Refresh" },
"resource": { "id": "66fa6f3be1577b0b4e9fd001", "name": "Hana Sato" },
"dateFrom": "2025-10-20T00:00:00.000Z",
"dateTo": "2025-10-24T00:00:00.000Z",
"hoursPerDay": 6,
"startFrom": "09:00",
"note": "Workshop preparation",
}
}When a secret is configured, compare the X-ResourcePlanner-Signature header with your own HMAC computation:
const crypto = require('crypto');
function verifySignature(secret, payload, signature) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature || '', 'hex'),
Buffer.from(expected, 'hex')
);
}Use a timing-safe comparison to avoid leaking information if the signature fails.
Webhooks fire in the background and do not block the UI or API responses. If your endpoint returns a non-2xx status code or is unreachable, the event is logged but not retried automatically. We recommend making your handler idempotent and returning quickly (e.g. enqueue work for processing).