Skip to content

Integrations

Leadnote webhooks: events, signatures and retries

Send signed lead events from Leadnote to your own server, verify the signature, understand retries and replays, and rotate the signing secret safely.

Last updated 4 min read

An outbound webhook makes Leadnote send a signed JSON message to an address you choose when something happens, such as a lead being created. Use it to keep your own system in step without polling. Only Account Owners and Managers can add, change and delete webhooks.

This article is about webhooks that Leadnote sends. Portals and tools that post leads into Leadnote use a private webhook URL instead. See IndiaMART and lead portals.

Add a webhook

  1. Open Settings and choose API Integration, or find the Other Enterprise Systems (API) card on the integrations hub. The page is titled API and webhooks.
  2. Open the Outbound webhooks tab and choose Add webhook.
  3. Enter the Endpoint URL. It must be a public https:// (or http://) address.
  4. Add a Description if you like, such as "Billing system".
  5. Under events, choose Select events and tick the events you want. You need at least one.
  6. Choose Create webhook.
  7. Copy the signing secret from the window that opens. It is shown once. If you lose it, rotate the secret.

The list shows each endpoint with its events, its Active or Paused status, the number of deliveries and the date of the last one. In the row menu you can Edit, Send test, Rotate secret and Delete. Switch a webhook to Paused: no events are sent to stop it without deleting it.

Events

Event When it is sent
lead.created A lead is added, by a person, an import, a form or an integration
lead.updated A lead's details change
lead.deleted A lead is deleted or merged into another
lead.stage_changed A lead moves to another stage
lead.assigned A lead gets a new owner
campaign.completed A campaign finishes sending
import.completed An import job finishes
integration.needs_reconnect An integration login expired and needs reconnecting

What Leadnote sends

Each delivery is a POST with a JSON body:

{
  "id": "DELIVERY_ID",
  "event": "lead.created",
  "createdAt": "2026-10-29T10:00:00.000Z",
  "data": { "id": "LEAD_ID", "listId": "LIST_ID", "firstName": "Asha", "email": "asha@example.com", "phone": "+919876543210", "source": "Enquiry form" }
}

The data object depends on the event. Event data holds ids and the changed values, not the whole lead. Read the full lead with the public API if you need more. See the public API for developers.

Header Meaning
X-Leadnote-Event The event name
X-Leadnote-Delivery The delivery id. It is the same on every retry, so use it to ignore duplicates.
X-Leadnote-Timestamp Unix seconds when the delivery was signed
X-Leadnote-Signature v1= followed by the hex HMAC-SHA256 signature
X-Leadnote-Signature-Previous Only while a rotated secret is still in its grace period
X-Leadnote-Replay-Of Only on a replay: the id of the original delivery

Verify the signature

The signature is the HMAC-SHA256 of the text timestamp.body, made with your webhook secret. In Node.js:

import { createHmac, timingSafeEqual } from 'node:crypto';

function isValid(secret, timestamp, rawBody, signature) {
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false; // older than 5 minutes
  const expected = 'v1=' + createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex');
  const a = Buffer.from(expected), b = Buffer.from(signature || '');
  return a.length === b.length && timingSafeEqual(a, b);
}

Follow these rules:

  • Compute the signature over the raw bytes you received, never over re-serialised JSON.
  • Compare in constant time.
  • Reject a delivery that is more than 5 minutes old.
  • Ignore a delivery id you have already processed.

Retries and dead deliveries

Answer with any 2xx status within 8 seconds to accept a delivery. Leadnote does not follow redirects. If your server fails, answers with another status or times out, Leadnote retries after 1 minute, 5 minutes, 30 minutes and 2 hours. After the fifth attempt the delivery is marked Dead.

A delivery shows one of four statuses: Pending, Retrying, Delivered or Dead.

Delivery log, Retry and Replay

Choose Deliveries on a webhook to see each delivery with its event, status, attempts, response and time. Filter by event and status. Open one to see the payload that was sent.

  • Send test sends a sample lead.created event through the real queue and shows the result.
  • Retry tries the same delivery again now. It keeps its id.
  • Replay sends the same event and payload as a new delivery with a new id. Use it when your server already handled or refused the original for good.

Rotate the signing secret

  1. Choose Rotate secret in the row menu.
  2. Set the Grace period (hours), from 0 to 168. The default is 24. At 0 the old secret stops immediately.
  3. Copy the new secret. It is shown once and used at once.

During the grace period every delivery carries two signatures, X-Leadnote-Signature with the new secret and X-Leadnote-Signature-Previous with the old one. Accept either while you deploy the new secret.

Frequently asked questions

What does my server have to answer?

Any 2xx response within 8 seconds accepts the delivery. Anything else, or a timeout, counts as a failure and Leadnote retries.

How often does Leadnote retry?

After 1 minute, 5 minutes, 30 minutes and 2 hours. That is 5 attempts in total, and then the delivery is marked Dead.

What is the difference between Retry and Replay?

Retry attempts the same delivery again and keeps its id. Replay sends the same event as a new delivery with a new id and puts the original id in the X-Leadnote-Replay-Of header.

Can I point a webhook at localhost?

No. Webhooks can only call public internet addresses over http or https. Private, local and metadata addresses are refused.