Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.adipredictstreet.com/llms.txt

Use this file to discover all available pages before exploring further.

Rate limits are enforced at the core-api edge. Every authenticated request passes through two independent buckets:
  • ip — per source IP (behind the ingress; respects X-Forwarded-For set by the trusted load balancer). Cheap edge defence that applies to anonymous and authenticated traffic alike.
  • wallet — per your key’s associatedWallet (single_wallet partners) or per the X-User-Wallet header value (multi_wallet partners). Prevents a single wallet identity from exceeding the platform’s per-user ceiling regardless of how the calls are distributed across your keys.
Both must pass; a single rejection returns 429 and sets Retry-After to the tightest bucket’s reset delta. Response headers (X-RateLimit-Limit, -Remaining, -Reset) expose the tightest applicable bucket. A per-partner organisation-wide bucket lives on the partner record (rateLimitPerMin) but is not currently enforced at the request boundary. If you need a partner-wide ceiling, operations can lower your per-wallet cap as a stop-gap — contact your integration manager.

Limits

Trading and write paths use per-second wallet windows (anti-burst); read paths use per-minute windows. The two scopes (ip and wallet) are independent — each request must pass every applicable bucket.

Trading (writes)

EndpointScopeLimitWindow
POST /api/orders/placeip100060s
POST /api/orders/placewallet201s
POST /api/orders/cancelwallet201s
POST /api/orders/cancel-allwallet11s
POST /api/vault/split-signature, /merge-signature, /convert-signaturewallet31s
POST /api/vault/* (umbrella)ip10060s

Order reads

EndpointScopeLimitWindow
GET /api/orders/openwallet30060s
GET /api/orders/historywallet30060s
GET /api/orders/{id}wallet30060s
GET /api/orders/{id}/fillswallet30060s

Market data

EndpointScopeLimitWindow
GET /api/markets, /api/markets/:slug, /api/markets/:symbol/orderbookip60060s
GET /api/markets/:symbol/tradesip24060s
GET /api/markets/:symbol/price-historyip24060s
GET /api/markets/:symbol/tradersip12060s
GET /api/markets/:symbol/ohlc (deprecated)ip12060s

Portfolio (/me/*)

EndpointScopeLimitWindow
GET /api/me/vault, /me/balances, /me/positions, /me/portfolio, /me/fee-tier, /me/trades, /me/fees, /me/auto-redeemwallet60060s
GET /api/me/deposit-limitswallet12060s
POST /api/me/vault/emergencywallet12060s
GET /api/me/withdrawals, /me/withdrawals/{id}, /me/withdrawals/deposit-sourceswallet6060s
GET /api/me/withdrawals/feewallet3060s
POST /api/me/withdrawals/{id}/cancelwallet1060s
POST /api/withdrawals/requestip6060s

Discovery

EndpointScopeLimitWindow
GET /api/leaderboardip60060s
GET /api/leaderboard?search=…ip12060s
GET /api/search, /api/search/*ip6060s
Limits above are production defaults. Staging and mainnet may run tighter or looser values — your onboarding runbook contains the authoritative table for the environment you are connected to.

Counter behaviour

Buckets are fixed-window with a Redis-backed counter that re-applies its TTL on every access where the key has lost it (Redis maxmemory eviction races, manual PERSIST, replica-failover key loss, snapshot reload). Earlier deploys had a class of stuck-counter behaviour where a key without a TTL kept incrementing without ever expiring; clients saw X-RateLimit-Remaining flat-line at 0 and Retry-After never counting down. That class is fixed — every request you make now either decrements Remaining or surfaces a real countdown to refill. ip buckets key on the real client IP, not the immediate TCP peer. We honour X-Forwarded-For from the trusted ingress hop, so partners behind shared edges (Cloudflare, corporate egress proxies) no longer collide on a single bucket. If your traffic transits an extra proxy hop your onboarding manager hasn’t seen, raise it during integration so we can adjust the trusted-hop count.

Response headers

Every rate-limited response includes:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 60
  • X-RateLimit-Reset is delta-seconds until the bucket refills — i.e. the value 60 means “wait 60 seconds and the limit resets”. This deliberately matches Retry-After semantics; both are seconds-until-refill, not Unix epoch.
  • The HTTP header Retry-After is set to the same delta-seconds on every 429.
  • On 429 Too Many Requests, the response body uses the standard error envelope:
{
  "status": "error",
  "error": {
    "code": "rate_limited",
    "message": "place-order budget exhausted",
    "trace_id": "..."
  }
}
Read the seconds-to-wait from the Retry-After header — it is not duplicated inside the body.

Retry guidance

  1. On 429: wait Retry-After (header value, in seconds) before retrying. Do not retry sooner — the bucket has not refilled.
  2. Backoff on 5xx: exponential backoff with jitter, starting at 200ms, capped at 10s. Maximum 3 attempts for idempotent calls (GET, DELETE). Do not retry non-idempotent writes (POST /orders, POST /withdrawals/request) automatically — they accept a clientOrderId / nonce for deduplication if your design requires retries.
  3. Circuit-break on persistent 5xx: if your error rate exceeds 50% over 30 seconds, stop sending new requests for 60 seconds.

Higher limits

Partners with justified high-throughput needs (market makers, volume traders) can request bespoke limits at onboarding:
  • wallet-scoped ceilings can be lifted 10–50× on the place / cancel endpoints.
  • ip-scoped limits are lifted on a per-whitelisted-IP basis.
  • Platform-wide ceilings cannot be exceeded; they protect the shared matcher.
Contact partners@predictstreet.com with your expected peak throughput profile.