Wallet top-ups
Wallet top-ups
How credits get into a wallet after the initial grant: a one-off charge the customer pays for, an amount they choose themselves, or an automatic top-up that fires when the balance runs low.
Why this matters
A customer on credit-based pricing stops being able to use your product the moment their wallet hits zero. Topping it up is therefore not an admin task you want to be in the middle of: the customer should be able to buy more credits themselves, or never notice the problem because a top-up fires automatically.
Both routes charge an on-demand pricing item that grants credits to the wallet. You model the bundle once as a pricing item, and the same item backs the manual purchase, the customer-chosen amount and the automatic top-up.
How it works
A top-up is always a charge of one or more on-demand pricing items on a pricing plan schedule. The charge produces a one-off invoice, the invoice is paid with a stored payment method, and the wallet grant attached to the pricing item’s config is booked against the wallet.
Charge a top-up
POST /v1/invoices/charge-on-demand-pricing-items charges the items and returns the resulting invoice.
Send preview: true to price the top-up before the customer commits, which is what an order summary needs. Nothing is charged and no wallet grant is booked.
See Charge on-demand pricing items for the full schema.
Let the customer choose the amount
When the pricing item uses flexible pricing, the customer picks how much to spend within a band and receives credits in proportion. Pass their choice as flexible_amount on the item:
The amount is validated against the item’s pricing band: the currency has to match the band’s currency, and the quantity has to sit between its minimum and maximum. A rejection names the field as pricing_items.{index}.flexible_amount, so you can point the customer at the input they got wrong.
Charge a top-up from the customer portal
The same call exists as POST /v1/portal/invoices/charge-on-demand-pricing-items, scoped to the signed-in customer by the portal session and authenticated with the portal access token rather than an API key. The body is identical, so a self-service top-up screen previews with preview: true and then charges with the same payload.
Automatic top-ups
An auto top-up config (atco_) is a resource on the wallet. It watches one wallet and charges an on-demand item whenever the balance drops below a threshold, so the customer never runs out mid-usage.
Threshold units
The threshold is compared against the wallet’s balance in the unit that wallet keeps its ledger in, not in the unit you happen to express the threshold in. A CREDIT wallet holds credits even when it is funded by a monetary amount converted at a rate, so its threshold belongs in credits; a BALANCE wallet holds money, so its threshold belongs in amount.
Getting this wrong used to be silent: a credit wallet whose top-ups were denominated in currency compared two different units and so never crossed its threshold, meaning the top-up simply never fired. The comparison now converts to the wallet’s own unit before testing it.
topup_amount is what makes “top up $50 whenever I drop below 100 credits” expressible without modelling a fixed-price item for every amount you want to offer. It is validated against the same flexible pricing band as a manual charge, at the moment the config is created rather than when it first fires, so a misconfigured band surfaces immediately.
Switch a config on and off with activate and deactivate rather than deleting and recreating it, which keeps the history intact:
List the configs for a wallet with GET /v1/auto-top-up-configs and its wallet_id filter.
Manage automatic top-ups from the customer portal
/v1/portal/auto-top-up-configs gives the customer the same control over their own wallet: create a config, list the configs for a wallet_id, fetch one, and activate or deactivate it. There is no delete, so a customer turning automatic top-ups off deactivates the config and can switch it back on later without re-entering anything.
The wallet grant from an automatic top-up is booked synchronously, so the new balance is visible as soon as the top-up completes rather than after the next asynchronous pass.
Read a wallet with its top-up rules
GET /v1/wallets and GET /v1/wallets/{id} accept expand[]=auto_top_up_configs, which returns the configs above inline with the wallet instead of as a separate lookup, and expand[]=wallet_type_id for the wallet’s denomination. Both also work through the customer balance call using the nested key, for example expand[]=wallet_balances.wallet.wallet_type_id. See Read a wallet with its type and top-up rules.
Show the available top-ups
To render a top-up screen you need the balance and the options in one go. POST /v1/customers/{id}/wallets/balance returns the balance of every wallet of a customer and can expand charge_on_demand_pricing_items, the on-demand items that can top each wallet up.
Each entry carries the pricing_item_id and the pricing_plan_schedule_id you need for the charge call. Add expand[]=wallet_balances.charge_on_demand_pricing_items.pricing_item_id to inline the full pricing_item as well, which gives you the name and price to render on the button. Without this expansion you would have to resolve the customer’s schedules and filter their items yourself.
See Get wallet balances for the full schema.
Edge cases
- The pricing item has to grant credits to that wallet. An on-demand item without a wallet grant, or one granting to a different wallet type, produces an invoice but no credits.
- A threshold is denominated like its wallet. Use
creditsfor a credit wallet andamountfor an amount wallet, as covered in Threshold units. - Deactivating is not the same as deleting. An inactive config stops firing but stays on the wallet, so a customer who turns top-ups back on keeps the same threshold and payment method.
- A failed payment leaves the invoice behind. The charge produces the one-off invoice first and pays it second, so a declined payment leaves an unpaid invoice, not a silently dropped top-up. Watch invoice payment status to catch customers whose automatic top-ups are failing.
preview: truenever books anything. Use it for order summaries; a preview that looks right is not a charge.