Set up webhooks
Let zolar call your system instead of polling GET /leads.
Steps
-
1
Pick an event
lead:boughtfires when your organisation buys a lead;lead:deletedfires when a lead you bought has its personal data erased (privacy request or retention expiry), so you can erase your copy. Every request carries the event in thex-zolar-eventheader. -
2
Create an endpoint
Add a secret header, such as
Authorization, so your system can verify the request comes from zolar.curlcurl -X POST https://demo.api.lead.zolar.tech/api/public/v2/installer/webhooks \ -H "Authorization: Bearer sk_[YOUR DEMO KEY]" \ -H "Content-Type: application/json" \ -d '{ "event": "lead:bought", "url": "https://crm.example.com/zolar/leads", "headers": [ { "name": "Authorization", "value": "Bearer [YOUR WEBHOOK SECRET]" } ] }'The response is the endpoint with its
id; header values are never returned, onlyheaderNames. -
3
Test it
zolar sends a sample event matching the endpoint's event (a bought lead or a deletion) and returns the status and response body your system answered with.
curlcurl -X POST https://demo.api.lead.zolar.tech/api/public/v2/installer/webhooks/[WEBHOOK ID]/test \ -H "Authorization: Bearer sk_[YOUR DEMO KEY]" # { "status": 200, "body": "ok" }Status
501means your endpoint could not be reached;555means a custom body could not be filled. -
4
Manage endpoints
These are the same endpoints as in the portal under Settings → Integrations.
curl# List curl https://demo.api.lead.zolar.tech/api/public/v2/installer/webhooks \ -H "Authorization: Bearer sk_[YOUR DEMO KEY]" # Replace (leave out "headers" to keep the stored ones; [] removes them) curl -X PUT https://demo.api.lead.zolar.tech/api/public/v2/installer/webhooks/[WEBHOOK ID] \ -H "Authorization: Bearer sk_[YOUR DEMO KEY]" \ -H "Content-Type: application/json" \ -d '{ "event": "lead:bought", "url": "https://crm.example.com/zolar/v2" }' # Delete curl -X DELETE https://demo.api.lead.zolar.tech/api/public/v2/installer/webhooks/[WEBHOOK ID] \ -H "Authorization: Bearer sk_[YOUR DEMO KEY]"PUTis a full replace: a left-outname,enabledorbodyTemplatereturns to its default. -
5
Send a custom body
OptionalSet
bodyTemplateto a JSON template if your system expects its own shape: a JSON object up to 16 KB, with{{ lead.firstName }}or{{ path | filter }}placeholders in string values. A value that is exactly one placeholder keeps its type; unknown variables or filters are rejected on save.All variables and filters are listed under Body template reference below; the portal's template editor (Custom body) shows the same list with a live preview. If a template can't be filled for a lead, nothing is sent and the run shows as failed under Recent runs.
Standard payload
Without a custom body, a lead:bought request carries this JSON;
id is your leadOfferId.
{
"id": "00000000-0000-4000-8000-000000000001",
"salutation": "woman",
"firstName": "Erika",
"lastName": "Musterfrau",
"email": "erika@example.org",
"phone": "+4915100000000",
"country": "DE",
"city": "Musterstadt",
"postalCode": "12345",
"street": "Musterstraße 12",
"properties": {
"interest": { "pv": "interestNew", "battery": "interestNew" },
"building": { "type": "residential", "isOwner": true }
},
"marketPlace": "My Marketplace"
}
{
"id": "00000000-0000-4000-8000-000000000001",
"leadId": "00000000-0000-4000-8000-000000000002",
"event": "lead:deleted",
"reason": "gdpr",
"deletedAt": "2026-10-23T09:30:00.000Z",
"marketPlace": "My Marketplace"
}
reason is gdpr or retention.
Delivery and limits
-
A
2xxanswer counts as delivered. There are no automatic retries: a request that fails, times out (10 s) or gets a non-2xx answer is not sent again. Redirects are not followed. - Failed runs show under the endpoint's Recent runs in Settings → Integrations, where Retry resends them by hand and Send past purchases delivers earlier purchases.
- Up to 20 webhook endpoints per organisation.
-
Host,Content-Length,Transfer-Encoding,Connectionandx-zolar-eventcan't be set as headers; each name only once. -
The URL must use
httporhttpson port 80 or 443 and point at a public host — notlocalhostor a private, loopback or link-local address. - Permissions: Read webhooks to list, Manage webhooks to create, replace, delete and test.
Body template reference
Templates may be up to 16 KB. Below an object or array of lead.properties marked "any path below it too", paths that are not listed still work; they are filled with the lead's value, or null.
| Variable | Type | Values | Example |
|---|---|---|---|
leadOffer.id | string | — | c1a2… |
lead.id | string | — | 9f8e… |
lead.salutation | enum or null | man, woman, diverse | man |
lead.firstName | string | — | Jan |
lead.lastName | string | — | de Vries |
lead.email | string | — | jan@example.com |
lead.phone | string | — | +31612345678 |
lead.street | string | — | Kerkstraat 12a |
lead.streetName | string or null | — | Kerkstraat |
lead.houseNumber | string or null | — | 12 |
lead.houseNumberExtension | string or null | — | a |
lead.postalCode | string | — | 1234 AB |
lead.city | string | — | Utrecht |
lead.country | string | — | NL |
lead.language | string or null | — | nl |
lead.comment | string or null | — | Call after 18:00 |
lead.properties | object | — | { "interest": … } |
lead.properties.interest | object any path below it too | — | { "pv": "interestNew" } |
lead.properties.interest.pv | enum or null | existing, interestNew, interestUpgrade, service, repair | interestNew |
lead.properties.interest.battery | enum or null | existing, interestNew, interestUpgrade, service, repair | interestNew |
lead.properties.interest.heatPump | enum or null | existing, interestNew, interestUpgrade, service, repair | interestNew |
lead.properties.interest.ev | enum or null | existing, interestNew, interestUpgrade, service, repair | interestNew |
lead.properties.interest.ac | enum or null | existing, interestNew, interestUpgrade, service, repair | interestNew |
lead.properties.interest.wallbox | enum or null | existing, interestNew, interestUpgrade, service, repair | interestNew |
lead.properties.interest.balconyPv | enum or null | existing, interestNew, interestUpgrade, service, repair | interestNew |
lead.properties.interest.floorInsulation | enum or null | existing, interestNew, interestUpgrade, service, repair | interestNew |
lead.properties.interest.roofInsulation | enum or null | existing, interestNew, interestUpgrade, service, repair | interestNew |
lead.properties.interest.cavityWallInsulation | enum or null | existing, interestNew, interestUpgrade, service, repair | interestNew |
lead.properties.interest.timeHorizonMonths | object or null any path below it too | — | { "from": 0, "to": 3 } |
lead.properties.building | object any path below it too | — | { "type": "residential" } |
lead.properties.building.type | string or null | — | residential |
lead.properties.building.isOwner | boolean or null | — | true |
lead.properties.building.ownershipType | string or null | — | owner |
lead.properties.building.builtYear | string or null | — | before_2019 |
lead.properties.roof | object or null any path below it too | — | { "material": "brick" } |
lead.properties.roof.material | string or null | — | brick |
lead.properties.roof.lastRenovation | string or null | — | after_1990 |
lead.properties.roof.faces | array or null any path below it too | — | [{ "tilt": 30 }] |
lead.properties.energyConsumption | object or null any path below it too | — | { "amount": 3500 } |
lead.properties.energyConsumption.amount | number or null | — | 3500 |
lead.properties.energyConsumption.profile | string or null | — | h0 |
lead.properties.availability | object or null any path below it too | — | { "anyTime": true } |
lead.properties.availability.anyTime | boolean or null | — | true |
lead.properties.availability.daytime | array or null any path below it too | — | ["morning"] |
lead.properties.availability.weekdays | array or null any path below it too | — | ["Mo", "Tu"] |
marketplace.name | string | — | zolar NL |
event.type | string | — | lead:bought |
event.boughtAt | string | — | 2026-09-18T09:30:00.000Z |
| Variable | Type | Values | Example |
|---|---|---|---|
leadOffer.id | string | — | c1a2… |
lead.id | string | — | 9f8e… |
marketplace.name | string | — | zolar NL |
event.type | string | — | lead:deleted |
event.reason | enum | gdpr, retention | gdpr |
event.deletedAt | string | — | 2026-09-20T09:30:00.000Z |
| Filter | Argument | Example |
|---|---|---|
number | — | "12" → 12 |
upper | — | "nl" → "NL" |
lower | — | "NL" → "nl" |
trim | — | " a " → "a" |
default:"" | required | null → "x" |
map:a=X,*=Z | required | man → M (map:man=M,woman=V,*=O) |
join:", " | optional | ["a","b"] → "a, b" |
truncate:20 | required | first 20 chars |