Reference
API reference
Every endpoint, in one place, checked against what the build actually serves.
Two surfaces
| Surface | Auth | What it is for |
|---|---|---|
/api/v1/* | Operator key + scope | The partner contract. Opaque contract ids, exact money, keyset cursors, no venue named anywhere. |
/api/* | None | The public catalogue and the public demo. It powers a page anyone can open; it is not a contract. |
They are different routes with different rules rather than one route with a flag. Adding auth to the public surface would break the demo; leaving it off the partner surface would make an operator's orders placeable by anyone who learns a player id.
Authorization: Bearer pk_test_... # or sk_live_... in production
X-Predicta-User: your-own-player-id # on every quote and order
Content-Type: application/jsonA machine-readable OpenAPI 3.1 document covering all eighteen paths is at /openapi.json.
Catalogue
/api/v1/eventsAPI keymarkets:read. category, sort, dir, search, tradable, closesAfter, closesBefore, limit (1–100, default 25), cursor. An unrecognised filter value is a 400, not a silently unfiltered catalogue./api/v1/events/{id}API key{id} is an event id or its slug. Scope markets:read./api/v1/categoriesAPI key?category= accepts, with live event counts. Scope markets:read./api/v1/images/{id}No auth{id} is the event id. The only unauthenticated route on this surface, because it is a URL a browser loads.Trading
/api/v1/quotesAPI keyquotes:write. Exactly one of stake (sizes a BUY) or contracts (sizes a SELL). Requires X-Predicta-User./api/v1/ordersAPI keyorders:write. Idempotent on clientOrderId: 201 on creation, 200 with idempotentReplay: true on a replay. Requires X-Predicta-User./api/v1/ordersAPI keyorders:read. externalUserId, clientOrderId (with externalUserId), status, since, until, limit (1–200, default 50), cursor./api/v1/orders/{id}API keysettlementState. Scope orders:read. ?fills=true includes the individual executions.Positions
/api/v1/positionsAPI keypositions:read. externalUserId, status, limit (1–200, default 50), cursor./api/v1/positions/{id}API keypositionId. Scope positions:read.Settlement and reconciliation
/api/v1/settlementsAPI keysettlements:read. externalUserId, outcome, settledFrom, settledTo, limit (1–500, default 100), cursor./api/v1/settlements/positionsAPI keysettledAt. Superseded by /api/v1/settlements, which its own response says in supersededBy: this one pages with no tiebreaker, and settlements written in one transaction share a timestamp exactly./api/v1/reconciliationAPI keyledger:read. Optional from./api/v1/reconciliation/feedAPI keyledger:read. cursor, type (repeatable), externalUserId, limit (1–500, default 100).Sandbox only
These five answer 403 sandbox_only in live mode
They model a per-user balance held by Predicta, which exists so an integration can be learned against simulated money. A live operator owns its customers' cash ledger, so there is nothing here for it to read — the live contract is operatorMoney, operatorExitMoney and settlementCredit.
/api/v1/users/{id}/balanceAPI keyledger:read. Optional currency./api/v1/users/{id}/ledgerAPI keyledger:read. limit (1–200, default 50), cursor./api/v1/funding/supported-assetsAPI keyfunding:write. symbol, symbols, chainId./api/v1/funding/deposit-addressAPI keyfunding:write. 201 on success./api/v1/funding/deposits/{id}API keyfunding:write. ?sync=false skips the bridge poll.Public — no credentials
These power the public site and the public demo. They are useful to read and they are not the partner contract: they name contracts by internal ids, take no key, and carry no operator scoping.
/api/eventsNo auth/api/events/{key}No authrange is 1d, 1w, 1m or all./api/marketsNo auth/api/markets/{id}No auth/api/markets/quotes?ids=…No auth/api/categoriesNo auth/api/settlementsNo auth/api/healthNo auth503 only when the database is down./api/demo/quotesNo auth/api/demo/ordersNo authDo not integrate against /api/demo/* or /api/*
The demo exists so the public page exercises the production path rather than a parallel implementation of it. It is unauthenticated, its identity model is not yours, and it is not a contract. The public catalogue is likewise a website feed: partners read /api/v1/events.
Conventions that hold everywhere
- Auth.
Authorization: Bearer <key>on every/api/v1/*request except/api/v1/images/{id}. Scope is checked before the rate limit is consumed, so a scope mistake never arrives disguised as a429on the retry. - Identity.
X-Predicta-Usercarries your id for the player. Predicta never authenticates end users and stores only that opaque value. A write path creates a user on first use; a read never does. - Idempotency.
clientOrderIdon orders, enforced by a unique index on (operator, user, clientOrderId) rather than by a check in a handler. Retrying is the correct response to a timeout. - Money. Exact decimal strings inside
operatorMoney,operatorExitMoneyand a settlement. Numbers elsewhere are for display. Contract prices are 0–1, and sub-cent prices are real. - Cursors. Keyset, not offset. Loop on
nextCursor; a last page legitimately has none. A malformed cursor is refused rather than treated as “from the beginning”. - Errors. A JSON body with a machine-readable
error. Branch on the code, never on the message. - Rate limits. Per key, per minute.
RateLimit-Limit,RateLimit-RemainingandRateLimit-Resetare on every response, not only on a429. - Timestamps. ISO-8601, UTC, always as strings.
- Sourcing. No response on this surface names a venue. A contract is a
ctr_…id.
Scopes
| Scope | Reaches |
|---|---|
markets:read | events, events/{id}, categories |
quotes:write | quotes |
orders:write | POST orders |
orders:read | GET orders, orders/{id} |
positions:read | positions, positions/{id} |
settlements:read | settlements, settlements/positions |
ledger:read | reconciliation, reconciliation/feed, and the sandbox balance and ledger |
funding:write | all three funding routes, including the two reads |

