Polymarket Node
The Polymarket node works with prediction markets on Polymarket ↗, the world's largest prediction market platform. It has twelve modes in three families:
- Discovery (browse, search, lookup) finds events and their markets.
- Market data (snapshot, quotes, event, history, depth) reads live prices, order books and price history.
- Who is trading (trades, holders, open interest, resolution) shows the money behind a market and how it settles.
Every API it uses is public and free, with no key. The output shape is discriminated on mode.
Configuration
Polymarket
Public API — no key required
Discovery, market-data or flow mode
Filter by category tag
Result Limit
Max markets returned (1–100)
Polymarket API Data, Without Writing Code
Polymarket exposes its data through three public APIs, and this node wraps them. The Gamma API serves market discovery: questions, slugs, event IDs, tags, volume, liquidity, and current implied probabilities. The CLOB API serves live bid/ask/mid pricing, last trades and full orderbook depth. The Data API serves price history and who is trading: trades, holders, open interest and resolutions.
None of them requires a key, and the node handles pagination, identifier resolution, retries and field normalization for you, plus the traps that catch hand-written code (filters the APIs silently ignore, the market-wide last trade on the order book). What you would otherwise script against three APIs becomes one configured node:
| You want | Mode | Upstream API |
|---|---|---|
| Top markets by volume or liquidity | Browse | Gamma |
| Markets matching a phrase | Search | Gamma |
| One known event's markets | Lookup | Gamma |
| Every outcome's price, bid/ask, last trade | Snapshot | CLOB |
| A whole event (every market of a game) with live quotes | Event | Gamma + CLOB |
| A flat quote table for many outcomes | Quotes | CLOB |
| Price history as a timeseries | History | Data API |
| Full orderbook, one outcome | Depth | CLOB |
| Who is betting which side, and how much | Trades | Data API |
| Largest holders and their entry prices | Holders | Data API |
| USD locked in a market | Open interest | Data API |
| UMA status, disputes, winner, rules | Resolution | Data API |
Every mode returns normalized JSON you can pass straight to an LLM node, a Function node, or a Polymarket Order node downstream.
Try a Public Data Request
Run this read-only request to fetch one currently active market from Gamma:
curl 'https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=1'
A verification on September 7, 2026 returned HTTP 200 and one market with a condition ID and two outcome token IDs. The selected market and its prices can change; inspect your own response rather than copying an old identifier.
The raw Gamma response includes conditionId, plus JSON-encoded strings such as clobTokenIds and outcomes. Protocol V2 markets (version: "v2") carry their token IDs in positionIds; the node picks the right field for each market. Nick decodes them into events[] and markets[], each market with named outcomes[] (label, token ID, price). Use the node's actual output fields when connecting it downstream.
For a first workflow, connect Browse to a report and a notification. Add a no-results branch for an empty array. Then pass a discovered condition ID to Snapshot when you want every outcome's live price. The Polymarket Signal Scanner ↗ shows a concrete reporting design.
Data versus orders: this data node is read-only and needs no wallet credential. The Polymarket Order node is a separate authenticated action. Its permissions and results must be reviewed independently.
Source: Polymarket market discovery ↗.
How Polymarket Data Is Organised
An event holds markets, and each market has outcomes, each with its own token. The node works down that chain for you, from text or a link to the event, the market (by type) and the outcome token (by label).
Every event is classified by how its markets relate (kind):
| Kind | Examples | How it's built |
|---|---|---|
single | "Strait of Hormuz traffic normal by Dec 31", a BTC 15-minute window | One market: Yes/No, or two named sides (Up/Down) |
sports_game | An NBA game (~460 markets), an NFL game (~300), a LoL match (47), a UFC fight, a tennis match | One moneyline plus spreads, totals, period markets (Game 1, 1H, Q3, Set 2) and props (player points, kills, method of victory) |
exclusive | Election fields, Fed decision buckets, temperature or tweet-count ranges, champions, soccer exact score | One Yes/No market per mutually exclusive outcome. outcomes lists them most likely first; their prices sum to about 1 (outcomeSum) |
independent | "What price will Bitcoin hit" (↑100,000, ↓60,000), "Bitcoin above X on Nov 7", teams to advance | Yes/No strikes that can all resolve Yes. strikes are sorted by strike. Never sum them |
A few rules hold everywhere:
- Outcomes are labels. "Yes"/"No", team or player names, "Over"/"Under", "Up"/"Down". Select an outcome by its label with the Outcome field or
outcomes[].label. Never by position: two spreads of the same NBA game can list the teams in opposite orders. - Soccer moneylines have three outcomes. Home, "Draw (A vs B)" and away are three Yes/No markets, shown together as the event's
outcomes. A match is split into sibling events (<slug>,<slug>-more-markets,<slug>-exact-score); Event mode with All markets joins them. - A spread's line belongs to its first outcome: "Spread: Thunder (-3.5)" is Thunder -3.5.
activemeans listed, not tradable. CheckacceptingOrders.pastEndDatemeans the end date has passed and the result is pending.closedmeans resolved.
tokenIds.yes/no and outcomePrices.yes/no are kept so saved workflows keep working. For a named market they hold the first and second outcome by position. New workflows should read outcomes[] by label.Discovery Modes
These modes return events[] (each event with its typed markets, ranked) and markets[] (the same markets flattened and cut to Limit, for a Loop).
Within an event, a game's moneyline comes first, then its main spread and total, then period markets, then props. Markets per event decides how many you get:
- Main markets (what new nodes store): a game's moneyline, its most traded spread and its most traded total, plus every live outcome of other events.
- All markets: every market, props and inactive placeholders included.
A node saved before Markets per event existed has no scope: Search, Browse and Lookup keep returning every market for it.
Market types filters the markets by Polymarket market type (moneyline, spreads, totals, map_handicap, child_moneyline, points…) or by label, comma-separated. For example, Browse with tag league-of-legends and Market types moneyline lists every LoL match winner.
Browse (default)
| Field | Description | Default |
|---|---|---|
| Tag | Category or sport slug (politics, crypto, nba, league-of-legends…) | — |
| Status | active, closed, or all | active |
| Sort By | volume_24hr, volume, liquidity, end_date (ending soonest first), start_date | volume_24hr |
| Min Volume / Min Liquidity | Applied to each market | — |
| Limit | Maximum markets to return (1–100) | 10 |
Search
| Field | Description |
|---|---|
| Query | Search terms (required), ranked by 24h volume. Supports f(x) interpolation. |
| Within tag | Optional sport or category slug to search within. |
Polymarket's search matches the words in event titles. The node rewrites a query to that spelling before searching (btc → bitcoin, 15 minute → 15m), and expands team codes in a matchup (KC vs T1 → Karmine Corp T1). searchedFor shows what was searched. Search by team, player or competition names, not tournament stages: a stage ends and its query starts matching other games.
Lookup
Market ID takes a numeric event ID, an event slug, or a market slug. A market slug returns that market in markets[], and its event, with its markets, in events[].
Market-Data and Flow Modes
These modes read one market, or one event, per execution. They share the Market field, which accepts a condition ID (0x + 64 hex), a token ID, a market or event slug, or any polymarket.com link (event, event/market, /sports/...). Use f(x) to pass one from upstream, e.g. {discovery.markets[0].conditionId}.
When the input names a whole event, the node reads its main market: a game's moneyline, or an exclusive event's favourite. Set Market type to read another (map_handicap, spreads, Game 1 Winner, Gavin Newsom). Every result says which market it read in pickedBecause.
Outcome picks the side by label (T1, Over, Up, Draw). History and Depth read one outcome token; Trades and Holders filter by it. Without it, the node reads the token you passed, else Yes, else the first outcome.
Snapshot
Every outcome's price, best bid and ask, mid, spread and its own last trade, plus tick size, minimum order size and fees. Open markets only.
Quotes
A flat quote table, one row per outcome: every in-scope market of the event you named, or the one market you named.
Event
A whole event: every in-scope market with live quotes on every outcome, plus the event's exclusive outcomes or strikes. With All markets, a soccer match's sibling events come back in relatedEvents.
History
| Field | Description | Default |
|---|---|---|
| Interval | 5m, 15m, 1h, 4h, 1d | 1h |
| Lookback | Intervals counted back from End time, or from now | 24 |
| Start / End time | An absolute window (ISO-8601 or epoch seconds) | — |
Windows over 15 days are split into requests and stitched (up to about a year per run). summary gives open, close, high, low and change over the whole window. Resolved markets keep their history up to resolution; an empty window comes back with a notice saying to set an earlier end time.
Depth
One outcome's order book, up to Depth Levels per side (1–50), with that token's own last trade.
Trades
Recent trades on the market, newest first, with flow (buy and sell USD per outcome). Filter by Side, Min trade size (USD; 1000 shows large trades only) and Outcome. filters echoes what was applied. Each fill is listed once (taker side).
Holders
The largest holders of each outcome, with shares, average entry price, current value and P&L. Limit is per outcome.
Open interest
USD locked in the market's outstanding shares.
Resolution
UMA status (posed, proposed, disputed, resolved), dispute flags, payouts, the winning outcome once resolved, and the market's rules and resolution source. Resolution sources differ: a BTC 15-minute window settles on a Chainlink price stream, "What price will Bitcoin hit" on Binance.
Workflow Examples
Monitor Top Political Markets
Find the most active political prediction markets each morning and summarize them with an LLM.
Configure the Discovery node with tag=politics, sortBy=volume_24hr, limit=10. The LLM receives the markets array and formats a digest of the most liquid political bets with their current implied probabilities.
Search and Alert on New Markets
Search for markets matching a topic and alert when new ones appear above a liquidity threshold.
Use search mode with query="fed rate cut 2026". The Function node filters for markets with liquidity > 10000. The Conditional node checks if filtered.markets.length > 0 before sending a Telegram alert.
Lookup a Specific Market
Fetch all outcome markets for a known event by slug and pass identifiers to a downstream node.
Pricing & Credits
Each Polymarket call costs a flat 2 credits, regardless of mode (discovery or market data) or number of markets returned.
Output
The output is discriminated on mode.
| Path | Description |
|---|---|
| {discovery.mode} | The mode that was executed |
| {discovery.events} | (discovery) Events with their typed markets |
| {discovery.markets} | (discovery) The same markets flattened, cut to Limit |
| {discovery.snapshot} | (snapshot) { market, outcomes[], pickedBecause } |
| {discovery.event} | (event) The event with quoted markets and outcomes |
| {discovery.quotes} | (quotes) One row per outcome with bid, ask, mid, spread, last trade |
| {discovery.history} | (history) { tokenId, outcome, points[], summary, notice } |
| {discovery.depth} | (depth) { outcome, bids[], asks[], lastTradePrice, … } |
| {discovery.trades} | (trades) Trades, with flow and filters beside them |
| {discovery.holders} | (holders) Holders per outcome |
| {discovery.openInterestUsd} | (open_interest) USD locked |
| {discovery.resolution} | (resolution) UMA state, payouts; winner and rules beside it |
| {discovery.metadata.source} | polymarket-gamma, polymarket-clob or polymarket-data-api |
| {discovery.metadata.dataPoints} | Markets, outcomes, points or rows returned |
| {discovery.metadata.creditsUsed} | Credits charged (always 2) |
discovery with your edge label. If the connecting edge is labeled markets, use {markets.markets[0].question}.Market Object Structure
| Field | Type | Description |
|---|---|---|
question, slug, conditionId | string | The market |
version | "v1" | "v2" | v1: Polymarket's original Conditional Tokens markets. v2: Protocol V2 markets. Both read the same way; outcomes[].tokenId is already the right ID for either |
eventId, eventSlug, eventTitle, url | Its event and its polymarket.com link | |
marketType | string | null | Polymarket's sports market type (moneyline, spreads, points…) |
label | string | null | The market's label inside its event (Game 1 Winner, Spread -3.5, Gavin Newsom) |
period, line, player | match, Game 2, 1H, Q3…; the spread or total line; a prop's player | |
outcomes | { label, tokenId, price }[] | Read by label |
bestBid, bestAsk | number | null | First outcome's best bid and ask |
volume, volume24hr, liquidity | number | USD |
endDate, gameStartTime | string | Resolution date; a game's start time |
active, acceptingOrders, closed, pastEndDate | boolean | Listed; tradable; resolved; awaiting a result |
negRisk, resolutionSource, tags | ||
tokenIds, outcomePrices | Deprecated positional fields kept for saved workflows |
Common Errors
| Error | Cause | Fix |
|---|---|---|
| Polymarket Gamma resource not found (404) | Invalid slug or event ID in Lookup mode | Verify the slug from the Polymarket URL, e.g. polymarket.com/event/my-slug |
| Polymarket Gamma rate limit exceeded | Too many calls in a short window | Space out calls or reduce schedule frequency |
| Polymarket Gamma request timed out | Slow upstream response | Retry — the Gamma API is normally fast |
| Query is required for search mode | Mode is search but Query field is empty | Set a search query or switch to Browse mode |
| Market ID is required for lookup mode | Mode is lookup but Market ID field is empty | Set a slug or event ID |
| Market identifier is required | A data or flow mode has an empty Market field | Pick a market, paste a polymarket.com link, or pass a condition/token ID via f(x) |
| No Polymarket market or event matches this identifier | The slug, ID or link names nothing | Use Search to find it, or copy the link from polymarket.com |
| "…" has no "…" market | Market type names no market of the event | The error lists the event's market types; pick one |
| "…" has no outcome "…" | Outcome names no outcome of the market | The error lists the outcomes; use one of those labels |
| This market is resolved… | Snapshot, Depth or Quotes on a resolved market | Use History with an earlier End time, or Resolution |
| Lookback (number of intervals ≥ 1) is required for history mode | History Lookback is empty or < 1 | Set Lookback to a positive integer (count of intervals) |
Next Steps
- LLM Node — Feed market data and implied probabilities into an LLM to generate trading analysis.
- Function Node — Filter, sort, or transform the
markets[]array with custom JavaScript. - Conditional Node — Branch your workflow based on odds thresholds or liquidity levels.