Core Concepts
Recovery Cases
Every failed invoice payment creates a Recovery Case — the central object Savby uses to track the full lifecycle of a payment recovery attempt.
State machine
A Recovery Case moves through a defined set of states. All transitions are recorded in an immutable audit trail.
The case has been created following a payment failure. Actions are scheduled but not yet executing.
Actions are actively executing — charge retries are queued or in progress.
Execution has been temporarily halted, either by you or automatically.
A retry attempt succeeded — the invoice has been paid and the revenue recovered.
All retry attempts have been made without success, or the case was manually dismissed.
Action types
Each Recovery Case has a sequence of RecoveryAction records — the individual steps Savby executes to recover the payment:
Savby calls stripe.invoices.pay() with a unique idempotency key. If the charge succeeds, the case moves to RECOVERED. If it fails, the action is marked failed and the next scheduled action takes over.
Savby sends a transactional email to the customer via Resend. For notify-only codes, this email contains a secure link for the customer to update their payment method.
Savby marks the case as requiring human intervention and transitions it to EXHAUSTED. Used for high-risk decline codes or when all retries have been exhausted.
Bulk actions
From the Payments dashboard you can select multiple cases and apply bulk actions:
| Action | What it does | Permission required |
|---|---|---|
| Retry | Immediately enqueues a RETRY_CHARGE for each selected case | Owner or Admin |
| Dismiss | Marks selected cases as EXHAUSTED and sets resolvedAt | Owner or Admin |
Audit trail
Every state transition is recorded in an immutable RecoveryCaseAudit entry that captures the previous state, the new state, the reason for the transition, the actor (user ID or "system"), and a timestamp. This gives you a full history of every action taken on a case.