Skip to main content
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)

Order reads

Market data

Portfolio (/me/*)

Discovery

Limits above are testnet 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-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:
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.