REST API
匹配数据流、实时套利视图、配对详情,以及目录与反馈相关端点。每个请求都需要以 Bearer 令牌的形式携带你的 API 密钥。
REST API 提供跨平台匹配数据流、基于其上的套利视图,以及配对详情。它适用于所有套餐,包括 Free。基础 URL 为 https://api.dino.markets。
身份验证
每个请求都需要以 Bearer 令牌的形式携带你的 API 密钥。在控制台中创建密钥;密钥只会显示一次。
Authorization: Bearer sk_live_...
速率限制
请求按套餐、按分钟计量上限:Free 60 次,Basic 300 次,Pro 1200 次。超过上限的请求会返回 429。流不采用这种计量方式,而是受连接数上限约束。
GET /v2/markets
规范的市场列表。不加筛选条件时,这是身份目录:每场已匹配比赛对应一行,包含平台代码和覆盖标记,价格字段留空为 null。添加 signal=arb 可获取同一批行基于实时机会快照定价的结果,且只返回已确认的套利。添加 signal=candidates 可获取基于 candidates 频道历史定价的待审核行。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
sport | 查询参数 | string | 限定为单个运动大类,例如 baseball。省略则包含所有运动。 |
league | 查询参数 | string | 在某个运动大类内进一步限定到某个联赛,不区分大小写,例如 MLB。当 signal=arb 时该参数会被忽略。 |
status | 查询参数 | string | 逗号分隔:open、live、closed、settled。默认 open,live。 |
signal | 查询参数 | string | spread(默认目录视图)、arb(已定价,仅返回已确认的套利行)或 candidates(待审核行)。 |
sort | 查询参数 | string | start_time(默认)或 -spread_pts,后者会将跨平台价差最大的行排在最前。 |
include | 查询参数 | string | 逗号分隔的可选数据块:ids、depth、settlement。参见附加数据说明。 |
limit | 查询参数 | integer | 1 到 1000。默认 500。 |
有效的运动键为 baseball、basketball、football、hockey、soccer、tennis、cricket、lol、dota2、valorant、cs2、r6、ow、mma。每一行还包含 league 字段,当该平台的系列赛未命名联赛时,该字段可能为 null。调用 /v2/leagues 可查看当前处于赛季中的运动与联赛。
curl -s "https://api.dino.markets/v2/markets?sport=baseball&league=MLB" \
-H "Authorization: Bearer sk_live_..."
{
"count": 1,
"sport": "baseball",
"has_more": false,
"markets": [
{
"id": "dino_8f3a1c92-47e8-4c3f-b9d2-f1a8e6c4d5f2",
"slug": null,
"sport": "baseball",
"league": "MLB",
"title": "Nyy vs Bos",
"home": null,
"away": null,
"start_time": "2026-07-01T23:05:00+00:00",
"status": "open",
"match": "high_confidence",
"signal": "spread",
"spread_pts": null,
"potential_arb_pct": null,
"coverage": { "kalshi": false, "polymarket": false },
"outcomes": [],
"result": null,
"updated_at": "2026-07-01T22:55:00+00:00",
"priced_at": "2026-07-01T22:55:00+00:00",
"links": { "kalshi": "https://kalshi.com/markets/KXMLBGAME-26JUL01NYYBOS", "polymarket": null }
}
]
}
未筛选的视图不带任何价格。outcomes 为空,signal 始终为 spread,coverage 在两个平台上都读作 false。这是预期行为:这是身份目录。此视图中的 priced_at 是该行的 updated_at(该配对本身最后一次变化的时间),而不是实时的定价时刻——目前每一行还没有单独存储的定价时间戳。如需同一批行的实时价格,请请求 signal=arb(仅返回已确认的套利),或在 /v2/pairs/{market_id} 上针对单个市场添加 include=depth。
套利视图:GET /v2/markets?signal=arb
同一个端点,基于实时机会快照定价,并筛选出匹配引擎已确认为套利的行:结算一致性已确认、没有阻断性结算风险,且每个结果在两个平台上都已定价。它取代了旧版专用的机会数据流。v2 中不存在单独的套利端点,这只是市场目录之上的一个视图。支撑它的快照是尽力而为型的,无论哪个套餐都大约有两分钟的延迟。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
sport | 查询参数 | string | 限定为单个运动大类,例如 baseball。 |
include | 查询参数 | string | 逗号分隔的可选数据块:ids、depth、settlement。 |
limit | 查询参数 | integer | 1 到 1000。默认 500。 |
上文的目录参数同样适用于该视图:status、sort 和 include 的作用方式相同(唯一的例外是 league 过滤器,在此视图中会被忽略)。
curl -s "https://api.dino.markets/v2/markets?signal=arb&sport=baseball" \
-H "Authorization: Bearer sk_live_..."
{
"count": 1,
"sport": "baseball",
"has_more": false,
"markets": [
{
"id": "dino_8f3a1c92-47e8-4c3f-b9d2-f1a8e6c4d5f2",
"slug": null,
"sport": "baseball",
"league": "MLB",
"title": "Nyy vs Bos",
"home": null,
"away": null,
"start_time": "2026-07-01T23:05:00+00:00",
"status": "open",
"match": "high_confidence",
"signal": "arb",
"spread_pts": 2.0,
"potential_arb_pct": 1.83,
"coverage": { "kalshi": true, "polymarket": true },
"outcomes": [
{ "key": "NYY", "name": "NYY", "kalshi": 0.52, "polymarket": 0.54, "cheaper": "kalshi" },
{ "key": "BOS", "name": "BOS", "kalshi": 0.50, "polymarket": 0.46, "cheaper": "polymarket" }
],
"result": null,
"updated_at": "2026-07-01T22:55:00+00:00",
"priced_at": "2026-07-01T22:55:00+00:00",
"links": { "kalshi": "https://kalshi.com/markets/KXMLBGAME-26JUL01NYYBOS", "polymarket": null }
}
]
}
markets 为空数组、count 为 0,是套利之间的正常静默状态。potential_arb_pct 是以卖价对卖价计算的毛收益率,尚未扣除平台手续费。它是对快照的一次观测,尽力而为,可能来自缓存,存在延迟。outcomes[].kalshi 与 .polymarket 是各平台对该结果的卖价,取值 0 到 1;cheaper 标明该结果在哪个平台的卖价更低。在 REST 上,priced_at 反映的是 updated_at(该配对的最后一次写入),而非实时快照的瞬间时刻;WebSocket 数据流则会在每一次价格变动中携带真实的订单簿读取时间戳。
Candidates:GET /v2/markets?signal=candidates
待审核行:匹配引擎已经形成、但尚未确认的匹配。基于同一份为 candidates:{sport} WebSocket 频道(Pro)提供数据的频道历史,尽力而为地定价。处于待审核状态的市场,无论携带什么价格,都始终会归结为 spread;该视图永远不会返回 signal: "arb" 的行。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
sport | 查询参数 | string | 限定为单个运动大类。 |
league | 查询参数 | string | 在某个运动大类内进一步限定到某个联赛。 |
include | 查询参数 | string | 逗号分隔的可选数据块:ids、depth、settlement。 |
limit | 查询参数 | integer | 1 到 1000。默认 500。 |
curl -s "https://api.dino.markets/v2/markets?signal=candidates&sport=baseball" \
-H "Authorization: Bearer sk_live_..."
上文的目录参数同样适用于该视图:status、sort 和 include 的作用方式相同。
返回的行采用与目录视图相同的规范结构。当某个候选项已经有定价匹配时,outcomes 和 coverage 的填充方式与套利视图相同;当价格尚不可用时,价格字段会保留为 null。
Includes
include 会为每个市场对象附加可选启用的数据块。未指定的数据块表示该键完全不存在,而不是值为 null。请只请求你需要的内容。
| 值 | 附加内容 | 说明 |
|---|---|---|
ids | venues、confidence | 平台标识(kalshi.event_ticker、polymarket.condition_id)以及匹配引擎的实体/结算置信度,取值 0 到 1。 |
depth | outcomes[].kalshi_book、outcomes[].polymarket_book | 按结果划分的订单簿详情(卖价、深度、平台代码或 token id),与标量卖价字段并列存在。这是同级字段,不会替代 outcomes[].kalshi 或 .polymarket。 |
settlement | settlement | parity(布尔值)、risks[]、平台披露文本,以及结算后才有的 verdict。 |
GET /v2/pairs/{market_id}
按 id 返回单个规范市场对象,默认应用 include=ids,depth,settlement。这是详情视图。接受 dino_<uuid>(即 /v2/markets 返回的 id 字段)或裸 UUID。
| 参数 | 位置 | 类型 | 说明 |
|---|---|---|---|
market_id | 路径 | string | 来自 /v2/markets 的市场 id,可以是 dino_<uuid> 或裸 UUID。 |
示例:MLB 套利(已确认结算一致性)
curl -s "https://api.dino.markets/v2/pairs/dino_8f3a1c92-47e8-4c3f-b9d2-f1a8e6c4d5f2" \
-H "Authorization: Bearer sk_live_..."
{
"id": "dino_8f3a1c92-47e8-4c3f-b9d2-f1a8e6c4d5f2",
"slug": null,
"sport": "baseball",
"league": "MLB",
"title": "Nyy vs Bos",
"home": null,
"away": null,
"start_time": "2026-07-01T23:05:00+00:00",
"status": "open",
"match": "high_confidence",
"signal": "arb",
"spread_pts": 2.0,
"potential_arb_pct": 1.83,
"coverage": { "kalshi": true, "polymarket": true },
"outcomes": [
{ "key": "NYY", "name": "NYY", "kalshi": 0.52, "polymarket": 0.54, "cheaper": "kalshi",
"kalshi_book": { "ask": 0.52, "bid": null, "depth": 3100, "ticker": "KXMLBGAME-26JUL01NYYBOS-NYY" },
"polymarket_book": { "ask": 0.54, "bid": null, "depth": 2900, "token_id": "0x1a2b..." } },
{ "key": "BOS", "name": "BOS", "kalshi": 0.50, "polymarket": 0.46, "cheaper": "polymarket",
"kalshi_book": { "ask": 0.50, "bid": null, "depth": 2400, "ticker": "KXMLBGAME-26JUL01NYYBOS-BOS" },
"polymarket_book": { "ask": 0.46, "bid": null, "depth": 3300, "token_id": "0x9f8e..." } }
],
"result": null,
"updated_at": "2026-07-01T22:55:00+00:00",
"priced_at": "2026-07-01T22:55:00+00:00",
"venues": {
"kalshi": { "event_ticker": "KXMLBGAME-26JUL01NYYBOS" },
"polymarket": { "condition_id": "0x1a2b...", "slug": null }
},
"confidence": { "entity": 1.0, "resolution": 1.0 },
"settlement": { "parity": true, "risks": [], "kalshi_text": null, "poly_text": null, "verdict": null },
"links": { "kalshi": "https://kalshi.com/markets/KXMLBGAME-26JUL01NYYBOS", "polymarket": null }
}
示例:KBO 价差(跨平台结算风险)
curl -s "https://api.dino.markets/v2/pairs/dino_5c2b9f7e-d4a1-4e6c-8b3f-a9c2e5f1d8a4" \
-H "Authorization: Bearer sk_live_..."
{
"id": "dino_5c2b9f7e-d4a1-4e6c-8b3f-a9c2e5f1d8a4",
"sport": "baseball",
"league": "KBO",
"title": "Kia vs Kiw",
"start_time": "2026-07-15T10:00:00+00:00",
"status": "open",
"signal": "spread",
"spread_pts": null,
"potential_arb_pct": null,
"coverage": { "kalshi": false, "polymarket": false },
"outcomes": [],
"settlement": {
"parity": false,
"risks": [
{
"event": "tie",
"severity": "high",
"note": "This league can tie, but one venue's market does not carry an explicit tie->50/50 clause. A held two-leg position may not return $1 on a tie. Verify before trading."
}
],
"kalshi_text": null,
"poly_text": null,
"verdict": null
},
"links": { "kalshi": "https://kalshi.com/markets/KXMLBGAME-26JUL15KIWKIA", "polymarket": null }
}
一旦该配对存在 high 或 critical 严重程度的风险,即便价格完全吻合,signal 也会被强制归为 spread;这项检查是决定 signal 的四道关卡之一,会针对该配对完整的内部风险集合运行。返回的 risks[] 永远不包含取消类(cancel_*)事件,这些事件已在服务端被过滤。无论是 arb 还是 spread,行动之前都请先阅读 settlement.risks。如果该 id 无法解析,响应会是 404,并返回 { "error": "pair not found" }。
GET /v2/leagues
当前处于赛季中的运动与联赛,来自活跃数据流,并附带每个运动的生命周期计数。
leagues 数组列出该运动下观测到的非空联赛;count 是该运动下已匹配比赛的总数,包括联赛字段为 null 的行。open 目前与 count 相同;live 和 settled 始终为 0,因为比赛进行中的计数和已撤回行的计数尚未接入此端点。
curl -s "https://api.dino.markets/v2/leagues" \
-H "Authorization: Bearer sk_live_..."
{
"sports": [
{ "sport": "baseball", "leagues": ["KBO", "MLB", "NPB"], "count": 54, "open": 54, "live": 0, "settled": 0 },
{ "sport": "soccer", "leagues": ["World Cup"], "count": 15, "open": 15, "live": 0, "settled": 0 },
{ "sport": "tennis", "leagues": ["ITFW"], "count": 165, "open": 165, "live": 0, "settled": 0 }
]
}
GET /v2/coverage
平台覆盖普查:列出 Kalshi 上架的每个对战类联赛,无论是否已接入匹配数据流,并附带其聚合状态。匹配引擎每一轮都会重新构建该普查,大约每小时一次。状态取值:aggregated(已实时配对)、pending(已接入,等待对应方或其确认流程完成)、quiet(已接入,但当前没有开放项)、kalshi_only(在该平台上架,但尚未接入配对)、dormant(系列赛存在,但没有开放项)。poly_unpaired 携带该运动级别的 Polymarket 侧盈余,即该轮匹配中未找到 Kalshi 对应配对的已解析赛事。
curl -s "https://api.dino.markets/v2/coverage" \
-H "Authorization: Bearer sk_live_..."
{
"as_of": "2026-07-04T03:30:21+00:00",
"counts": { "aggregated": 20, "pending": 7, "quiet": 43, "kalshi_only": 13, "dormant": 139 },
"series": [
{ "series_ticker": "KXFIBAGAME", "league": "FIBA", "sport": "basketball", "wired": true,
"status": "aggregated", "kalshi_open_events": 49, "paired": 46, "sport_poly_fixtures": 88,
"last_pass_at": "2026-07-04T03:30:21+00:00" }
],
"poly_unpaired": [ { "sport": "soccer", "fixtures": 258, "paired": 7, "unpaired": 251 } ]
}
该普查仅通过 API 提供;内部的覆盖视图使用的是同一份数据。
POST /v1/stream/token
为实时流生成一张短期有效的票据。该端点没有迁移到 /v2,仍然保留在 /v1/stream/token。它需要 Basic 或 Pro 套餐;Free 密钥会收到 402。完整的连接流程见 WebSocket 流页面。
{
"ticket": "eyJhbGciOi...",
"ws_url": "wss://stream.dino.markets/connection/websocket",
"expires_in": 120,
"allowed": { "channels": ["markets:all", "status"], "max_conns": 3 }
}
POST /v2/report-bad-arb
举报一个看起来有问题的机会。系统会为我们的审核队列生成一条记录。请至少填写以下字段之一。对于 opp_id,请传入该市场在 /v2/markets 中的 id 值。
| 字段 | 类型 | 说明 |
|---|---|---|
opp_id | string | 该市场的 id 值(dino_<uuid>)。 |
reason | string | 简短的原因或备注。 |
sport | string | 没有 opp_id 时填写运动项目。 |
market | string | 市场或比赛。 |
detail | string | 任何其他详情。 |
curl -s -X POST "https://api.dino.markets/v2/report-bad-arb" \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "opp_id": "dino_8f3a1c92-47e8-4c3f-b9d2-f1a8e6c4d5f2", "reason": "legs do not settle the same way" }'
举报成功会返回 202 以及 { "status": "received" }。请至少发送 opp_id、reason、sport、market、detail 中的一项;空请求体会返回 400。