A lead field webhook sends a small JSON message to a URL on your own server (or another service) the moment a specific field on a lead changes. Use it to react to a status change, a new event date, a changed total and similar events without polling the API for changes.
This is different from the older report based webhook, which runs on a schedule from a filter and an automation. See API - Webhooks for that one. Both can be used on the same account.
Before You Start
- You need a public URL that accepts an HTTPS (or HTTP) POST on port 443 or 80. Private network addresses, other ports, and URLs with a username, password or # fragment are rejected.
- The worker setting this up needs the Settings Lead Fields permission and access to leads.
- Each delivery counts as one API transaction. See API - Transaction Charges.
- Test with a few leads and confirm your server handles the data correctly before relying on it.
How to Set Up a Lead Field Webhook
- Go to Settings > Fields > Lead Fields.
- Open the field you want to watch, for example Status, Event Start or Total. Accounts with several locations have one entry per location, and a webhook only fires for leads of that location.
- Under Webhooks, click Add webhook.
- Choose the Event (see the table below) and, for comparison events, the Value to compare with.
- Enter the Webhook URL.
- Optionally choose Additional fields (hold Ctrl to choose several) and a report under Report values to send more of the lead's data with the event.
- Save. A field can have up to 50 webhooks. Untick Enabled to pause one without deleting it.
Events
The event is checked against the value saved on the lead. A save that leaves the field unchanged sends nothing.
| Event | Sent as | Fires when | Available for |
|---|---|---|---|
| Set | set | The field was empty and now has a value | All fields |
| Unset | unset | The field had a value and is now empty | All fields |
| Change | change | The value is different from before | All fields |
| Equal to | equal | The value changed and now equals your value | All fields |
| Not equal to | not_equal | The value changed and now differs from your value | All fields |
| Greater than | greater | The value changed and is now above your value | Number fields |
| Less than | less | The value changed and is now below your value | Number fields |
| After date | after | The date changed and is now after your date | Date fields |
| Before date | before | The date changed and is now before your date | Date fields |
| Moves up (earlier position) | moves_up | The lead moved to a status that is earlier in your status order | Status |
| Moves down (later position) | moves_down | The lead moved to a status that is later in your status order | Status |
- Comparison dates are entered as YYYY-MM-DD in the location's time zone.
- For checkboxes, enter 1 for checked and 0 for unchecked.
- For number fields, zero counts as a value, so a total going from empty to 0 is a Set event.
What Triggers a Webhook
Webhooks are sent when a lead is saved from:
- The lead form in the software, including status changes
- The API (API - Leads - Create or Update)
- Your website quote and checkout forms
- An automation that sets a field
Payment and contract fields do not have their own events. Amount Paid, Balance Due, Deposit Paid, Balance Received and Contract Received are updated by payments and contract signing, outside of a lead save. You can still send their current values as additional fields on another field's webhook.
What Your Server Receives
Data is sent as an HTTP POST with a JSON body.
POST /your/webhook/path HTTP/1.1
Content-Type: application/json
Accept: application/json
{
"version": 1,
"event_id": "3f9c2a7be1d04c5a9b6e8d2f41a07c35",
"event": "change",
"occurred_at": "2026-11-13T15:04:05+00:00",
"lead": { "id": 520247, "location_id": 0 },
"field": { "id": "quote_statusid", "name": "Status", "value": "1482" },
"fields": {
"quote_eventname": "Rivera Birthday",
"quote_eventstarttime": 1795708800,
"quote_total": 425.13
},
"report": {
"id": 9012,
"name": "Webhook Lead Summary",
"values": [
{ "field": "contact_email", "name": "Customer Email", "value": "jordan@example.com" },
{ "field": "balance_due", "name": "Lead $ Balance Due", "value": 125.13 }
]
}
}| Name | Description |
|---|---|
| version | Format version, currently 1 |
| event_id | Unique ID of this event. A retry of the same event carries the same ID |
| event | The event that fired, as listed in the "Sent as" column above |
| occurred_at | When the event was recorded, ISO 8601 in UTC |
| lead.id | The lead ID. Use it with the API to read anything else about the lead |
| lead.location_id | The lead's location, 0 for accounts with a single location |
| field | The watched field: its ID, its name as shown on your lead form, and its new value |
| fields | The additional fields you chose, by field ID. Empty object when none are chosen |
| report | The report you chose with one entry per column, or null when none is chosen |
Value Formats
- Text: a string
- Numbers and money: a number without currency symbol, for example 425.13
- Dates and times: a Unix timestamp in seconds, for example 1795708800
- Checkboxes: true or false
- Choices such as Status and Location: the ID of the choice. See API - Lookup Lists for the names
- Empty values: null
Reading the Data in PHP
<?php
$event = json_decode(file_get_contents('php://input'), true);
$lead_id = $event['lead']['id'];
$new_value = $event['field']['value'];
// Skip an event you already processed (see Delivery and Retries).
// Save or process the data here, then answer with a 200 status.
http_response_code(200);
echo 'ok';Sending More Data: Additional Fields and Report Values
Additional fields lets you pick up to 100 lead and customer fields, including your custom fields. Their saved values are sent under fields.
Report values lets you reuse the column list of a Leads report. The option only appears when your account has at least one report that qualifies:
- It is a Leads report that you are allowed to see, and you have access to Reports.
- Every column is a single value of the lead or its customer: lead fields, customer fields, your custom fields, and the Paid, Balance Due, End Date/Time, Rental Total, Tax and Total columns.
- It has 100 columns or fewer.
A report with any other kind of column, such as rental items, payments or workers, is not offered. If you do not see Report values, create a Leads report with only lead and customer columns, then open the lead field again.
The report's columns are read when the webhook is saved. After changing the report, open the lead field and save it again.
Rental items are not part of the webhook. The Rental Total field tells you that the items or their prices changed, but not which ones. To get the item names and quantities, use lead.id from the webhook with API - Leads - Retrieve Details.
Delivery and Retries
- Webhooks are queued when the lead is saved and sent in the background, so expect a short delay.
- Your server has 10 seconds to answer. Answer with a 2xx status code (such as 200) to confirm you received the data. Any other answer, including a redirect, counts as a failure.
- HTTPS destinations need a valid certificate.
- A failed delivery is tried again after 1 hour, then after 8 hours, then after 24 hours. After that, or once it is a week old, it is dropped.
- The first attempt counts as one API transaction, whether or not it succeeds. Retries are free.
- The same event can occasionally arrive more than once. Store the event_id and ignore one you have already processed.
- Events are not guaranteed to arrive in order. Use occurred_at, or read the lead from the API, when the order matters.
- Disabling or deleting a webhook cancels its deliveries that are still waiting.