Webhook Keluar

Menerima callback status pengiriman di server Anda dengan tanda tangan HMAC.

#Event & Payload

Berlangganan di Console → Settings → Webhooks: isi URL https, pilih event, lalu salin signing secret (hanya tampil sekali).

EventDikirim saat
message.sentPesan diterima provider channel
message.deliveredPesan sampai ke penerima
message.readPesan dibaca
message.failedPengiriman gagal permanen
execution.completedWorkflow selesai (COMPLETED atau PARTIAL)
execution.failedSemua pengiriman gagal
Body
{
  "id": "evt_k3p1q9z8m2x7c4v6b0n5",
  "type": "message.failed",
  "created_at": "2026-10-27T10:31:31+00:00",
  "data": { "message_id": "01m5…", "execution_id": "01m5…", "channel": "WHATSAPP", "status": "FAILED", "error_code": "http_400" }
}

Header: X-Notifora-Event, X-Notifora-Delivery (ID pengiriman, berguna sebagai kunci dedup), X-Notifora-Signature. Respons dengan status 2xx dalam 10 detik dianggap sukses. Redirect tidak diikuti.

#Verifikasi Signature

Header X-Notifora-Signature: t=<unix>,v1=<hex> berisi HMAC-SHA256 dari string "{t}.{body mentah}" memakai signing secret Anda. Verifikasi body mentah (sebelum di-parse) dan tolak timestamp lebih dari 5 menit.

php
function verifyNotifora(string $rawBody, string $header, string $secret, int $tolerance = 300): bool
{
    parse_str(str_replace(',', '&', $header), $p);          // t=...&v1=...
    if (empty($p['t']) || empty($p['v1']) || abs(time() - (int) $p['t']) > $tolerance) {
        return false;
    }
    $expected = hash_hmac('sha256', $p['t'].'.'.$rawBody, $secret);
    return hash_equals($expected, $p['v1']);
}

// Laravel: $request->getContent() adalah body mentah
abort_unless(verifyNotifora($request->getContent(), $request->header('X-Notifora-Signature', ''), config('services.notifora.webhook_secret')), 401);
javascript
import crypto from 'node:crypto';

export function verifyNotifora(rawBody, header, secret, tolerance = 300) {
  const p = Object.fromEntries(header.split(',').map((kv) => kv.split('=')));
  if (!p.t || !p.v1 || Math.abs(Date.now() / 1000 - Number(p.t)) > tolerance) return false;
  const expected = crypto.createHmac('sha256', secret).update(`${p.t}.${rawBody}`).digest('hex');
  const a = Buffer.from(expected), b = Buffer.from(p.v1);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// Express: gunakan express.raw({ type: 'application/json' }) agar req.body adalah Buffer mentah
python
import hmac, hashlib, time

def verify_notifora(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
    p = dict(kv.split("=", 1) for kv in header.split(","))
    if "t" not in p or "v1" not in p or abs(time.time() - int(p["t"])) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{p['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, p["v1"])

#Retry & Penonaktifan Otomatis

Jika endpoint Anda tidak membalas 2xx, pengiriman diulang dengan jadwal: 1 menit, 5 menit, 30 menit, 2 jam, 6 jam, 24 jam. Setelah itu status pengiriman menjadi failed.

  • Bila gagal beruntun mencapai 50, webhook dinonaktifkan otomatis dan admin workspace menerima email.
  • Aktifkan kembali dan kirim ulang pengiriman tertentu dari Console → Settings → Webhooks (tombol “Kirim ulang”).
  • Keamanan: URL harus https. Host yang mengarah ke alamat privat/loopback/metadata ditolak (proteksi SSRF) dan DNS di-pin saat pengiriman.
Notifora Engineering Knowledge Base · Terakhir diperbarui: Oktober 2026 · Rilis v1.0 Kembali ke atas ↑

© 2026 notifora. All rights reserved. Created by notifora