Appearance
Webhooks
Webhooks tell your own system the moment something happens in Propool, such as a new lead or a new booking, by sending it an HTTPS request. Use them instead of checking the API over and over.
Events
| Event | When | Data |
|---|---|---|
lead.created | A lead is created, from the app, the API, an import or an integration | id, reference, pipelineId, stageId, resourceUrl |
lead.stage_changed | A lead moves to a different stage | The same, plus previousStageId; stageId is the new stage |
booking.created | A booking first appears in Propool, from a channel, your website, a manual entry or an import | id, listingId, status, arrival, departure, source, imported, resourceUrl |
webhook.test | You choose Send test | A message; nothing is created |
Changes to an existing booking don't send another booking.created. Calendar blocks and unconfirmed website requests aren't bookings.
Events carry no names, contact details, notes or amounts. To get the full record, call its resourceUrl on https://app.propool.ai with an API key that has leads:read or bookings:read.
Add an endpoint
Only admins can manage webhooks.
- Go to Settings → Webhooks and choose Add endpoint.
- Enter your callback URL: a public
https://address on port 443. Private networks and redirects are refused. - Choose the events to send.
- Copy the signing secret. It starts with
pwhsec_and is shown only once. - Choose Send test, then check the delivery history for your server's response.
A workspace can have up to 25 endpoints. A new endpoint receives events from then on, not earlier ones.
What you receive
Each event is a POST with a JSON body:
json
{
"id": "ac757ca0-6323-47f1-9b6d-5d2d278bc187",
"type": "lead.created",
"occurredAt": "2026-10-04T12:00:00.000Z",
"schemaVersion": "2026-10-01",
"workspaceId": "ae81317d-e699-45e7-a67b-de2ac3b1d729",
"data": {
"id": "dc16af64-55bd-4476-a5cc-c9ea570d60be",
"reference": "L-1042",
"pipelineId": "018f3191-c4af-4e08-bd54-d75b3df75cd6",
"stageId": "07fd8a32-01a6-4c90-8810-c2d38726283c",
"resourceUrl": "/api/public/v1/pipelines/018f3191-c4af-4e08-bd54-d75b3df75cd6/leads/dc16af64-55bd-4476-a5cc-c9ea570d60be"
}
}and these headers:
text
X-Propool-Event-Id: <event ID>
X-Propool-Delivery-Id: <delivery ID>
X-Propool-Timestamp: <Unix seconds>
X-Propool-Signature: v1=<hex HMAC-SHA256>New fields may be added to events, so ignore fields you don't recognise.
Check the signature
Anyone can send a request to your URL, so check every one came from Propool before you trust it. The signature is an HMAC-SHA256 of the timestamp, a ., and the raw request body, using your whole signing secret (including pwhsec_) as the key.
js
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody, timestamp, signature, secret) {
if (!/^\d{10,12}$/.test(timestamp ?? "")) return false;
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
if (!/^v1=[a-f0-9]{64}$/.test(signature ?? "")) return false;
const expected = createHmac("sha256", secret)
.update(`${timestamp}.`)
.update(rawBody)
.digest();
const actual = Buffer.from(signature.slice(3), "hex");
return actual.length === expected.length && timingSafeEqual(actual, expected);
}- Check before parsing the JSON. Parsing and re-encoding changes the bytes, and the signature no longer matches.
- Reject old timestamps, more than five minutes from your clock, so a captured request can't be replayed later.
Reply quickly, and expect repeats
Reply with any 2xx status as soon as you've safely stored the event, then do slower work afterwards. Propool waits at most 10 seconds and doesn't follow redirects.
- The same event can arrive more than once. Keep the event
idand skip ones you've already handled, but still reply 2xx. - Events can arrive out of order, even for the same lead. If order matters, fetch the current record from the API.
If your server doesn't answer 2xx, Propool tries again after 1 minute, 5 minutes, 15 minutes, 1 hour, 3 hours, 6 hours and 12 hours: eight attempts in all. After that the delivery is marked failed. In Settings → Webhooks you can see every delivery and its response code, and replay one.
Change or rotate the secret
Choose Rotate secret to get a new signing secret. For a few minutes, requests already on their way may still be signed with the old one, so accept both until the change settles, then remove the old one.
Disabling or deleting an endpoint stops new deliveries. Changing its URL or events cancels deliveries that were still waiting.