Skip to main content

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
The integrator API (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).
Never ship an API key to a browser, mobile app bundle, public repo, or any environment a user can inspect. A leaked key is equivalent to a leaked seed phrase for your associated wallet — rotate immediately via the admin panel.

Format

X-Api-Key: ps_live_0123456789abcdef_AbCdEfGhIjKlMnOpQrStUvWxYz1234567
           ├─── env ───┤├── keyId ──┤├──────── secret ─────────┤
SegmentWhat it is
ps_live_ / ps_test_environment prefix — live is production / dev; test reserved for sandbox
keyId16 hex chars. Public handle we look up — safe to put in logs, audit trails, dashboards
secret32 bytes of entropy, base64url-encoded (43 chars). Never logged, never persisted in plaintext server-side
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.
KindWhen ops picks itActing wallet resolution
single_wallet (default)One bot, one strategy, one wallet — the legacy contractpartner.associatedWallet is fixed at creation; every request acts on that wallet
multi_walletTrading firm with N sub-accounts, copy-trading platform, custodial broker — one key fans out across many walletsCaller declares the actor on every request via the X-User-Wallet header
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 the requirePerWalletKyc boolean on the partner record:
requirePerWalletKycCompliance contractUse case
true (default, safe)Each X-User-Wallet sub-account must clear retail KYC via SumSub before the platform accepts orders/withdrawals on its behalf. KycGuard enforces tier ≥ 1 per request.Sub-account models where each wallet is a distinct human (e.g. white-label retail brokers).
falseThe partner has been KYB-onboarded as a legal entity and takes compliance responsibility for every sub-account it dispatches. KycGuard skips. New sub-accounts are auto-onboarded on first request — core.users row created, vault deploy enqueued — without retail KYC.Trading firms / market makers / submitters whose sub-accounts are operational addresses, not retail identities.
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. The associatedWallet 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 plus X-User-Wallet: 0x… on every request:
curl -X POST https://core.api.dev.predictstreet.sde.adifoundation.ai/api/orders/place \
  -H "X-Api-Key: ps_live_0123456789abcdef_AbCdEfGhIjKlMnOpQrStUvWxYz1234567" \
  -H "X-User-Wallet: 0x1234567890AbCdEf1234567890aBcDeF12345678" \
  -H "Content-Type: application/json" \
  -d '{ "maker": "0x1234…", "signature": "0x…", … }'
The header value is lower-cased server-side and becomes the request’s effective wallet for balances, positions, trades, fees, rate-limit buckets, and audit trails — exactly as if a single_wallet key were attached to that wallet. Rules:
  • Header missing → 401 api_key_user_wallet_required.
  • Header malformed (not 0x + 40 hex) → 401 api_key_user_wallet_invalid.
  • KYC enforcement on the header wallet is controlled by the partner’s requirePerWalletKyc flag (see Partner kinds table above). Two options:
    • requirePerWalletKyc: true (default) — every X-User-Wallet sub-account must clear retail KYC (status APPROVED, 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 a vault deploy; subsequent requests use the deployed vault as soon as match-submitter confirms.
  • Each acting wallet still needs its own private key to sign the EIP-712 payload on writes. The on-chain CTFExchange and Vault contracts verify signer ↔ vault cryptographically — looser API-layer attribution costs nothing structurally because the chain is the floor.
  • The wallet you pass in X-User-Wallet must match the maker field inside the order payload (and the EIP-712 signer for that order). Mismatches are caught at the matcher / on-chain layer with bad_signature.

Getting a key

Keys are issued by PredictStreet ops via the admin panel, never self-service. Contact your integration manager with:
  1. Partner name — internal label.
  2. Contact email — for rotation notices, incident pages, and SLA comms.
  3. Partner kindsingle_wallet (default) or multi_wallet. Pick multi_wallet if 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.
  4. Associated wallet — required for single_wallet partners that need write scopes; must have completed SIWE once and cleared KYC tier 1. For multi_wallet partners this field is optional and informational — KYC moves to the partner legal entity.
  5. IP allowlist (optional, recommended). Your egress IPs — if set, any request from a different IP is rejected at the edge.
  6. Requested scopes — what endpoints you plan to hit (see table below).
You will receive the plaintext key exactly once on creation. Copy it into a secrets manager (AWS Secrets Manager, HashiCorp Vault, Kubernetes Secret, 1Password) immediately. We cannot show it to you again — if lost, we revoke and issue a new one.

Scopes

Each key carries a set of scopes. Requests are rejected with 403 api_key_scope_missing if the endpoint requires a scope the key doesn’t carry.
ScopeGrants
markets:readpublic market & orderbook reads (raises your rate-limit ceiling; unauthenticated callers can still hit these)
events:readpublic events reads
matches:readpublic matches reads
portfolio:read/api/me/balances, /api/me/positions, /api/me/trades, /api/me/fees, /api/me/fee-tier, /api/me/vault, /api/me/vault/emergency, /api/me/portfolio, /api/me/deposit-limits, /api/me/withdrawals (list / detail / fee / deposit-sources)
orders:read/api/orders/open, /api/orders/history, /api/orders/{id}, /api/orders/{id}/fills
orders:write/api/orders/place, /api/orders/cancel, /api/orders/cancel-all — for single_wallet partners requires associatedWallet with KYC tier ≥ 1; for multi_wallet partners KYC is at the partner level
vault:write/api/vault/split-signature, /api/vault/merge-signature, /api/withdrawals/request, /api/me/withdrawals/{id}/cancel — same KYC rule as orders:write
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

Require X-Api-Key with the listed scope.
EndpointMethodScope
/api/orders/placePOSTorders:write
/api/orders/cancelPOSTorders:write
/api/orders/cancel-allPOSTorders:write
/api/orders/openGETorders:read
/api/orders/historyGETorders:read
/api/orders/{id}GETorders:read
/api/orders/{id}/fillsGETorders:read
/api/me/vaultGETportfolio:read
/api/me/vault/emergencyGETportfolio:read
/api/me/balancesGETportfolio:read
/api/me/positionsGETportfolio:read
/api/me/tradesGETportfolio:read
/api/me/feesGETportfolio:read
/api/me/fee-tierGETportfolio:read
/api/me/portfolioGETportfolio:read
/api/vault/split-signaturePOSTvault:write
/api/vault/merge-signaturePOSTvault:write
/api/withdrawals/requestPOSTvault:write
/api/me/withdrawalsGETportfolio:read
/api/me/withdrawals/{id}GETportfolio:read
/api/me/withdrawals/feeGETportfolio:read
/api/me/withdrawals/deposit-sourcesGETportfolio:read
/api/me/withdrawals/{id}/cancelPOSTvault:write
/api/me/deposit-limitsGETportfolio:read

Public endpoints

No authentication required. Sending an X-Api-Key is still allowed and raises your per-partner rate-limit ceiling:
  • GET /api/markets, /api/markets/{symbol}, /api/markets/{symbol}/orderbook, /api/markets/{symbol}/trades, /api/markets/{symbol}/ohlc
  • GET /api/events, /api/events/{id}
  • GET /api/matches, /api/matches/{id}
  • GET /api/tags
  • GET /api/platform/notices, /api/platform/status
  • GET /api/compliance/geo
  • GET /health, /ready

WebSocket

Both WebSocket gateways authenticate with the same X-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).
GatewayURLRequired scope
/ws/userwss://ws-gateway.dev.predictstreet.sde.adifoundation.ai/ws/userportfolio:read (for user_activity)
/ws/marketwss://ws-gateway.dev.predictstreet.sde.adifoundation.ai/ws/market— (any active key)
WS channelGatewayRequired scope
user_activity/ws/userportfolio:read
token_trades / token_book / condition_status / system/ws/market

Not available via API key

A small number of surfaces are intentionally not exposed to integrators — they require retail-user SIWE identity and live on app.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:
curl -X POST https://core.api.dev.predictstreet.sde.adifoundation.ai/api/orders/place \
  -H "X-Api-Key: ps_live_0123456789abcdef_AbCdEfGhIjKlMnOpQrStUvWxYz1234567" \
  -H "Content-Type: application/json" \
  -d '{
    "marketId": "UAE-CUP-FINAL-20260425",
    "side": "buy",
    "outcome": "0",
    "price": "0.55",
    "quantity": "100",
    "nonce": "1730289600000000",
    "expiry": 1730376000,
    "maker": "0xYOUR_ASSOCIATED_WALLET",
    "signature": "0x…EIP-712 signature over the order…"
  }'
multi_wallet partner — add X-User-Wallet:
curl -X POST https://core.api.dev.predictstreet.sde.adifoundation.ai/api/orders/place \
  -H "X-Api-Key: ps_live_0123456789abcdef_AbCdEfGhIjKlMnOpQrStUvWxYz1234567" \
  -H "X-User-Wallet: 0x1234567890AbCdEf1234567890aBcDeF12345678" \
  -H "Content-Type: application/json" \
  -d '{
    "marketId": "UAE-CUP-FINAL-20260425",
    "side": "buy",
    "outcome": "0",
    "price": "0.55",
    "quantity": "100",
    "nonce": "1730289600000000",
    "expiry": 1730376000,
    "maker": "0x1234567890AbCdEf1234567890aBcDeF12345678",
    "signature": "0x…EIP-712 signed by that maker's key…"
  }'
maker must equal the request’s effective wallet (the associatedWallet for single_wallet, or the X-User-Wallet header value for multi_wallet) or its VaultFactory-derived vault, and the EIP-712 signature must be signed by that wallet’s private key. Your API key authenticates the HTTP request; the EIP-712 signature authorises the on-chain trade. Neither alone is sufficient — on-chain CTFExchange verifies the signature cryptographically before the tx settles.

What happens on every request

  1. Parse the X-Api-Key header into (env, keyId, secret). Bad shape → 401 api_key_bad_format.
  2. Lookup the key by keyId (Redis cache, 60s TTL; falls through to Postgres on miss). Unknown → 401 api_key_unknown_key.
  3. Verify the hash in constant time. Mismatch → 401 api_key_bad_secret.
  4. Lifecycle checks: revoked → 401 api_key_revoked; expired → 401 api_key_expired; partner suspended → 401 api_key_suspended; source IP not in allowlist (if set) → 401 api_key_ip_denied.
  5. Scope check. Missing → 403 api_key_scope_missing with the required scope in the response body.
  6. Resolve effective wallet — depending on partner kind:
    • single_walletpartner.associatedWallet. Not attached → 401 api_key_no_associated_wallet.
    • multi_wallet → the X-User-Wallet header (lower-cased). Header missing → 401 api_key_user_wallet_required; not a 0x-prefixed 40-hex address → 401 api_key_user_wallet_invalid.
  7. 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 associatedWallet for single_wallet, or the X-User-Wallet header value for multi_wallet). Same ceiling regardless of call volume distribution across your keys.
Both must pass. Response headers expose the tightest applicable bucket’s state (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 — for single_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.
Process:
  1. Issue the replacement key via admin. Both keys now work.
  2. Roll your services to the new key. No downtime.
  3. Revoke the old key via admin. Propagation is near-instant (Redis pub-sub invalidation); worst-case lag 60s.
A revoked key rejects every subsequent request with 401 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. CTFExchange verifies 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-Signature header over timestamp + method + path + body) is on the roadmap as an optional hardening for production partners; not required today.