Overview
Polymarket’s REST and WebSocket APIs handle real-time trading, order placement, and market discovery. But a significant layer of on-chain data sits outside those APIs entirely: token balances, CTF (Conditional Token Framework) operations, historical open interest, and wallet-level profit and loss.
That data lives in five specialized subgraphs hosted by Goldsky, each indexing a different slice of Polymarket’s on-chain activity on Polygon. You query them using standard GraphQL POST requests – no API key required, no authentication, no rate limit headers to manage.
This guide covers all five subgraphs, the entities they expose, common query patterns, pagination strategies, and the Bitquery alternative for when you need analytics-grade queries or real-time streaming.
Prerequisites: Basic familiarity with GraphQL syntax and HTTP POST requests. Experience with the Polymarket REST API is helpful but not required.
Subgraph Reference
Polymarket splits its on-chain data across five purpose-built subgraphs. Each one indexes a specific domain of activity from the Polymarket smart contracts on Polygon.
| Subgraph | Data | Key Entities |
|---|---|---|
| Positions | User token balances | UserBalance, Condition, Market |
| Orders | Order book and trade events | OrderFilled, OrderMatched, GlobalStats |
| Activity | Splits, merges, redemptions | Split, Merge, Redemption, NegRiskEvent |
| Open Interest | Per-market and global OI | MarketCondition, GlobalOI |
| PNL | User position P&L | UserPNL, Position |
All five subgraphs share the same query method: send a POST request with a JSON body containing your GraphQL query to the Goldsky-hosted endpoint. The orders subgraph endpoint, for example, looks like this:
https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/0.0.1/gn
Each subgraph has its own endpoint URL following the same pattern, with the subgraph name and version in the path.
Positions Subgraph
The Positions subgraph indexes user token balances across all Polymarket markets. Every time a wallet holds outcome tokens (YES or NO shares), this subgraph tracks the balance. Key entities include UserBalance (the core record linking a user address to a token balance), Condition (the on-chain condition representing a market outcome), and Market (the parent market structure).
Use this subgraph when you need to know what a specific wallet holds, aggregate positions across markets, or build portfolio-tracking tools.
Orders Subgraph
The Orders subgraph captures every order book event that settles on-chain. OrderFilled records individual fill events with maker, taker, asset IDs, and amounts. OrderMatched provides a higher-level view of matched orders. GlobalStats aggregates platform-wide trading metrics like total volume and number of trades.
This is your go-to subgraph for historical trade analysis, volume tracking, and building trade feeds.
Activity Subgraph
The Activity subgraph tracks CTF (Conditional Token Framework) operations that happen outside the order book. Split events occur when a user splits collateral into outcome tokens. Merge events record the reverse – combining outcome tokens back into collateral. Redemption events capture users redeeming winning tokens after market resolution. NegRiskEvent entities track operations specific to Polymarket’s negative-risk market type.
This subgraph is essential for understanding the full lifecycle of positions beyond simple trading.
Open Interest Subgraph
The Open Interest subgraph provides both per-market and global open interest data. MarketCondition entities track OI for individual market conditions, while GlobalOI provides platform-wide totals. Open interest reflects the total value of outstanding positions in a market and is a key indicator of market depth and participant commitment.
PNL Subgraph
The PNL subgraph calculates realized and unrealized profit and loss at the wallet level. UserPNL entities aggregate P&L across a user’s positions, while Position entities break it down by individual market. This subgraph handles the math of tracking cost basis, realized gains from trades and redemptions, and unrealized gains on open positions.
Common Queries
The following queries demonstrate the most frequently used patterns across the subgraphs. Replace placeholder values (wallet addresses, condition IDs) with real data from your application.
Get User Positions by Wallet
Query the Positions subgraph to retrieve all token balances for a specific wallet address. This returns every outcome token the wallet currently holds or has held.
{
userBalances(where: { user: "0xYOUR_WALLET_ADDRESS" }) {
id
balance
netBalance
condition {
id
questionId
}
}
}
The balance field shows the raw token balance, while netBalance accounts for any pending operations. The condition relationship links each balance to the specific market outcome it represents, with questionId mapping to the Polymarket market.
Get Recent Trades
Query the Orders subgraph to fetch the most recent trade events. This returns fills in reverse chronological order.
{
orderFilleds(first: 100, orderBy: timestamp, orderDirection: desc) {
id
maker
taker
makerAssetId
takerAssetId
makerAmountFilled
takerAmountFilled
timestamp
}
}
The makerAssetId and takerAssetId fields identify which outcome tokens were exchanged. The makerAmountFilled and takerAmountFilled fields indicate the amounts on each side of the trade. Use the timestamp field for time-series analysis.
Get Market Open Interest
Query the Open Interest subgraph to retrieve open interest for a specific market condition.
{
marketConditions(where: { conditionId: "CONDITION_ID" }) {
id
openInterest
conditionId
}
}
The conditionId corresponds to the on-chain condition identifier for a market. You can obtain condition IDs from the Gamma API or the Positions subgraph.
Querying in Python
Here is a complete Python example that queries the Orders subgraph for recent trades and prints the results.
import requests
SUBGRAPH_URL = "https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/0.0.1/gn"
query = """
{
orderFilleds(first: 10, orderBy: timestamp, orderDirection: desc) {
id
maker
taker
makerAmountFilled
timestamp
}
}
"""
response = requests.post(SUBGRAPH_URL, json={"query": query})
data = response.json()["data"]
for trade in data["orderFilleds"]:
print(f"Trade {trade['id']}: {trade['makerAmountFilled']} at {trade['timestamp']}")
The same pattern works for any subgraph – change the URL and the query to match the subgraph you need. No authentication headers are required. Error handling should check for response.status_code and the presence of an errors key in the JSON response.
Pagination
GraphQL subgraphs enforce result limits on queries. The default maximum per request is typically 1,000 entities. For larger datasets, you need pagination.
Skip-based pagination uses the first and skip parameters. This is simpler but becomes slow for large offsets because the subgraph must still process all skipped records:
{
orderFilleds(first: 1000, skip: 2000, orderBy: timestamp, orderDirection: desc) {
id
timestamp
}
}
Cursor-based pagination with id_gt is more efficient for iterating through large result sets. After each batch, pass the last id you received to fetch the next page:
{
orderFilleds(first: 1000, where: { id_gt: "LAST_ID" }, orderBy: id) {
id
timestamp
makerAmountFilled
}
}
For production systems processing large amounts of historical data, cursor-based pagination is strongly recommended. It avoids the performance penalty of skip-based pagination and handles new records being added between queries more gracefully.
Tip: When paginating, always include orderBy: id to ensure deterministic ordering. If you order by timestamp, records with identical timestamps may appear inconsistently across pages.
Bitquery Alternative
Bitquery provides a third-party GraphQL API that covers Polymarket trading data from a different angle. Where the native subgraphs give you raw on-chain events, Bitquery offers analytics-level queries with built-in aggregations, filtering, and enrichment.
Bitquery’s Polymarket coverage includes:
- Trades – Individual trade records with token metadata and USD values.
- Settlements – Market resolution events and payouts.
- Market lifecycle – Creation, trading, and settlement phases.
- Wallet analytics – Aggregated activity per wallet across markets.
Bitquery also offers Kafka streaming for real-time data, which can serve as an alternative to Polymarket’s native WebSocket API for on-chain events.
Key differences from native subgraphs:
- Requires an API access token (free tier available).
- Provides pre-computed aggregations that would require multiple subgraph queries.
- Covers data across multiple chains and protocols, not just Polymarket.
- Kafka streaming adds a real-time dimension not available from subgraphs alone.
Use Bitquery when you need cross-market analytics, pre-built aggregations, or real-time streaming of on-chain events. Use the native subgraphs when you need the most granular, lowest-latency access to specific on-chain data.
When to Use Subgraph vs REST APIs
Polymarket’s data ecosystem spans REST APIs, WebSockets, and on-chain subgraphs. Each tool serves a different purpose. Choosing the right one depends on what data you need and how you intend to use it.
| Use Case | Best Tool |
|---|---|
| Real-time prices and orderbook | REST API or WebSocket |
| Order placement and trading | REST API (CLOB) |
| Market discovery and search | Gamma API (REST) |
| User token balances (on-chain) | Positions subgraph |
| Historical trade events | Orders subgraph |
| CTF operations (split/merge/redeem) | Activity subgraph |
| Open interest tracking | Open Interest subgraph |
| Wallet-level P&L | PNL subgraph |
| Cross-market analytics | Bitquery |
General rule: If you need to take action (place orders, cancel orders), use the REST API. If you need to read on-chain state or historical on-chain events, use the subgraphs. If you need pre-computed analytics or real-time event streaming, consider Bitquery.
The subgraphs and REST APIs are complementary. A typical trading bot might use the REST API for order execution, WebSockets for real-time price feeds, the Positions subgraph for portfolio tracking, and the PNL subgraph for performance reporting.
FAQ
What data is available in the Polymarket subgraphs?
Five subgraphs cover: Positions (user token balances), Orders (order book and trade events), Activity (splits, merges, redemptions), Open Interest (per-market and global OI), and PNL (user position profit/loss). All provide on-chain data not available through REST APIs.
How do I query the Polymarket subgraph?
Send a POST request with a GraphQL query to the Goldsky-hosted endpoint. For example, the orders subgraph endpoint is https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/0.0.1/gn. Use standard GraphQL query syntax. No API key or authentication is required.
When should I use the subgraph instead of the REST API?
Use the subgraph for on-chain data like token balances, CTF operations (splits/merges/redemptions), historical open interest, and wallet-level P&L. Use REST APIs for real-time trading, order placement, and current market data. The two are complementary – most production systems use both.
What is the Bitquery alternative for Polymarket data?
Bitquery provides a GraphQL API for Polymarket trading data including trades, settlements, market lifecycle, and wallet analytics. It also offers Kafka streaming for real-time data. It requires an API access token. It is useful as a complementary data source or when you need analytics-level queries that would require multiple subgraph requests to assemble.
See Also
- Polymarket API Guide – Full REST API reference
- Polymarket Gamma API Deep Dive – Market discovery and price history
- Polymarket WebSocket Guide – Real-time streaming alternative
- py_clob_client Reference – Python SDK methods
- Polymarket Rate Limits Guide – REST API rate limits
- Prediction Market API Reference – Cross-platform comparison
This guide is maintained by AgentBets.ai. Found an error or API change we missed? Let us know on Twitter.
Not financial advice. Built for builders.
