MisarMisar Docs

Auto-load (Auto-recharge)

GET/PUT /io/wallet/autoload — configure automatic wallet top-ups when the balance runs low. 1 credit = $1.

Auto-load automatically tops up a user's wallet by charging their saved card off-session whenever the balance drops below a threshold — so metered features never stall on an empty wallet.

GET  https://api.misar.io/io/wallet/autoload
PUT  https://api.misar.io/io/wallet/autoload

How it works

  1. Save a card. The first manual top-up runs Checkout with setup_future_usage: off_session, so the buyer's card is attached to a Stripe Customer and saved. The webhook stores the customer + card on the wallet.
  2. Enable auto-load. PUT /io/wallet/autoload with enabled: true, a threshold (credits) and an amountDollars (dollars to charge). Enabling requires a saved card.
  3. Trigger. When a deduct drops the balance below the threshold, the wallet atomically claims the charge (under the wallet row lock, with a 5-minute cooldown so concurrent deducts can't double-charge) and creates an off-session PaymentIntent on the saved card. Credits are granted through the same idempotent top_up_wallet path as a manual top-up (keyed on the PaymentIntent id).
  4. Recover from failure. A declined charge is recorded; after 3 consecutive failures auto-load disables itself and the user is emailed to update their card.

Safety net

Besides the inline trigger, a scheduled scan (POST /io/wallet/autoload/run, Bearer CRON_SECRET) re-checks enabled wallets whose balance is below threshold and charges any that the inline path missed. The same atomic claim + cooldown guarantees no double-charge.

Authentication

SSO bearer (own config) or service key (+ user_id).

Authorization: Bearer <sso_access_token>
# — or —
x-wallet-service-key: <WALLET_SERVICE_KEY>   # with ?user_id=<uuid> / body.user_id

GET — read the configuration

curl "https://api.misar.io/io/wallet/autoload" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
{
  "enabled": true,
  "threshold": 10,
  "amountDollars": 50,
  "hasPaymentMethod": true,
  "cardBrand": "visa",
  "cardLast4": "4242",
  "failureCount": 0,
  "lastError": null,
  "lastSuccessAt": "2026-07-27T09:14:22.000Z"
}
enabledboolean
Whether auto-load is active.
thresholdnumber | null
Balance (credits) below which a recharge fires.
amountDollarsnumber | null
Dollars charged per recharge (1 credit = $1).
hasPaymentMethodboolean
Whether a card is saved. Must be true to enable.
cardBrandstring | null
Saved card brand, e.g. visa (display only).
cardLast4string | null
Saved card last 4 digits (display only).
failureCountnumber
Consecutive charge failures; auto-load disables itself at 3.
lastErrorstring | null
Last decline/error reason, if any.
lastSuccessAtstring | null
ISO timestamp of the last successful auto-load.

PUT — update the configuration

enabledbooleanbodyrequired

Turn auto-load on or off.

thresholdnumberbody

Balance (credits) that triggers a recharge. Required when enabled: true. Range 0–1000000.

amountDollarsintegerbody

Dollars to charge per recharge. Required when enabled: true. Integer in 10–100000.

curl -X PUT "https://api.misar.io/io/wallet/autoload" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true, "threshold": 10, "amountDollars": 50 }'

Returns the updated config (same shape as GET).

Enabling requires a saved card

PUT with enabled: true and no saved card returns 409 { "error": "...", "reason": "no_payment_method" }. Prompt the user to make one manual top-up first — that saves their card. Invalid threshold/amountDollars return 400.

Emails

Every auto-load money event emails the user (via the central api.misar.io/mail/v1/send from no-reply@trans.misar.io):

EventEmail
Auto-load charged the card and credited the walletAuto-reload succeeded (amount, credits, new balance, receipt)
Off-session charge declinedAuto-reload failed — update your card (+ "disabled after 3 failures" note)
Balance low but auto-load off / no cardLow-balance warning
Saved card expiring / auto-updatedCard-expiring reminder (auto-updated cards are refreshed silently)