Webhook & Event Pengiriman

Hubina mengirim setiap perubahan status pengiriman ke endpoint HTTPS milik Anda sebagai POST JSON yang ditandatangani. Halaman ini menjelaskan cara mendaftarkan endpoint, daftar event, format payload, verifikasi tanda tangan, kebijakan percobaan ulang, dan bagaimana Hubina sendiri menerima laporan dari penyedia.

Mendaftarkan endpoint

  1. Buka Dashboard → Webhooks.
  2. Isi Nama endpoint dan URL endpoint — wajib HTTPS dan alamat publik.
  3. Pilih tipe event yang ingin diterima, lalu simpan. Signing secret ditampilkan satu kali; salin dan simpan di server Anda.

Setiap endpoint memiliki tombol Kirim tes (mengirim event webhook.test dan langsung menampilkan hasil HTTP-nya), Riwayat (10 percobaan terakhir), serta aksi nonaktifkan/aktifkan, rotasi secret, dan hapus. Endpoint yang nonaktif tidak menerima event apa pun. Maksimal 10 endpoint per akun.

URL harus alamat publik Permintaan dikirim dari server Hubina, jadi URL yang menunjuk ke alamat privat, loopback, atau link-local (localhost, 10.x, 192.168.x, 169.254.x, dan sejenisnya), memakai HTTP, atau memuat kredensial ditolak saat pendaftaran.

Tipe event

Pilih satu atau beberapa tipe; memilih semuanya berarti endpoint menerima seluruh laporan status pengiriman.

EventKapan dikirim
message.acceptedPenyedia menerima tanggung jawab atas pesan. Bukan berarti pesan sudah sampai.
message.deliveredPesan diterima server tujuan.
message.failedKegagalan sementara, misalnya mailbox penuh atau penundaan di sisi penerima.
message.bouncedBounce permanen: alamat tujuan tidak ada atau menolak secara permanen.
message.rejectedPenyedia menolak pesan sebelum menerimanya.
message.complainedPenerima menandai pesan sebagai spam.
webhook.testEvent uji dari tombol Kirim tes; selalu dikirim tanpa memandang pilihan tipe.

Format payload

POST ke URL endpoint
{
  "id": "whd_9f2c1d7a4b6e8f0a1c2d3e4f5a6b7c8d",
  "type": "message.delivered",
  "created_at": "2026-10-16T10:12:44.382Z",
  "data": {
    "message_id": "msg_1a2b3c4d5e6f708192a3b4c5d6e7f809",
    "status": "delivered",
    "recipient": "[email protected]",
    "from": "[email protected]",
    "to": ["[email protected]"],
    "subject": "Struk pembayaran",
    "severity": null,
    "reason": null,
    "provider_event_id": "evt-9f2c1d7a",
    "occurred_at": "2026-10-16T10:12:44.000Z",
    "test": false
  }
}
HeaderIsi
Hubina-EventTipe event, misalnya message.delivered.
Hubina-DeliveryID percobaan pengiriman, sama dengan id di payload — pakai untuk deduplikasi.
Hubina-TimestampWaktu tanda tangan dibuat (detik Unix).
Hubina-Signaturet=<timestamp>,v1=<hmac>.

Isi pesan (teks/HTML) tidak pernah dikirim ke webhook dan tidak disimpan Hubina — payload hanya membawa metadata rute dan status.

Verifikasi tanda tangan

Tanda tangan adalah HMAC-SHA256 dari {timestamp}.{raw body} memakai signing secret endpoint. Bandingkan dengan perbandingan waktu-tetap, dan hitung atas raw body yang diterima (bukan hasil parsing ulang), karena urutan kunci dapat berubah.

verifikasi (Node.js)
import crypto from 'node:crypto';

function verifyWebhook(rawBody, headers, signingSecret) {
  const header = headers['hubina-signature'] || '';
  const parts = Object.fromEntries(header.split(',').map((part) => part.split('=')));
  if (!parts.t || !parts.v1) return false;
  const expected = crypto
    .createHmac('sha256', signingSecret)
    .update(`${parts.t}.${rawBody}`)
    .digest('hex');
  const given = Buffer.from(parts.v1);
  const wanted = Buffer.from(expected);
  return given.length === wanted.length && crypto.timingSafeEqual(given, wanted);
}
  • Tolak yang basi. Tanda tangan yang lebih tua dari 5 menit sebaiknya ditolak; event yang benar-benar hilang tetap dapat dikirim ulang oleh Hubina.
  • Deduplikasi. Gunakan header Hubina-Delivery (atau data.message_id + type) supaya percobaan ulang tidak diproses dua kali.
  • Balas cepat. Cukup balas 2xx setelah event disimpan; pekerjaan berat sebaiknya dilakukan asinkron.

Percobaan ulang dan penonaktifan

  • Balasan 2xx berarti selesai. Semua balasan lain, redirect, timeout 10 detik, atau kegagalan koneksi dihitung sebagai gagal.
  • Percobaan ulang mengikuti jeda bertingkat: 30 detik, 2 menit, 10 menit, 30 menit, 2 jam, 6 jam, 12 jam, lalu 24 jam — delapan percobaan, setelah itu percobaan ditandai gagal permanen dan alasannya tersimpan di riwayat.
  • Setelah 15 kegagalan berurutan, endpoint dinonaktifkan otomatis agar antrean tidak tumbuh tanpa batas. Aktifkan kembali dari dashboard setelah penerima diperbaiki; penghitung kegagalan direset saat itu.
  • Riwayat percobaan disimpan 30 hari, dan setiap baris menampilkan kode HTTP, waktu, jumlah percobaan, serta pesan error penerima.

Alur internal: laporan dari penyedia

Endpoint webhook pelanggan di atas adalah jalur keluar. Jalur masuk tetap sama seperti sebelumnya: penyedia mengirim laporan pengiriman ke Hubina, dan Hubina yang meneruskannya.

endpoint penerima event
POST https://api.hubina.net/v1/hooks/mailgun

Endpoint ini menerima laporan dari penyedia pengiriman (bukan dari aplikasi Anda), memverifikasi keasliannya, lalu mencatatnya ke pesan yang sesuai. Selain jalur push ini, job sinkronisasi berjalansetiap 5 menit untuk menarik ulang event yang gagal terkirim, sehingga event yang terlewat tetap tercatat dan diteruskan ke webhook Anda.

StatusKondisiIsi
200Payload valid dan diproses{ "status": "ok", "received": n, "recorded": n, "duplicates": n, "unmatched": n }
400Payload tidak memuat event yang bisa diprosesinvalid_request
401Signature tidak valid atau kedaluwarsainvalid_signature / stale_timestamp
429Melebihi batas 600 permintaan per menit per alamat IPrate_limited
503Signing key penyedia belum dikonfigurasiwebhook_not_configured
  • Dua bentuk amplop. Payload modern (event-data sebagai objek maupun array) dan form legacy sama-sama diterima.
  • Deduplikasi. Setiap event penyedia dikunci oleh ID event (atau digest deterministik bila tidak ada), jadi percobaan ulang tidak pernah menggandakan riwayat atau tagihan.
  • Status monoton. Status pesan hanya bergerak maju: accepted yang telat tidak menurunkan delivered, dan complained tetap yang terkuat.
  • Satu sumber kebenaran. Setiap event masuk ke timeline pesan sebelum diteruskan, sehingga Sending & Logs dan webhook Anda menceritakan hal yang sama.

Di halaman ini