Skip to main content
Every webhook delivery Lusha sends includes a cryptographic signature you can use to confirm the request genuinely came from Lusha. Verifying signatures before processing any payload protects your endpoint from spoofed or replayed requests.

How signatures work

Lusha signs each delivery using HMAC-SHA256 with your account webhook secret as the key. Two signature-related headers are included in every request, alongside standard delivery headers: Every delivery also includes Content-Type: application/json and User-Agent: Lusha-Webhooks/1.0. The signed payload is formed by concatenating the timestamp, a period, and the JSON-serialized request body:

Step-by-step verification

1

Extract the headers

Read X-Lusha-Signature and X-Lusha-Timestamp from the incoming request headers.
2

Build the signed payload string

Concatenate the raw timestamp value, a literal ., and the JSON-serialized request body:
3

Compute the expected signature

Calculate an HMAC-SHA256 digest of the signed payload using your account webhook secret as the key, then encode the result as a hex string.
4

Compare signatures

Use a timing-safe comparison to check whether the computed signature matches the value in X-Lusha-Signature. Reject the request if they differ.

Verification example

Always use a timing-safe comparison such as crypto.timingSafeEqual. Standard string equality is vulnerable to timing attacks.

Account secret management

Your account webhook secret is the key used to sign and verify all deliveries. When you regenerate the secret:
  • The new secret immediately invalidates the old one across all subscriptions
  • The secret is returned only once in the response - store it in your secrets manager before the response is gone
  • If no secret existed, a new one is created automatically
An account secret must exist before Lusha can deliver webhooks. Call POST /api/account/secret/regenerate as the first step when setting up webhooks.

Security best practices

  • Store the secret securely. Use a secrets manager (for example, AWS Secrets Manager, HashiCorp Vault, or environment variables injected at runtime). Never commit the secret to source control.
  • Verify every request. Check the signature on every incoming delivery, not just during initial setup.
  • Reject invalid signatures immediately. Return 401 Unauthorized and do not process the payload.
  • Use HTTPS endpoints. Lusha requires HTTPS for production webhook URLs. This protects the headers and payload in transit.
  • Check the timestamp. To prevent replay attacks, reject deliveries where X-Lusha-Timestamp is significantly older than the current time (for example, more than five minutes).
  • Rotate secrets periodically. Use POST /api/account/secret/regenerate to rotate your secret and update your stored value promptly.