Developer documentation
Webhooks
Receive material credit changes with signature verification, replay protection and bounded retries.
Create a subscription
POST /webhooks accepts an HTTPS URL and one or more event names. Material events currently emitted by account reporting are credit.default.reported and credit.delinquency.reported. rcn.test is returned by the test endpoint for verifier checks.
{
"url": "https://lender.example/webhooks/rcn",
"events": ["credit.default.reported", "credit.delinquency.reported"]
}Delivery format
| Header | Meaning |
|---|---|
| RCN-Timestamp | Unix timestamp used in the signature |
| RCN-Event-ID | Stable identifier for deduplication |
| RCN-Signature | HMAC signature over timestamp and canonical payload |
| Content-Type | application/json |
Respond with any 2xx status only after the event is durably accepted. The sender uses a ten-second timeout and does not follow redirects.
Verify before processing
- Parse the JSON, then serialize it with keys sorted, no insignificant spaces and UTF-8 encoding—the canonical form used by RCN.
- Reject stale timestamps according to your replay window, normally five minutes.
- Build the signed value as {timestamp}.{canonical_json}.
- Compute its HMAC-SHA256 with the subscription secret and prefix the lowercase hexadecimal digest with v1=.
- Compare signatures in constant time.
- Deduplicate on RCN-Event-ID in durable storage.
- Queue the verified event, return 2xx, and process business effects asynchronously.
import hashlib, hmac, json, time
def verify_rcn(payload: dict, timestamp: str, signature: str, secret: str) -> bool:
if abs(time.time() - int(timestamp)) > 300:
return False
canonical = json.dumps(payload, separators=(",", ":"), sort_keys=True)
signed = f"{timestamp}.{canonical}".encode()
expected = "v1=" + hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)Test first
POST /webhooks/{webhook_id}/test returns a representative payload and signed headers. Use it to validate your verifier before enabling business effects.
Retries and recovery
Non-2xx responses, timeouts and transport failures are retried with bounded exponential backoff. Automated delivery stops after eight failed attempts; backoff is capped at one hour.
- GET /webhooks/{webhook_id}/deliveries returns the latest 100 delivery records.
- POST /webhooks/deliveries/{delivery_id}/retry requeues an eligible delivery; a delivery at the maximum attempt count returns 409.
- Rotate the signing secret when exposure is suspected. The current rotation is immediate, so coordinate receiver configuration carefully.
- DELETE /webhooks/{webhook_id} disables the subscription and returns 204.