语言前缀
所有端点都以语言代码为前缀:/zh/...(中文)/en/...(英文)/de/...(德文)
sportId、fixtureId等)与语言无关。
体育、锦标赛、赛季
sportId
- 整数。
- 嵌入到多个下游ID中的前两位数字。
- 通过
/sports发现。
tournamentId
- 整数。
- 属于恰好一项体育运动。
- 通过
/tournaments发现。
seasonId
- 整数。
- 属于恰好一个锦标赛。
- 通过
/seasons发现。
完整的运动覆盖表列出了每个 sportId 及其是否以赛事、期货或两者形式提供。
实体层级
API 中的一切都挂在同一棵树上:赛事如何运作(体育)
**赛事(fixture)**是两个参与者(球队或球员)之间的单场比赛:- 赛事对象承载日程与状态:
startTime(纪元秒)、statusId、participant1Id/participant2Id、seasonId、场馆 —— 完整结构见fixtures频道和 REST 参考。 - 比分按赛段存储,以
result、p1、p2……为键 ——result行是权威的最终/当前比分;赛段行用于结算赛段盘口。参见scores频道。 - 赔率通过下方的赔率标识符附加到赛事上 —— 每个价格对应一个
{fixtureId}:{bookmaker}:{outcomeId}:{playerId}。
期货如何运作(预测市场)
**期货(future)**是针对整个赛季或事件(而非单场比赛)的冠军类盘口 —— “谁将赢得英超?” —— 同一模型也覆盖非体育预测市场(“谁将赢得 2028 年美国大选?”、“比特币会涨到 10 万美元吗?”)。 对于体育项目,期货挂在与其赛事完全相同的赛季之下 —— 只有叶子节点不同:阿森纳 vs 切尔西是赛季 130281 中的一场比赛;Winner 期货则是针对整个赛季的盘口。同一棵树、同一个 seasonId —— 赛事在 90 分钟内出结果,期货在赛季结束时出结果。
非体育预测市场复用完全相同的模型 —— 周期性主题即锦标赛,每一届即赛季:
- 一个期货 = 一个赛季内的一个冠军类盘口。
futureId末尾的futureMarketId表示盘口种类。它按运动分配,因此同一个问题在每项运动中都是不同的盘口:
因此足球的 Winner 盘口是
10001,政治的 Prediction 盘口是 69002。位置 002 在体育项目中是 topscorer,在非体育区间中是 prediction —— 二者永不冲突,因为没有任何一项运动同时拥有两者。
- 期货赔率以
{futureId}:{bookmaker}:{futureOutcomeId}:{participantId}为键 —— 参见期货赔率ID。 - 非体育主题(政治、选举、金融、加密货币、天气……)被建模为
sportId69+ 的”运动”,且仅以期货形式存在;赛马类(79–81)为赛前(ante-post)期货。确切区间见运动覆盖。
盘口和选项
摘要 —— 每个选项都遵循固定层级:
marketType → period → handicap → side,全部编码进 outcomeId —— 因此同一个投注始终解析为相同的 marketId / outcomeId,通过坐标定位而非对博彩公司名称做字符串匹配。唯一不在 outcomeId 中的是球员,由 playerId 承载。同一盘口的所有选项共享其 marketId,即该盘口的首个 outcomeId。盘口如何分解(确定性层级)
每一个outcomeId 都由单一、确定性的分解逻辑生成 —— OddsPapi 将每个盘口拆分为固定层级:
marketId / outcomeId 上。
关键规则: 由于每个盘口线都有自己的marketId,“大于 2.5” 和 “大于 3.5” 是不同的盘口 —— 而非同一盘口的两个选项。在单个marketId内,选项仅为该确切盘口线的各个方向(例如Over 2.5+Under 2.5)。
示例 —— 足球(sportId 10)
示例 —— 足球(sportId 10)
真实足球盘口映射的代表性切片。每个
marketId 等于其首个 outcomeId,且每个盘口线都是独立的盘口:读取第一行:
marketType=1x2、period=fulltime、handicap=0.0、outcomeName=1 —— 即全场比赛结果盘口的主队方向。marketId和outcomeId之间的关系
盘口和选项在设计上紧密耦合:
- 盘口代表一个完整的投注市场(例如独赢、1x2、大小球)。
- 盘口包含多个选项。
- 属于同一盘口的所有选项共享相同的
marketId。 - 盘口的第一个
outcomeId始终等于marketId。
marketLength
marketLength 是一个 marketId 下的选项数量 —— 即可供投注的方向数,它们共同构成完整的概率空间(在去除利润率之前,其隐含概率之和约等于 1)。示例:moneyline → 2、1x2 → 3、winningmargin → 所提供的赢球差区间数量。
ID结构
marketId和outcomeId都是整数,构造如下:
11xxxx→ 篮球盘口或选项14xxxx→ 美式橄榄球盘口或选项
- 每项运动无限的盘口和选项
- 按运动快速分组
- 立即可见的盘口关系
为什么marketId很重要(套利和建模)
单个marketId下的所有选项共同代表一个完整的概率空间。
这使得marketId特别适用于:
- 套利检测
- 超出率/利润率计算
- 概率归一化
- 盘口完整性检查
marketId对赔率分组。
参与者和球员
participantId
- 整数。
- 代表赛事中的球队或参赛者。
- 通过
/participants发现。
playerId
- 整数。
- 用于球员投注盘口。
playerId = 0通常代表非球员盘口。- 通过
/players发现。
赛事ID
fixtureId结构
fixtureId是一个编码多条信息的字符串:
id→ 内部命名空间前缀 —— 视为不透明值11→ sportId(2位数字)000132→ tournamentId(6位数字)62926199→ 该命名空间内的原生赛事ID
fixtureId 即可推断出运动和锦标赛 —— 便于日志记录和跨系统关联。
若要与另一套系统的赛事 ID 关联,请使用赛事频道上的 externalProviders 区块或映射端点 —— 参见作为第二数据源运行 OddsPapi。
期货ID
futureId结构
futureId遵循与fixtureId相同的原则:
prefix→ 内部命名空间前缀(例如id、pm、ks)—— 视为不透明值sportId→ 2位数字seasonId→ 赛季/赛事实例futureMarketId→ 该期货所问的冠军盘口(5位数字 —— 见下文)
futures 负载的 tournament.tournamentId 读取;将其排除在 ID 之外,正是为了在提供商把某赛季重新挂到另一个锦标赛下时,futureId 仍保持稳定。
期货盘口与选项
期货盘口是一种问题类型 —— “谁赢得英超?""谁是最佳射手?""X 会在 Y 之前发生吗?” —— 而非统计模板。同一个盘口被提出该问题的每个期货复用,并由futures 负载上的 market.marketId 标识:即 futureId 末尾携带的同一个 5 位 futureMarketId。
盘口有两种形态:
与赛事盘口有两处刻意的差异:
handicap位于选项上,而非盘口上。 对赛事而言每条线值都是独立的marketId。期货是按(赛季,问题)铸造的,铸造时无从得知某家博彩商会提供哪一档线值梯度,因此一个期货盘口承载多条线值。- 没有
period。 期货在其赛季或问题出结果时结算。
赔率标识符
摘要 —— 单个价格由
{fixtureId}:{bookmaker}:{outcomeId}:{playerId}(赛事)或 {futureId}:{bookmaker}:{futureOutcomeId}:{participantId}(期货)唯一标识。请将这些 oddsId 字符串用作存储中的主键,以实现干净的去重、更新与对账。赛事赔率键
对于赛事,单个价格由以下唯一标识:bookmaker,剩下的就是选项本身 —— {fixtureId}:{outcomeId}:{playerId} —— 这是与博彩公司无关的评级 / 结算键,因为一个选项在任何博彩公司处的输赢都相同。无需 marketId;outcomeId 已编码了盘口。
选项键让跨博彩商与跨数据源的比对变得廉价 —— 如何据此接入已有数据源,参见作为第二数据源运行 OddsPapi。
期货赔率ID
期货赔率由四段标识,与赛事赔率键保持一致:0 是哨兵值,正如非球员赛事赔率的 playerId 取 0 —— 它是一个真实且稳定的键值,而不是空值。两个 ID 空间在构造上永不重叠:futureMarketId 至多 5 位,futureOutcomeId 恒为 6 位(≥ 100001),因此任何取值都不可能被误读为另一类 ID。
请将 oddsId 视为不透明字符串。 可以用它作为存储主键,但请从赔率行的显式字段读取 bookmaker、futureOutcomeId、participantId 等取值,而不要拆分各段。
时间戳(秒与毫秒)
此API有意同时使用纪元秒和纪元毫秒,具体取决于上下文。该规则在赛事和期货中保持一致:纪元秒(UTC)
所有开始时间均为整数纪元秒:startTime/endTimestartTimeFromstartTimeTo
纪元毫秒(UTC)
所有赔率更新时间均为整数纪元毫秒 —— 赛事和期货皆是如此:changedAt/bookmakerChangedAt- 赔率
since过滤器(/fixtures/odds、/fixtures/odds/main、/futures/odds) - WebSocket 信封
ts以及entryId的时间戳部分
建议
- 将时间戳存储为整数。
- 经验法则:赛程时间为秒,赔率更新时间为毫秒。
- 仅在需要时进行内部归一化。
运营提示
服务器位置很重要
要实现实时更新的最低延迟:- 最快的交付区域是中欧(推荐)和美国东部。
- 为获得最佳性能,请将后端部署在我们使用的相同数据中心,例如:
- 如果您正在构建对延迟敏感的预测市场或模型,请考虑:
- 通过Netcup部署在奥地利(AT),或
- 使用AWS eu-west-1(爱尔兰)
与我们流媒体基础设施位于同一位置的服务器可以更快地接收更新,跳数更少。
快照 + 实时模式
可靠的集成模式:1
订阅 WebSocket
连接并以您的过滤器登录,收到
login_ok 后立即开始按行键应用更新。2
获取 HTTP 快照
通过 REST 拉取当前状态(赛事、赔率或期货)并合并 —— 按键比较,
changedAt 较新者胜出。3
按信号重新获取快照
如果 WebSocket 发出
snapshot_required 信号,请以同样的合并规则重新获取 HTTP 快照。高效回填
- 在可用时使用
since参数 - 除非需要,否则避免完整的历史获取
- 按赔率标识符存储赔率以进行去重
速率限制
有关请求头、各端点限制以及 429 退避处理,请参阅速率限制。历史赔率与 CLV
实时 WebSocket 的odds 和 oddsFutures 频道在固定的约 10 毫秒批处理窗口上传输最新状态 —— 窗口内被取代的中间报价会合并为最新值(状态不会丢失),因此并非逐笔账本。参见传输语义。
使用实时数据流进行交易,使用 REST 历史端点进行衡量 —— CLV 模型、成交审计和回测。当您需要某个结果的完整价格变动,或其开盘价与收盘价时,请使用 REST 历史端点。它们与实时
odds 频道共享相同的 oddsId 格式({fixtureId}:{bookmaker}:{outcomeId}:{playerId}),因此您可以将实时成交直接关联到其历史记录和收盘价记录。
交易用例:
- CLV 建模 —— 将您的成交价与收盘价进行比较,以衡量优势。
- 成交审计 —— 将成交价格与已记录的时间线进行核对,以检测滑点。
- 回测 —— 重放完整的历史时间线,以根据真实的价格变动测试策略。
术语表
API 中常用核心术语的快速定义。 标识符与数据模型- sportId —— 运动数字标识符;下游
marketId、outcomeId和fixtureId的前两位数字。 - fixtureId —— 单场比赛/事件的字符串键,编码运动、锦标赛和原生赛事 ID。
- futureId —— 期货 / 冠军盘口的字符串键,编码运动、锦标赛、赛季和盘口。
- marketType —— 盘口种类(
1x2、totals、spreads、bothteamsscore等)。 - period —— 盘口适用的赛段(
fulltime、p1、p2)。 - handicap —— 盘口线 / specifier;每个不同的盘口线都是独立的
marketId。 - marketId —— 将一个盘口所有选项分组的整数;等于盘口的首个
outcomeId。 - marketLength —— 一个
marketId下的选项数量:即可供投注的各个方向,其概率之和约等于 1。 - outcomeId —— 标识一个完全分解后的选择的整数:
marketType+period+handicap(盘口线)+ 方向。它编码了除球员以外的一切 —— 球员由playerId补充。 - playerId —— 在球员盘口中将选项关联到某个球员;
playerId = 0为非球员盘口。 - participantId —— 标识赛事中球队或参赛者的整数。
- oddsId —— 价格复合键。赛事:
{fixtureId}:{bookmaker}:{outcomeId}:{playerId}。期货:{futureId}:{bookmaker}:{futureOutcomeId}:{participantId}。
- OLV —— 开盘线价值:选项的首个记录价格。
- CLV —— 收盘线价值:选项结算前的最后价格;评估执行质量的基准。
- staleOdds —— 表示某博彩公司连接降级、其赔率可能并非最新的标志。
- settlement(结算) —— 赛后端点,返回逐结果的结果(赢 / 输)、最终比分和盈亏幅度。
- serverEpoch + entryId —— 每频道游标;
serverEpoch变化表示客户端必须重新获取快照。 - resume / replay(恢复 / 重放) —— 在
resumeWindowMs(默认60000)内重连并重放丢失的消息。 - snapshot_required —— 表示游标已超出恢复窗口、需重新获取 REST 快照的信号。