Developers

Webhooks

Events by HTTPS POST, ids only, signed with HMAC-SHA256 and retried for 24 hours.

Endpoints

A reader adds an endpoint with POST /v1/reader/webhooks, a platform with POST /v1/connect/webhooks; https only. The answer holds the signing secret once: keep it in your secret store.

A body holds ids only (event_type, the ids, severity, occurred_at): never a name, a finding or personal data. Use the ids to fetch the detail, signed in.

Check the signature first

Each delivery carries KaribuID-Signature: t=<unix seconds>,v1=<hex>. Decode your secret (it is given base64-encoded), compute HMAC-SHA256 with it over t, a full stop and the raw body, compare it with v1 in constant time, and refuse a t more than 300 seconds from your clock.

KaribuID-Delivery identifies the delivery: deliveries may repeat, so handle each id once.

Retries

Answer 2xx quickly. A failed delivery is retried with exponential backoff for 24 hours, then held for Karibu ID staff to replay. Deliveries stop for a revoked grant and a suspended platform.

Checking a delivery (Node.js)

import { createHmac, timingSafeEqual } from "node:crypto";

/** True when the delivery is Karibu ID's: check this before anything else. */
export function verifyDelivery(rawBody: string, header: string, secretBase64: string): boolean {
  const parts = Object.fromEntries(header.split(",").map((p) => p.trim().split("=")));
  const t = Number(parts.t);
  if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > 300) return false;
  const key = Buffer.from(secretBase64, "base64"); // the secret is given base64-encoded
  const expected = createHmac("sha256", key).update(`${parts.t}.${rawBody}`).digest("hex");
  const given = Buffer.from(String(parts.v1 ?? ""), "hex");
  const wanted = Buffer.from(expected, "hex");
  return given.length === wanted.length && timingSafeEqual(given, wanted);
}

Every event your reader endpoints can receive, with a sample body and the exact bytes a delivery signs, is listed in the webhook catalogue (GET /v1/reader/webhooks/catalogue), in your workspace under Webhooks and API.

Open Webhooks and API