Webhooks
Receive, verify and retry event deliveries.
Webhooks push platform events to your own HTTPS endpoint as they happen, so you don't have to poll for state changes.
Endpoints
Manage endpoints via /v1/webhook-endpoints — create, list, fetch, update, delete,
and rotate the signing secret. Two policies are enforced on every endpoint URL:
- HTTPS only. Plain-
http://URLs are rejected at registration time. - No redirects, 10-second timeout. Delivery attempts don't follow
3xxresponses — a redirect counts as a failed attempt, the same as a non-2xxstatus or a timeout.
The signing secret is returned exactly once: on creation, and again on each rotation. During a rotation window the previous secret stays valid alongside the new one, so in-flight verification doesn't break.
curl -X POST https://api.rigid.fi/v1/webhook-endpoints \
-H "Authorization: Bearer $RIGID_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"url": "https://example.com/webhooks/rigid",
"event_types": ["card.created", "authorization.decided", "cardholder.updated"]
}'Reference: Create a webhook endpoint.
Verifying signatures
Every delivery carries an X-Platform-Signature header:
X-Platform-Signature: t=1610000000,v1=<hex hmac-sha256>t is the Unix timestamp the delivery was signed at. Each v1 is the hex
HMAC-SHA256 of `${t}.${rawBody}` (the exact bytes of the delivered body, not
a re-serialization), keyed by one of the endpoint's active secrets. During a
secret rotation you'll see two v1 values — accept the delivery if any of
them matches.
const crypto = require("node:crypto");
function verifySignature(secret, rawBody, header, toleranceSeconds = 300) {
const parts = header.split(",").map((p) => p.trim());
let t;
const signatures = [];
for (const part of parts) {
const eq = part.indexOf("=");
if (eq === -1) continue;
const scheme = part.slice(0, eq);
const value = part.slice(eq + 1);
if (scheme === "t") t = Number(value);
else if (scheme === "v1" && value !== "") signatures.push(value);
}
if (t === undefined || signatures.length === 0) return false;
if (Math.abs(Math.floor(Date.now() / 1000) - t) > toleranceSeconds) return false;
const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const expectedBuf = Buffer.from(expected, "hex");
return signatures.some((candidate) => {
const candidateBuf = Buffer.from(candidate, "hex");
return (
candidateBuf.length === expectedBuf.length &&
crypto.timingSafeEqual(candidateBuf, expectedBuf)
);
});
}Compute the HMAC over the raw request body — parse it for your own use only after verification, since re-serializing JSON can change the byte sequence the signature was computed over.
Retries
A delivery gets one immediate attempt, then up to five retries at fixed offsets from that first attempt: 1 minute, 5 minutes, 30 minutes, 2 hours, and 24 hours. If the final retry still fails, the platform stops attempting that delivery — it does not keep retrying indefinitely, and there is no webhook event delivered to notify you of the final failure. Check delivery status through the event log and use redelivery to retry manually.
Event catalog
Every delivery is wrapped in the same envelope:
{
"id": "evt_01hz...",
"type": "card.created",
"created_at": "2026-08-07T12:00:00Z",
"data": { "...": "event-specific payload" }
}See the full event catalog for every event type you can
subscribe to and the payload shape of each. A handful of catalogued types are
marked planned rather than live — they're a committed contract (schema and
docs are final) but no producer emits them yet, so subscribing to one is safe but
will never deliver until it ships; each type's own page states which it is.
authorization.decided's decline_reason field is a closed vocabulary — see the
Decline reasons guide for every value it can
carry and safe copy to show a customer for each.
Redelivery
Trigger a fresh delivery attempt for a past event to a given endpoint:
curl -X POST https://api.rigid.fi/v1/events/{id}/redeliver \
-H "Authorization: Bearer $RIGID_API_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{ "endpoint_id": "<endpoint-id>" }'Reference: Redeliver an event.