Build an integration
Webhooks
Receive signed notifications when customers, jobs, estimates, and other CRM records change.
On this page
1. Connect a receiving endpoint
Open Security & access → Developer in the CRM to manage webhook endpoints and inspect delivery history. Subscribe only to the events your integration uses.
For subscriptions created through the API, provide a public HTTPS receiver. A local receiver needs a public HTTPS address before it can receive those deliveries.
2. Verify the signature
New integrations should read X-Webhook-Signature-V1. Its value is sha256= followed by an HMAC-SHA256 hex digest of the exact request body bytes, using your endpoint’s signing secret.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyWebhook(
rawBody: Buffer,
signatureHeader: string,
secret: string
): boolean {
if (!/^sha256=[a-f0-9]{64}$/i.test(signatureHeader)) return false;
const expected = createHmac('sha256', secret)
.update(rawBody)
.digest();
const received = Buffer.from(signatureHeader.slice(7), 'hex');
return received.length === expected.length
&& timingSafeEqual(received, expected);
}
// Read X-Webhook-Signature-V1 and the raw body bytes.
// Verify before parsing the body or processing the event.Capture the raw body before JSON parsing, reject a mismatch, and use a constant-time comparison. The compatibility header X-Webhook-Signature contains the same digest without the sha256= prefix.
3. Process deliveries reliably
- Verify the signature and validate the event body.
- Record
X-Webhook-Idempotency-Keyso the same event does not apply a change twice. - Save or queue the work durably, then return a successful
2xxresponse quickly. - Process the event in your background worker. Do not depend on the order of separate deliveries.
Timed-out and non-success responses retry automatically with exponential backoff. Repeated failures can disable an endpoint. Use delivery history in the CRM to investigate problems before replaying work.
- X-Webhook-Event
- The event name, such as customer.created.
- X-Webhook-Delivery
- The delivery identifier for tracing a received request.
- X-Webhook-Timestamp
- The event timestamp included in the signed body.
- X-Webhook-Idempotency-Key
- The value to record when avoiding duplicate processing.
Choose the events you need
These are common CRM event groups. Use the subscription endpoints and the event reference for the available operations and event contracts.
- Customers
- customer.createdcustomer.updatedcustomer.deleted
- Appointments
- appointment.createdappointment.updatedappointment.completedappointment.cancelled
- Invoices
- invoice.createdinvoice.updatedinvoice.sentinvoice.paid
- Estimates
- estimate.createdestimate.updatedestimate.sentestimate.acceptedestimate.declined
Read the event body
The body includes the event name, event timestamp, and data for the changed record. The fields inside data depend on the event.
{
"event": "customer.created",
"timestamp": "2026-03-20T14:30:00Z",
"data": {
"id": "uuid",
"organization_id": "uuid"
}
}