Complete market catalog
curl --request GET \
--url https://api.polynode.dev/v3/markets \
--header 'x-api-key: <api-key>'import requests
url = "https://api.polynode.dev/v3/markets"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.polynode.dev/v3/markets', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.polynode.dev/v3/markets",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.polynode.dev/v3/markets"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.polynode.dev/v3/markets")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.polynode.dev/v3/markets")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"markets": [
{
"condition_id": "<string>",
"status": "open",
"tag_slugs": [
"<string>"
],
"volume_all_time": null,
"liquidity": null,
"outcome_prices": null,
"question": "<string>",
"slug": "<string>",
"outcomes": [
"<string>"
],
"end_date": "<string>",
"active": true,
"closed": true,
"archived": true,
"enable_order_book": true,
"closed_time": "<string>",
"neg_risk": true,
"neg_risk_market_id": "<string>",
"image": "<string>",
"icon": "<string>",
"event_slug": "<string>",
"event_title": "<string>",
"group_item_title": "<string>",
"winning_outcome_index": 123,
"category": "<string>",
"updated_at": "<string>",
"pm_created_at": "<string>",
"pm_updated_at": "<string>"
}
],
"rows_returned": 1,
"has_more": true,
"limit": 150,
"next_cursor": "<string>",
"sort": "updated",
"order": "desc",
"filters": {
"status": "open",
"event_slug": "<string>"
}
}Markets & Search
Market Catalog
Walk the complete Polymarket market catalog with stable cursor pagination and optional status or event filters.
GET
/
v3
/
markets
Complete market catalog
curl --request GET \
--url https://api.polynode.dev/v3/markets \
--header 'x-api-key: <api-key>'import requests
url = "https://api.polynode.dev/v3/markets"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.polynode.dev/v3/markets', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.polynode.dev/v3/markets",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.polynode.dev/v3/markets"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.polynode.dev/v3/markets")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.polynode.dev/v3/markets")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"markets": [
{
"condition_id": "<string>",
"status": "open",
"tag_slugs": [
"<string>"
],
"volume_all_time": null,
"liquidity": null,
"outcome_prices": null,
"question": "<string>",
"slug": "<string>",
"outcomes": [
"<string>"
],
"end_date": "<string>",
"active": true,
"closed": true,
"archived": true,
"enable_order_book": true,
"closed_time": "<string>",
"neg_risk": true,
"neg_risk_market_id": "<string>",
"image": "<string>",
"icon": "<string>",
"event_slug": "<string>",
"event_title": "<string>",
"group_item_title": "<string>",
"winning_outcome_index": 123,
"category": "<string>",
"updated_at": "<string>",
"pm_created_at": "<string>",
"pm_updated_at": "<string>"
}
],
"rows_returned": 1,
"has_more": true,
"limit": 150,
"next_cursor": "<string>",
"sort": "updated",
"order": "desc",
"filters": {
"status": "open",
"event_slug": "<string>"
}
}GET /v3/markets is the exhaustive market-listing route. Use it when every
market matters. Use Search Markets when relevance
search is more useful than a complete cursor walk.
Rows are ordered by updated_at descending, with rows that have no update
timestamp placed last.
Request
GET /v3/markets
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 100 | Rows per page. Values below 1 use 1; values above 300 use 300. |
cursor | string | none | Opaque next_cursor returned by the preceding page. |
status | string | all | open, closed, inactive, or all. Matching is case-insensitive. |
event_slug | string | none | Exact parent event slug. |
sort | string | updated | Only updated is available. |
order | string | desc | Only desc is available. |
First page
curl "https://api.polynode.dev/v3/markets?status=open&limit=2" \
-H "x-api-key: $POLYNODE_API_KEY"
{
"markets": [
{
"condition_id": "0x1111111111111111111111111111111111111111111111111111111111111111",
"question": "Will the example market resolve Yes?",
"slug": "will-the-example-market-resolve-yes",
"outcomes": ["Yes", "No"],
"active": true,
"closed": false,
"status": "open",
"event_slug": "example-event",
"event_title": "Example event",
"tag_slugs": ["example"],
"category": "examples",
"image": "https://example.com/market.png",
"updated_at": "2026-08-27T20:00:00Z",
"volume_all_time": null,
"liquidity": null,
"outcome_prices": null
}
],
"rows_returned": 1,
"has_more": true,
"limit": 2,
"next_cursor": "mec1.example-cursor",
"sort": "updated",
"order": "desc",
"filters": {
"status": "open",
"event_slug": null
}
}
Continue pagination
Passnext_cursor unchanged and keep the same status and event_slug
filters:
curl "https://api.polynode.dev/v3/markets?status=open&limit=2&cursor=$NEXT_CURSOR" \
-H "x-api-key: $POLYNODE_API_KEY"
has_more is false. The last page returns next_cursor: null.
Cursors expire, so complete a page walk promptly rather than storing a cursor
as a permanent market ID.
Response envelope
| Field | Type | Description |
|---|---|---|
markets | array | Market rows in this page. |
rows_returned | integer | Number of rows returned. |
has_more | boolean | Whether another page exists. |
limit | integer | Effective page size. |
next_cursor | string or null | Cursor for the next page, or null on the last page. |
sort | string | Always updated. |
order | string | Always desc. |
filters.status | string or null | Canonical status filter, or null for all statuses. |
filters.event_slug | string or null | Event filter, or null. |
Market fields
| Field | Type | Nullable | Description |
|---|---|---|---|
condition_id | string | no | Market condition ID. |
question | string | yes | Market question. |
slug | string | yes | Market slug. |
outcomes | array<string> | yes | Outcome labels. |
status | string | no | open, closed, or inactive. |
active, closed, archived | boolean | yes | Market state flags when available. |
enable_order_book | boolean | yes | Whether orderbook trading is enabled. |
end_date, closed_time | string | yes | Market timestamps when available. |
neg_risk | boolean | yes | Whether the market uses neg-risk settlement. |
neg_risk_market_id | string | yes | Neg-risk market ID when available. |
event_slug, event_title | string | yes | Parent event identity. |
group_item_title | string | yes | Group label for a market inside an event. |
image, icon | string | yes | Image URLs when available. |
tag_slugs | array<string> | no | Market tags. An untagged market returns an empty array. |
category | string | yes | Market category when available. |
winning_outcome_index | integer | yes | Winning outcome index after resolution. |
updated_at, pm_created_at, pm_updated_at | string | yes | Market timestamps when available. |
volume_all_time, liquidity, outcome_prices | null | yes | Reserved financial fields. This catalog currently returns null; do not treat them as zero. |
Errors
| Status | Error | When it occurs |
|---|---|---|
400 | invalid_request | Invalid status, event slug, sort, order, or use of offset. |
400 | invalid_cursor | A cursor is malformed, expired, or used with different filters. |
401 | authentication error | The API key is missing or invalid. |
410 | invalid_cursor | The page walk referenced by the cursor is no longer available. Start again without a cursor. |
503 | temporarily_unavailable | Markets and events are temporarily unavailable. |
Authorizations
Query Parameters
Required range:
1 <= x <= 300Opaque next_cursor from the preceding page.
Available options:
open, closed, inactive, all Exact parent event slug.
Available options:
updated Available options:
desc Response
Cursor-paginated markets
Show child attributes
Show child attributes
Required range:
x >= 0Required range:
1 <= x <= 300Allowed value:
"updated"Allowed value:
"desc"Show child attributes
Show child attributes

