X-Api-Key —
backed by a per-partner secret your ops contact hands you at
onboarding. There is no OAuth, no SIWE, no cookie session. Public
read endpoints (markets / events / matches / tags) need no key. They
are rate-limited per source IP, so sending a key does not change
their limit.
First time here?
1
Get an API key
Partner keys are issued by PredictStreet ops, never self-service. Email
your integration manager (or
partners@predictstreet.com)
with the items listed in
API keys → Getting a key:
partner name, contact email, partner kind (
single_wallet or
multi_wallet), associated wallet (the EOA you’ll sign EIP-712
orders with; required for single_wallet write keys), and the
scopes you need.2
Walk through the testnet quickstart
Quickstart walks the private key of your
associatedWallet through five steps — mint test USDC, get your
vault address, approve and deposit, sign and place orders, and
split USDC into YES + NO so you can sell. Every code block is real
ethers v6 against the live testnet; copy-paste, swap your secrets,
run.3
Mental model — Wallet, vault, scopes
A
single_wallet key is bound at issue time to one associated
wallet — the EOA whose private key you hold and which signs
EIP-712 orders. A multi_wallet key is not bound to a wallet: you
name the acting wallet on every request with the X-User-Wallet
header. Each acting wallet has its own vault contract that
holds your USDC and your outcome shares; the vault is the maker
field of every signed Order. The platform deploys vaults for you
when the wallet is onboarded (see
Backend auto-deploy) — for
multi_wallet partners without per-wallet KYC, on the wallet’s
first API request — so you never call
VaultFactory.deployVault() yourself. Scopes
on the key gate which endpoint groups the key can hit
(orders:write, portfolio:read, vault:write, public reads).
The full mental model lives at
Platform overview; the concept pages on
Vaults and
Deposits round it out.Authentication on the playground
Every locked endpoint shows a lock icon withApiKey. To enable
Try-it-out:
- Click Authorize.
- Paste the full key (e.g.
ps_live_0123456789abcdef_AbCdEfGhIjKlMnOpQrStUvWxYz1234567) into the X-Api-Key field. - The key persists across endpoint pages in your browser session.
orders:write, portfolio:read, etc.) or
the request returns 403 api_key_scope_missing.
For multi-wallet partners (one key dispatching N actor wallets), set
the X-User-Wallet header on every request to the actor wallet
the call should run as. Single-wallet partners ignore that header —
the key’s static associatedWallet is used unconditionally. See
Partner kinds
for the full distinction.
See API keys for format, full scope taxonomy,
endpoint coverage table, rate-limit buckets, and rotation
procedure.
Endpoint groups
Use the left sidebar to browse. The Scope column lists the API-key scope each group requires — write scopes (orders:write,
vault:write) are issued to a single_wallet key only once its
associatedWallet has cleared KYC tier 1. For multi_wallet
partners the check moves to request time: each X-User-Wallet must
clear KYC itself unless the partner has requirePerWalletKyc: false;
see Partner kinds.
Surfaces that require a signed-in retail user session (user profile, KYC
submission, consent management, responsible-gambling, session
management) live on the retail web surface — the web app at
app.dev.predictstreet.sde.adifoundation.ai on testnet, adipredictstreet.com on
mainnet — and are intentionally not exposed to integrators. The
SUMSUB / geo-fingerprinting layer expects a live retail session for
those flows. Partners who need a use case currently outside the
API-key surface should reach out — some can be unlocked with a
stricter scope set, others are architecturally out of scope.
Conventions
- Base URL:
https://core.api.dev.predictstreet.sde.adifoundation.ai(testnet). Staging and mainnet URLs delivered at partner onboarding. - Numeric fields are encoded as strings to preserve precision
(e.g.
"price": "0.52", not0.52). Deserialize intodecimal.Decimal/BigDecimal/ethers.parseUnits— notNumber. - Timestamps are ISO-8601 UTC (e.g.
"2026-04-22T10:31:05.124Z"). - Errors share a common envelope:
{ status, error: { code, message, trace_id?, retryAfterSec?, retryable?, details? } }. Switch onerror.code. See Errors overview and Error codes for the full catalogue. - Rate limits — each endpoint applies a per-IP bucket, a
per-wallet bucket, or both (the
/api/v1/partner/*feeds are also bucketed per partner); see Rate limits. - Pagination — list endpoints use endpoint-specific offset, page-number, cursor, or time-cursor pagination. See Pagination for the complete endpoint matrix and limits.
- Business rejects on some endpoints return HTTP
200(or201for POSTs) with astatus: "REJECTED"+codefield inside the response envelope — notablyPOST /api/orders/place, which returns201 Createdeven when the matcher rejects the order. Always read the body’sstatusfield, not just the HTTP code. Full catalogue in Errors overview. - Enum query params reject unknown values with HTTP
400instead of returning an empty page; the code is endpoint-specific. For example,?status=CANCELED(one L) on/api/orders/historyreturnsinvalid_request(the failing field is inerror.details.fields), and an unknown?interval=on/api/markets/{symbol}/ohlcreturnsinvalid_intervalwith the accepted values inerror.details.allowed. - Unknown query params — handling is endpoint-specific.
/api/orders/open,/api/orders/history,/api/v1/partner/trades,/api/v1/partner/mm-kpisand/api/v1/partner/reconciliation/snapshotreject any parameter they don’t define with400 invalid_request./api/eventsrejectsoffset,cursor,skip,startandpageSizewith a400. Other endpoints currently ignore unknown parameters. Send only the parameters documented for each endpoint. - Address case — compare addresses case-insensitively. Most
responses return lowercase addresses, but some fields are EIP-55
checksum-cased — for example
walletAddresson/api/leaderboardandmakerWallet/takerWalleton/api/markets/{symbol}/trades. Lowercase both sides before comparing. Request bodies and headers accept either case. - Order id field — created via
POST /api/orders/placereturns the identifier underorderId; the same value surfaces underidonGET /api/orders/{id},GET /api/orders/open, andGET /api/orders/history. The cancel request body usesorderIdto match the placement response. Treat both names as the same value — the variance is request-vs-response convention, not a different identifier. Without the id (for example after a place request timed out),GET /api/orders/lookupfinds the order by yourclientOrderIdor its EIP-712orderHash. - Standard response headers — every response carries these
beyond the rate-limit triple already documented in
Rate limits:
X-API-Version— additive version tag (2026-04-01today). Breaking changes go to/api/v2/*; the header lets a client pin behaviour without parsing URLs.X-Server-Time— server wall-clock in ms epoch, stamped when the request is received, before it is processed. The WebSocket companion is theserverTsfield stamped on every outbound frame; compare the two to order events across the transports. The response body may already reflect events stamped slightly afterX-Server-Time.X-Request-Id— unique per-request identifier echoed in audit logs. Include it when filing a support ticket so ops can correlate end-to-end. All three are in the CORSAccess-Control-Expose-Headersallowlist so browser clients can read them on cross-origin responses.
Where to go next
API keys — format, scopes, rotation
The canonical reference for the auth header, scope taxonomy,
multi_wallet vs single_wallet kinds, and key rotation procedure.
Quickstart — testnet end-to-end
Five-step copy-paste from API key to deposited, trading vault
against the live testnet.
Vaults — what they are + how they deploy
Why every partner has a vault, how auto-deploy works, what
Order.maker should be, and when you’d ever deploy manually.EIP-712 signing — Order struct + domain
The 11-field
Order struct, the binary vs neg-risk
verifyingContract swap, and end-to-end signing examples.