PMWallets
中文

Polymarket token IDs, condition IDs and slugs: how they connect

A Polymarket market has a slug for people, a condition ID for the contracts, and one token ID per outcome for trading. Every data source speaks a different one of the three, and joining them is the first thing any Polymarket tool has to get right.

Three identifiers

The slug is the human name in a polymarket.com URL; an event (say, an election) has its own slug and contains one or more markets, each with a slug. The condition ID is a 32-byte hash that identifies the market in the Conditional Tokens contract. Each outcome of a market is a token with a 256-bit token ID — the CTF position ID — and that is what the order book and the chain trade.

Where each one appears

Polymarket's Gamma API describes markets and events: slug, question, conditionId, outcomes and clobTokenIds, plus flags such as negRisk and the fee settings. The Data API's trades and positions carry the token ID (as asset), the conditionId and the slugs. The CLOB order book and its WebSocket are keyed by token ID. On-chain fills carry only token IDs.

Mapping them

From a slug, ask Gamma for the market and read its conditionId and clobTokenIds. From a token ID seen in a log, the exchange contracts' TokenRegistered events give the pair of token IDs and their condition ID, and the CTF contract can confirm it; Gamma's markets endpoint can also be queried by clob_token_ids. Two quirks: outcomes and clobTokenIds arrive as JSON-encoded strings that have to be parsed, and their order matches — the first token is the first outcome.

python
import json, requests

m = requests.get("https://gamma-api.polymarket.com/markets",
                 params={"slug": "<market-slug>"}).json()[0]
outcomes  = json.loads(m["outcomes"])        # e.g. ["Yes", "No"]   — a JSON string, not a list
token_ids = json.loads(m["clobTokenIds"])    # same order as outcomes — also a JSON string
print(m["conditionId"], dict(zip(outcomes, token_ids)))

The JavaScript trap

Token IDs are up to 78 digits long. JavaScript numbers are exact only up to 2^53, so JSON.parse on a raw token ID silently rounds it to a different number. Keep token IDs as strings, or as BigInt when arithmetic is needed — the clobTokenIds string helps here, because its elements are already strings.

When a token has no market

Newly created markets can trade before every index has caught up, and a few tokens never get a public market name. A tool should say a fill is unmapped rather than drop it or guess. PMWallets maps every token through three sources — the exchanges' registrations, its own backfilled registrations and the CTF's condition data — and holds the leaderboard back if more than a small share of traded value is still unmapped.

Questions

How do I find the token ID of a Polymarket market?

Ask Polymarket's Gamma API for the market by slug and parse clobTokenIds — a JSON-encoded list in the same order as outcomes. Each element is the token ID of that outcome.

What is the difference between a condition ID and a token ID?

The condition ID identifies the market in the Conditional Tokens contract; a token ID identifies one outcome of it, and is what is traded. A binary market has one condition ID and two token IDs.

Why do Polymarket token IDs change when I parse them in JavaScript?

They are larger than the biggest integer a JavaScript number holds exactly, so they get rounded. Keep them as strings or BigInt.

Related