Who this is for
Your backend calls the PredictStreet integrator API. Examples:- Market-maker bot quoting a pre-approved wallet
- Copy-trading service mirroring strategy signals
- Data pipeline pulling your positions / fills into a warehouse
- Mobile backend that never ships secrets to the device
core.api.dev.predictstreet.sde.adifoundation.ai) is designed for
server-to-server traffic. Retail users don’t authenticate here —
they log into app.predictstreet.io with SIWE (off the scope of
this documentation).
Format
Only a SHA-256 hash of
secret (peppered with a server-side salt) is
stored. If our database leaks, your secret does not.
Partner kinds
Every partner is one of two kinds. The kind is set at partner creation and decides where the request’s acting wallet comes from.
Kind is stamped on the key when admin issues it. Switching kinds
post-issuance is supervised — operations refuses the flip if any active
key under the partner relies on the prior contract.
Compliance toggle on multi_wallet
Multi_wallet partners come in two compliance flavours, set by therequirePerWalletKyc boolean on the partner record:
Single_wallet partners always enforce KYC at API key creation time
(the partner’s
associatedWallet must be APPROVED tier ≥ 1 before
any write-scope key issues), so the toggle is inert there.
single_wallet flow
Send the API key, nothing else. TheassociatedWallet on the partner
record is the request’s effective wallet for KYC, compliance, and
rate-limit buckets. Any X-User-Wallet header is ignored — the
legacy contract is preserved for SDKs that don’t know about the header.
If a single_wallet partner has no associatedWallet attached yet,
every authenticated endpoint rejects with 401
api_key_no_associated_wallet — admin must attach one before writes
or /me reads work.
multi_wallet flow
Send the API key plusX-User-Wallet: 0x… on every request:
- Header missing → 401
api_key_user_wallet_required. - Header malformed (not
0x+ 40 hex) → 401api_key_user_wallet_invalid. - KYC enforcement on the header wallet is controlled by the partner’s
requirePerWalletKycflag (see Partner kinds table above). Two options:-
requirePerWalletKyc: true(default) — every X-User-Wallet sub-account must clear retail KYC (statusAPPROVED, tier ≥ 1) via the same SumSub flow a retail user goes through. Used for sub-account models where each underlying wallet is a distinct person (Coinbase Prime style). -
requirePerWalletKyc: false— the partner is KYB-onboarded as a legal entity and takes compliance responsibility for its sub-accounts. KycGuard skips. Used for trading firms / market makers / submitters whose addresses are operational, not retail identities. The first request through the key for a previously unseen X-User-Wallet auto-enqueues:- vault deploy (
VaultFactoryon-chain, ~10 sec to confirm); - on-chain cap-opening —
DepositLimitRegistry.setCustomCapsto 100,000 USDC across singleDeposit / 30d / 12m, plussetDepositsRestricted(false)/setTradingRestricted(false)/setWithdrawalsRestricted(false). Match-submitter broadcasts all four ops; the sub-account is fully usable end-to-end (deposit + trade + withdraw) within ~30 sec of the first request. Without this auto-step the wallet would otherwise be stuck at retail-tier 0 caps (0/0/0) which would block everyvault.depositERC20withDepositCapExceededand everyplaceOrderwith the trading-restricted flag.
- vault deploy (
-
- Each acting wallet still needs its own private key to sign the EIP-712
payload on writes. The on-chain
CTFExchangeandVaultcontracts verify signer ↔ vault cryptographically — looser API-layer attribution costs nothing structurally because the chain is the floor. - The wallet you pass in
X-User-Walletmust match themakerfield inside the order payload (and the EIP-712 signer for that order). Mismatches are caught at the matcher / on-chain layer withbad_signature.
Getting a key
Keys are issued by PredictStreet ops via the admin panel, never self-service. Contact your integration manager with:- Partner name — internal label.
- Contact email — for rotation notices, incident pages, and SLA comms.
- Partner kind —
single_wallet(default) ormulti_wallet. Pickmulti_walletif one key needs to act across many end-user wallets (trading desk with N sub-accounts, copy-trading platform, custodial broker). See Partner kinds above. - Associated wallet — required for
single_walletpartners that need write scopes; must have completed SIWE once and cleared KYC tier 1. Formulti_walletpartners this field is optional and informational — KYC moves to the partner legal entity. - IP allowlist (optional, recommended). Your egress IPs — if set, any request from a different IP is rejected at the edge.
- Requested scopes — what endpoints you plan to hit (see table below).
Scopes
Each key carries a set of scopes. Requests are rejected with 403api_key_scope_missing if the endpoint requires a scope the key
doesn’t carry.
Multiple scopes listed on an endpoint are all required (intersection,
not union). For most partners,
orders:write + orders:read +
portfolio:read covers the day-one scope.
Endpoint coverage
Authenticated endpoints
RequireX-Api-Key with the listed scope.
Public endpoints
No authentication required. Sending anX-Api-Key is still allowed
and raises your per-partner rate-limit ceiling:
GET /api/markets,/api/markets/{slug},/api/markets/{symbol}/orderbook,/api/markets/{symbol}/trades,/api/markets/{symbol}/ohlcGET /api/events,/api/events/{id}GET /api/matches,/api/matches/{id}GET /api/tagsGET /api/platform/notices,/api/platform/statusGET /api/compliance/geoGET /health,/ready
WebSocket
Both WebSocket gateways authenticate with the sameX-Api-Key as
HTTP — send either the X-Api-Key header on the upgrade or a
?key=<token> query parameter (for browser clients that can’t set
headers on the WebSocket upgrade).
Not available via API key
A small number of surfaces are intentionally not exposed to integrators — they require retail-user SIWE identity and live onapp.predictstreet.io. As of the current release these include the
self-service profile / consent / KYC submission flows: partners
shouldn’t drive end-user identity capture from server-side because
SUMSUB and the geo-fingerprinting layer expect the live retail
session.
Withdrawals are now fully partner-driven via API key (request,
list, detail, cancel) — the vault-owner EIP-712 signature still gates
funds movement, so an API key alone cannot move money out of a vault.
See Withdrawals overview for the
dual-signature flow.
If you have a use case that needs something currently outside the
API-key scope, reach out — some can be unlocked with a stricter scope
set, others are architecturally out of scope.
Making a request
single_wallet partner:X-User-Wallet:
What happens on every request
- Parse the
X-Api-Keyheader into(env, keyId, secret). Bad shape → 401api_key_bad_format. - Lookup the key by
keyId(Redis cache, 60s TTL; falls through to Postgres on miss). Unknown → 401api_key_unknown_key. - Verify the hash in constant time. Mismatch → 401
api_key_bad_secret. - Lifecycle checks: revoked → 401
api_key_revoked; expired → 401api_key_expired; partner suspended → 401api_key_suspended; source IP not in allowlist (if set) → 401api_key_ip_denied. - Scope check. Missing → 403
api_key_scope_missingwith the required scope in the response body. - Resolve effective wallet — depending on partner kind:
single_wallet→partner.associatedWallet. Not attached → 401api_key_no_associated_wallet.multi_wallet→ theX-User-Walletheader (lower-cased). Header missing → 401api_key_user_wallet_required; not a 0x-prefixed 40-hex address → 401api_key_user_wallet_invalid.
- Set identity — the resolved wallet becomes the request’s effective wallet for all downstream checks (KYC, compliance, rate-limit buckets, audit trails).
Rate limits
Every API-key request passes through two independent buckets:- IP bucket — shared edge defence (same as anonymous traffic).
- Wallet bucket — per effective wallet (the
associatedWalletfor single_wallet, or theX-User-Walletheader value for multi_wallet). Same ceiling regardless of call volume distribution across your keys.
X-RateLimit-Limit, -Remaining, -Reset). On
429, Retry-After is set to the bucket-reset delta.
Per-partner organisation-wide bucket exists in the partner record
(rateLimitPerMin) but is not currently enforced at the request
boundary. Contact your integration manager if you need a
partner-wide ceiling — operations can lower the per-wallet cap as
a stop-gap.
Geo handling
Geographic blocking (FATF blacklist / greylist) does not apply to API-key requests — integrator egress IPs are data-centre / VPN class and blocking them isn’t a meaningful control (you could proxy trivially). Compliance stays in force at the wallet level via KYC / AML / RG gates on the effective wallet — forsingle_wallet
that’s the partner’s associatedWallet, for multi_wallet that’s
the partner legal entity that took on the regulated counterparty
obligation.
Rotation
Rotate keys pre-emptively on any of:- Employee who had access leaves.
- Secrets-manager misconfiguration suspected.
- Source-code leak.
- Routine 6-month rotation hygiene.
- Issue the replacement key via admin. Both keys now work.
- Roll your services to the new key. No downtime.
- Revoke the old key via admin. Propagation is near-instant (Redis pub-sub invalidation); worst-case lag 60s.
api_key_revoked. Re-enabling is not supported — issue a new key.
Security invariants
- X-Api-Key is the only session scheme. No cookies, no bearer
tokens, no basic-auth fallback on
core.api.dev.predictstreet.sde.adifoundation.ai. Missing or malformed header on an authenticated endpoint → 401. - Scopes are enforced server-side. Adding a scope to your key’s stored list is the only way to access a gated endpoint — client-side claims are ignored.
- Writing still requires EIP-712. The API key proves you’re a
pre-approved partner; the EIP-712 order signature proves you
authorised the specific trade.
CTFExchangeverifies this cryptographically on-chain — no compromise of our infrastructure lets anyone move your funds without your private key. - HMAC request signing (adding an
X-Api-Signatureheader overtimestamp + method + path + body) is on the roadmap as an optional hardening for production partners; not required today.