Cara HubSpot mengirim webhook

Satu batas waktu 5 detik mencakup batch berisi hingga 100 notifikasi, dan eventId didokumentasikan sebagai tidak dijamin unik. Signature v3 dan verifier Node.

Perilaku pengiriman

Diambil dari dokumentasi resmi vendor, terakhir diperiksa 2026-08-06. Jika vendor tidak menyebut angka, tabel ini juga tidak mencantumkannya.

Batas waktu respons5 detik

Berlaku untuk seluruh batch, yang dapat berisi hingga 100 notifikasi

Periksa apakah handler Anda menjawab tepat waktu

Percobaan ulangHingga 10 upaya yang tersebar selama 24 jam
Berhenti mencobatidak dipublikasikan vendor
Sumberhttps://developers.hubspot.com/docs/api-reference/latest/webhooks/guide

Tanda tangan

Diverifikasi dengan verifier yang berfungsi dan dibuktikan oleh test suite, bukan dibaca dari dokumentasi. Terakhir diverifikasi 2026-08-20.

AlgoritmaHMAC-SHA256
Payload bertanda tanganPOST{decodedUrl}{body}{timestamp}
Encodingbase64
Headerx-hubspot-signature-v3
Toleransi5 menit

Verifikasi

Raw body dari permintaan, byte demi byte, sebelum parsing JSON apa pun. Setiap skema di halaman ini rusak begitu framework melakukan serialisasi ulang pada payload.

const crypto = require("node:crypto");

// v3: base64(HMAC-SHA256(secret, "POST" + url + body + timestamp))
const ts = req.headers["x-hubspot-request-timestamp"];
if (Math.abs(Date.now() - Number(ts)) > 300_000) throw new Error("stale");

const expected = crypto
  .createHmac("sha256", clientSecret) // the app's client secret
  .update("POST" + fullUrl + rawBody + ts)
  .digest("base64");
const received = Buffer.from(req.headers["x-hubspot-signature-v3"] ?? "");
const wanted = Buffer.from(expected);
// timingSafeEqual throws on a length mismatch, so check that first.
const valid =
  received.length === wanted.length && crypto.timingSafeEqual(received, wanted);

fullUrl adalah URL publik persis yang dipanggil HubSpot, termasuk query string, setelah URL-decoding. Di belakang proxy yang menulis ulang header Host, susun ulang URL itu dari header forwarded, atau tanda tangannya tidak akan pernah cocok.

Yang sering menjebak

Batas waktu 5 detik berlaku per permintaan, dan satu permintaan dapat membawa batch berisi hingga 100 notifikasi. Jika semuanya diproses inline, batas waktu Anda yang sebenarnya adalah 50ms per notifikasi.

HubSpot mendokumentasikan eventId-nya sebagai tidak dijamin unik dan tidak menjanjikan urutan, jadi kebiasaan dari Stripe untuk deduplikasi berdasarkan event id tidak berlaku di sini.

Baca juga

AnyHook berada di depan endpoint yang menerima webhook dari HubSpot: AnyHook menjawab dalam sekitar satu detik, mencoba ulang sesuai jadwalnya sendiri saat server Anda mati, dan menyimpan setiap event agar dapat diputar ulang (replay). Ganti satu URL, kode Anda tetap; agar percobaan ulang dan putar ulang diterima, periksa AnyHook-Signature, karena tanda tangan milik HubSpot kedaluwarsa setelah 5 menit.

Cara kerjanya →