Billing & commission
Two separate flows: how you pay for buys, and how you earn commission.
Paying for buys
When you buy on behalf of a user, the amount debits your partner balance and the assets credit the user. Fund that balance in two ways:
Prepaid float — top up in advance; buys draw it down. Postpaid credit — buy on a credit line (up to your limit) and settle on a cycle. Postpaid is part of the Pro plan.
Earning commission
You earn commission on every trade that goes through your integration — your embed, your whitelabel domain or your API. It doesn't matter whether the user is new to OroPocket or already had an account: if the buy or sell happened through you, it counts. Your users and their balances are managed as sub-wallets.
| Field | Type | Description | |
|---|---|---|---|
| Buy commission | 0.5% or higher | optional | 0.5% on the free plan and a higher rate on Pro, set with you, of the net metal value of every buy (gold, silver, SIP installment) made through your integration: what reaches us for metal, which is the amount paid less our 0.25% platform fee, the 3% GST and any markup of yours. Your exact rate is on your Earnings page. Always payable. |
| Sell commission | Pro | optional | On Pro, at significant volume, on terms set with you. The free plan earns on buys only. |
| Settlement | Monthly | optional | Statements finalize on the 1st of each month at 01:00 IST for the prior month. |
| Reversals | — | optional | A voided buy or sell voids the matching commission entry, retroactively for statements not yet paid. |
| Field | Type | Description | |
|---|---|---|---|
| Buy commission | Your agreed rate | optional | Your agreed rate, of the net metal value of every buy (gold, silver, SIP installment) made through your integration: what reaches us for metal, which is the amount paid less our 0.25% platform fee, the 3% GST and any markup of yours. Your exact rate is on your Earnings page. Always payable. |
| Sell commission | Where agreed | optional | Only where your agreement includes it. |
| Settlement | Monthly | optional | Statements finalize on the 1st of each month at 01:00 IST for the prior month. |
| Reversals | — | optional | A voided buy or sell voids the matching commission entry, retroactively for statements not yet paid. |
Statements and reconciliation
GET /partner/dashboard/statements returns one statement per calendar month (IST), newest first. Until it is paid, a reversal voids the affected entries and the statement is recomputed in place: same id, revision plus one. Your invoice must match the latest revision. A paid statement never changes; a reversal after payment is set off on the next statement as adjustment_inr.
GET /partner/dashboard/transactions?month_bucket=YYYY-MM lists the entries behind it. Each carries your user_code, the trade's transaction_id (and payment_id for hosted checkout), commission_base_inr (the net metal value) and commission_inr. On a buy, price holds the amounts fixed when the order was priced: amount paid, platform fee, metal GST, markup and net metal value. The non-void entries carrying a statement_id add up exactly to that statement's lines, and their count is entries_count. In a month below your sell threshold, sells are listed with status void, a void_reason and no statement_id; their volume still counts in total_sell_inr, which is what the threshold is tested against.
Both lists page with page and limit (transactions up to 100, statements up to 60) and return total. Transactions are ordered created_at then id, newest first, and a closed month gains no new entries, so paging until you hold total rows (or a page comes back short) gives you the whole month. month_bucket is the IST calendar month the entry was created in, as YYYY-MM; anything else returns 400 INVALID_MONTH_BUCKET. Without it you get every month. Both lists put page, limit and total directly in data, next to rows.
Reading a statement consistently. A paid statement and its entries never change. Before payment, an entry's status can change (void on a reversal, paid at payout), the statement can be recomputed (revision plus one), and payment fills in its payout fields. Entries are never added to a closed month or removed from it, so pages don't shift. To take a snapshot: read the statement, page every entry for its month, then read the statement again. Keep it when revision and status are unchanged and a second pass gives the same id, status, statement_id and commission_inr for every entry. If an unpaid statement doesn't reconcile, a reversal is being applied: read it again later and invoice the latest revision. In the current month, new entries arrive at the top of page 1, so de-duplicate by id.
| Field | Type | Description |
|---|---|---|
| total_payable_inr | 4 dp | Buy + sell commission + markup + referral earnings. Your invoice's taxable value is this, to the paisa. |
| invoice | object | null | Your invoice for the month: number, date, taxable value, GST, total and review status. |
| tds | object | null | Set when the month is paid: section, rate_pct, base_inr and amount_inr withheld. While the tax year is within ₹20,000: section null and the rest 0. |
| entries_count | integer | The buy, sell and markup entries attached to this statement (statement_id = its id, not void). |
| adjustment_inr | number | Set-offs of reversals from earlier paid months, deducted from this transfer. Always zero or positive: anything we owe you is paid as an entry on a statement, through your invoice. |
| adjustments | array | One item per reversed trade: statement_id (the paid month it came from), transaction_id, payment_id (hosted checkout, else null) and amount_inr. The amounts add up to adjustment_inr. adjustment_note holds the same items as text: stmt=412 txn=… pay=… inr=2.35, separated by ;. |
| net_payout_inr | number | null | What was transferred: invoice total − tds.amount_inr − gateway_fees_inr − adjustment_inr. payment_reference is the UTR. |
Testing statements in sandbox
A sandbox key has no commission ledger. GET /partner/dashboard/statements returns an empty page, and GET /partner/dashboard/transactions returns your sandbox trade history in the /trades format (data.trades and data.pagination), limited to the IST month when you pass month_bucket. Both carry simulated: true.
To test reconciliation against the live format, add fixture=billing-v1 to either call with your sandbox key. You get a made-up partner's statements and entries exactly as live returns them (same fields, paging, limits and ordering, with month_bucket applied), plus simulated: true and fixture on the page. It is not your account's data, and a version never changes. With a live key, fixture returns 400 FIXTURE_SANDBOX_ONLY.
| Field | Type | Description |
|---|---|---|
| 2026-05 | paid | Below the sell threshold: sells are void with no statement_id. The tax year is within ₹20,000, so tds has section null and 0s. |
| 2026-06 | paid | 268 entries, three pages at limit=100. Above the sell threshold, so sells earn commission. The year passes ₹20,000 here: tds.base_inr is May's taxable value plus June's. |
| 2026-07 | paid | A set-off: a June buy refunded after June was paid. adjustments names statement 9102, the trade and its payment, and net_payout_inr = invoice total − TDS − set-off. |
| 2026-08 | finalized, revision 2 | A buy and its markup refunded before payment: both void with void_reason partner_buy_refund, keeping their statement_id. Not yet paid, so invoice, tds and net_payout_inr are null. |
| 2026-09 | open | The current month: entries accruing, no statement yet. |
fixture=billing-v1-r1 is the same data with August as it was at revision 1, before the refund. Read it, then billing-v1, to check that your collector notices a revision change. Each variant is also available whole, without a key, for offline tests: /partner/fixtures/billing-v1.json and /partner/fixtures/billing-v1-r1.json.
The fixture shows the format and the arithmetic. That your own trades produce the entries you expect, and the invoice and payout steps, are checked on your first live month.
Rounding
From 28 October 2026 every stage rounds half up (ties away from zero) in exact decimal arithmetic, in this order. Entries booked before that date keep their booked amounts.
| Field | Type | Description |
|---|---|---|
| Per trade | 4 dp | commission_inr = commission_base_inr × your rate. Buy, sell and markup are separate entries, each rounded on its own. ₹0.70 × 1.75% = ₹0.01225 → ₹0.0123. |
| Statement | exact | Each line is the exact sum of its entries — no rounding. |
| Invoice | paisa | Taxable value = total_payable_inr, rounded once after aggregation. GST = 18% of the taxable value. Total = taxable value + GST. |
| TDS | paisa | The rate × the TDS base. 2% of ₹1,000.25 = ₹20.005 → ₹20.01. |
TDS on commission
We deduct TDS on commission under section 393(1) [Table, Sl. No. 1(ii)] of the Income-tax Act, 2025 (formerly section 194H): 2% of your invoice's taxable value — GST shown separately is excluded — or 20% if we have no PAN for you. It applies once your credits from us in a tax year (April–March) exceed ₹20,000, counting buy and sell commission, markup and referral earnings together; the month that crosses it also covers that year's earlier months. A valid lower-deduction certificate's rate applies within its validity and amount.
TDS is deducted on each month's commission before any set-off, withheld from that month's transfer and deposited by the 7th of the following month. You receive a quarterly TDS certificate from TRACES. Bill the full amount: TDS comes off the transfer, not your invoice. Our TAN is DELS67861D; it is on the invoice template and in the “Made out to” block on Earnings. We take your business PAN when you go live; to change it or send a lower-deduction certificate, email partners@oropocket.com.
Merchant markup (Pro)
Commission is what we pay you. The merchant markup is what you charge: your own spread on our rates, on top of commission rather than instead of it. There are two percentages — one added to our buy rate, one taken off our sell rate — each capped at 5% and each independent of the other. Set them in Earnings, or over the API — the Raw API guide has the endpoints, parameters and error codes.
The same pair applies everywhere your users see a price: API quotes, the hosted checkout, and any screen you build on GET /partner/prices. It does not apply to gifting/send or delivery, which carry their own fee structure.
At our rate of ₹10,000/g with a 2% markup, a ₹10,200 buy works out like this. The commission line uses 0.5%, Free's published rate, purely for illustration — Pro rates are agreed per partner, and yours is on your Earnings page. Note that the markup applies to the investable amount — what is left after the 0.25% platform fee and 3% GST — not to the gross, because the fee and GST come off the top of every buy before any metal is bought.
| Field | Type | Description |
|---|---|---|
| Quoted to your user | ₹10,200/g | Our ₹10,000 plus your 2%. Returned on the buy quote as rate_inr_per_gram, with base_rate_inr_per_gram and markup_amount_inr alongside it. |
| Your wallet is debited | ₹10,200 | The full order. You fund the markup up front and it comes back at settlement — it is not netted off the debit. |
| Platform fee | −₹25.50 | 0.25% of the order, taken before anything else. |
| GST | −₹296.35 | 3% on the remainder. Shown on your user's tax invoice. |
| Investable | ₹9,878.15 | What actually buys metal. Your markup is a spread on THIS, which is why the rupee figures are not round. |
| Your user is credited | 0.968446 g | Investable ÷ your marked-up rate. Without your markup the same ₹10,200 would have bought 0.987815 g — the markup is the difference. |
| Markup passthrough | +₹193.69 | ₹200 per gram on the 0.968446 g sold. A separate line on your monthly statement (markup_passthrough_inr); no threshold gates it, it is your own money. |
| Buy commission | +₹48.42 | 0.5% (illustrative — your rate is on Earnings) of our ₹9,684.46 metal cost — not of your marked-up price, and not of the fee and GST either. Commission is on what reached us for metal, so you never pay us a cut of your own margin. |
| Your net cost | ₹9,957.89 | ₹10,200 out, ₹242.11 back the following month. |
On a buy, the markup is added to our rate and comes back to you in full on the monthly statement. Your commission is calculated on our metal cost — not on your marked-up price, and not on the platform fee and GST.
Selling works the other way round, and the mechanics differ. On a buy your user gets fewer grams for the same rupees. On a sell the grams are already fixed — so we sell the full quantity at our rate and credit your user less, and the difference is yours. At our ₹10,000/g with a 1% sell markup, a 1 g sell looks like this:
| Field | Type | Description |
|---|---|---|
| Quantity sold | 1.000000 g | The full amount leaves your user's holding. A sell markup never changes how much metal is sold — only what the payout is. |
| Our rate | ₹10,000/g | What we buy the metal back at. Returned on the sell quote as base_net_amount_inr before fees. |
| Gross proceeds | ₹10,000 | Before the platform fee. |
| Platform fee | −₹25.00 | 0.25%, the same as on a buy. Sells attract no GST. |
| Your markup | −₹100.00 | 1% of the gross. Returned on the quote as markup_amount_inr, with effective_rate_inr_per_gram showing your user's ₹9,900/g. |
| Your user is credited | ₹9,875.00 | net_amount_inr on the quote — what actually lands in their INR wallet. |
| Markup passthrough | +₹100.00 | Yours in full, on the same monthly statement line as buy markup (markup_passthrough_inr). |
| Sell commission | on ₹9,875 | Where your terms include sell commission, the same rule as the buy side: charged on what actually reached your user, so our fee and your own spread are both out of it. You already keep the spread in full. |
The markup is visible on every quote, so your integration always sees both prices. If you downgrade from Pro, a stored markup simply stops applying — your buys and sells keep working at our rate rather than failing.
Funding your own wallet
For the gifting/send use case you hold assets yourself. Top up gold, silver or INR from the Money page via Cashfree or bank transfer.