Skip to content

GuidesResources

Each rule below follows from something documented elsewhere. The reasoning is included so you can decide when it does not apply to you.

Response compression is rolling out on data.predictefy.com from 2026-10-05: JSON and NDJSON responses of 1,024 bytes or more are compressed (gzip or deflate) when the client sends Accept-Encoding (the SDKs do this automatically); exec.predictefy.com does not compress responses. Make a proxy safe before it reaches you. Any HTTP client that decompresses transparently (Node.js fetch, undici, node-fetch, Python requests, httpx, aiohttp) returns decoded bodies but retains upstream Content-Encoding and Content-Length. Before re-emitting a response, drop both headers, re-serialize parsed JSON without upstream headers, or request Accept-Encoding: identity.

Read the venue’s has map or the capabilities field rather than discovering a gap through a caught exception. Seventeen venues genuinely differ, and NOT_SUPPORTED is an answer rather than a fault. See Capability-honest data.

Venues without a real order book return a book-shaped response labelled synthetic. It is a faithful representation of price and is not orders anyone can fill against. Feeding it into a sizing calculation produces a number with no meaning.

Do not equate similar markets across venues

Section titled “Do not equate similar markets across venues”

Matched clusters carry a similarity score, not an identity claim, and two venues can settle what looks like the same question differently. A price gap is an indicative price discrepancy until every executable gate passes.

A timestamp you generate on receipt describes your request. asOf describes the data.

Slugs derive from titles and change when a venue renames a market. See Identifiers.

Follow cursors instead of parallelising offsets

Section titled “Follow cursors instead of parallelising offsets”

nextCursor freezes the catalog snapshot from page one, so a long walk never skips or double-counts rows that move while you page. Parallel offset pages give up that guarantee and spend the rate allowance faster.

Offsets above 10,000 are rejected. Snapshot/offset cursors are signed; if a cursor fails validation, restart the walk from page one.

Cursors do not live forever: each one carries a TTL, and on live-published surfaces such as arbitrage it is also pinned to the publish it started on. Either way a stale cursor returns 400 VALIDATION_ERROR with Cursor has expired — treat that as the signal to restart the walk from page one, not as an error to retry.

fetchOrderBooks takes many outcomes in one request. It is priced by items, so it saves rate allowance rather than credits.

A WebSocket subscription delivers book and trade updates without consuming the request window. Streaming is metered at 2 credits per connection-minute (800 while a Polymarket pending-fills subscription is held); polling also consumes the request allowance and the endpoint’s credits.

Capability maps and taxonomy change rarely. Re-fetching them per query is pure overhead. Authenticated API responses carry Cache-Control: no-store, so browsers and shared HTTP caches do not store them; keep those values in your own application cache instead.

History is priced per query regardless of range, but a narrower window returns faster and is less likely to hit a lane bound.

Branch on code and retryable, not on HTTP status

Section titled “Branch on code and retryable, not on HTTP status”

Several codes share a status, and retryable is the field that answers the question you are actually asking. See Errors.

Retry only when retryable is true, with exponential backoff and jitter

Section titled “Retry only when retryable is true, with exponential backoff and jitter”

That includes retryable 502 upstream and relay failures as well as 429 and 503. Errors marked non-retryable fail identically on the second attempt. INSUFFICIENT_CREDITS in particular will not resolve by retrying.

A market with no trades today returns an empty tape. fetchSeries on a venue without the concept returns an empty list. Neither is an error.

Handle 503 on billing-session writes while other routes keep flowing

Section titled “Handle 503 on billing-session writes while other routes keep flowing”

When rate limiting is degraded, only the zero-credit checkout, subscribe, and portal routes fail closed. Reads and other writes are not in that special fail-closed set. The narrow guard prevents unlimited billing-session creation while the limiter is unavailable.

Send keys in the Authorization header, never in a query string

Section titled “Send keys in the Authorization header, never in a query string”

Query strings end up in request logs, browser history, and referrer headers.

Only a hash of the key authenticates requests; the console keeps an encrypted copy solely so the API keys page can show it to its owner again. A key that reaches a browser bundle is disclosed permanently and must be revoked or regenerated.

Predictefy REST sends no CORS headers by design, so proxy browser history calls through your server. WebSocket first-frame authentication is the one sanctioned browser use. Give that page a dedicated read-only key with no trade or sql scope, treat it as disclosed, and be prepared to revoke it.

Rate limits and credit spend are tracked per key, so one key across staging and production makes both untraceable and lets a test loop exhaust a production allowance.