Webhooks

Outbound notifications and signature verification

Webhooks

Declined sends outbound webhooks when recovery events occur. Configure endpoints in the dashboard under Webhooks & SDK. Each endpoint can subscribe to specific event types or all events (*).

Outbound event types

  • recovery.started
  • recovery.completed
  • recovery.failed
  • message.delivered
  • message.opened
  • message.clicked
  • incentive.accepted

Payload format

json
{
  "type": "recovery.completed",
  "data": {
    "recovery_attempt_id": "ra_abc123",
    "customer_id": "cus_123",
    "invoice_id": "inv_456",
    "amount_cents": 24900,
    "currency": "usd"
  },
  "created_at": "2026-06-12T14:30:00.000Z"
}

Signature verification

Declined sends X-Declined-Signature containing the hex-encoded HMAC-SHA256 of the raw request body using your endpoint signing secret. Always verify against the raw bytes before parsing JSON.

typescript
import crypto from "crypto";

function verifySignature(payload: string, signature: string, secret: string): boolean {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(payload)
    .digest("hex");
  if (signature.length !== expected.length) return false;
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

Retry policy

Failed deliveries are retried with exponential backoff according to the endpoint's retry_policy. Disabled endpoints stop receiving new deliveries immediately; in-flight retries may still complete. View delivery logs and replay from the dashboard Webhooks page.

Inbound provider webhooks

Payment provider webhooks (Stripe, Paddle, Chargebee, etc.) are configured separately under Payment Providers. Those ingest normalized billing events into the same recovery pipeline but use provider-specific signature headers — not X-Declined-Signature.