@solvapay/react; this guide covers the full stack: the backend route, the server
helpers, the React surface, and the combined top-up + auto-recharge flow.
Wire the backend route
All three verbs share a single route and a single provider key,api.autoRecharge
(default /api/auto-recharge):
saveAutoRecharge accepts the input as a second argument or parses it from the request body, so
the one-liner route above is all you need.
Configuration input
saveAutoRecharge and the autoRecharge field on createTopupPaymentIntent accept an
AutoRechargeInput:
Validation enforces both amounts
<= 10,000 major units and a per-currency Stripe minimum on the
top-up amount (for example $0.50 for USD/EUR/CHF/CAD/AUD, £0.30 for GBP).
SaveAutoRechargeInput additionally accepts deferSetupIntent?: boolean — see
staging with the first top-up.
Reading the config
getAutoRecharge returns { config: AutoRechargeConfig | null }. The stored config uses
minor units:
Thresholds and amounts are stored in display-currency minor units and re-resolved to credits
against live FX at trigger time — no fixed credit threshold is persisted.
React components and hooks
@solvapay/react ships a drop-in <AutoRecharge> component and a useAutoRecharge hook. Both
read and write through the /api/auto-recharge route:
@solvapay/react/primitives.
See Credit Top-Ups & Auto-Recharge in the React guide for
component props, useAutoRecharge return values, and custom-UI patterns.
Stage auto-recharge with the first top-up
Auto-recharge can be armed as part of the customer’s initial top-up charge, so there is no separate card-setup step:- Render
<AutoRecharge deferCardSetup onPendingConfig={...}>alongside your top-up amount step. - Saving the form sends
deferSetupIntent: true— the config is staged aspending_setupwithout creating a Stripe SetupIntent, andonPendingConfigreceives theAutoRechargeInput. - Pass that payload into
TopupForm.Root(orcreateTopupPaymentIntent) asautoRecharge. - The backend creates the payment intent with
setup_future_usage: 'off_session', saves the card on that same charge, and flips the config frompending_setuptoactivewhen the confirmation webhook lands.
pending_setup) config is not armed until the card is saved on the top-up charge.
Monthly spend cap
The optionalmaxMonthlySpendMajor cap limits total auto-recharge spend per UTC calendar
month:
- Spend is tracked in
monthlySpendMinorunder themonthlySpendPeriodkey (YYYY-MM, UTC). - When the next recharge would exceed the cap, the charge is skipped. The config stays
active— charges resume automatically when the UTC month rolls over. No webhook fires for a cap skip. - The drop-in
<AutoRecharge>shows current-period spend (for example$45 / $100 this month) and a Monthly spend limit reached status when applicable.
Handling failed recharges
Off-session declines are surfaced explicitly:- After repeated declines,
config.statusflips to'failed'andfailureCountincrements. - Declines are delivered via the
customer.credit.auto_topup_failedwebhook — they are not returned in thetrackUsage/ usage-debit response. autoRecharge.triggered: trueon a usage-debit response means an off-session charge was initiated, not that credits were booked inline. Credits mint when the charge succeeds.
config.status === 'failed' and pair it with
<UpdatePaymentMethodButton> so the customer can update their card and resume recharging.
Next steps
- React guide —
TopupForm,AutoRecharge,useTopup, anduseAutoRechargein depth - Purchase lifecycle management —
activatePlanand thetopup_requiredflow that leads customers here - Webhooks — handle
customer.credit.topped_upandcustomer.credit.auto_topup_failed