Polymarket Gamma API tutorial
Code-level walkthrough for fetching markets and events from the Polymarket Gamma API, including pagination, filtering, and best practices for developers.
Polymarket Gamma API tutorial
This Polymarket Gamma API tutorial teaches you how to fetch markets and events from Polymarket's Gamma surface, handle pagination, and apply common filters. Examples use curl and TypeScript so you can integrate reads into bots, dashboards, or analytics pipelines.
Key takeaways
- Gamma's base URL is https://gamma-api.polymarket.com and requires no auth for reads.
- Use the /markets and /events endpoints with cursor-based pagination via after_cursor; do not use offset.
- Respect rate limits: /markets has 300 req / 10 s; combined /markets + /events listing limit is 900 req / 10 s. Overall API limit is 4000 req / 10 s.
- Filter by fields such as condition_ids, clob_token_ids, slug, and tag_id to reduce payload and avoid hitting limits.
- Use small page sizes and exponential backoff for production clients.
1. Gamma basics: endpoints and limits
The Gamma read base URL is:
https://gamma-api.polymarket.com
Endpoints you'll use in this tutorial:
- GET /markets — market list and single-market queries
- GET /events — grouped events (useful for event-level metadata)
Important rate limits to design around:
- /markets: 300 requests per 10 seconds
- /markets + /events listing combined: 900 requests per 10 seconds
- Overall Gamma API: 4000 requests per 10 seconds
If your client will poll or backfill large datasets, batch and stagger requests and respect these limits.
2. Fetching markets: minimal curl example
A minimal request to list markets with default parameters:
curl "https://gamma-api.polymarket.com/markets"
To control page size (limit) and ordering:
curl "https://gamma-api.polymarket.com/markets?limit=100&order=volume24hr&ascending=false"
Notes:
- limit max is 1000. Default is 20.
- Gamma rejects offset-based pagination (HTTP 422). Use after_cursor for keyset pagination instead.
3. Cursor-based pagination (after_cursor)
Gamma returns a next_cursor in listing responses. Use that value in after_cursor to fetch the next page. Example flow in TypeScript follows.
TypeScript example (node-fetch or native fetch):
import fetch from 'node-fetch';
const BASE = 'https://gamma-api.polymarket.com';
type MarketsResponse = {
markets: any[];
next_cursor?: string | null;
};
async function fetchAllMarkets(limit = 200) {
let cursor: string | undefined;
const all: any[] = [];
while (true) {
const url = new URL('/markets', BASE);
url.searchParams.set('limit', String(limit));
if (cursor) url.searchParams.set('after_cursor', cursor);
const res = await fetch(url.toString());
if (!res.ok) throw new Error(`Gamma error ${res.status}`);
const body: MarketsResponse = await res.json();
all.push(...body.markets);
if (!body.next_cursor) break;
cursor = body.next_cursor;
// small delay to avoid spike; tune for your rate budget
await new Promise((r) => setTimeout(r, 100));
}
return all;
}
Best practices shown:
- Use limit to control page size and network usage.
- Respect next_cursor and stop when it's absent.
- Add small delays or backoff when you're near rate limits.
4. Filtering and query parameters worth knowing
Gamma supports many query parameters. Most useful when you want targeted reads:
- slug, id, question_ids, condition_ids, clob_token_ids, market_maker_address — all arrays
- closed (boolean), active, archived
- tag_id — filter by category
- order — comma-separated fields like volume24hr, volume, liquidity, endDate
- ascending — boolean (default true)
Example: fetch active markets in a tag, ordered by 24h volume descending:
When you only need specific markets, pass arrays for slug or id to reduce payload and avoid list scans.
5. Events endpoint
The /events endpoint groups markets under event-level metadata (for example: "2026 Presidential Election" as an event containing multiple market conditions).
Basic call:
curl "https://gamma-api.polymarket.com/events?limit=50"
Events also use after_cursor for pagination and share the combined listing limit with /markets (900 req / 10 s for combined listings).
6. Practical TypeScript example: fetch markets by condition_ids
This example fetches markets for a list of condition IDs, with concurrency control and exponential backoff.
import fetch from 'node-fetch';
const BASE = 'https://gamma-api.polymarket.com';
async function fetchMarketsByCondition(conditionIds: string[]) {
const results: any[] = [];
for (const id of conditionIds) {
let cursor: string | undefined;
let retries = 0;
while (true) {
const url = new URL('/markets', BASE);
url.searchParams.set('limit', '200');
url.searchParams.set('condition_ids', id);
if (cursor) url.searchParams.set('after_cursor', cursor);
const res = await fetch(url.toString());
if (res.status === 429) {
// respect rate limits with exponential backoff
await new Promise((r) => setTimeout(r, 1000 * Math.pow(2, retries)));
retries = Math.min(retries + 1, 5);
continue;
}
if (!res.ok) throw new Error(`Gamma ${res.status}`);
const body = await res.json();
results.push(...body.markets);
if (!body.next_cursor) break;
cursor = body.next_cursor;
}
}
return results;
}
Notes on production use:
- Use a concurrency limiter (p-map, p-limit) if conditionIds is large.
- Cache unchanged results (ETag/If-None-Match) if the API supports them for your use case.
- Monitor your request rate against the documented limits.
7. Common pitfalls and troubleshooting
- Do not use offset — Gamma returns HTTP 422 for offset parameters.
- Requesting huge pages without cursors can hit rate limits and memory pressure; prefer smaller limits and cursor traversal.
- Combined /markets + /events listing limits mean heavy polling both endpoints can throttle you quickly.
- The API returns next_cursor for keyset pagination; treat it as opaque and pass it back verbatim.
8. Integrating with real-time data
Gamma is the REST surface for metadata and historical listings. For real-time order-book and tick events, use the Market WebSocket at wss://ws-subscriptions-clob.polymarket.com/ws/market. The WebSocket supports up to 500 instruments per connection and emits price_change, best_bid_ask, last_trade_price, and tick_size_change events.
Keep REST for backfills and WebSocket for live updates.
9. How this affects your trading or tooling
If you're building trading bots, dashboards, or data pipelines, Gamma is the canonical read source for market metadata, tags, and listings. Use cursor pagination, filter aggressively, and pair Gamma reads with the CLOB API or Market WebSocket for price and order-book data. Plan your polling cadence around the documented rate limits to avoid throttling.
Gamma is read-only for public data; no API key is required for the examples above. For order placement and book operations use the CLOB API at https://clob.polymarket.com, which requires API key + HMAC.
Closing
This Polymarket Gamma API tutorial covered the practical steps to fetch markets and events, handle cursor pagination, and avoid common pitfalls. Use these patterns as the basis for reliable bots and analytics that respect Gamma's rate limits and pagination model.
Frequently asked questions
Do I need an API key to read from the Gamma API?
No. Gamma's public read endpoints do not require authentication. The base URL is https://gamma-api.polymarket.com. Only the CLOB endpoint requires API key + HMAC for trading.
How do I page through large market lists?
Use cursor-based pagination. Each listing returns next_cursor; pass that value as after_cursor to fetch the next page. Gamma rejects offset-based pagination with HTTP 422.
What are the important rate limits to consider?
/markets has a limit of 300 requests per 10 seconds. Combined /markets + /events listing calls count toward a 900 req / 10 s combined limit. The overall Gamma API limit is 4000 req / 10 s. Stagger requests and implement backoff to avoid throttling.
Should I use Gamma or the Market WebSocket for real-time data?
Use Gamma for metadata, listings, and historical reads. Use the Market WebSocket (wss://ws-subscriptions-clob.polymarket.com/ws/market) for real-time order-book and tick events; the WebSocket supports up to 500 instruments per connection.
Can I filter markets by tag or condition?
Yes. Gamma supports filters such as tag_id, condition_ids, clob_token_ids, slug, and others. Passing specific filters reduces payload and helps stay within rate limits.
Related guides
- Polymarket arbitrage: complete 2026 guide
- Intra-market binary arbitrage explained
- Combinatorial Arbitrage on Polymarket: Buying Complete Sets
- Polymarket endgame arbitrage: buying 95–99% outcomes near resolution
- How to fund Polymarket with USDC
- Polymarket fees explained
- Polymarket gasless trading: how the Relayer works
- Polymarket CLOB explained
Educational only. Not financial, legal or tax advice. Polymarket may not be available in your jurisdiction.