Webhooks
What this is. A webhook tells another system the moment something changes here (a new lead, an accepted proposal, a paid invoice) by sending a message to a web address that system gives you. You set one up on Settings > API and webhooks: paste the address, pick the events, save. The rest of this page is for whoever builds the receiving end.
Setting one up
Subscribe a URL to events on Settings > API and webhooks, or from an automation platform with POST /api/public/v1/webhooks (see the webhooks endpoints). We POST JSON to it within seconds of the change:
{ "id": "…", "type": "lead.created", "occurredAt": "…", "organizationId": "…", "data": { … }, "changes": [ … ] }Before anything is delivered, the address has to answer a check.
What each message carries
A subscription carries thin payloads unless you choose full ones. Thin: data is { "id", "object", "url" }, the record's id, its type and the path of the API that returns it (for example /api/public/v1/leads/<id>), and changes names the fields an *.updated event changed, without their values. Fetch the record with your API key: an endpoint that is not who it should be learns that something changed, not what. Full: data is the object as the API returns it, holding only what the subscriber may see, and changes carries each field's previous and current value. Choose with payloadMode (thin or full) in POST /api/public/v1/webhooks, or on Settings > API and webhooks, where switching to full asks for your second factor. The same id can arrive more than once, so handle it idempotently.
Fetching the record behind a thin payload uses the API: see Signing in. Each event's own entry under Events shows both payloads in full.
Every delivery is an HTTPS POST with a JSON body and these headers:
| Header | What it holds |
|---|---|
Content-Type | application/json; charset=utf-8 |
User-Agent | Webhooks/1.0 |
X-Webhook-Id | The delivery's id. It is the same on every retry of that delivery; a resend from the delivery log is a new delivery with a new id. |
X-Webhook-Event | The event name, the same as the body's type. |
X-Webhook-Timestamp | Unix seconds when this attempt was signed. |
X-Webhook-Signature | t=…,v1=…: see Checking deliveries. |
| Your extra header | Only if you gave the subscription one: see When you cannot check a signature. |
The body: id (the event's id: the same on every retry and every resend), type, occurredAt (UTC), organizationId, data, changes (null unless the event lists changed fields), and redacted (only on a full payload whose personal fields were set to null, for a key that may not read personal data).
Checking deliveries
Every request is signed: X-Webhook-Signature: t=<unix seconds>,v1=<hex>, where the hex is HMAC-SHA256 over <t>.<raw body> with the subscription's secret (whsec_…, shown once). For 24 hours after the secret is rotated the header carries two signatures, t=…,v1=<new>,v1=<old>, so you can switch secrets without dropping a delivery. To verify:
- Compute the HMAC over the raw request body, before any JSON parsing.
- Compare it in constant time with each
v1; accept if any matches. - Reject the request when
tis more than 300 seconds from your clock, either way: that stops replays. - Skip an event you have already handled:
X-Webhook-Idrepeats on every retry of a delivery, and the body'sidon every retry and every resend from the delivery log.
Node.js:
const parts = header.split(',').map(p => p.split('='));
const t = Number(parts.find(([k]) => k === 't')[1]);
const expected = Buffer.from(crypto.createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex'));
const fresh = Math.abs(Date.now() / 1000 - t) <= 300;
const valid = fresh && parts.some(([k, v]) => k === 'v1' && v.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(v), expected));C#:
var parts = header.Split(',').Select(p => p.Split('=', 2)).ToList();
var t = long.Parse(parts.First(p => p[0] == "t")[1]);
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var expected = Encoding.ASCII.GetBytes(Convert.ToHexStringLower(hmac.ComputeHash(Encoding.UTF8.GetBytes($"{t}.{rawBody}"))));
var fresh = Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - t) <= 300;
var valid = fresh && parts.Any(p => p[0] == "v1"
&& CryptographicOperations.FixedTimeEquals(Encoding.ASCII.GetBytes(p[1]), expected));When you cannot check a signature
If your endpoint cannot verify a signature (an API gateway, a no-code tool), give the subscription an extra header on Settings > API and webhooks, or with authHeaderName and authHeaderValue in POST /api/public/v1/webhooks: for example Authorization: Bearer <token>, Authorization: Basic <base64> or X-Api-Key: <key>. It is sent with every delivery, in addition to the signature, and its value is never shown again.
Confirming your address
Nothing is delivered to a URL until it proves it wants the events. When a subscription is made, when its URL changes, and when you press Verify now, we POST a signed request with X-Webhook-Event: webhook.verification:
{ "type": "webhook.verification", "challenge": "…", "subscriptionId": "…" }Check its signature as above, then answer with a 2xx whose body is the challenge, as plain text or as { "challenge": "…" }. Any other answer fails, and the subscription sends nothing until it passes. The check is repeated every 30 days: an endpoint that stops answering it stops receiving deliveries, and the organisation's Owners are emailed. Its events are paused, not lost: the check is tried again every hour, and once it passes everything waiting goes out. After 24 hours of failed checks the webhook is switched off. Subscriptions that existed before the check was introduced count as verified from that day and are first challenged 30 days later.
Node.js (Express, after the signature check):
const event = JSON.parse(rawBody);
if (event.type === 'webhook.verification') {
return res.status(200).type('text/plain').send(event.challenge);
}C# (minimal API, after the signature check):
using var doc = JsonDocument.Parse(rawBody);
if (doc.RootElement.GetProperty("type").GetString() == "webhook.verification")
return Results.Text(doc.RootElement.GetProperty("challenge").GetString());What your endpoint must answer
- Any 2xx status within 10 seconds counts as delivered. The body of a 2xx is ignored.
- Anything else is a failure, and is retried: a 4xx or 5xx, no answer within 10 seconds, a connection that cannot be made, and a 3xx: redirects are not followed, so give the subscription the final address.
- We read at most the first 4 KB of your answer and keep the first 1,000 characters in the delivery log, where your organisation's admins read it. Never echo the payload, a secret or a token back.
- Answer first, work later: store the event or put it on a queue, answer at once, and do slow work afterwards. A slow answer becomes a timeout, and a timeout a retry.
- Expect repeats: keep the ids you have handled and skip one you have seen (see Checking deliveries).
- A long outage pauses deliveries, it does not lose them: after 24 hours with nothing delivered the webhook is switched off, and events are kept for it for 7 days (see When a webhook is switched off).
The one exception is the address check, which must answer with its challenge: see Confirming your address.
A minimal answer:
HTTP/1.1 200 OK Content-Length: 0
Retries and resending
A delivery gets up to 8 attempts in total: the first, then a retry after each of these waits: 1 min, 5 min, 30 min, 2 h, 6 h, 12 h and 24 h. The last attempt comes 44 h 36 min after the first (about 45 hours).
- After the last attempt fails, the delivery is marked Failed. It stays in the subscription's delivery log on Settings > API and webhooks, from where it can be sent again.
- A delivery that may no longer be sent fails at once, with no retries: the subscription was deleted, its address is no longer allowed, the API key that made it was revoked, suspended or has expired, the person it acts for has lost access, or the organisation's plan no longer includes webhooks.
- Order is not guaranteed: a retry can arrive after a later event, and a delivery can arrive more than once. Order by
occurredAt, and recognise repeats by the body'sid.
A webhook whose endpoint keeps failing is switched off, but its events are not thrown away. The rest of this section is how.
When a webhook is switched off
Only when both are true: its last 20 attempts in a row have failed, and nothing has been delivered to it for 24 hours. One successful delivery resets both. So a burst of failures during a short outage leaves it on, and so does an endpoint that fails now and then. When it is switched off, the person who made it is emailed.
While it is off
Nothing is sent, and what was waiting is not lost: its deliveries are paused, kept but not attempted.
- Switched off automatically: it keeps collecting new events, paused, for 7 days after it was switched off. Fix your endpoint and switch it back on within that time, and nothing is lost.
- Switched off by a person: it collects nothing new while it is off. Only what was already waiting is kept.
- A waiting delivery more than 7 days old is marked Failed while the webhook is off ("switched off for more than 7 days"). It stays in the log and can be resent.
Switching it back on
Switch it back on under Settings > API and webhooks. Everything still waiting goes out at once, oldest first, each with a fresh set of 8 attempts, and the failure count starts again from zero.
Resending failed deliveries
Resend all failed, in the webhook's delivery log, sends again every failed delivery of the last 30 days: one per event (its most recent failed copy), oldest first, skipping any event that has since been delivered or queued again. It queues up to 500 at a time; press it again for the rest. The webhook must be switched on and its address verified. A single delivery can be resent from the log too.
Every resend is a new delivery, with a new X-Webhook-Id and fresh retries, but the same body, so its id tells you it is a repeat (see Checking deliveries).
An example
Your endpoint goes down at 09:00 on day 1, and events keep happening.
| When | What happens |
|---|---|
| Day 1, 09:00 onwards | Each delivery fails and is retried on the schedule above. A busy hour can reach 20 failures in a row; the webhook stays on, because it has not been failing for 24 hours yet. |
| Day 2, 09:00 | 24 hours without a single delivery: the next failed attempt switches the webhook off, and its creator is emailed. What is waiting is paused, not failed. |
| Day 5, 09:00 | Your endpoint is fixed and the webhook switched back on: everything that waited, and every event since, goes out at once, oldest first. |
| Day 9, 09:00 | Had it stayed off this long, it would stop collecting new events, and deliveries more than 7 days old would be marked failed: Resend all failed sends them once it is back on. |
Where messages may go
An organisation can list the domains its webhooks may deliver to on Settings > API and webhooks. An entry also allows its subdomains: example.com allows hooks.example.com, not example.com.evil.net. With a list, a subscription to anywhere else is refused (errors.webhooks.destinationNotAllowed), and an existing one outside it stops delivering. Changing the list asks for your second factor. Request-inspection services that publish whatever they receive (such as webhook.site and requestbin.com) are always refused (errors.webhooks.destinationBlocked). Every new subscription and every URL change is emailed to the organisation's Owners, with the destination.
Events
Every event: what it means, exactly when it fires, the record it carries, and an example request in each payload mode. A subscriber receives an event only while it may view the records it is about.
| Event | What happened | The subscriber needs to view |
|---|---|---|
lead.created | A lead is created | crm.leads |
lead.updated | A lead is changed | crm.leads |
lead.stage_changed | A lead moves to another stage | crm.leads |
lead.converted | A lead becomes a customer | crm.leads |
customer.created | A customer is created | crm.customers |
customer.updated | A customer is changed | crm.customers |
customer.stage_changed | A customer moves to another stage | crm.customers |
company.created | A company is created | crm.companies |
company.updated | A company is changed | crm.companies |
task.created | A task is created | crm.tasks |
task.status_changed | A task's status changes | crm.tasks |
proposal.created | A proposal is created | crm.proposals |
proposal.status_changed | A proposal's status changes | crm.proposals |
proposal.accepted | A proposal is accepted | crm.proposals |
invoice.created | An invoice is created | crm.invoices |
invoice.status_changed | An invoice's status changes | crm.invoices |
invoice.paid | An invoice is paid | crm.invoices |
invoice.overdue | An invoice becomes overdue | crm.invoices |
The example bodies are built by the code that sends real ones, with sample values. They are shown indented; a real body is compact, and its signature is computed over exactly those bytes.
lead.created
A lead is created.
- Fires
- When a lead is created.
- Carries
- full payload:
PublicLead· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.leads
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: lead.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=61a02a022d18eea8e71709ce92e7fec0ec7504044a1a9061bef5383f3262f9fa
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "lead.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "lead",
"url": "/api/public/v1/leads/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: lead.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=af3d73d3ef1035742dabba20de7a445885da49d20abe4d629534f0ff4d0bf688
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "lead.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"firstName": "Ana",
"lastName": "Example",
"email": "[email protected]",
"phone": null,
"address": null,
"city": "Limassol",
"district": null,
"postalCode": null,
"countryCode": "CY",
"status": "New",
"stageId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"priority": "medium",
"source": "website",
"companyId": null,
"ownerUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"assignedUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"estimatedBudgetEur": 12000,
"propertyType": null,
"notes": null,
"nextFollowUpAt": null,
"convertedCustomerId": null,
"createdAt": "2026-10-04T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z",
"kind": "person"
},
"changes": null
}lead.updated
A lead is changed.
- Fires
- When a save changes any of a lead's details (name, contact details, address, country, status, priority, source, owner, assignee, company, notes, follow-up date, contact preferences and the other fields on the lead), or when someone adds a note to it. One delivery per save, however many fields changed: changes lists each one, and a new note is listed as note. Saving without changing anything sends nothing. A move to another pipeline stage is lead.stage_changed; logging a call, visit, email or meeting sends nothing.
- Carries
- full payload:
PublicLead· thin payload:WebhookThinData - changes
- Each field the save changed (
WebhookChange): its name only in a thin payload, with itspreviousandcurrentvalue in a full one. - Needs
- View on
crm.leads
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: lead.updated
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=2f2a66a033776fa774491ee5b4495f3ae72e058e2575297fd1797f2aef667482
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "lead.updated",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "lead",
"url": "/api/public/v1/leads/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": [
{
"field": "status"
},
{
"field": "priority"
}
]
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: lead.updated
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=346bede227ba08d9cae4e794975b298af578f1b6ec550ac49a86b8fd5465e15d
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "lead.updated",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"firstName": "Ana",
"lastName": "Example",
"email": "[email protected]",
"phone": null,
"address": null,
"city": "Limassol",
"district": null,
"postalCode": null,
"countryCode": "CY",
"status": "Contacted",
"stageId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"priority": "high",
"source": "website",
"companyId": null,
"ownerUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"assignedUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"estimatedBudgetEur": 12000,
"propertyType": null,
"notes": null,
"nextFollowUpAt": null,
"convertedCustomerId": null,
"createdAt": "2026-10-04T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z",
"kind": "person"
},
"changes": [
{
"field": "status",
"previous": "New",
"current": "Contacted"
},
{
"field": "priority",
"previous": "medium",
"current": "high"
}
]
}lead.stage_changed
A lead moves to another stage.
- Fires
- When a lead is moved to another pipeline stage.
- Carries
- full payload:
PublicLead· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.leads
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: lead.stage_changed
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=2d5cdacb2d8c496348cd0835b97dc0c45c0a8c86155ff75d77778670b53251f9
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "lead.stage_changed",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "lead",
"url": "/api/public/v1/leads/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: lead.stage_changed
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=ee535abf9bd7f7dd5d0b5754d75622d75ffcffd038435137c7db7ddab78e9b4a
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "lead.stage_changed",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"firstName": "Ana",
"lastName": "Example",
"email": "[email protected]",
"phone": null,
"address": null,
"city": "Limassol",
"district": null,
"postalCode": null,
"countryCode": "CY",
"status": "Contacted",
"stageId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"priority": "medium",
"source": "website",
"companyId": null,
"ownerUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"assignedUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"estimatedBudgetEur": 12000,
"propertyType": null,
"notes": null,
"nextFollowUpAt": null,
"convertedCustomerId": null,
"createdAt": "2026-10-04T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z",
"kind": "person"
},
"changes": null
}lead.converted
A lead becomes a customer.
- Fires
- When a lead is converted into a customer. The lead in data carries the new customer's id in convertedCustomerId.
- Carries
- full payload:
PublicLead· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.leads
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: lead.converted
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=f8e0a275683cfcc3a6cc0bf1c9fbda2249787c34444ef3968ece7678bbd998de
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "lead.converted",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "lead",
"url": "/api/public/v1/leads/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: lead.converted
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=aef511909ac44c006e7aebaf9be5af494d510715dc82bda83c76e623c5c7e6c4
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "lead.converted",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"firstName": "Ana",
"lastName": "Example",
"email": "[email protected]",
"phone": null,
"address": null,
"city": "Limassol",
"district": null,
"postalCode": null,
"countryCode": "CY",
"status": "Won",
"stageId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"priority": "medium",
"source": "website",
"companyId": null,
"ownerUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"assignedUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"estimatedBudgetEur": 12000,
"propertyType": null,
"notes": null,
"nextFollowUpAt": null,
"convertedCustomerId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"createdAt": "2026-10-04T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z",
"kind": "person"
},
"changes": null
}customer.created
A customer is created.
- Fires
- When a customer is created.
- Carries
- full payload:
PublicCustomer· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.customers
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: customer.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=991e3d130e4b361ab716a44c338208d390b499464739fcaf3ce396e8002c675c
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "customer.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "customer",
"url": "/api/public/v1/customers/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: customer.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=63b8f1c2e517448bbd18fe7627d2571d1f29c47e317d6da1f681f76bddbf1a53
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "customer.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"firstName": "Ana",
"lastName": "Example",
"email": "[email protected]",
"phone": null,
"address": null,
"city": "Limassol",
"district": null,
"postalCode": "3025",
"countryCode": "CY",
"companyId": null,
"ownerUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"assignedTeamId": null,
"stageId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"notes": null,
"source": "api",
"archivedAt": null,
"createdAt": "2026-09-07T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z",
"kind": "person"
},
"changes": null
}customer.updated
A customer is changed.
- Fires
- When a save changes any of a customer's details (name, contact details, address, country, owner, company, billing details, notes, follow-up date, contact preferences and the other fields on the customer), when someone adds a note to it, or when it is archived or restored. One delivery per save, however many fields changed: changes lists each one, and a new note is listed as note. Saving without changing anything sends nothing. A move to another stage is customer.stage_changed; logging a call, visit, email, maintenance or complaint sends nothing.
- Carries
- full payload:
PublicCustomer· thin payload:WebhookThinData - changes
- Each field the save changed (
WebhookChange): its name only in a thin payload, with itspreviousandcurrentvalue in a full one. - Needs
- View on
crm.customers
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: customer.updated
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=6ead37901b9a985fbad78459b471b4a297fca220f042e0657e0b1273a6b1602c
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "customer.updated",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "customer",
"url": "/api/public/v1/customers/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": [
{
"field": "city"
},
{
"field": "postalCode"
}
]
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: customer.updated
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=dde8309db60f868898970607b0f12c9b1b7cf10d20b57e4b3f990f1728a7942a
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "customer.updated",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"firstName": "Ana",
"lastName": "Example",
"email": "[email protected]",
"phone": null,
"address": null,
"city": "Nicosia",
"district": null,
"postalCode": "1010",
"countryCode": "CY",
"companyId": null,
"ownerUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"assignedTeamId": null,
"stageId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"notes": null,
"source": "api",
"archivedAt": null,
"createdAt": "2026-09-07T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z",
"kind": "person"
},
"changes": [
{
"field": "city",
"previous": "Limassol",
"current": "Nicosia"
},
{
"field": "postalCode",
"previous": "3025",
"current": "1010"
}
]
}customer.stage_changed
A customer moves to another stage.
- Fires
- When a customer is moved to another stage.
- Carries
- full payload:
PublicCustomer· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.customers
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: customer.stage_changed
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=71fb8298fb0a7675e1cb71c1c6f6a3ee3053cd60a931ca902033b368d827ac0f
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "customer.stage_changed",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "customer",
"url": "/api/public/v1/customers/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: customer.stage_changed
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=0fb12629a08a3449a0e7cecd6f3162a6349357424fc844d31ca22eb823c66759
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "customer.stage_changed",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"firstName": "Ana",
"lastName": "Example",
"email": "[email protected]",
"phone": null,
"address": null,
"city": "Limassol",
"district": null,
"postalCode": "3025",
"countryCode": "CY",
"companyId": null,
"ownerUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"assignedTeamId": null,
"stageId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"notes": null,
"source": "api",
"archivedAt": null,
"createdAt": "2026-09-07T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z",
"kind": "person"
},
"changes": null
}company.created
A company is created.
- Fires
- When a company is created.
- Carries
- full payload:
PublicCompany· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.companies
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: company.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=976d6c708c05239c4ed89f08162f88775f057efb4f27d9891e6b0740ad6cbe81
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "company.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "company",
"url": "/api/public/v1/companies/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: company.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=043558715475fbb2ad4d2680c136e1426ba23257b0341eb03535536d9f27f233
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "company.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"name": "Example Trading Ltd",
"vatNumber": "CY10000000X",
"countryCode": "CY",
"address": null,
"city": "Limassol",
"postalCode": null,
"phone": null,
"email": "[email protected]",
"website": null,
"notes": null,
"ownerUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"viesStatus": null,
"viesCheckedAt": null,
"createdAt": "2026-08-08T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z",
"tradingName": null,
"legalForm": null,
"registrationNumber": null,
"taxId": null,
"industry": null,
"employeeBand": null
},
"changes": null
}company.updated
A company is changed.
- Fires
- When a company's details are saved. changes is null: the delivery says the company changed, not which fields.
- Carries
- full payload:
PublicCompany· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.companies
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: company.updated
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=5fb8a0f997cbc49758c785ab3ce68c7d27dd6502c4b559f74af8475f1b2b1760
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "company.updated",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "company",
"url": "/api/public/v1/companies/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: company.updated
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=97a6f9c2ab3c830adaa0cf720cb66c38629f9e95c6508a2251e765f312001dec
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "company.updated",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"name": "Example Trading Ltd",
"vatNumber": "CY10000000X",
"countryCode": "CY",
"address": null,
"city": "Limassol",
"postalCode": null,
"phone": null,
"email": "[email protected]",
"website": null,
"notes": null,
"ownerUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"viesStatus": null,
"viesCheckedAt": null,
"createdAt": "2026-08-08T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z",
"tradingName": null,
"legalForm": null,
"registrationNumber": null,
"taxId": null,
"industry": null,
"employeeBand": null
},
"changes": null
}task.created
A task is created.
- Fires
- When a task is created.
- Carries
- full payload:
PublicTask· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.tasks
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: task.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=666f97c1dee69b678c7c1ad72327ce01f995f00dbde772dff12adccfb9bb4be2
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "task.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "task",
"url": "/api/public/v1/tasks/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: task.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=1aa47ebfa8d35031d0b1f1b5ea0e971efaf4f8f53416358dc8f51f21ef3fc90e
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "task.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"title": "Call back about the quote",
"description": null,
"category": null,
"priority": "medium",
"status": "pending",
"dueDate": "2026-10-08",
"dueTime": null,
"assignedUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"assignedTeamId": null,
"customerId": null,
"leadId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"createdByUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"completedAt": null,
"createdAt": "2026-10-06T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z"
},
"changes": null
}task.status_changed
A task's status changes.
- Fires
- When a task's status changes, for example when it is completed.
- Carries
- full payload:
PublicTask· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.tasks
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: task.status_changed
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=b669125fdcb452069e0ca08642e3878fbf1369cbd60e94c84c326f90ae2291f3
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "task.status_changed",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "task",
"url": "/api/public/v1/tasks/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: task.status_changed
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=fb8fc9264577139785718873da4c1915bb66889df3f84c7be74a587ab8a6b179
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "task.status_changed",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"title": "Call back about the quote",
"description": null,
"category": null,
"priority": "medium",
"status": "completed",
"dueDate": "2026-10-08",
"dueTime": null,
"assignedUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"assignedTeamId": null,
"customerId": null,
"leadId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"createdByUserId": "2a3b4c5d-6e7f-4801-9a2b-3c4d5e6f7a8b",
"completedAt": "2026-10-07T09:30:00Z",
"createdAt": "2026-10-06T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z"
},
"changes": null
}proposal.created
A proposal is created.
- Fires
- When a proposal is created.
- Carries
- full payload:
PublicProposal· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.proposals
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: proposal.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=736c39a353a6e4d7e7e3818791ff893a5b95c6fdad97a8949dad75fd9d07541d
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "proposal.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "proposal",
"url": "/api/public/v1/proposals/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: proposal.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=c23fdec56a3b141651c09441f74ed788491ca52831a10c75dc907ff4571a6ef3
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "proposal.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"proposalNumber": "P-2026-0042",
"status": "Draft",
"customerId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"leadId": null,
"customerName": "Ana Example",
"subtotalEur": 10000,
"vatAmountEur": 1900,
"totalCostEur": 11900,
"sentAt": null,
"viewedAt": null,
"acceptedAt": null,
"expiresAt": "2026-11-04T09:30:00Z",
"createdAt": "2026-10-04T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z"
},
"changes": null
}proposal.status_changed
A proposal's status changes.
- Fires
- When a proposal's status changes to anything but Accepted (for example Sent, Viewed, Rejected or Expired).
- Carries
- full payload:
PublicProposal· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.proposals
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: proposal.status_changed
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=7454b55be24e32056fd1a6fa59880932f3f74c7a157792f7503327d004c979c5
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "proposal.status_changed",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "proposal",
"url": "/api/public/v1/proposals/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: proposal.status_changed
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=f05a92994e3706e6d01a41d2f59a5b1cf81fa1ec1ce1be20e865b9192013dfc3
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "proposal.status_changed",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"proposalNumber": "P-2026-0042",
"status": "Sent",
"customerId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"leadId": null,
"customerName": "Ana Example",
"subtotalEur": 10000,
"vatAmountEur": 1900,
"totalCostEur": 11900,
"sentAt": "2026-10-05T09:30:00Z",
"viewedAt": null,
"acceptedAt": null,
"expiresAt": "2026-11-04T09:30:00Z",
"createdAt": "2026-10-04T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z"
},
"changes": null
}proposal.accepted
A proposal is accepted.
- Fires
- When a proposal's status becomes Accepted. It is sent instead of proposal.status_changed, not as well.
- Carries
- full payload:
PublicProposal· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.proposals
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: proposal.accepted
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=f38335b936cec9e7cb76c30821bae200dd3297effcf7c4a0191bf291c0a7d7a6
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "proposal.accepted",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "proposal",
"url": "/api/public/v1/proposals/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: proposal.accepted
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=c50adf47d439aface2a60d3121de21d024f4f8d65585f8a2d38489ce7a5f2900
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "proposal.accepted",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"proposalNumber": "P-2026-0042",
"status": "Accepted",
"customerId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"leadId": null,
"customerName": "Ana Example",
"subtotalEur": 10000,
"vatAmountEur": 1900,
"totalCostEur": 11900,
"sentAt": "2026-10-05T09:30:00Z",
"viewedAt": null,
"acceptedAt": "2026-10-07T09:30:00Z",
"expiresAt": "2026-11-04T09:30:00Z",
"createdAt": "2026-10-04T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z"
},
"changes": null
}invoice.created
An invoice is created.
- Fires
- When an invoice is created.
- Carries
- full payload:
PublicInvoice· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.invoices
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: invoice.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=90817c6e0eadd8ae07f1b48763aaea2ea23200a559194782d3e3aca1b15e72a7
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "invoice.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "invoice",
"url": "/api/public/v1/invoices/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: invoice.created
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=4a968ba779fdd1fe2733b995b687aad54397377c124f7174670c462cb41a6065
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "invoice.created",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"invoiceNumber": "INV-2026-0107",
"type": "one_off",
"status": "draft",
"customerId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"currency": "EUR",
"subtotal": 1000,
"vatAmount": 190,
"total": 1190,
"amountPaid": 0,
"issueDate": "2026-09-01",
"dueDate": "2026-10-01",
"paidDate": null,
"billingName": "Ana Example",
"billingVatNumber": null,
"createdAt": "2026-09-01T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z"
},
"changes": null
}invoice.status_changed
An invoice's status changes.
- Fires
- When an invoice's status changes, for example from draft to sent.
- Carries
- full payload:
PublicInvoice· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.invoices
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: invoice.status_changed
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=0f54c8012c88634ce4b8688907bb24e542ace1799c358242d974ca26c448c9d6
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "invoice.status_changed",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "invoice",
"url": "/api/public/v1/invoices/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: invoice.status_changed
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=d4a44346b4450e0dfaec859ea63e85359342ae0d8cb3b9706d7caf6941f8783c
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "invoice.status_changed",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"invoiceNumber": "INV-2026-0107",
"type": "one_off",
"status": "sent",
"customerId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"currency": "EUR",
"subtotal": 1000,
"vatAmount": 190,
"total": 1190,
"amountPaid": 0,
"issueDate": "2026-09-01",
"dueDate": "2026-10-01",
"paidDate": null,
"billingName": "Ana Example",
"billingVatNumber": null,
"createdAt": "2026-09-01T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z"
},
"changes": null
}invoice.paid
An invoice is paid.
- Fires
- When an invoice is recorded as paid.
- Carries
- full payload:
PublicInvoice· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.invoices
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: invoice.paid
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=cc596f451c561a185ec9beebb6581cd2b6b626136bd74d134a31e011e5d91038
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "invoice.paid",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "invoice",
"url": "/api/public/v1/invoices/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: invoice.paid
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=9850585476aa56fe9fc33d60e204929ff1cb050e5515fd5bebd10159a0b4db21
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "invoice.paid",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"invoiceNumber": "INV-2026-0107",
"type": "one_off",
"status": "paid",
"customerId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"currency": "EUR",
"subtotal": 1000,
"vatAmount": 190,
"total": 1190,
"amountPaid": 1190,
"issueDate": "2026-09-01",
"dueDate": "2026-10-01",
"paidDate": "2026-10-07",
"billingName": "Ana Example",
"billingVatNumber": null,
"createdAt": "2026-09-01T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z"
},
"changes": null
}invoice.overdue
An invoice becomes overdue.
- Fires
- When an unpaid invoice passes its due date.
- Carries
- full payload:
PublicInvoice· thin payload:WebhookThinData - changes
null- Needs
- View on
crm.invoices
Example request: thin payload (the default)
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: invoice.overdue
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=0ab2f532d3084835284fccde9de7280babb8419ec23083c41dd73e44e8b765ba
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "invoice.overdue",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"object": "invoice",
"url": "/api/public/v1/invoices/0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01"
},
"changes": null
}Example request: full payload
POST /your/webhook/path HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Webhooks/1.0
X-Webhook-Id: 9d8c7b6a-5f4e-4d3c-b2a1-0f9e8d7c6b5a
X-Webhook-Event: invoice.overdue
X-Webhook-Timestamp: 1791365400
X-Webhook-Signature: t=1791365400,v1=aeb123e6c0fb753daf7eeeb7c9ccb662f5e27668d332437c9f325c26cf73c76c
Authorization: Bearer … (only if you gave the subscription an extra header)
{
"id": "c4a1e9d2-3f5b-4a6c-8d7e-9f0a1b2c3d4e",
"type": "invoice.overdue",
"occurredAt": "2026-10-07T09:30:00Z",
"organizationId": "6f1d8c2e-4b7a-4e19-9a53-2c0e7b1d4f60",
"data": {
"id": "0b9e2f6a-7c31-4d8e-a2f4-5e6d7c8b9a01",
"invoiceNumber": "INV-2026-0107",
"type": "one_off",
"status": "overdue",
"customerId": "7e6d5c4b-3a29-4817-a6b5-c4d3e2f1a0b9",
"currency": "EUR",
"subtotal": 1000,
"vatAmount": 190,
"total": 1190,
"amountPaid": 0,
"issueDate": "2026-09-01",
"dueDate": "2026-10-01",
"paidDate": null,
"billingName": "Ana Example",
"billingVatNumber": null,
"createdAt": "2026-09-01T09:30:00Z",
"updatedAt": "2026-10-07T09:30:00Z"
},
"changes": null
}