Before you start
- A Growth or Scale plan, and a workspace admin to set it up under Settings, Webhooks.
- An address on the public internet that starts with
https://and can answer within 10 seconds. - Someone who can check a signature on your side. Examples for Node.js and PHP are below.
Note
Webhooks are included in the Growth and Scale plans. An administrator of the workspace sets them up under Settings, Webhooks.
The four steps
Add an endpoint
Open Settings, then Webhooks, and press Add endpoint. Enter the address that should receive events. It must start with
https://and be a public website. Choose the events you want, and whether messages should include the person’s name, phone and email.Copy the signing secret
VelBEE shows the secret once. Store it where your system can read it. If you lose it, create a new one: the old one keeps working for 24 hours so you can switch over.
Send a test
Press Send a test. VelBEE sends a sample event and tells you what your address answered. Anything from 200 to 299 counts as received.
Check the signature in your system
Each message carries a signature so you know it came from VelBEE and was not changed. See the check below, then answer with a 2xx status quickly and do the slow work afterwards.
What a message looks like
X-VelBEE-Event: lead.created
X-VelBEE-Event-Id: evt_01f2c3d4e5f6...
X-VelBEE-Timestamp: 1790000000
X-VelBEE-Signature: v1=3c9a...
{
"id": "evt_01f2c3d4e5f6...",
"type": "lead.created",
"schema_version": "2026-10-01",
"created_at": "2026-10-04T09:15:00+00:00",
"workspace_slug": "acme",
"data": {
"object": {
"id": "…", "status": "open", "source": "Website", "interested_in": "3 BHK",
"stage": "New Lead", "assignee": { "id": "…", "name": "Karan" },
"contact": { "name": "Asha Rao", "phone": "+91 98765 43210", "email": "asha@example.com" }
}
},
"actor": { "type": "user", "id": "…" }
}Check the signature
The signature is an HMAC-SHA256 of the timestamp, a dot and the raw request body, using your secret. Compare it in constant time and reject messages whose timestamp is more than five minutes old.
import crypto from "node:crypto";
function verify(rawBody, headers, secret) {
const ts = headers["x-velbee-timestamp"];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = "v1=" + crypto.createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex");
// during a secret change the header can hold two signatures separated by a comma
return headers["x-velbee-signature"].split(",").some((s) =>
s.length === expected.length && crypto.timingSafeEqual(Buffer.from(s), Buffer.from(expected)));
}$ts = $_SERVER['HTTP_X_VELBEE_TIMESTAMP'];
$raw = file_get_contents('php://input');
$expected = 'v1=' . hash_hmac('sha256', $ts . '.' . $raw, $secret);
$fresh = abs(time() - (int) $ts)Events you can choose
| Event | When it is sent |
|---|---|
lead.created | A lead is created, from any source |
lead.updated | A lead's priority, value, campaign, interest or follow-up date changes |
lead.assigned | A lead is given to a person or team |
lead.stage_changed | A lead moves to another stage (the old stage is included) |
lead.converted | A lead is won |
lead.lost | A lead is lost (the reason is included) |
task.created | A task is created |
task.completed | A task is completed |
appointment.created | A visit or appointment is booked |
appointment.updated | Its time, person, place or title changes |
appointment.completed | It is completed (the outcome is included) |
appointment.cancelled | It is cancelled |
booking.created | A booking is recorded |
How delivery works
- At least once. A message can arrive twice. Ignore an
idyou have already handled. - Retries. If your address does not answer 2xx within 10 seconds, VelBEE tries again after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 24 hours, then gives up. A 4xx answer other than 408, 425 or 429 is treated as a mistake on your side and is not retried.
- Switched off. An answer of
410 Gone, or many failures in a row over several days, switches the endpoint off and tells your organization’s owner and admins. Switch it on again after fixing it. - Safe addresses only. VelBEE will not call private or internal addresses, does not follow redirects, and uses only
https. - The log. Settings, Webhooks, Delivery log shows each try for 30 days, never the message contents, and lets you send one again.
- One company only. A workspace’s endpoints receive only that workspace’s events.
What you will have at the end
- An endpoint that receives a signed message for each event you chose.
- A signature check on your side, so only genuine messages are acted on.
- A delivery log in VelBEE that shows every try for 30 days.
Troubleshooting
| What you see | Likely cause | What to do |
|---|---|---|
| The test says your address did not answer 2xx | The address is wrong, slow (over 10 seconds), or answered with an error. | Answer 200 to 299 straight away and do the slow work afterwards. The test shows what your address answered. |
| The signature does not match | The body was changed before checking, the wrong secret was used, or the timestamp was left out. | Sign the raw body: the timestamp, a dot, then the body. During a secret change the header can hold two signatures separated by a comma. |
| Messages are rejected as too old | Your system’s clock is off, or checking happens long after receiving. | Check the time on your server. Messages more than five minutes old should be rejected. |
| The same event arrives twice | Delivery is at least once. | Remember the id of each event and ignore one you have already handled. |
| The endpoint switched itself off | It answered 410 Gone, or failed many times in a row over several days. | Fix the cause, then switch it on again. Your organization’s owner and admins are told when it switches off. |
| The address is refused when saving | It does not start with https://, or points at a private or internal address. | Use a public https:// address. VelBEE does not follow redirects. |
| No messages for an event you expected | The event was not ticked for that endpoint. | Open the endpoint and choose the events. |
Questions
Do the messages include a person’s details?
Only if you choose that for the endpoint. You can include the name, phone and email, or leave them out.
What if I lose the signing secret?
Create a new one. The old one keeps working for 24 hours so you can switch over.
Can I see what was sent?
The delivery log shows each try for 30 days, but never the message contents. You can send one again from there.
Looking to send leads *into* VelBEE instead? See Zapier, Make and n8n and the API reference.