Getting started
Environments
Sandbox is a property of the tenant, not of a request or a host name. Read simulated on every response rather than inferring the environment from the URL you happen to be pointed at.
What each layer does
| Layer | State | What that means for you |
|---|---|---|
| Market catalogue | Live | Real questions, real outcomes, normalised and de-duplicated across sources. |
| Prices | Live | Streamed or polled from upstream books. Age is published on every quote. |
| Quotes | Live pricing, real expiry | Priced from a real book where one exists. Expiry is enforced against the stored timestamp: 30 seconds by default (configurable between 5 and 300), 10 seconds on a contract trading live or near its close, and 5 seconds on a five-minute contract. Read expiresAt rather than assuming any of them. |
| Orders | Live | A durable Parity order id, real idempotency, a real state machine and real collateral. The row is written before anything is sent, and the reserve handshake is what makes an order executable. |
| Fills and positions | Real rows | A fill opens or extends a position, with real weighted averages. A tenant whose execution ceiling is simulated (the usual sandbox set-up) gets a locally produced fill by default, written to the same tables in the same shape. Asking for `executionIntent: "simulate"` on a tenant whose ceiling is above simulated is refused with 422 simulation_not_permitted, and a tenant without a simulated ceiling records the order as an intent instead of filling it. A live order fills once it is transmitted: live transmission is enabled for your account at go-live, and each order is armed. Read `transmissionState`. |
| Settlement | Real | Positions settle against their contract’s resolution and the credit is computed once, on our side. |
| Money movement | Yours | Parity returns exact debit, release and credit instructions. Your ledger applies them. |
| Webhook delivery | Per endpoint | Events are durable rows, delivered signed and retried to every endpoint your account team registers for you. `/api/v1/reconciliation` is the authoritative record: poll it alongside. |
Swipe the table sideways for more columns.
Who holds the money
This is the fact that decides how your integration is shaped, and it does not change between sandbox and live: the operator owns its customers' cash ledger. Parity never holds player funds. What Parity returns is an exact instruction against your own ledger: authorizationAmount to reserve, actualDebit to take, releaseAmount to give back, sellProceeds to credit on an exit, settlementCredit or voidCredit when a position resolves.
Those amounts are exact decimal strings on the wire ("25.00"), never JSON numbers. The float fields beside them (stake, notional, platformFee, averagePrice) are for display.
Some endpoints are sandbox-only
Sandbox has simulated money, because somebody learning the flow needs funds to spend and somewhere to watch them move. Test funds arrive as a SANDBOX_CREDIT movement from house equity, and the balance and movement reads report it back. Parity tops up test players on request: name the sandbox players and we credit them.
| Endpoint group | In live mode |
|---|---|
GET /api/v1/users/{id}/balance | 403 sandbox_only |
GET /api/v1/users/{id}/ledger | 403 sandbox_only |
/api/v1/funding/* | 403 sandbox_only |
/api/v1/sandbox/* | 403 sandbox_only. The scenario and resolution test controls |
Swipe the table sideways for more columns.
A Parity-held balance is not the production integration path
These endpoints model a per-user cash position derived from Parity's own ledger. That is real and useful in the sandbox and it is the wrong model for a live operator: a partner reading a balance from here 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 that describes something else.
So they refuse in live mode rather than returning a figure that invites the misreading. Build against the instructions on quotes, orders and settlements, and your own wallet stays the authority on what a player may stake.
The simulated flag
Every quote, order and settlement payload carries simulated. It is present on every response and never omitted when inconvenient, because a simulated fill that looks identical to a real one is exactly what an integrator should not have to read the docs to discover.
"simulated": true // this fill was produced locally; no order reached a venueRead this
simulated: true is the answer wherever a fill was produced locally: every sandbox response, and every response to a caller that asked for executionIntent: "simulate". Read it as “was this fill real”, and read transmissionState for “did this order reach a venue”. They are different questions and the API answers them separately.
A live order that has not been transmitted has no fill at all, so neither flag describes it. Before you confirm the reserve it reads status: reserve_pending; after confirm-reserve it reads status: pending_venue_execution, transmissionState: not_transmitted and settlementState: pending. Hold the authorization and do not treat the absence of simulated: true as evidence a venue took it.
It is a fact about that order, not about the platform
One Parity platform serves sandbox and live accounts at the same time, and they are not in the same execution mode. So simulated is derived per order from the venue that answered it, and two orders created seconds apart on the same platform can disagree. Read the field on the order in front of you.
Do not infer it from the host name you are pointed at, from the prefix on your key, or from an earlier order. Those describe your credential and our infrastructure; this field describes one fill.
Routing, stated precisely
Parity groups questions across sources by exact match. That grouping is a display fact: it says two listings ask the same question, not that the contracts are interchangeable. Cutoff times, resolution sources and edge cases in the rules all differ.
- An order is bound to the contract that was quoted. The quote reports
routing.consideredVenues, how many sources could have competed, androuting.routable, whether any actually may. - The alternatives themselves are never listed, because naming them is naming the venues. No partner-facing payload identifies a source anywhere.
routableisfalseuntil a human has verified a group as equivalent.- Parity does not claim best execution across sources.
Sandbox and production hosts
Sandbox and live accounts share one platform. A key does not encode a host, and one host serves both modes: your integration host is issued to you directly, together with your sandbox key. Configure it as a variable rather than hard-coding it, so a different host can be swapped in without a code change.
PARITY_BASE=https://<issued-to-you>
PARITY_KEY=pk_test_... # sandbox tenant. Live keys are sk_live_...Sandbox is a property of the tenant
Not of a request, not of a header, not of the URL. The operator record carries the mode and every request inherits it, so there is no parameter a caller could set to reach the other environment and no way to place a live order with a test key by accident.
A key's prefix follows the tenant's mode when it is minted: pk_test_ on a sandbox tenant and sk_live_ on a live one. New tenants are created in sandbox mode. Parity moves your account to live as a managed step, once the checks on Going live pass and the commercial terms are agreed.
The sandbox is not a lesser environment
It runs the production pipeline: live prices, real quote expiry, real idempotency, real settlement, the same tables and the same code. What differs is that the fill is produced locally instead of at a venue, and that the money endpoints above are open. Everything you prove there about idempotency, recovery and settlement transfers unchanged.
Health and status
GET /api/health is unauthenticated and answers one question for the public: can the platform serve. It is a liveness check, not a status page.
{
"status": "ok",
"timestamp": "2026-08-20T04:43:02.980Z"
}200with"ok"means the platform can serve. A single upstream feed running degraded is stillokhere: it is an operating state, not an outage.503means it cannot serve, and the body'sstatussays why in one word (for exampleunhealthy).- The detailed report (feed freshness, queues, webhook sender state) is for Parity operations only and is not part of the partner contract. Monitor your own integration by the responses it receives, and ask us if you need a figure from it.

