Webhooks

Webhook Konektor mengirim event secara asynchronous ketika perubahan lead terjadi. Delivery menggunakan queue, sehingga integrasi Anda harus mengasumsikan model at-least-once delivery.

Header Webhook

Setiap request webhook menyertakan header:

  1. Content-Type: application/json
  2. X-Konektor-Signature: t=<unix_timestamp>,v1=<hex_hmac_sha256>
  3. X-Konektor-Event: <event_name>
  4. User-Agent: Konektor-Webhook/1.0

Event yang Dikirim

Event utama pada flow lead:

  1. lead.created
  2. lead.updated

Payload body berisi objek event langsung (bukan envelope tambahan).

Contoh lead.created

{
  "lead": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "uniqueCode": "API_1A2B3C4D",
    "externalRef": "crm-001",
    "firstName": "Budi",
    "email": "budi@example.com",
    "phone": "6281234567890",
    "status": "new",
    "priority": "medium",
    "city": null,
    "country": null
  },
  "source": "api"
}

Contoh lead.updated

{
  "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"
}

Event Inbox

Selain event lead di atas, Inbox mengirim empat event lewat webhook yang sama:

  1. inbox.message.received
  2. inbox.message.sent
  3. inbox.message.status
  4. inbox.conversation.owner_changed

Body event Inbox membungkus payload, berbeda dari event lead di atas yang mengirim payload langsung:

{
  "event": "inbox.message.received",
  "payload": { "...": "isi event" }
}

Header webhook, verifikasi signature, dan aturan idempotensi pada halaman ini berlaku sama untuk event Inbox. Contoh payload lengkap keempat event ada di Agent Inbox API.

Verifikasi Signature (Timing-Safe)

Gunakan raw body request saat menghitung HMAC. Jangan pakai body yang sudah di-parse lalu di-stringify ulang.

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)
}

Idempotensi

Webhook dikirim via queue dan bisa terkirim ulang saat retry. Endpoint Anda harus idempotent:

  1. Simpan event key internal (misalnya kombinasi leadId + updatedAt + event).
  2. Abaikan event duplikat yang sudah diproses.
  3. Selalu balas 2xx jika event valid sudah pernah diproses.

Timeout dan Respons

Konektor mengirim webhook dengan timeout request singkat (5s). Endpoint receiver sebaiknya:

  1. Validasi signature.
  2. Enqueue pekerjaan berat ke worker internal.
  3. Segera balas 200 OK.

Catatan Keamanan

  1. Simpan webhook secret di server-side secret manager.
  2. Rotasi secret secara berkala.
  3. Tolak request tanpa header signature valid.
  4. Terapkan allowlist IP jika infrastruktur Anda membutuhkannya.

Langkah berikutnya

Butuh Bantuan Lebih Lanjut?

Tim kami siap membantu Anda memaksimalkan tracking iklan dan atribusi bisnis.

© 2026 Konektor. Seluruh hak cipta dilindungi.