Response is relayed verbatim from Kalshi. Each side is a {price: size} object: yes_bids are bids on the YES outcome, no_bids are bids on the NO outcome. To buy YES, walk no_bids from highest price down (each no_bids entry at price p implies a YES seller at 1 - p).
Every block below is an independent example. Each one redeclares the env consts and the headers object so you can copy and run any one of them on its own. Many markets return 404 when they have no active orderbook (finalized, illiquid, or off-hours).
import "dotenv/config";const DFLOW_METADATA_API_URL = process.env.DFLOW_METADATA_API_URL ?? "https://dev-prediction-markets-api.dflow.net";const DFLOW_API_KEY = process.env.DFLOW_API_KEY; // optional; not needed for dev endpointsconst headers: HeadersInit = {};if (DFLOW_API_KEY) headers["x-api-key"] = DFLOW_API_KEY;const mintAddress = "OUTCOME_OR_LEDGER_MINT_ADDRESS";const book = await fetch( `${DFLOW_METADATA_API_URL}/api/v1/orderbook/by-mint/${mintAddress}`, { headers }).then((r) => r.json());if (!book.yes_bids) { throw new Error(`No orderbook for mint "${mintAddress}". Pick a mint from an active market. Response: ${JSON.stringify(book)}`);}console.log(JSON.stringify(book, null, 2));
Walk the best bids on the NO side to estimate how much it costs to buy a target number of YES contracts. Each entry no_bids[p] implies a YES seller at price 1 - p, so the highest NO bid is the lowest YES ask.
Estimate average fill price
import "dotenv/config";const DFLOW_METADATA_API_URL = process.env.DFLOW_METADATA_API_URL ?? "https://dev-prediction-markets-api.dflow.net";const DFLOW_API_KEY = process.env.DFLOW_API_KEY; // optional; not needed for dev endpointsconst headers: HeadersInit = {};if (DFLOW_API_KEY) headers["x-api-key"] = DFLOW_API_KEY;const ticker = "MARKET_TICKER_HERE";const TARGET_CONTRACTS = 50;const book = await fetch( `${DFLOW_METADATA_API_URL}/api/v1/orderbook/${encodeURIComponent(ticker)}`, { headers }).then((r) => r.json());if (!book.no_bids) { throw new Error(`No orderbook for "${ticker}". Pick an active market. Response: ${JSON.stringify(book)}`);}// no_bids is { priceString: sizeString }. Sort by price descending so the// highest NO bid (= lowest implied YES ask) is walked first.const levels = Object.entries(book.no_bids) .map(([price, size]) => [parseFloat(price), parseFloat(size as string)] as [number, number]) .sort((a, b) => b[0] - a[0]);let remaining = TARGET_CONTRACTS;let cost = 0; // in dollarsfor (const [noPrice, size] of levels) { const yesAskPrice = 1 - noPrice; const take = Math.min(remaining, size); cost += take * yesAskPrice; remaining -= take; if (remaining <= 0) break;}if (remaining > 0) { console.log(`Insufficient depth: short by ${remaining} contracts`);} else { const avg = cost / TARGET_CONTRACTS; console.log(`Avg fill for ${TARGET_CONTRACTS} YES contracts: $${avg.toFixed(4)} (${(avg * 100).toFixed(2)}ยข) per contract, $${cost.toFixed(2)} total`);}