Endpoints
Instruments & Symbols
| Method | Endpoint | Description |
|---|
POST | /v1/refdata/symbols | List all symbols |
POST | /v1/refdata/instruments | List instruments (filter by symbols in body) |
POST | /v1/refdata/metadata | Get instrument metadata |
Sports Data
| Method | Endpoint | Description |
|---|
GET | /v1/refdata/sports | List all sports with metadata |
GET | /v1/refdata/sports/teams | List teams with optional filtering |
GET | /v1/refdata/sports/teams/provider | Get teams by provider-specific IDs |
See Sports Reference Data for detailed documentation.
No Participant ID RequiredThese endpoints only require Auth0 JWT authentication with read:instruments scope. You do not need to provide the x-participant-id header or complete KYC onboarding to access reference data.
No GET endpoint for single instrumentTo get a single instrument, use POST /v1/refdata/instruments with {"symbols": ["SYMBOL-NAME"]} in the body.
Filtering Instruments
The /v1/refdata/instruments endpoint supports configurable query parameters to filter and paginate results.
Request Parameters
| Parameter | Type | Description |
|---|
pageSize | int32 | Results per page (default: 50, max: 1000) |
pageToken | string | Pagination cursor from previous response |
symbols | string[] | Filter by exact instrument symbols |
productId | string | Filter by exact product ID |
tradableFilter | enum | TRADABLE_FILTER_TRADABLE, TRADABLE_FILTER_NON_TRADABLE, or TRADABLE_FILTER_ALL |
states | enum[] | Filter by instrument states (multiple values = OR logic) |
eventSeries | string | Filter by event series (e.g., cbb, nfl, nba) |
eventCategory | string | Filter by event category (e.g., SPR, POL, CUL) |
clearingSym | string | Filter by clearing symbol (e.g., AEC-NFL, AEC-BASKETBALL) |
startTimeGte | string | Instruments starting on or after date (format: YYYY-MM-DD) |
startTimeLte | string | Instruments starting on or before date |
endTimeGte | string | Instruments expiring on or after date |
endTimeLte | string | Instruments expiring on or before date |
All parameter names accept both camelCase and snake_case (e.g., eventSeries and event_series are equivalent). This is standard protobuf JSON serialization behavior.
Protobuf Enum CautionThe states and tradableFilter parameters use protobuf enums. Unrecognized values (typos, made-up states, etc.) silently map to the default enum value and return misleading results — they do not error or return empty. Only use the exact values documented here.
Response Fields
| Field | Type | Description |
|---|
instruments | array | List of matching instruments |
nextPageToken | string | Token for next page (empty if no more results) |
eof | boolean | True when no more results |
Use pageSize and pageToken to paginate through large result sets.
# First page
curl -X POST "https://api.preprod.polymarketexchange.com/v1/refdata/instruments" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"pageSize": 100}'
# Next page (use nextPageToken from previous response)
curl -X POST "https://api.preprod.polymarketexchange.com/v1/refdata/instruments" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"pageSize": 100, "pageToken": "eyJvIjoxMDB9"}'
Filtering by State
Filter instruments by their current trading state using the states parameter.
curl -X POST "https://api.preprod.polymarketexchange.com/v1/refdata/instruments" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"states": ["INSTRUMENT_STATE_OPEN"],
"pageSize": 100
}'
You can specify multiple states to match any of them:
{
"states": ["INSTRUMENT_STATE_OPEN", "INSTRUMENT_STATE_SUSPENDED"],
"pageSize": 100
}
Filtering by Series
Filter instruments by series (e.g., NFL, NBA, US Presidential):
curl -X POST "https://api.preprod.polymarketexchange.com/v1/refdata/instruments" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"event_series": "nba",
"states": ["INSTRUMENT_STATE_OPEN"],
"pageSize": 1000
}'
Filtering by Category
Filter instruments by category (e.g., SPR for sports, POL for politics):
curl -X POST "https://api.preprod.polymarketexchange.com/v1/refdata/instruments" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"event_category": "SPR",
"states": ["INSTRUMENT_STATE_OPEN"],
"pageSize": 1000
}'
Combining Filters
You can combine multiple filters:
curl -X POST "https://api.preprod.polymarketexchange.com/v1/refdata/instruments" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"eventSeries": "nfl",
"eventCategory": "SPR",
"clearingSym": "AEC-NFL",
"states": ["INSTRUMENT_STATE_OPEN"],
"pageSize": 1000
}'
Advanced Filtering
The filter parameter supports two approaches that can be used independently or combined. When both are provided, results must match both conditions (AND).
Option A: whereClause — A SQL-like string expression:
curl -X POST "https://api.preprod.polymarketexchange.com/v1/refdata/instruments" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"filter": {
"whereClause": "symbol LIKE '\''aec-nfl-%'\'' AND state = '\''INSTRUMENT_STATE_OPEN'\''"
}
}'
Supported operators: =, LIKE (with % wildcard), AND
Supported columns:
| Column | Notes |
|---|
state | Instrument state enum values |
symbol | Exact match or LIKE pattern |
event_series | e.g., 'cbb', 'nfl' |
event_category | e.g., 'SPR' |
clearing_sym | e.g., 'AEC-BASKETBALL' |
clearing_house | e.g., 'QCC' |
product_id | Product identifier |
Do not use instrument_product, outcome_type, or event_subcategory in whereClause — these cause HTTP 500 errors. The column event_id is accepted but returns 0 results for known values.
Option B: fieldFilters — Structured, type-safe filters:
{
"filter": {
"fieldFilters": [
{
"field": "event_series",
"operator": "FILTER_OPERATOR_EQ",
"stringValue": "nfl"
},
{
"field": "state",
"operator": "FILTER_OPERATOR_IN",
"stringList": {
"values": ["INSTRUMENT_STATE_OPEN", "INSTRUMENT_STATE_PREOPEN"]
}
}
]
}
}
Each field filter has a field name, an operator, and a typed value (stringValue or stringList). Multiple entries are ANDed together. The same columns supported in whereClause work in fieldFilters.
Available operators:
| Operator | Description | Value field |
|---|
FILTER_OPERATOR_EQ | Exact match | stringValue |
FILTER_OPERATOR_IN | Match any in list | stringList ({"values": [...]}) |
FILTER_OPERATOR_LIKE | SQL LIKE pattern (% wildcard) | stringValue |
Instrument Data
Each instrument includes:
| Field | Type | Description |
|---|
symbol | string | Unique trading symbol |
tickSize | double | Minimum price increment |
baseCurrency | string | Base currency (e.g., "USD") |
multiplier | double | Contract multiplier |
minimumTradeQty | string (int64) | Minimum order quantity |
startDate | Date | Market start date ({year, month, day}) |
expirationDate | Date | Expiration date |
terminationDate | Date or null | Termination date (null when not set) |
tradingSchedule | TradingHours[] | Trading schedule segments (empty array when none) |
description | string | Human-readable instrument description |
clearingHouse | string | Clearing house code (e.g., "QCC") |
minimumUnaffiliatedFirms | string (int64) | Minimum unaffiliated firms requirement |
nonTradable | boolean | Whether instrument is non-tradable |
jsonAttributes | string | Additional JSON attributes (empty when unused) |
productId | string | Product identifier |
priceLimit | PriceLimit | Price limits ({low, high, lowSet, highSet, ...}) |
orderSizeLimit | OrderSizeLimit or null | Order size limits (null when not set) |
expirationTime | TimeOfDay | Expiration time of day ({hours, minutes, seconds}) |
tradeSettlementPeriod | string (int64) | Settlement period |
state | string (enum) | Current instrument state (e.g., "INSTRUMENT_STATE_OPEN") |
priceScale | string (int64) | Price scale divisor for converting integer prices to decimals |
fractionalQtyScale | string (int64) | Fractional quantity scale |
settlementCurrency | string | Reserved for future use |
settlementPriceScale | string (int64) | Reserved for future use |
metadata | map<string,string> | Key-value metadata (sports league, market category, game IDs, etc.) |
eventAttributes | EventAttributes | Event resolution details ({question, payoutValue, ...}) |
createTime | string (Timestamp) | Instrument creation time (RFC 3339) |
updateTime | string (Timestamp) | Last update time (RFC 3339) |
Integer Fields Encoded as Strings in JSONFields typed as int64 in the protocol buffer definition (such as minimumTradeQty, priceScale, fractionalQtyScale, priceLimit.low, priceLimit.high) are serialized as strings in JSON responses per the proto3 JSON specification. Parse these values as numbers in your client code.For example, "priceScale": "100" is the string "100", not the number 100.
Instrument States
Primary State Flow
| State | Description |
|---|
PENDING | Initial state for a newly created instrument which has not yet begun trading. |
OPEN | In this state, the instrument is open for continuous order entry and matching. |
CLOSED | In this state, orders can not be entered, modified, or canceled, and no matching occurs. Any existing Day orders will be expired. |
EXPIRED | An instrument moves to this state when its Expiration Date/Time is reached. In this state, any resting orders are expired and no new orders can be entered. |
TERMINATED | When an instrument’s Termination Date is reached, the order book is removed from the matching engine, orders are canceled, and positions are closed. Historical data will still remain in Polymarket US ledgers. |
Exception States
| State | Description |
|---|
SUSPENDED | Orders can be canceled but no matching occurs, and no order entry or modification is allowed. |
HALTED | This state is similar to SUSPENDED, with the exception that orders cannot be canceled. |
Other Possible States
| State | Description |
|---|
PREOPEN | Orders can be entered and modified, but no matching occurs. When the instrument transitions to an OPEN state, the orders entered during PREOPEN will match at a single opening price that is automatically determined by an algorithm that is designed to maximize the volume traded at the open. |
MATCH_AND_CLOSE_AUCTION | This state is similar to PREOPEN, with the exception that matching will occur upon the transition of this state to any other state. This state is useful if you want matching to occur at the end of the state, but you don’t want the instrument to be open after. |
Price Scale
Prices in the API are represented as integers. Divide by priceScale to get decimal prices:
decimal_price = int_price / instrument.price_scale
# Example: 52500 / 1000 = $52.50
Cache Reference DataInstrument metadata changes infrequently. Cache reference data locally and refresh periodically (e.g., daily or on startup) rather than fetching for every request.
Usage Notes
- Reference data is static during a trading session
- Use
/v1/refdata/instruments to get priceScale for price conversions
- Instrument states change based on market schedule