Events

Ingest billing signals that drive recovery sequences

Events

Send billing events to Declined via POST /v1/events. Events drive dunning sequences, recovery attempts, and analytics. Each event requires a unique event_id for idempotency across retries and worker redelivery.

Supported event types

  • payment_failed
  • payment_recovered
  • invoice_paid
  • invoice_opened
  • payment_method_updated
  • subscription_canceled
  • subscription_past_due
  • subscription_renewed

Payment failed

Start or continue a recovery sequence when a charge fails:

json
{
  "event_id": "evt_unique_001",
  "type": "payment_failed",
  "customer_id": "cus_123",
  "invoice_id": "inv_456",
  "amount": 24900,
  "currency": "usd",
  "provider": "stripe",
  "metadata": { "attempt_count": 2 }
}

Payment recovered

Notify Declined when a customer pays outside hosted recovery or via your own checkout. This stops active sequences and marks the invoice paid. See Recoveries for resolution rules when multiple attempts exist.

json
{
  "event_id": "evt_unique_002",
  "type": "payment_recovered",
  "customer_id": "cus_123",
  "invoice_id": "inv_456",
  "amount": 24900,
  "currency": "usd",
  "provider": "stripe"
}

Successful response

New events return HTTP 201:

json
{
  "status": "accepted",
  "event_id": "evt_unique_001",
  "inbound_event_id": "ie_abc123",
  "payment_event_id": "pe_def456",
  "recovery_attempt_id": "ra_ghi789"
}

recovery_attempt_id is present when the event creates or updates an active recovery. Duplicate event_id values return 200 with status: "duplicate" and no new side effects.

cURL example

curl
curl -X POST https://app.declined.io/api/v1/events \
  -H "Authorization: Bearer decl_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"event_id":"evt_1","type":"payment_failed","customer_id":"cus_1","invoice_id":"inv_1","amount":24900,"currency":"usd","provider":"stripe"}'