Wallet

The prepaid wallet reserves money for an order, charges for what is delivered, and returns the rest.

Your wallet is prepaid, in US dollars. Every amount on this page, and every wholesale cost the wallet pays, is an integer in US cents. What you charge a customer can be in another currency: a price list, quote, sale or invoice carries its own currency, in minor units too. See Currency.

curl https://resellerhq.com/api/v1/wallet \
  -H "Authorization: Bearer $RHQ_API_KEY"
{ "available": 20500, "held": 4500, "currency": "USD" }
  • available is what you can spend now.
  • held is reserved for orders still in progress.

How an order is paid for

  1. Reserve. The order's total moves from available to held. If the wallet cannot cover it, the order is refused with 402 insufficient_funds and nothing changes.
  2. Charge. Each item that is delivered is charged from the reserved amount.
  3. Return. Anything reserved for items that could not be delivered goes back to available.

So a failed order costs nothing, and a partly filled order costs only the part that was filled.

History

GET /v1/wallet/transactions lists every movement, newest first:

kindMeaning
topupFunds added
holdReserved for an order
captureCharged from a reservation
releaseReservation returned
refundMoney returned after a charge, for example a cancelled number
debitAn adjustment taken out by our staff, such as to claw back a wrong credit
writeoffA provider charge that could not be delivered or billed on, booked as a loss
transfer_outSent to a sub-reseller's own wallet
transfer_inReceived into a sub-reseller's own wallet, from its parent
marginA sub-reseller's margin paid to its parent as the sub-reseller's purchase is captured
clawbackMargin a parent already received taken back on a sub-reseller's refund

Every movement is recorded as a balanced double-entry journal line, so the history always adds up to the balance.

Adding funds

In the sandbox, add test funds from the Wallet page. They cost nothing, never reach Stripe, and cannot be spent on anything real.

On the live side, Add funds opens a Stripe Checkout session for a card payment. POST /v1/wallet/top-ups does the same thing for an API caller:

curl -X POST https://resellerhq.com/api/v1/wallet/top-ups \
  -H "Authorization: Bearer $RHQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount": 10000}'
{ "id": "wtp_01JABCDEFG1234567890ABCD", "url": "https://checkout.stripe.com/...", "amount": 10000, "creditAmount": 10000 }

Open url to pay. The wallet is credited by Stripe's webhook once the payment is confirmed, never by this response - a card top-up can take a moment to settle, especially for a delayed payment method, so poll GET /wallet or watch for wallet.topped_up rather than assuming the balance moved the instant Checkout finishes. Dashboard payments return to the Wallet page with a "payment received" message that works the same way: a confirmation, not a credit.

amount must be between WALLET_TOPUP_MIN_CENTS and WALLET_TOPUP_MAX_CENTS (creditAmount is amount unless the deployment is configured to pass Stripe's own card fee on, in which case it is a little less - the Checkout page's line item says which). A refund or a lost dispute on a top-up debits the wallet back by the same amount, recorded in the history below with its reason; this never suspends the account, even if it takes the balance negative.

Without a Stripe key configured on the deployment, POST /v1/wallet/top-ups answers 422 stripe_not_configured and the dashboard keeps today's "add funds by invoice" message. Card top-ups may also not be offered on every account on a given deployment - an account that sees this has the same "by invoice" path as one on a deployment with no Stripe key at all.

In the API reference