Polymarket Gamma API 是 Polymarket 的公共目录层:它无需认证即可暴露事件、市场、标签、系列和体育元数据,是发现工作流的正确起点。它不提供实时订单簿或执行交易;这些职责属于 CLOB 和 Data API。本文解释 Gamma 的数据层级,展示可运行的请求以列出和分页市场,并逐步介绍一个包含验证和故障排除步骤的可复现摄取管道。文章还涵盖 Gamma 的边界在哪里,以及如何测量你自己管道的行为,而不是依赖假设的限制。
Gamma API 是什么以及它适合放在哪里
Polymarket Gamma API 是一个位于 https://gamma-api.polymarket.com 的只读 REST 接口,返回 Polymarket 上事件和市场的索引元数据。其公共读取端点无需 API 密钥,这使其成为任何预测市场应用中的自然首次调用:你使用 Gamma 发现存在什么,然后将得到的代币标识符交给其他服务进行定价和执行。
重要的架构要点是关注点分离。Gamma 是目录,不是交易场所。它回答诸如“哪些市场是活跃的”、“这个事件 slug 是什么”以及“哪些结果代币属于这个市场”等问题。它不回答“当前最佳买价是多少”或“下这个订单”。这些属于 CLOB API,而用户持仓和交易历史属于 Data API。将 Gamma 视为发现层,将其他 API 视为执行和分析层,可以保持集成整洁并隔离故障模式。
本指南假设你有一个可用的 HTTP 客户端、对 JSON 有基本了解,以及一个持久化数据的地方,例如数据库或对象存储。所有示例使用占位符和公共读取路径;所示操作不需要凭据。
- Gamma:事件、市场、标签、系列、体育元数据、搜索。
- CLOB:订单簿、价格、下单和撤单。
- Data API:交易、持仓和用户特定活动。
- Subgraph:当你需要原始链上状态时直接查询链上数据。
事件与市场层级
Gamma 以层级方式组织数据。一个系列将相关事件分组,例如一个重复的体育联赛或一组季节性问题。一个事件是页面级概念,通常对应 Polymarket 网站上的一个问题,可以包含一个或多个市场。市场是可交易单元,携带结果代币、交易量、流动性和状态字段。
每个市场暴露你下游需要的标识符。conditionId 标识市场合约,clobTokenIds 是结果(通常是 Yes 和 No)的代币标识符数组。当你从 Gamma 转到 CLOB 进行定价时,传递这些代币标识符而不是市场 slug。在摄取时持久化 slug、conditionId 和代币 ID 之间的映射,可以节省后续重复查找。
事件和市场还携带状态字段,例如 active 和 closed。这些是独立的:一个市场可以是活跃但未关闭、已关闭且不活跃,或处于结算前后的过渡状态。当你想要当前可交易的库存时,对两者都进行过滤,并记录你观察到的值,以便推断随时间的变化。
使用 curl 列出活跃事件
从一个最小请求开始,列出按近期交易量排序的活跃、开放事件。响应包含 has_more 标志和事件对象本身。在编写任何管道代码之前,手动检查一个响应,以便了解你的 API 版本返回的字段名称。
以下命令可以安全地对公共端点运行。它不需要认证,也不会改变状态。
curl -s "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume_24hr&ascending=false&limit=5" \
| python -m json.tool | head -n 80分页遍历市场而不遗漏行
Gamma 支持基于偏移的分页,使用 limit 和 offset,响应包含 has_more。可靠的模式是请求一页、处理它,然后将偏移增加实际返回的记录数,直到 has_more 为 false。不要假设服务器返回正好 limit 条记录;最后一页通常较短,过滤器可能减少页面大小。
一个微妙的故障模式是偏移漂移。如果你在按交易量排序的实时列表上分页,同时新事件进入排序顶部,行可能在页面之间移动,你可能会看到重复或遗漏记录。对于快照式摄取,按稳定字段(如 start_date 或 id,如果可用)排序,或接受重复并在下游按市场标识符去重。Gamma 还暴露键集式端点,如 markets/keyset 和 events/keyset;当你需要稳定遍历大型结果集时,优先使用这些端点。
下面的 Python 示例演示了一个有界、去重的分页器。它限制总页数,防止失控循环冲击端点,并记录已见过的标识符。
import time
import requests
BASE = "https://gamma-api.polymarket.com"
def iter_markets(limit=100, max_pages=20, pause=0.5):
seen = set()
offset = 0
for _ in range(max_pages):
resp = requests.get(
f"{BASE}/markets",
params={"active": "true", "closed": "false", "limit": limit, "offset": offset},
timeout=15,
)
resp.raise_for_status()
batch = resp.json()
if not batch:
break
for market in batch:
key = market.get("conditionId") or market.get("slug")
if key and key not in seen:
seen.add(key)
yield market
offset += len(batch)
time.sleep(pause)
for m in iter_markets():
print(m.get("slug"), m.get("conditionId"))按 slug 解析单个市场
当你已经知道市场的 slug 时,直接获取它而不是扫描列表。slug 端点返回市场对象,然后你可以将其与存储的元数据连接。这是在 webhook 处理器或面向用户的详情页中使用的模式,其中延迟很重要,完整列表会很浪费。
同样的原则适用于事件:events 端点接受 slug 参数并返回匹配的事件及其嵌套市场。将这些定向查找用于读取路径,并将列表端点保留用于计划摄取。
curl -s "https://gamma-api.polymarket.com/markets?slug=fed-decision-in-october" \
| python -c "import sys,json; d=json.load(sys.stdin); print(json.dumps(d[0] if d else {}, indent=2)[:1200])"设计可复现的摄取管道
围绕 Gamma API 的生产管道应该是无聊且可观察的。将其结构化为四个阶段:获取、规范化、持久化和验证。在获取阶段,应用显式过滤器和有界页数。在规范化中,将 Gamma 字段映射到你自己的模式,并将 clobTokenIds 提取到单独的表。在持久化中,按 conditionId 进行 upsert,使重复运行具有幂等性。在验证中,将行数和校验和与上一次运行进行比较。
在运行日志中记录每个页面的请求参数、响应状态和记录数。当以后出现问题时,该日志是五分钟诊断与一下午猜测之间的区别。将原始 JSON 与规范化行一起存储至少几次运行,以便无需重新获取即可重放。
在测量之前,将速率限制视为未知。公共 API 是共享基础设施,因此在页面之间建立保守的暂停,对 429 响应采用指数退避,并且永远不要对共享端点进行激进并行化。如果你的工作负载增长超出礼貌的公共使用允许范围,考虑专用数据层或你自己的缓存层,而不是增加请求压力。
- 按 conditionId 进行 upsert;保留 slug 作为辅助键。
- 持久化原始负载以用于重放和模式漂移检测。
- 记录每次运行的页面参数、状态码和行数。
- 对 429 和 5xx 进行退避;限制重试次数并在耗尽时告警。
验证运行并读取结果表
每次摄取运行后,生成一个小结果表,以便一目了然地比较运行。下表是一个模板:用你自己的观察值填充它。不要从文档或其他文章复制数字;重点是为你自己的环境和过滤器建立基线。
| 运行时间戳 | 过滤器集 | 获取页数 | 看到记录数 | 更新插入记录数 | 跳过重复数 | 错误 | p95 延迟 (ms) |
|---|---|---|---|---|---|---|---|
健康的运行显示看到记录数大于或等于更新插入记录数,首次运行时跳过重复数接近零,增量运行时更高,并且零错误。重复数突然跳升通常意味着排序列表上的偏移漂移。相同过滤器下看到记录数下降通常意味着过滤器值改变或端点返回了客户端未引发错误的错误页面。
对于延迟,在客户端测量端到端请求时间,并记录每次运行的 95 百分位。跨运行比较,而不是与固定目标比较;网络路径和服务器负载都会变化。如果你需要稳定、低延迟的路径进行相邻的链上读取,来自 OnFinality RPC 服务等提供商的托管端点可以消除一个方差来源,但 Gamma 本身仍然是 Polymarket 运营的服务。
排查常见的 Gamma 集成问题
大多数 Gamma 问题属于几类。空响应通常意味着过度约束的过滤器组合,例如 active=true 与 closed=true 和狭窄的标签。在组合它们之前,独立检查每个过滤器。slug 查找时意外的 404 通常意味着 slug 已更改或市场已重命名;如果你存储了 conditionId,则回退到按 conditionId 搜索。
当添加字段或嵌套对象改变形状时,模式意外很常见。防御性解析,即读取可选字段并记录未知键,可以防止单个新字段破坏管道。如果你的客户端反序列化为严格类型,请对模型进行版本控制并容忍未知属性。
速率限制表现为 429 响应,有时没有 Retry-After 头。实现带抖动的指数退避,将摄取并发限制为一次一个请求,并在退避超过阈值时告警。持续的 5xx 错误应视为中断:暂停运行,保留最后一个良好快照,并从最后提交的偏移恢复,而不是从零重新开始。
- 空结果:一次放宽一个过滤器。
- slug 404:通过 conditionId 或搜索重新解析。
- 解析错误:记录原始负载和未知键。
- 429:带抖动退避;降低并发。
- 5xx:暂停,保留快照,从检查点恢复。
限制、权衡以及何时添加另一层
Gamma 针对发现进行了优化,而不是高频读取或历史分析。它提供当前元数据和状态,但不是时间序列存储。如果你需要历史价格序列、订单簿深度或跨场所比较,你将需要 CLOB API、Data API 或单独的分析层。对于专注的产品,自己构建这些连接是合理的,对于广泛的产品则成本高昂。
还有一个新鲜度权衡。缓存 Gamma 响应可减少负载和延迟,但意味着你的目录可能滞后于现实。根据用户需要多快看到新市场来选择缓存持续时间;对于大多数发现 UI,带有后台刷新的短缓存就足够了。对于交易 UI,在呈现可操作报价之前,始终对照 CLOB 确认价格和可用性。
最后,考虑你的基础设施边界。Gamma 是 Polymarket 服务,但你堆栈的其余部分可能直接读取链状态。如果你正在查询 Polygon 以获取结算或余额数据,可靠的 RPC 端点与可靠的目录同样重要。你可以通过 OnFinality 网络目录查看可用网络和端点选项,并在承诺提供商之前比较 RPC 定价页面上的计划。
生产集成的后续步骤
一旦你的 Gamma 摄取稳定,从三个方向扩展它。首先,添加 CLOB 读取路径,以便你的应用可以在目录元数据旁边显示实时价格。其次,如果你正在构建投资组合视图,添加 Data API 路径以获取用户持仓和交易历史。第三,添加监控,对摄取失败、模式漂移和延迟回归进行告警,而不是等待用户报告缺失市场。
如果你的应用还需要直接链访问以进行结算检查或钱包余额,评估专用节点或托管 RPC 服务,以便目录读取和链读取独立失败。你可以探索专用节点选项和更广泛的 API 服务产品,以决定托管基础设施是否符合你的可靠性目标。
对于想要具体端点推荐而不是方法论的团队,RPC Assistant 是提问的正确地方;本指南故意停留在集成和测量层面,以便你的选择基于你自己观察到的行为。
- 在 Gamma 元数据旁边添加 CLOB 定价。
- 添加 Data API 读取以获取持仓和活动。
- 对摄取进行插桩,对漂移和失败告警。
- 分离目录和链基础设施故障域。