Webhooks
Konektor webhooks are sent asynchronously when lead changes occur. Delivery uses queue-based dispatch, so you should assume at-least-once delivery semantics.
Webhook Headers
Each webhook request includes:
Content-Type: application/jsonX-Konektor-Signature: t=<unix_timestamp>,v1=<hex_hmac_sha256>X-Konektor-Event: <event_name>User-Agent: Konektor-Webhook/1.0
Emitted Events
Lead flow currently emits:
lead.createdlead.updated
The HTTP body contains the event payload directly, without an extra wrapper.
lead.created Example
{
"lead": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"uniqueCode": "API_1A2B3C4D",
"externalRef": "crm-001",
"firstName": "John",
"email": "john@example.com",
"phone": "6281234567890",
"status": "new",
"priority": "medium",
"city": null,
"country": null
},
"source": "api"
}
lead.updated Example
{
"lead": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"uniqueCode": "API_1A2B3C4D",
"status": "qualified"
},
"leadId": "550e8400-e29b-41d4-a716-446655440000",
"previousStatus": "new",
"newStatus": "qualified",
"changes": ["status"],
"source": "api"
}
Signature Verification (Timing-Safe)
Always verify using the raw request body. Do not re-stringify parsed JSON before hashing.
import crypto from 'node:crypto'
function verifyKonektorSignature(rawBody, signatureHeader, secret) {
const parts = signatureHeader.split(',')
const timestamp = parts.find(p => p.startsWith('t='))?.slice(2)
const signature = parts.find(p => p.startsWith('v1='))?.slice(3)
if (!timestamp || !signature) return false
const now = Math.floor(Date.now() / 1000)
if (Math.abs(now - Number(timestamp)) > 300) return false
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex')
const providedBuf = Buffer.from(signature, 'hex')
const expectedBuf = Buffer.from(expected, 'hex')
if (providedBuf.length !== expectedBuf.length) return false
return crypto.timingSafeEqual(providedBuf, expectedBuf)
}
Idempotency Requirements
Because queue retries can resend events, your receiver must be idempotent:
- Store an internal event key (for example
leadId + updatedAt + event). - Ignore duplicate events that already completed.
- Return
2xxfor valid duplicates to stop further retries.
Timeout and Receiver Behavior
Konektor sends webhook requests with a short timeout (5s). A reliable receiver should:
- Verify signature.
- Enqueue heavy processing internally.
- Respond
200 OKquickly.
Security Notes
- Store webhook secrets in server-side secret storage.
- Rotate secrets on a fixed schedule.
- Reject missing or invalid signature headers.
- Apply infrastructure-level IP allowlists if required by your environment.
Need More Help?
Our team is ready to help you maximize ad tracking and business attribution.
Email Supportsupport@konektor.id
YouTubeYouTube
© 2026 Konektor. All rights reserved.
