Reference

Sub-wallets

How balances are scoped per partner — and why a user's portfolio can look smaller through your API than it does in their app.

An end user has one combined OroPocket balance. They see all of it in the OroPocket app. You do not. Each partner sees and moves only its own sub-wallet: the slice of that combined balance which was transacted through your integration.

Everything else in the user's holdings — assets they bought directly in the OroPocket app, or through a different partner — is invisible to you. It never appears in a portfolio read, and it cannot be sold, gifted, delivered or withdrawn through your API.

What lands in your sub-wallet

SourceCredited to you
API buysServer-to-server buys you made on the user's behalf.
Embed buysBuys the user made inside your hosted embed session, however they paid.
Embed SIPsRecurring plans created through your integration, and every installment they execute.
BTC cashbackBitcoin cashback earned on those buys — it follows the buy that produced it.
Sell proceedsINR from sells you executed, credited to your INR sub-wallet.
Top-upsINR the user added through your integration.

1. Reads are scoped

The portfolio endpoint and the activity feed return your sub-wallet only. Same response shape as always — the numbers are simply your share.

GET/partner/users/:user_code/portfoliobalance
GET/partner/transactions/alltransactions

So if a user holds 5g of gold in total but bought 1.2g of it through you, your portfolio read reports 1.2g. That is not a bug and not a stale cache — it is the number you are allowed to act on.

2. Writes are validated against your claim

Sells, gifts, deliveries and withdrawals are all checked against your sub-wallet, not the combined balance. Ask for more than you hold a claim on and the call fails with an INSUFFICIENT_* error that carries the scoped availability figure — so the error itself tells you your real ceiling.

{
  "success": false,
  "request_id": "req_9f2c…",
  "mode": "live",
  "error": {
    "code": "INSUFFICIENT_USER_BALANCE",
    "message": "The user holds 1.2000g gold via your integration; this needs 5.0000g.",
    "details": {
      "required_grams": 5,
      "available_grams": 1.2
    }
  }
}

Read available_grams rather than assuming the user is short of funds overall — they may be holding plenty, just not through you.

3. User-side activity can reduce your balance

This is the rule that surprises people. Your sub-wallet can shrink with no API call from you. In the OroPocket app the user sells against their combined balance — they have no concept of which partner an asset came through, and we do not stop them.

When that happens the sale is drained in a defined order:

OrderConsumed
FirstThe user's own OroPocket-side portion — anything not claimed by a partner.
ThenPartner sub-wallets, largest-first: the biggest remaining claim is consumed before smaller ones.

You are told about it: those sales fire sell.completed webhooks to your endpoint exactly like an API sell would, so the drain is observable in real time rather than something you discover at reconciliation.

This is the one that bites integrators. A balance you read an hour ago may no longer be yours to spend — reconcile from webhooks, and never cache a sub-wallet balance indefinitely. Re-read before you act on it, and treat an INSUFFICIENT_* on a previously-valid amount as expected, not exceptional.

4. KYC and bank accounts are global

Identity is not per-partner. A user verified anywhere is verified everywhere: if they completed KYC in the OroPocket app or through another partner, they arrive at your integration already verified, and you do not need to re-collect anything. The same holds for bank accounts — one verified account is usable across every channel.

Practically: check KYC status before you assume a user needs onboarding, and expect a brand-new user of yours to occasionally already be fully verified.

5. Failed withdrawals restore claims

A withdrawal consumes your sub-wallet claim when it is initiated. If the payout is later rejected or fails, the money comes back to the user and the consumed claim is restored to your sub-wallet in the same motion. You do not need to reconcile it yourself or ask support to re-credit anything.

No integration changes required

Nothing about your code has to change for any of this. Request and response shapes are identical — every endpoint in the Raw API guide keeps the same fields and the same errors. Only the values are scoped to you. The work, if any, is in your assumptions: stop treating a portfolio read as the user's whole net worth, and stop treating your last-known balance as authoritative.

Building a "total holdings" screen for your users? Show it as assets held through your app, not as their OroPocket balance — otherwise the number will disagree with the OroPocket app and generate support tickets you cannot answer.