GuidesCookbook
Compare one market across every venue
“Will the Fed cut in January?” trades on several venues at once, under different titles, different tickers, and occasionally different resolution rules. This recipe lines them up.
The one-call version
Section titled “The one-call version”compareMarketPrices exists for exactly this. Call it on the router exchange with a market from
any venue and it returns that anchor’s cross-venue comparison directly — no cluster lookup needed.
curl -s "$PREDICTEFY_API_URL/api/router/compareMarketPrices?marketId=polymarket:MARKET_ID&live=true" \ -H "Authorization: Bearer pk_live_YOUR_KEY"It takes a canonical venue:marketId value or slug, plus live, limit, offset and
page. The anchor market is excluded; each row is one other cluster member:
{ "success": true, "data": [ { "market": { "...": "the normalized market record for this venue" }, "venue": "polymarket", "clusterId": "clr_9f2a7c41", "similarity": 0.94, "reasoning": null, "bestBid": 0.412, "bestBidMeta": { "asOf": "2026-08-12T14:31:04.882Z", "source": "live-book" }, "bestAsk": 0.418, "bestAskMeta": { "asOf": "2026-08-12T14:31:04.882Z", "source": "live-book" }, "indicativeYesPrice": 0.415, "indicativeNoPrice": 0.585, "label": "indicative price comparison", "asOf": "2026-08-12T14:31:04.882Z" } ], "meta": { "live": true, "liveUnavailable": false }}Two pairs of price fields, and the difference matters:
bestBid/bestAskcome from the live book overlay. They are never a stored snapshot — if the overlay could not run, they are null rather than stale.indicativeYesPrice/indicativeNoPriceare the catalog’s view, which may be a stored value.
Check meta.liveUnavailable before you present anything as live. When it is true, the live
overlay was requested and did not succeed, and the row is telling you so instead of quietly
serving you older numbers.
The cluster route
Section titled “The cluster route”Use this when you want the grouping itself rather than one market’s neighbours.
# Browse clusters. Note: filters are category / hasDiscrepancy / sort — there is no# text search on this route. Find the market first with fetchMarkets, then compare.curl -s "$PREDICTEFY_API_URL/v1/clusters?hasDiscrepancy=true&limit=20" \ -H "Authorization: Bearer pk_live_YOUR_KEY"
# Expand one cluster into its members.curl -s "$PREDICTEFY_API_URL/v1/clusters/CLUSTER_ID" \ -H "Authorization: Bearer pk_live_YOUR_KEY"A cluster carries question, normalizedQuestion, category, venueCount, venues,
hasDiscrepancy, aggAvgYes, aggSpread, maxSpread, similarity, closeDate and asOf.
Expanding it adds members, each with marketPk, venue, yesPrice, noPrice, volume24h,
liquidity and its own similarity.
Standing gaps
Section titled “Standing gaps”/v1/discrepancies lists clusters that currently disagree on price. It filters on category
and live — not by cluster id — and each row is a spread with its two ends:
curl -s "$PREDICTEFY_API_URL/v1/discrepancies?expand=markets&limit=100" \ -H "Authorization: Bearer pk_live_YOUR_KEY"{ "clusterId": "clr_9f2a7c41", "question": "Will the Fed cut rates at the January 2026 meeting?", "venues": ["kalshi", "polymarket"], "spread": 0.023, "low": { "venue": "kalshi", "canonicalMarketId": "kalshi:FED-26JAN-CUT", "yesPrice": 0.415, "market": { "...": "catalog metadata for the kalshi leg" } }, "high": { "venue": "polymarket", "canonicalMarketId": "polymarket:0x7d3f", "yesPrice": 0.438, "market": { "...": "catalog metadata for the polymarket leg" } }, "similarity": 0.94, "matchProbability": 0.97, "label": "indicative price discrepancy", "asOf": "2026-08-12T14:31:04.901Z"}expand=markets adds that market object to every leg: title, venue, status, close time,
image URL when stored, imageResolved and imageSource (both nullable), liquidity, and volume.
The optional volume24hSource key is present only when the market’s volume source is known.
The CSV expand query parameter supports only
markets today; any other value returns 400. It adds no extra metering weight.
Stored requests keep the existing limit default of 20 and maximum of 100; this
documents the pre-existing range rather than adding headroom. live=true now has an explicit
maximum of 10 because every live cluster recomputes from real order books. The tighter cap
bounds that cost; the old shared maximum of 100 was an accidental abuse vector on the live path.
label has exactly one permitted value here — indicative price discrepancy. That is not
hedging: this route makes no claim about depth, fees, or resolution equivalence, so it cannot
call anything executable.
To ask whether one of these survives those checks, qualify it:
curl -s "$PREDICTEFY_API_URL/v1/discrepancies/CLUSTER_ID/qualification?size=1000" \ -H "Authorization: Bearer pk_live_YOUR_KEY"That route takes size and an optional venues filter. See
the scanner recipe for what qualification actually
tests.
checks.netPositive.netEdgeandgrossEdgeare rates, not total-dollar profit. Each divides the corresponding profit by the walk’sexecutableSize. For example,netEdge: 0.031means an estimated net return equal to 3.1% of executable spend; multiply it byexecutableSizeto recover the total-dollar estimate.
Reading the comparison honestly
Section titled “Reading the comparison honestly”similarityis a match score, never a confidence. A 0.94 pair can still settle differently.matchProbabilityis a separate field and a separate claim.- Render
asOfnext to every price. Presenting a snapshot as live is the most common way a comparison UI misleads the person reading it. - Label the book type per row. Some venues serve reconstructed books — faithful as price, not executable as depth. Venue coverage records which venues have a real book; read it from there rather than hard-coding a list that will go stale.
- Handle
NOT_SUPPORTEDper row, not per request. One venue that cannot serve a book should not blank the table. See Capability-honest data. page.totalmay benull— that means not counted, not zero. Paginate onhasMoreandnextCursor.- Treat a non-null
page.totalas a cluster-grain estimate, never an exact count. Clusters can merge, split, appear, or disappear between snapshot ticks, so the total can drift between page reads. This is the same cluster-grain caveat as the match verbs: use the value for paging UX only, never to reconcile an exact count.
Cluster lookups and cross-venue comparisons are priced above catalog reads because each one walks stored relationship data. Market matching itself is a background pipeline and is not billed per request, so cache the cluster id, not the prices. Current weights are in Credits & billing.
Related
Section titled “Related”- Scan for qualified cross-venue opportunities — whether a gap is tradeable
- Cross-venue data — how matching works
- Prediction markets — why venues legitimately disagree