Webhooks

What it does
Section titled “What it does”Webhooks let you send real-time notifications from HARi to any external system when events happen in your CRM. Use them to connect HARi to custom applications, automation platforms, or internal tools.
How it works
Section titled “How it works”- Create a workflow in HARi with a Call Webhook action
- Specify the target URL (your server, Zapier, Make, n8n, etc.)
- When the workflow triggers, HARi sends an HTTP POST request to your URL with the event data
Payload format
Section titled “Payload format”Every webhook delivers a JSON payload:
{ "event": "record.created", "entity": "contact", "timestamp": "2026-03-31T14:30:00Z", "workspace": "yourcompany", "record": { "id": "a1b2c3d4-...", "name": "Jane Smith", "email": "jane@example.com", "company": "Acme Corp", "owner": "Vincent", "created_at": "2026-03-31T14:30:00Z" }, "changes": { "stage": { "old": "qualification", "new": "proposal" } }}The changes object is included only for update events and contains only the fields that changed.
Available events
Section titled “Available events”You can trigger webhooks on any workflow event:
| Event | Description |
|---|---|
record.created | A new record was created |
record.updated | A record was modified |
record.deleted | A record was deleted |
stage.changed | A BPF stage transition occurred |
status.changed | Record status changed (active/inactive/archived) |
assignment.changed | Record owner changed |
Setup guide
Section titled “Setup guide”Step 1: Create the receiving endpoint
Section titled “Step 1: Create the receiving endpoint”Your server needs an HTTP endpoint that accepts POST requests and returns a 200 status code:
POST https://your-server.com/webhooks/hariContent-Type: application/jsonStep 2: Create a webhook workflow
Section titled “Step 2: Create a webhook workflow”- Go to Settings > Workflows > + New Workflow
- Set the trigger (e.g., “When an opportunity is updated”)
- Add conditions if needed (e.g., “Stage changed to Closed Won”)
- Add action: Call Webhook
- Enter your endpoint URL
- Select which record fields to include in the payload
- Save and activate
Step 3: Test
Section titled “Step 3: Test”You have two ways to verify a webhook reaches your endpoint:
-
Test fire from Settings (fastest). Open Settings → Webhooks, find the row for the webhook you just configured, and click Test fire. HARi sends a sample payload to the URL immediately. A result panel appears below the row showing the HTTP status code, response time, and the response body (truncated at 500 characters with a “Show more” link for longer payloads). Connection or timeout errors are surfaced in red. The panel persists until you click Dismiss or fire another test, so you can compare runs.
-
Trigger from a real event. Create or update a record that matches the workflow’s trigger conditions. The workflow fires its full payload to your endpoint and the delivery shows up in the webhook log under Settings → Webhooks.
Use the Test fire button when you’re iterating on the URL or payload shape. Use a real event when you want to verify the workflow’s own conditions and field selection.
Retry policy
Section titled “Retry policy”HARi sends each webhook within about a minute of the save — longer after a large import, when many deliveries queue up at once. A Call Webhook step in a workflow is tried up to 3 times in total, a fraction of a second apart, when your endpoint does not answer or answers with a 5xx status; a 4xx answer stops the retries; each attempt has a 15-second limit. A webhook set up in Settings → Webhooks is sent once, with a 5-second limit.
Saving a record never waits for your endpoint. The record is saved, the delivery is queued, and the send runs on its own shortly after — so a slow or unreachable endpoint cannot hold up the people using the CRM.
A Call Webhook step in a workflow
Section titled “A Call Webhook step in a workflow”- Attempts: up to 3 in total — the first send, a retry 0.2 seconds after it, then a last retry 0.4 seconds after that.
- Retried: no answer at all (connection refused, DNS failure, timeout), and any 5xx status.
- Not retried: any 4xx status. RFC 9110 describes that class as responses where “the client seems to have erred” (RFC 9110, section 15.5) — your server received the call and refused it, so sending the same body again would get the same answer. HARi makes no exception for 408 or 429: those stop the retries too.
- Time limit: 15 seconds per attempt, 5 of them to open the connection.
A webhook you set up in Settings
Section titled “A webhook you set up in Settings”Sent once, with no retry, and a 5-second limit per send (3 of them to open the connection). If your endpoint is down at that moment, that event is not sent again — use a Call Webhook step in a workflow when you need the retries.
What is recorded
Section titled “What is recorded”Each delivery writes one line to the webhook log, which workspace admins open from Settings → Webhooks: the status code, the first 1,000 characters of your endpoint’s answer, and the error when there was no answer. The retries of one delivery share that line. If HARi is interrupted mid-send (a restart, a deployment), the delivery is not attempted a second time and the line says so, so your endpoint never receives a surprise duplicate hours later.
Security
Section titled “Security”Signature verification
Section titled “Signature verification”When the webhook has a configured secret, HARi sends two headers with each delivery:
X-Webhook-Secret— your shared secret (so the receiver can validate without HMAC if simpler)X-Webhook-Signature— HMAC-SHA256 of the raw JSON body using the same secret as the key
Verify either (or both) on your server to confirm the webhook came from HARi. Your webhook secret is configured in Settings > Webhooks.
HTTPS only
Section titled “HTTPS only”Webhook URLs must use HTTPS. HTTP endpoints are rejected for security.
Rate limits
Section titled “Rate limits”HARi sends webhooks one at a time, oldest first, up to 20 per workspace per minute. A burst — a bulk edit, an import — is spread over the minutes that follow rather than dropped, so your endpoint never receives a flood from us.
If your own processing is slow, answer quickly and do the work afterwards — put the payload on a queue of your own (AWS SQS, RabbitMQ, or a database table) and return a 200 right away. An attempt that takes longer than the time limit counts as no answer.