Polymarket Bot Tutorial · Chương 7 trên 32

Polymarket Gamma API deep dive: các endpoint /events và /markets, pagination, tag IDs (864 Tennis, 745 NBA, v.v.), lọc theo volume 24h, rate limits, và các code sample Python và Node.

Chương này bao gồm gì

Gamma là catalog API của Polymarket - nó liệt kê mọi event, mọi market, tag, image và resolved outcome mà front-end hiển thị. CLOB API dùng để trade; Gamma mô tả những gì có thể trade. Phần lớn bug của bot ở lớp discovery đến từ việc nhầm lẫn hai hệ thống này, hoặc do bỏ sót pagination contract. Chương này là tài liệu tham chiếu thực chiến cho các endpoint chính của Gamma, với hành vi tham số chính xác mà các fetcher production của chúng tôi phụ thuộc vào.

  • Gamma vs CLOB: khi nào dùng cái nào
  • Anatomy của endpoint /events
  • Anatomy của endpoint /markets
  • Tags và tag IDs (danh sách đã xác minh)
  • Filtering: active, closed, sắp xếp volume24hr
  • Pagination và limits
  • Rate limits và caching
  • Code: fetch top market theo 24h-volume

Gamma vs CLOB: khi nào dùng cái nào

Hai dịch vụ khác nhau cho hai công việc khác nhau.

Gamma (gamma-api.polymarket.com): catalog. Liệt kê events, markets, tags, descriptions, images, resolved outcomes, volume 24 giờ, tổng volume, ngày kết thúc. Chỉ đọc qua HTTP. Phần lớn lượt đọc không cần xác thực. Được cập nhật liên tục nhưng eventual consistency - một market vừa đóng có thể vẫn hiển thị closed: false trong vài giây.

CLOB (clob.polymarket.com): trading + order book. Liệt kê best bid/ask hiện tại, độ sâu order book top-N, các giao dịch gần đây. Yêu cầu xác thực cho các endpoint ghi (đặt lệnh, hủy lệnh). Có các WebSocket channel real-time cho cập nhật book.

Quy tắc thực tế: dùng Gamma để tìm cái gì nên trade; dùng CLOB để trade nó. Một bot đọc giá từ Gamma là đang dùng dữ liệu cũ - các field giá của Gamma cập nhật chậm hơn order book của CLOB. Một bot đọc metadata market từ CLOB là đang thực hiện nhiều request hơn mức cần thiết.

Anatomy của endpoint /events

GET /events trả về dữ liệu ở cấp event. Một "event" là một trang Polymarket; một event đơn lẻ có thể chứa nhiều market (ví dụ, event 2024 Presidential Election có một market cho mỗi ứng viên).

Các field chính:

  • slug: định danh an toàn cho URL, ổn định trong suốt vòng đời của event.
  • title, description: hiển thị cho người dùng.
  • endDate (ISO 8601): khi event đóng.
  • active, closed: boolean; kết hợp trong query với ?active=true&closed=false cho các event đang chạy.
  • volume, volume24hr: tổng USD.
  • tags: mảng các tag object (xem phần tags bên dưới).
  • markets: mảng các child market object (xem phần anatomy của /markets).

Pattern discovery phổ biến nhất: GET /events?active=true&closed=false&order=volume24hr&ascending=false&limit=100. Trả về 100 event đang live có volume cao nhất.

Anatomy của endpoint /markets

GET /markets trả về dữ liệu ở cấp market. Một market là một hợp đồng Y/N hoặc multi-outcome; nó nằm bên trong một event.

Các field chính:

  • slug: định danh an toàn cho URL.
  • question: tiêu đề hiển thị trên trang giao dịch (ví dụ: "Will Trump be president on January 1, 2027?").
  • outcomes: JSON string của tên outcome, ví dụ '["Yes","No"]'. Binary luôn có hai phần tử; NegRisk thì nhiều hơn.
  • outcomePrices: JSON string của giá hiện tại dưới dạng decimal, ví dụ '["0.62","0.38"]'. Hai phía cộng lại xấp xỉ 1.0 trừ spread.
  • clobTokenIds: JSON string của ERC-1155 token IDs khớp với outcomes. Đây là các token bạn thực sự mua/bán.
  • negRisk: boolean; true với các market multi-outcome sum-to-1. Quan trọng cho việc đặt lệnh (chương 11).

Các field outcomes / outcomePrices / clobTokenIds được trả về dưới dạng JSON strings, không phải mảng đã parse - hãy JSON-decode trước khi dùng.

Tags và tag IDs (danh sách đã xác minh)

Tags là các nhãn phân loại (Sports, Crypto, Tennis, NBA, v.v.). Tag IDs production đã xác minh cho các category được dùng nhiều nhất:

TagIDTagID
Sports1NBA745
Crypto21NFL450
Politics2Tennis864
Bitcoin100196Esports702
Ethereum100383Soccer1059
Election3EPL739
Middle East1432UCL2186

Lọc theo tag bằng ?tag_id=745 cho một tag cụ thể, hoặc ?tag_slug=nba dùng slug. Lọc theo slug dễ đọc hơn trong code nhưng hơi chậm hơn; lọc theo ID là mặc định trong production.

Filtering: active, closed, sắp xếp volume24hr

Bốn chiều lọc bạn sẽ dùng 95% thời gian.

  • active=true|false: true loại trừ các market mà team Polymarket đã ẩn khỏi UI.
  • closed=true|false: false loại trừ các market đã resolved. Kết hợp active=true&closed=false là bộ lọc live phổ biến nhất.
  • order=volume24hr, order=volume, order=endDate: khóa sắp xếp. Hữu ích nhất là volume24hr để tìm các market đang hoạt động.
  • ascending=true|false: mặc định là true trên hầu hết endpoint; gần như lúc nào bạn cũng muốn false cho các kiểu sắp xếp theo volume.

Lưu ý: lọc theo tag_id kết hợp với order=volume24hrascending=false đôi khi trả về một trang trống khi tag đó có rất ít live market. Luôn over-fetch (request nhiều hơn số bạn hiển thị) và post-filter để xử lý trường hợp này.

Pagination và limits

Tham số limit nhận 1-500 cho mỗi lần gọi. Mặc định là 100 nếu không chỉ định. Trên 500, server sẽ tự giới hạn ngầm - bạn nhận 500 nhưng response không báo rằng còn nhiều hơn.

Pagination dựa trên offset: ?limit=500&offset=500 cho trang thứ hai. Không có pagination dựa trên cursor, nên các insert đồng thời có thể làm ranh giới trang dịch chuyển giữa các lần gọi. Với đa số mục đích discovery của bot, điều này chấp nhận được; với các lần scrape archive, hãy sắp xếp theo một field ổn định (endDate hoặc createdAt) và phát hiện overlap bằng slug.

Pattern thực tế cho "tất cả market đang live": fetch limit=500&order=volume24hr&ascending=false. Cách này bao phủ top 500 theo volume, về cơ bản là mọi market có hoạt động đáng kể. Đi xa hơn page 1 hiếm khi hữu ích - các market ở phần đuôi phân phối volume theo định nghĩa là nơi không có nhiều action.

Rate limits và caching

Gamma được Cloudflare bảo vệ ở phía trước và có soft rate limits theo IP. Các ngưỡng thực nghiệm quan sát được dưới tải production:

  • Khoảng đến ~30 req/sec từ một IP duy trì liên tục: ổn.
  • Burst 100+ req/sec: thỉnh thoảng có 429, retry thì thành công.
  • ~500 req/sec duy trì: rate-limit page hoặc block tạm thời (10-60 giây).

Response headers được công bố bao gồm giá trị Cache-Control từ 30-60 giây cho hầu hết endpoint. Hãy tuân thủ chúng - không có lợi ích gì khi fetch lại cùng một event 10 lần trong một phút. Pattern caching production: in-process LRU + TTL key theo toàn bộ URL, TTL 30 giây. Tiết kiệm số request và giảm latency.

Với các chiến lược tần suất cao, hãy mirror dữ liệu Gamma vào một local store được cập nhật bởi một fetcher process duy nhất; cho nhiều consumer đọc từ store đó. Một fetcher × nhiều consumer > nhiều fetcher × Gamma.

Code: fetch top market theo 24h-volume

Reference fetcher bằng ba ngôn ngữ, trả về top 50 live market theo volume 24 giờ.

Python:

import requests
r = requests.get("https://gamma-api.polymarket.com/events",
                 params={"active":"true","closed":"false",
                         "order":"volume24hr","ascending":"false","limit":50},
                 timeout=10)
for ev in r.json()[:50]:
    print(ev["slug"], ev.get("volume24hr"))

Node:

const url = "https://gamma-api.polymarket.com/events?active=true&closed=false" +
            "&order=volume24hr&ascending=false&limit=50";
const events = await fetch(url).then(r => r.json());
for (const ev of events) console.log(ev.slug, ev.volume24hr);

Curl:

curl -s "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume24hr&ascending=false&limit=50" \
  | jq '.[].slug'

Endpoint /events của Polymarket gamma KHÔNG hỗ trợ tham số tìm kiếm free-text - thêm ?q=foo hoặc ?search=foo sẽ âm thầm trả về thứ tự mặc định. Hãy lọc theo slug hoặc tag thay thế.

Các câu hỏi thường gặp

Polymarket Gamma API là gì?
Gamma là metadata và discovery API của Polymarket. Nó phục vụ danh sách event/market, tiêu đề, mô tả, ngày kết thúc, tags, và aggregate volume. Nó KHÔNG phục vụ dữ liệu order book real-time - phần đó nằm trên CLOB API. Với hầu hết use case discovery và analytics, bạn sẽ bắt đầu từ Gamma.
Sự khác nhau giữa event và market trên Polymarket là gì?
Một event nhóm một hoặc nhiều market cùng chung một chủ đề câu hỏi. Một market là một kết quả Yes/No cụ thể với order book và token IDs riêng. Một event "2026 NBA Champion" chứa 30 market (mỗi đội một market). Với các event binary Yes/No, event có 1 underlying market.
Làm sao để tìm Polymarket tag IDs?
Tags được cung cấp qua endpoint gamma /tags. Các ID đã xác minh mà chúng tôi dùng trong production: 864 Tennis, 745 NBA. Tag slug trong URL (?tag_slug=tennis) và free-text query (?q=tennis) không đáng tin cậy - chỉ dùng numerical tag_id. Kiểm tra /tags trước khi dựa vào slug.
Làm sao để sắp xếp Polymarket events theo volume 24h?
/events?order=volume24hr&ascending=false - đây là thứ đứng sau hầu hết widget "trending markets". Kết hợp với active=true&closed=false để loại bỏ các market đã hết hạn hoặc tạm dừng. Limit mặc định là 25; tối đa là 500 mỗi lần gọi.
Gamma có giới hạn pagination không?
Có. Các endpoint /events và /markets chấp nhận limit (tối đa 500 mỗi lần gọi) và offset cho pagination. Hầu hết thư viện không tự động paginate - nếu bạn cần toàn bộ dữ liệu, hãy loop với offset cho đến khi nhận được một page có ít hơn `limit` kết quả.
Gamma có hỗ trợ WebSocket không?
Không. Gamma chỉ hỗ trợ REST. Để cập nhật real-time (thay đổi giá, market mới, order book) hãy dùng CLOB WebSocket - được đề cập trong chương 8 của series này.