Skip to main content
Rate limits are enforced by the REST API and counted in three kinds of independent bucket:
  • 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. An IPv6 caller is counted per /64 prefix, not per address, so every address in one /64 shares a bucket. IPv4 is counted per address.
  • 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.
  • partner — per partner, shared by all of your API keys (partner-only endpoints such as GET /api/platform/maintenance). Scaled by your rate tier like wallet buckets.
Every bucket that applies to an endpoint (see the tables below) must pass. The first exhausted bucket returns 429, with Retry-After set to that bucket’s wait. The X-RateLimit-Limit / -Remaining / -Reset headers describe the endpoint’s own bucket (the wallet bucket where one applies), not necessarily the tightest one. A shared ip bucket, such as the 6000/min bucket that every /api/orders/* call from one IP counts against, can run out while these headers still show wallet headroom. If many wallets trade from one IP, budget for the ip buckets yourself. Your partner record carries a rate tier (rateLimitPerMin, default 600). On API-key requests it scales every wallet-scoped limit in the tables below: effective limit = floor(listed limit × rateLimitPerMin / 600), minimum 1. The default 600 gives the listed values; 1200 doubles every wallet limit. ip-scoped limits are the same for every caller and are never scaled.

Limits

Order placement / cancellation and the vault split / merge / convert signatures use per-second wallet limits (anti-burst); other paths use per-minute windows (a few, such as PUT /api/me/auto-redeem, longer). The two scopes (ip and wallet) are independent — each request must pass every applicable bucket.

Trading (writes)

Order reads

Market data

Portfolio (/me/*)

Discovery

Platform

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

Most buckets are fixed windows: the window starts with the first request and the count resets when it ends. The wallet buckets of POST /api/orders/place, /place-batch, /cancel and /cancel-batch are token buckets instead: the listed limit is the burst size, and it refills continuously at limit ÷ window (for place, a burst of 20, then 20 per second sustained). Every request you make either decrements X-RateLimit-Remaining or, once the bucket is empty, reports 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 each client is bucketed by the public IP it connects from, not by the platform’s own edge proxies. Clients that share one public egress IP (a corporate proxy or NAT) share one ip 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, not a Unix epoch. On fixed-window buckets it is the seconds until the window resets (60 means “the limit resets in 60 seconds”). On the token-bucket order endpoints it is 0 while you still have budget and, on a 429, the seconds until the next request fits.
  • 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:
error.retryAfterSec carries the same seconds-to-wait as the Retry-After header, for clients that cannot read response headers.

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). Never re-sign a write to retry it after a 5xx — a new signature is a second order or withdrawal. Resend the identical request instead. For POST /api/orders/place and /place-batch, the same signed order under the same clientOrderId returns the original result (see placement_unknown in Error codes). For POST /api/withdrawals/request, the same body with the same signed salt never creates a second withdrawal.
  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 a higher rate tier at onboarding:
  • wallet-scoped ceilings are raised through your partner rate tier (rateLimitPerMin), which scales every wallet-scoped limit together (see the top of this page).
  • ip-scoped limits are the same for every caller behind an IP; they are not raised per partner or per IP.
  • Platform-wide ceilings cannot be exceeded; they protect the shared matcher.
Contact partners@predictstreet.com with your expected peak throughput profile.