Money
The money contract
You own your customers’ cash ledger. Parity never holds a player’s funds. It returns the exact amounts to reserve, debit, release and credit against your own books.
Who holds what
| Step | Who does it | From which field |
|---|---|---|
| Reserve the stake | You | operatorMoney.authorizationAmount on the quote |
| Debit what actually filled | You | operatorMoney.actualDebit on the order |
| Hand back what did not | You | operatorMoney.releaseAmount on the order |
| Charge the platform fee | Parity | Already inside the debit: platformFee |
| Credit an exit | You | operatorExitMoney.sellProceeds |
| Credit a winner | You | operatorMoney.settlementCredit |
| Credit a void (a refund, or a split payout) | You | operatorMoney.voidCredit |
Swipe the table sideways for more columns.
Apply these amounts. Never recompute one.
The moment an integration multiplies a price by a quantity to work out what to debit, there are two answers to one question and only one of them is in our ledger. They will agree for months and then disagree by a cent on a position built from several fills, and nobody will be able to say which is right.
The two identities
authorizationAmount = actualDebit + releaseAmount
actualDebit = tradeAmount + platformFee + venueFeeThese are equalities, not tolerances. Every figure is an exact integer of minor units on our side: actualDebit is the sum of its parts rather than an independently rounded number, and releaseAmount is a subtraction rather than an independently derived remainder. There is no arrangement of prices that makes them drift, so a response that breaks one has been altered in transit and must not be booked.
Why the release exists
Parity takes its fee off the top of the stake rather than adding it on: a $50 stake at 120bps wagers $49.40. So the gross cash the player commits is exactly what you authorize, and a fully filled order releases nothing.
A partial fill is the case the contract exists for. The venue takes less cash than the stake covered, tradeAmount is the notional actually spent, and the difference is money you are holding that must go back. An operator that only ever debits the full stake silently keeps it.
{
"currency": "USD",
"authorizationAmount": "25.00", // you reserved this
"actualDebit": "12.30", // take this
"releaseAmount": "12.70", // give this back
"tradeAmount": "12.00",
"platformFee": "0.30",
"venueFee": "0.00",
"venueFeeKnown": false
}Read that example twice. An operator that debits "25.00" here has kept $12.70 of a customer's money, the books still balance on its own side, and nothing in any later response ever mentions it. That is the failure this whole page exists to prevent, and it is silent.
Rehearse it. A sandbox will not produce one on its own.
The simulated venue has no book to run out of, so a partial fill never happens by accident in the sandbox. Arm one deliberately with POST /api/v1/sandbox/scenarios and put a real order through it, then check that your wallet released the remainder. See Sandbox.
venueFeeKnown: false means the zero is a placeholder, not a fact: the execution fee is not priced into the quote, and the quote stores null rather than 0 precisely so “we do not know” stays distinguishable from “there is none”. The identity still needs a number for it, so it reports as zero. Where the fee is known, venueFeeKnown is true and venueFee is the amount, and the identity holds the same way.
All in: the debit is the stake, every fee inside it
On a live fill the execution venue takes its own taker fee from inside the amount Parity sends it, and delivers fewer contracts to fit. So every fee sits inside the stake: the platform fee comes off the top, the venue's fee comes out of what is left, and the customer is never debited more than authorizationAmount. On the order, venueFee is the fee the venue actually took, read from the fill, with venueFeeKnown: true; tradeAmount is what bought contracts; and any cent the venue did not use comes back as releaseAmount.
{
"currency": "USD",
"authorizationAmount": "3.00",
"actualDebit": "2.99",
"releaseAmount": "0.01",
"tradeAmount": "2.84",
"platformFee": "0.03",
"venueFee": "0.12",
"venueFeeKnown": true
}The consequence to plan for: on a market where the venue charges a fee, the quote's contracts (priced before that fee, while the quote's venueFee is null) is more than the fill delivers. filledQuantity on the order is what the player holds and what a win pays on. While a fill's venue fee is still being read, the order stays open (settlementState: pending) and the remainder stays held; the release you finally apply contains nothing the venue kept.
An exit credits. It never debits.
On a sell, operatorMoney is null and operatorExitMoney is populated. That nullability is the point of the field rather than an oversight: an exit that came back carrying an authorizationAmount would have a wallet applying the contract as written debit the player for selling their own position.
{
"action": "sell",
"operatorMoney": null,
"operatorExitMoney": {
"currency": "USD",
"sellProceeds": "12.20", // credit this. ALREADY NET
"platformFee": "0.15",
"venueFee": "0.00",
"venueFeeKnown": false
}
}The fees are reported beside the proceeds so you can show what the round trip cost, not so you can subtract them. Subtracting again is the double charge this shape exists to prevent. A round trip is two transactions and carries two fees.
The exit has an identity of its own, and it is an assertion, never a derivation:
sellProceeds = notional - platformFee - venueFeenotional on the exit is the gross contract value before any fee. The subtraction happens once, on our side, in exact minor units. Check it if you want the reassurance; credit sellProceeds either way.
One payout, two names
{ "settlementCredit": "17.15", "voidCredit": "0.00" } // won
{ "settlementCredit": "0.00", "voidCredit": "0.00" } // lost
{ "settlementCredit": "0.00", "voidCredit": "25.00" } // void, annulled: fee included
{ "settlementCredit": "0.00", "voidCredit": "17.15" } // void, split payout: fee keptA settlementCredit is winnings. A voidCredit is what a void pays, and a void comes in two kinds. When the market is annulled, it is a refund of everything the player committed, fee included. When the source settles the contract by splitting the payout between both sides (for example fifty cents a contract to each), the trade stood: voidCredit is the split payout for the player's contracts, rounded down to the cent, the platform fee is kept, and realisedPnl on the settlement says what the split cost. Both report outcome: "void". Operators book a credit and a refund differently, and collapsing them into a single “payout” would push that distinction back onto you, to be re-derived from an outcome string.
Amounts are exact decimal strings
Every figure inside operatorMoney, operatorExitMoney and a settlement is a string. A JSON number cannot carry an exact cent past a certain size and, worse, looks like it can. A client that parses 12.30 as a float has left the exact world before its own ledger sees the figure.
import { toMinorUnits, addDecimal } from './parity-sdk'; // the client Parity provides
toMinorUnits(order.operatorMoney!.actualDebit); // 1230n, exact
addDecimal(debit, release) === authorization; // the identity, in your own codeThe float fields beside them (stake, notional, platformFee, averagePrice, executionPrice) are for display. Prices are genuinely real numbers and 0.71 is an honest approximation of a market's view; the moment a price becomes an amount somebody is charged, it crosses into the exact world and stops being divisible.
What Parity will and will not refuse
- Where you hold the wallet, the funds check is yours: Parity cannot see your customer's balance and does not refuse on it. You decide what a player may stake before you ask for a price. There is no
insufficient_balancecode on this API.422 insufficient_fundsexists only where Parity holds the player's wallet, the sandbox included. - What Parity does refuse on: price and freshness (
price_stale,stake_exceeds_stale_limit,price_unverified), a line that cannot pay (line_not_available), book depth (stake_exceeds_available_depth), the limits you configured (over_wager_limit,over_period_limit,over_order_limit,over_tenant_exposure), a player you suspended (user_suspended), a market you are not offered (market_not_offered), and the operator's own float (insufficient_collateral), your trading pause (trading_paused), the live cash out rules (below_venue_minimum,insufficient_position,sell_not_available), and on a live account the caps agreed for it, per order, per player and overall, which withdraw an order before it is sent. Every code is on Errors. - The safe ordering is: reserve on your side, submit with a
clientOrderIdderived from that reservation, and release on anything other than a success, with one exception: an unresolved order, where you hold. See Orders.
Currency, units and rounding
- Every stored amount is US dollars. The ledger, every money block and every settlement are USD, and
currencyon each block says so. It is not configurable per operator. - A display currency is presentation only. Your players can be shown stakes in another currency (the embed reads your configured display currency: USD, EUR, GBP, CAD, BRL, USDT, USDC, DAI, BTC, ETH, SOL or ARB). The amount is converted for display, not relabelled, and nothing you book changes.
- Outputs are decimal strings in major units (
"12.30"is twelve dollars thirty). Inputs named...Minorare integers of cents (maxWagerMinor: 5000is fifty dollars). A quote'sstakeis a JSON number in dollars. - Rounding happens once. The stake is rounded to the cent once, and the fee, the wager and the figure the customer is told all derive from that one number. The fee rounds up to the cent, and a quoted payout and a settlement credit both round down to the cent. Every amount Parity hands you is already rounded: apply it, never re-round it.
The sandbox balance, and why it is not this
Sandbox only: 403 sandbox_only in live mode
GET /api/v1/users/{id}/balance and GET /api/v1/users/{id}/ledger return real derived figures from Parity's own double-entry books, and they exist so an integration can be learned against simulated money: a stake to spend, and somewhere to watch it move.
They are not the production integration path, and in live mode they answer 403 sandbox_only rather than returning a figure that invites the misreading. A live operator that read a balance from there would be treating Parity as a custodian of its players' funds, which Parity is not, and would eventually reconcile its own books against a number describing something else.
The accounting model behind them is worth understanding anyway, because the sandbox posts every movement exactly as production does. See Ledger.
The rest of the money model
- Settlement is the register you credit from, and how to consume it exactly once.
- Reconciliation is the verdict, and the fact stream your own books can be rebuilt from.
- Ledger (sandbox) is the chart of accounts, the movement types and the immutability rules.
- Bridge covers how value reaches the collateral asset, and the custody models.
Custody
Your customers' cash sits on your books, under your licence, in your ledger. Parity holds none of it, which is why this whole page is a set of instructions rather than a balance: nothing here asks you to move money to Parity and wait for it to come back.
The custody structure behind the collateral asset itself is agreed with Parity as part of your commercial arrangement rather than chosen through the API. What that model implies is on Bridge.

