Skip to content

Webhooks overview

Send Chain sends outbound, signed HTTP POST notifications for events on your account — payment lifecycle, wishlist funding, and prepaid-balance top-ups. Register an endpoint and choose which event types it receives from your dashboard’s Settings → Webhooks screen.

Every delivery is a JSON body shaped like:

{
"id": "evt_5f3c1e7b9a4d4e8a9c6f0b1a2d3e4f5a",
"type": "payment.completed",
"createdAt": "2026-09-13T00:00:00Z",
"data": { "...": "one of the event-specific shapes below" }
}

id is unique per delivery attempt group — use it to deduplicate, since delivery is at-least-once (a retried delivery reuses the same id).

Header Meaning
Tribute-Signature t=<unix seconds>,v1=<hex HMAC-SHA256> — see Verifying below. During a secret rotation’s rollover window, two v1= values may be present; either matching your secret verifies the request.
Tribute-Event-Id Same value as the body’s id, for convenience when you only need headers.

The signed payload is "<t>.<raw request body>", HMAC-SHA256’d with your endpoint’s signing secret (shown once at creation), hex-encoded. Always verify against the raw body bytes, before any JSON parsing, and reject timestamps outside a reasonable tolerance (5 minutes is a sane default) to guard against replay.

Terminal window
# Illustrative — verification happens in your receiver's code, not on the
# command line. Given a received body $BODY and header
# "Tribute-Signature: t=1700000000,v1=…":
TIMESTAMP="1700000000"
SIGNED_PAYLOAD="${TIMESTAMP}.${BODY}"
EXPECTED=$(printf '%s' "$SIGNED_PAYLOAD" | openssl dgst -sha256 -hmac "$ENDPOINT_SECRET" | sed 's/^.* //')
echo "expected v1=$EXPECTED"

A non-2xx response (or timeout) is retried up to six times on exponential backoff. Every delivery attempt is recorded and visible in your dashboard’s webhook log, where you can also manually redeliver a past event. An endpoint that fails persistently is auto-paused; resuming it re-queues everything from the outage window.