Vatic gives you information: which platforms offer a game, what each outcome means, live prices and the identifiers to act on an outcome. Vatic never places or signs orders for you. Orders are built and signed by your code, with your wallet or your platform account.
The path
1. Find the game
espn:401878773), status (scheduled, live, finished, postponed, cancelled), a time block (kickoff, estimated end, 90th-percentile end) and, once it has started, a score:
score is null before kickoff. It is refreshed about once a minute while the game is live, so it is minute-fresh, not tick-by-tick: do not use it to react faster than the markets themselves. platforms lists where the game is offered, and coverage tells you what we know about the rest (read Games and platforms before treating a missing platform as “not offered”).
If you already hold a platform’s own id (a Polymarket slug, for example), GET /games/lookup?source=polymarket&external_id=... returns our game id.
2. Compare the same bet across platforms
GET /games/{id}/markets returns every stored market of the game. Each has a canonical meaning so the same bet lines up across platforms:
Compare only markets with the same
(key, period, includes_overtime). Outcomes called not:<x> are complements: show the positive outcome and derive the other.
3. Open the live order books
markets=main is the 1X2 or moneyline, classified adds every market with a canonical meaning (totals, spreads, both-teams-to-score and their half-time variants), and all includes the rest. For each platform you get the socket URL, the identifiers to subscribe to, and the exact subscribe messages. Open one socket per platform, never one per outcome.
Limitless and Predict.fun publish only the YES book of a market. The NO side is derived: price
1 - p, bids and asks swapped (the book.side of each outcome tells you which side you are looking at).
In our tests (2026-10-10) the Predict.fun WebSocket streamed order books without an API key, while its REST API needs one. That is observed behaviour, not a documented guarantee: if your product depends on it, confirm with Predict.fun.
server/docs/game-graph/examples/best_price.js.
4. Act on an outcome: the trade object
Every outcome carries trade. Pick the outcome with the best price, then read the identifiers for its platform:
Every
trade also has complement (the opposite outcome’s identifiers, handy for selling by buying the other side), tradable, submit (how to build and send the order), caveats and reference links. Fields a platform does not give us are null.
What building the order looks like
These are the shapes from each platform’s own documentation or SDK. Check them against the platform’s current docs before you rely on them in production, and test with small sizes. Polymarket, with@polymarket/clob-client-v2 (our own validated V2 setup):
order action to POST https://api.hyperliquid.xyz/exchange, signed as an L1 action (use an official SDK for signing). The asset is the field from the trade object:
POST https://api.limitless.exchange/orders with marketSlug, your ownerId (your own profile id), orderType and an order signed with EIP-712. The domain is Limitless CTF Exchange, version 1, chain 8453, and verifyingContract is trade.contracts.exchange. The signed struct has salt, maker, signer, taker, tokenId, makerAmount, takerAmount, expiration, nonce, feeRateBps, side, signatureType, and tokenId is trade.instrument.token_id.
Predict.fun, with @predictdotfun/sdk:
What we do not store (so read it from the platform)
Thecaveats array of each trade object says this per outcome. In short: Hyperliquid does not publish tick size, lot size or minimum order for outcome markets (the quote token, USDC, is stored; its price rule is 5 significant figures and at most 8 minus szDecimals decimals); Limitless’s settings.minSize is exposed as order.min_size_raw exactly as returned (a 6-decimal raw integer string) because its unit is not documented, and it publishes no tick; Predict.fun publishes no minimum size; the collateral of Predict.fun yield-bearing markets is not published with the market; and Polymarket reports its minimum size without a unit. is_yield_bearing (Predict.fun) and the collateral (Limitless) fill in as soon as the worker re-reads a market and are null until then.
instrument.share_decimals is the number of decimals of the outcome (share) token, for sells, balances and rounding a size: Polymarket 6, Limitless 6, Predict.fun 18, Hyperliquid 0. share_decimals_basis says how we know. For the three CTF-based platforms one unit of collateral mints one unit of outcome token, so shares use the collateral’s decimals, which we read on-chain (Polygon pUSD 6, Base USDC 6, BNB USDT 18). Hyperliquid’s 0 is observed (integer sizes only), not published. For Predict.fun yield-bearing markets it is null, because their collateral is not published. Buying with a USD amount does not need it; sells, positions and size rounding do.
Some values are labelled by how we know them, so you can decide how far to trust them:
- Hyperliquid
order.observed: sizes were integers only and prices had at most 5 significant figures on every live outcome book we sampled (1,396 levels over 54 books, 2026-10-11). This is observed, not published by Hyperliquid. - Predict.fun
order.price(min,max,tick, withderived: true): derived fromdecimal_precision, not published as such.instrument.index_setis the outcome’sindexSetexactly as its market payload gives it (1 and 2); Predict.fun documents it for redemption only, so confirm its use for orders with one small order. - Limitless
order.fees:enabledis the market’smetadata.feeflag andfee_freeis its negation (scheduleisnullfor fee-free markets).scheduleis the CLOB taker curve published at docs.limitless.exchange/user-guide/fees (only the published points; takers only, buy fees paid in outcome tokens, sell fees in collateral). The per-userfeeRateBpscomes from your own profile (rank.feeRateBps), not from the market, and the signed order must carry the same value. - Limitless
order.min_size_rawissettings.minSize, described by Limitless as “minimum trade size in wei” (6-decimal base units); it does not say whether that counts shares or collateral.order.fees.enabledis the market’smetadata.feeflag; no fee rate is published in the market data.
5. Keep it healthy
- Keys and limits. Send
x-api-keyorAuthorization: Bearer. Limits are per key and reported inX-RateLimit-*; on429waitRetry-After. Data refreshes about every 15 seconds on our side, so poll/gamesno faster than that and sendIf-None-Match(a304is almost free). - Prices come from the platforms, not from us. Treat our REST data as discovery and identity, and the sockets as the source of live prices. A stale book (no update for about a minute) should be treated as unknown, not as the last price.
- Re-resolve when things change. A game can move (
time.previous_kickoffskeeps the history) and markets open and close. Re-read/marketsor/streamswhen a game’s status changes and before a session. - Your platform accounts are yours. Wallets, allowances, API keys and fees are between you and each platform. Vatic does not hold funds and does not see your orders.
- What you can show to whom. Every source carries a
redistributableflag. Keys only receive data from sources cleared for redistribution; if a game or platform you expect is missing,meta.withheldsays how many games were held back and why.
Related
Games and platforms
Games, coverage and canonical markets in detail.
Streams endpoint
Subscribe messages and identifiers per platform.
Markets endpoint
Markets with outcomes, order book keys and trade objects.