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
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 Unauthorizedand 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-Timestampis significantly older than the current time (for example, more than five minutes). - Rotate secrets periodically. Use
POST /api/account/secret/regenerateto rotate your secret and update your stored value promptly.