ReplySparrow Docs

Webhooks

Receive lead and reply notifications, and verify their signatures.

ReplySparrow can send real-time notifications when your agents qualify a new lead or a lead replies, to the webhook URLs you configure.

How to configure webhooks

  1. Log in to your ReplySparrow account at https://app.replysparrow.com
  2. Navigate to the Integrations page at https://app.replysparrow.com/integrations
  3. Add a Webhook integration by clicking the Webhook option
  4. Enter your webhook URL and pick its trigger: On Lead Created or On Lead Reply. Add another webhook to send each trigger to a different URL.
  5. Turn on "Automatically send webhooks for new contacts" if you use On Lead Created
  6. Save the configuration

Once configured, ReplySparrow sends POST requests to your webhook URLs whenever:

  • A new lead is created: one of your agents qualifies a lead (lead.created)
  • A lead replies on LinkedIn or by email (lead.replied)

Webhook URLs must be public http(s) addresses. Sync all qualified leads on the integration sends every lead your agents have qualified, not only new ones.

Payload

The body is JSON with the event, when it was sent, and the lead's data:

{
  "event": "lead.created",
  "sent_at": "2026-10-24T09:12:44.000Z",
  "data": {
    "lead": {
      "id": "8f1c2c3e-5b7a-4a51-9d0e-2b6f8f6d9c11",
      "first_name": "John",
      "last_name": "Doe",
      "full_name": "John Doe",
      "email": "john.doe@acme.com",
      "title": "Head of Sales",
      "headline": "Head of Sales at Acme Inc",
      "company": "Acme Inc",
      "company_domain": "acme.com",
      "linkedin_url": "https://www.linkedin.com/in/johndoe",
      "phone": null,
      "location": "Paris, France",
      "lead_score": 82,
      "agent": "VP Sales in US SaaS"
    }
  }
}

A lead.replied request also carries the reply next to the lead:

"reply": {
  "id": "b2d7…",
  "channel": "linkedin",
  "message": "Thanks, happy to chat next week.",
  "subject": null,
  "received_at": "2026-10-24 09:10:02",
  "teammate": "Jane Smith"
}

Each webhook request includes the headers x-kairo-event (the event name) and x-kairo-timestamp. Answer with a 2xx status. A 5xx or 429 answer, or no answer, is retried with backoff (up to 6 attempts); other 4xx answers are not retried.

Verifying webhook signatures (optional)

You can configure a signing secret on your Webhook integration (Generate creates one). When a secret is set, every webhook request also includes:

  • x-kairo-timestamp: the Unix timestamp (in seconds) at which the request was sent
  • x-kairo-signature: sha256= followed by the hex-encoded HMAC-SHA256 of {timestamp}.{rawBody} computed with your signing secret

To verify a request:

  1. Read the raw request body as a string (do not re-serialize parsed JSON).
  2. Concatenate the value of x-kairo-timestamp, a . character, and the raw body.
  3. Compute the HMAC-SHA256 of that string using your signing secret, hex-encoded, and prefix it with sha256=.
  4. Compare it to x-kairo-signature using a constant-time comparison.
  5. Reject requests whose timestamp is too old (we recommend a 5 minute tolerance) to prevent replay attacks.

Example in Node.js:

const crypto = require('crypto');

function verifyKairoSignature(rawBody, headers, secret) {
  const timestamp = headers['x-kairo-timestamp'];
  const signature = headers['x-kairo-signature'];
  if (!timestamp || !signature) return false;
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(timestamp + '.' + rawBody).digest('hex');
  return expected.length === signature.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}

If no signing secret is configured, the x-kairo-signature header is not sent.

All workspace events

To receive every workspace event (contact.created, signal.received, reply.classified, meeting.booked, email.unsubscribed and more), add an endpoint under Platform → Signed webhooks instead. Those requests are always signed: they carry x-linki-event, x-linki-timestamp and x-linki-signature, verified the same way with the endpoint's secret, and failed deliveries are retried with backoff for up to eight attempts.

On this page