PolymarketPolymarketDeveloper16 min read2025-12-11

Polymarket GraphQL & Subgraph Guide: Query Market Data

AL - Founder of PolyTrack, Polymarket trader & analyst

AL

Founder of PolyTrack, Polymarket trader & analyst

Polymarket GraphQL & Subgraph Guide: Query Market Data - Developer Guide for Polymarket Traders | PolyTrack Blog

Polymarket maintains 5 specialized GraphQL subgraphs for querying market data, positions, order books, and P&L. This guide covers all endpoints, query examples, and how to build analytics dashboards and trading bots using The Graph and Goldsky APIs.

Polymarket Data Architecture

Polymarket offers three types of APIs for different use cases:

API TypeBest ForAuth Required
GraphQL SubgraphsHistorical data, analytics, positionsAPI key (free tier available)
Gamma REST APIMarket metadata, categories, eventsNone
CLOB APITrading, real-time prices, order bookNone (read) / Keys (trade)

The 5 Polymarket Subgraphs

Polymarket hosts specialized subgraphs on Goldsky for different data types:

1. Orders Subgraph (v0.0.1)

Advanced orderbook analytics and market microstructure data.

# Endpoint
https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/0.0.1/gn

# Features
- Real-time orderbook depth
- Bid-ask spreads
- Liquidity analysis
- Last trade prices

2. Positions Subgraph (v0.0.7)

User position tracking with average price and realized P&L.

# Endpoint
https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/positions-subgraph/0.0.7/gn

# Features
- User positions by wallet
- Average entry price
- Realized PnL tracking
- Balance history

3. Activity Subgraph (v0.0.4)

User and market activity including split/merge/redemption events.

# Endpoint
https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/activity-subgraph/0.0.4/gn

# Features
- Trade history
- Split/merge events
- Redemption tracking
- User activity feeds

4. Open Interest Subgraph (v0.0.6)

Market and global open interest metrics.

# Endpoint
https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/oi-subgraph/0.0.6/gn

# Features
- Per-market open interest
- Global OI metrics
- Historical OI data

5. PnL Subgraph (v0.0.14)

Comprehensive profit and loss calculations.

# Endpoint
https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/pnl-subgraph/0.0.14/gn

# Features
- Realized PnL per position
- Unrealized PnL calculations
- Historical performance

The Graph Network Endpoint

For production applications, use The Graph's decentralized network:

# The Graph Network Endpoint
https://gateway.thegraph.com/api/{api-key}/subgraphs/id/Bx1W4S7kDVxs9gC3s2G6DS8kdNBJNVhMviCtin2DiBp

# Subgraph ID
QmdyCguLEisTtQFveEkvMhTH7UzjyhnrF9kpvhYeG4QX8a

GraphQL Query Examples

Query User Positions

{
  positions(where: { user: "0xYourWalletAddress" }, first: 10) {
    id
    condition
    outcomeIndex
    balance
    averagePrice
    realizedPnl
    user {
      id
    }
  }
}

Query Order Book Data

{
  orderBooks(first: 10, orderBy: timestamp, orderDirection: desc) {
    marketId
    currentSpread
    currentSpreadPercentage
    totalBidDepth
    totalAskDepth
    lastTradePrice
    timestamp
  }
}

Query Recent Trades

{
  trades(first: 20, orderBy: timestamp, orderDirection: desc) {
    id
    market {
      question
    }
    side
    price
    size
    timestamp
  }
}

See What Whales Are Trading Right Now

Get instant alerts when top traders make moves. Track P&L, win rates, and copy winning strategies.

Track Whales Free

Free forever. No credit card required.

Python Implementation

Using the gql Library

from gql import gql, Client
from gql.transport.requests import RequestsHTTPTransport

# Setup transport
transport = RequestsHTTPTransport(
    url='https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/0.0.1/gn',
    use_json=True,
)

client = Client(
    transport=transport,
    fetch_schema_from_transport=True,
)

# Query orderbook data
query = gql("""
{
    orderBooks(first: 5, orderBy: timestamp, orderDirection: desc) {
        marketId
        currentSpread
        lastTradePrice
        totalBidDepth
        totalAskDepth
    }
}
""")

result = client.execute(query)
print(result)

Using requests (Simple Approach)

import requests

def run_graphql_query(query, variables=None):
    url = 'https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/positions-subgraph/0.0.7/gn'
    response = requests.post(
        url,
        json={'query': query, 'variables': variables}
    )
    if response.status_code == 200:
        return response.json()
    raise Exception(f"Query failed: {response.status_code}")

# Get positions for a wallet
query = """
{
    positions(where: { user: "0xYourAddress" }, first: 10) {
        condition
        outcomeIndex
        balance
        averagePrice
        realizedPnl
    }
}
"""

result = run_graphql_query(query)
print(result)

Async Python with aiohttp

import asyncio
from gql import Client, gql
from gql.transport.aiohttp import AIOHTTPTransport

async def fetch_positions(wallet_address):
    transport = AIOHTTPTransport(
        url="https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/positions-subgraph/0.0.7/gn"
    )

    query = gql(f"""
    {{
        positions(first: 10, where: {{ user: "{wallet_address}" }}) {{
            condition
            outcomeIndex
            balance
            averagePrice
            realizedPnl
        }}
    }}
    """)

    async with Client(transport=transport) as session:
        result = await session.execute(query)
        return result

# Run the async function
result = asyncio.run(fetch_positions("0xYourAddress"))

JavaScript/TypeScript Implementation

Using Axios

const axios = require('axios');

const POSITIONS_ENDPOINT = 'https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/positions-subgraph/0.0.7/gn';

async function queryPositions(walletAddress) {
  const query = `{
    positions(where: { user: "${walletAddress}" }, first: 10) {
      condition
      outcomeIndex
      balance
      averagePrice
      realizedPnl
    }
  }`;

  const response = await axios.post(POSITIONS_ENDPOINT, { query });
  return response.data.data;
}

// Usage
queryPositions('0xYourAddress').then(console.log);

Using The Graph Network with API Key

const axios = require('axios');

const API_KEY = 'your-graph-api-key';
const ENDPOINT = `https://gateway.thegraph.com/api/${API_KEY}/subgraphs/id/Bx1W4S7kDVxs9gC3s2G6DS8kdNBJNVhMviCtin2DiBp`;

async function queryTheGraph(query) {
  const response = await axios.post(ENDPOINT, { query });
  return response.data.data;
}

const query = `{
  positions(first: 5) {
    condition
    outcomeIndex
    balance
  }
}`;

queryTheGraph(query).then(console.log);

Gamma Markets REST API

For market metadata and categories, use the Gamma API (no auth required):

Base URL

https://gamma-api.polymarket.com

Key Endpoints

# Get active markets
GET /markets?active=true&limit=100

# Filter by volume range
GET /events?volume_min=1.0&volume_max=2.0

# Filter by category/tag
GET /events?tag=politics
GET /events?tag=sports
GET /events?tag=crypto

# Get closed markets
GET /events?closed=true

# Get archived markets
GET /events?archived=true

Python Example: Paginated Market Fetch

import requests

def get_all_active_markets():
    base_url = "https://gamma-api.polymarket.com"
    markets = []
    offset = 0
    limit = 100

    while True:
        response = requests.get(
            f"{base_url}/markets",
            params={"limit": limit, "offset": offset, "active": "true"}
        )

        if response.status_code != 200:
            break

        data = response.json()
        if not data:
            break

        markets.extend(data)
        offset += limit

        if len(data) < limit:
            break

    return markets

markets = get_all_active_markets()
print(f"Total active markets: {len(markets)}")

Rate Limits and Authentication

APIFree TierAuthLimits
The Graph Network100K queries/monthAPI key required$4 per 100K after free tier
Goldsky SubgraphsYesNoneFair use policy
Gamma APIYesNoneCloudflare throttling
CLOB APIYesNone (read)1,000 calls/hour

Getting a Graph API Key

  1. Go to thegraph.com/studio
  2. Connect your wallet
  3. Navigate to API Keys page
  4. Create a new API key
  5. Use in your requests: /api/YOUR_KEY/subgraphs/id/...

Schema Reference

Position Entity

type Position @entity {
  id: ID!
  condition: String!      # Market condition ID
  outcomeIndex: Int!      # 0 = YES, 1 = NO
  user: User!             # Wallet address
  balance: BigInt!        # Token balance
  averagePrice: BigDecimal
  realizedPnl: BigDecimal
}

OrderBook Entity

type OrderBook @entity {
  marketId: String!
  currentSpread: BigDecimal!
  currentSpreadPercentage: BigDecimal!
  totalBidDepth: BigDecimal!
  totalAskDepth: BigDecimal!
  lastTradePrice: BigDecimal!
  timestamp: BigInt!
}

Market Entity (Gamma API)

{
  "id": "string",
  "question": "string",
  "conditionID": "string",
  "slug": "string",
  "description": "string",
  "category": "string",
  "endDate": "ISO date",
  "liquidity": "string",
  "liquidityNum": number,
  "volume": "string",
  "volumeNum": number,
  "negRisk": boolean
}

Use Cases

1. Portfolio Tracker

from py_clob_client.client import ClobClient

def track_portfolio(wallet_address):
    # Query positions from subgraph
    positions = query_positions_subgraph(wallet_address)

    # Get current prices from CLOB
    client = ClobClient("https://clob.polymarket.com")

    total_pnl = 0
    for pos in positions:
        current_price = client.get_midpoint(pos['token_id'])
        unrealized = (current_price - pos['averagePrice']) * pos['balance']
        total_pnl += unrealized + pos['realizedPnl']

    return total_pnl

2. Market Discovery Dashboard

import requests

def discover_hot_markets():
    # Get high-volume active markets
    response = requests.get(
        'https://gamma-api.polymarket.com/events',
        params={
            'active': 'true',
            'volume_min': '10000',
            'limit': '20'
        }
    )

    markets = response.json()

    # Sort by volume
    markets.sort(key=lambda x: x.get('volumeNum', 0), reverse=True)

    return markets

3. Whale Tracker

# Query large positions across all markets
query = """
{
  positions(
    first: 100,
    orderBy: balance,
    orderDirection: desc,
    where: { balance_gt: "1000000000000000000000" }
  ) {
    user { id }
    condition
    outcomeIndex
    balance
    averagePrice
  }
}
"""

whales = run_graphql_query(query)

Best Practices

  • Use WebSocket for real-time: GraphQL is for historical/analytical queries, use WebSocket for live data
  • Implement caching: Cache frequently accessed data with appropriate TTL
  • Handle rate limits: Implement exponential backoff for HTTP 429 errors
  • Batch queries: Combine multiple market queries into single requests
  • Use pagination: Always paginate large result sets with first and skip

Resources

  • Polymarket Docs: docs.polymarket.com/developers/subgraph
  • The Graph Explorer: thegraph.com/explorer
  • GitHub: github.com/Polymarket/polymarket-subgraph
  • Gamma API Playground: gamma-api.polymarket.com

Skip the Setup with PolyTrack

Building your own dashboard? PolyTrack already aggregates all this data into a clean interface with whale alerts, portfolio tracking, and market discovery. Try it free.

Frequently Asked Questions

Polymarket has 5 subgraphs hosted on Goldsky: Orders (orderbook analytics), Positions (user positions/PnL), Activity (trades/events), Open Interest (market OI), and PnL (profit/loss calculations). The Graph Network also hosts a combined subgraph.

12,400+ TRADERS

Stop Guessing. Start Following Smart Money.

Get instant alerts when whales make $10K+ trades. Track P&L, win rates, and copy winning strategies.

Track Whales FreeNo credit card required