Skip to main content
There’s no API call that registers a callback URL and fires as things happen to your leads. Getting a lead out to your own systems is a workspace feature you configure in the interface, and it works by push: we hold the address and decide when to call it.
Where
IntegrationsIntegrationsApps & CRM
Your role needs
Read access to Apps & CRM read-integrations. Admin, Member and Viewer have it by default.
To create or change
create-integrations to add one, update-integrations to change one, on top of the permission above.
If you cannot find this in your sidebar, your workspace may have a custom menu configuration. Contact support and we will check it for you.

How it behaves

There’s no endpoint to subscribe to

The whole public, versioned API is five endpoints under /api/v1: GET /me, GET /tags, POST /leads, POST /leads/batch and GET /leads/{id}. There is nothing alongside them to register a callback, list what you’ve subscribed to, or choose which events you want. That surface does not exist. Everything below is configuration you hold in the workspace, not something you register from your own code.

Two surfaces, one HTTP layer

Two things hold the configuration, and both are set up through the interface: The Webhook connector, set up once on . It holds an Endpoint URL, a Method, a Body format (JSON body or Form-encoded), authentication (No authentication, Bearer token, Custom header or Basic auth), a Field mapping from lead attributes to the key names your endpoint expects, and constants (custom fields and headers) sent with every request. Leave the mapping empty and we send a fixed default shape instead; in the dialog’s own words, “we’ll send our standard fields (id, name, email, phone, job title, company, stage, tags…)”. Three separate things fire a connector, all through the same code: the Auto-push analyzed leads switch on its card (off when you first connect it), the Push to CRM button on a lead, and the Send to CRM workflow block, which lists webhook connectors alongside the real CRMs. The Send Webhook block, a step on a workflow canvas. Its Endpoint control chooses the shape. Saved connector reuses a connector, taking its endpoint, method, body format, authentication and field mapping exactly as saved. Rotating a key is then one edit on the connector instead of one per workflow. Custom URL calls a one-off endpoint typed into the block, with its own Method, Body format, headers and fields, stored nowhere but that workflow. Values you type into the block are rendered as merge tags before the call, the custom URL included, so a lead’s email, a trigger value or an earlier block’s output can drop straight into the request. A saved connector’s own URL and headers are used exactly as stored. Those are not templated. Every one of those paths, plus the Send test button in the connect dialog, goes out through the same HTTP layer, so every rule below applies whatever sent the request.

The payload

A connector-built payload (every path that fires the connector, and the block’s Saved connector shape) is assembled in one order: your constant custom fields, then your mapped fields (or the standard default shape if you mapped nothing), then a reserved envelope added last. The envelope is event, lead_id and sent_at, and because it goes on last your field mapping cannot override those three key names. With the block, the fields you added on the block are merged on top of all of that, so those can override the envelope. event takes one of three values, and it tells you which path sent the request rather than which connector. lead is the default and covers everything that goes through the connector’s push: auto-push, the Push to CRM button and the Send to CRM block. workflow means a Send Webhook block sent it, in either shape. test means someone pressed Send test in the connect dialog, so nothing about that request should be treated as a real lead. A Custom URL block builds its own envelope instead: event (always the string workflow), lead_id, workflow_id and sent_at, plus whatever you map into the block’s fields. So a block with nothing configured beyond a URL still sends something usable. workflow_id appears only in this shape, and here the envelope wins the other way round: a block field whose name collides with an envelope key we are sending is dropped in favour of ours. lead_id is left out of the envelope entirely when the run has no lead, and a block field called lead_id then survives, because there is nothing to collide with. Whichever authentication you picked on the connector is attached to every call as a header for you: a bearer token and basic auth as Authorization, a custom header under the name you gave it. You never re-enter it in the block.

The network and delivery rules

Every call, whatever sent it, runs through the same guard rail:
  • Only http:// and https:// addresses are accepted, and credentials embedded in the URL itself (https://user:pass@host/…) are rejected outright: put them in the authentication fields instead.
  • Redirects are never followed. A 3xx counts as delivery failing, because the real endpoint never received the payload.
  • Every IP address the host resolves to is checked, and private, loopback, link-local and other reserved ranges are refused by default. A host that won’t resolve at all is treated the same way: not demonstrably public, so not called.
  • Two cloud metadata hosts are refused outright, whatever the private-network setting says.
  • Header names we own (Host, Content-Length, Connection, Transfer-Encoding) are always stripped from anything you send, along with any header whose name isn’t a valid header token. Line breaks are removed from header values.
  • The number of fields you can map and the number of headers you can add are both capped; rows past the cap are dropped silently rather than sent.
Blocking private-network addresses is on by default, and the configuration itself says to turn it off only for local development against a LAN endpoint. That is the usual explanation for a webhook that fires cleanly from a local setup and goes nowhere against a real workspace: the endpoint has to be reachable from the public internet, so a LAN address, a Docker service name or localhost no longer qualifies. Requests use a bounded timeout, so a slow endpoint can’t hold a workflow run open indefinitely, and the reply is truncated before it is stored on the run. Only a connection failure, a 408, a 429 or a 5xx is retried; every other outcome (a 400, a 401, a 404, a 3xx) is sent once and left alone. Send test is the exception: it never retries and it keeps far more of the reply, because you are reading that one.

What happens when a call fails

The Send Webhook block doesn’t fail the whole workflow because the far end rejected the request. It branches (Delivered or Failed) and carries the outcome forward: the status code, and either the reply or a short error. It branches on the HTTP status alone. An endpoint that answers 2xx and reports a problem in its own body takes the Delivered branch; the connector’s push and Send test do read the body and call that a failure. The same split applies to record IDs: only the connector’s push reads the created record’s id out of the reply and stores it on the lead, so a lead delivered by a Send Webhook block is never marked as synced. If you want the id stored from inside a workflow, use the Send to CRM block pointed at the connector instead, because that block goes through the connector’s push. The only failures treated as fatal are configuration mistakes, and they stop the run for that lead instead of quietly taking Failed on every lead:
  • The block is set to Saved connector and the connector isn’t there: never picked, deleted since, or not a webhook connector in this workspace.
  • The block is set to Custom URL and the URL is empty, or rejected by the rules above. The URL is rendered first and then checked, so a merge tag that resolves to a blocked address is fatal too.
Set to Saved connector with no lead in the run yet, the block takes Failed without calling the endpoint at all. A Custom URL block still calls, just without lead_id.

Limits

Connect a webhook (any CRM, Zapier, Make, n8n)

Set up the connector step by step (the endpoint, the authentication, the field mapping) and test it before you save.

Webhook testing, delivery rules and record IDs

Read a test result, understand why a 2xx isn’t proof, and fix the endpoints we refuse to call.

Auto-push and stage filters

Turn on automatic sending per connector, and narrow it to the stages you care about.

CRM and integration blocks

Every block that pushes a lead out from inside a workflow, including this one.