Skip to content

REST API

マッチング済みフィード、ライブのアービトラージビュー、ペア詳細、カタログおよびフィードバック用ルートのエンドポイント。すべてのリクエストはAPIキーをbearerトークンとして受け取ります。

REST APIは、venueを横断するマッチング済みフィード、その上に構築されたアービトラージビュー、ペア詳細を提供します。Freeを含むすべてのプランで利用できます。ベースURLは https://api.dino.markets です。

認証

すべてのリクエストには、APIキーをbearerトークンとして付与します。ダッシュボードでキーを作成してください。キーは一度しか表示されません。

Authorization: Bearer sk_live_...

レート制限

リクエストはプランごと、1分あたりで上限が決まっています。Free 60、Basic 300、Pro 1200です。上限を超えたリクエストは 429 を返します。ストリームはこの方式では計測されず、代わりに接続数の上限で制御されます。

GET /v2/markets

正規のmarket一覧です。フィルターなしの場合はアイデンティティ・カタログとなり、マッチング済みゲームごとに1行、venueのティッカーとカバレッジフラグを含み、価格は null になります。signal=arb を付けると、ライブの機会スナップショットから価格が付いた同じ行が、確定済みアービトラージのみに絞られて返ります。signal=candidates を付けると、candidatesチャンネルの履歴から価格付けされたレビュー待ち行が返ります。

パラメータ場所意味
sportquerystring1つの大分類スポーツに絞り込みます(例: baseball)。省略するとすべてのスポーツが対象です。
leaguequerystringスポーツ内で1つのリーグに絞り込みます。大文字小文字は区別しません(例: MLB)。signal=arb のときは無視されます。
statusquerystringカンマ区切り: openliveclosedsettled。デフォルトは open,live です。
signalquerystringspread(デフォルトのカタログビュー)、arb(価格付き、確定アービトラージ行のみ)、または candidates(レビュー待ち行)。
sortquerystringstart_time(デフォルト)または -spread_pts(venue間のギャップが最も大きい順)。
includequerystring追加ブロックをカンマ区切りで指定: idsdepthsettlementIncludesを参照してください。
limitqueryinteger1から1000。デフォルトは500です。

有効なsportキーは baseballbasketballfootballhockeysoccertenniscricketloldota2valorantcs2r6owmma です。各行には league フィールドもあり、venueのシリーズが名前を持たない場合は 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 は常に spreadcoverage は両venueとも false です。これはアイデンティティ・カタログとしての想定どおりの挙動です。このビューの priced_at は、その行の updated_at(そのペア自体が最後に変化した時刻)であり、ライブの価格ティックではありません。行ごとに個別の価格タイムスタンプはまだ保存されていないためです。同じ行のライブ価格を得るには、signal=arb(確定アービトラージのみ)を指定するか、/v2/pairs/{market_id}で1つの市場に include=depth を追加してください。

アービトラージビュー: GET /v2/markets?signal=arb

同じエンドポイントを、ライブの機会スナップショットから価格付けし、マッチングエンジンがアービトラージと確定した行(解決パリティ確認済み、解決リスクのブロックなし、すべてのoutcomeが両venueで価格付き)のみに絞り込んだものです。これは旧来の専用opportunitiesフィードを置き換えるものです。v2には個別のアービトラージ専用エンドポイントはなく、market catalogの上に構築されたビューです。その基になるスナップショットはベストエフォート型で、どのプランでも約2分遅延しています。

パラメータ場所意味
sportquerystring1つの大分類スポーツに絞り込みます(例: baseball)。
includequerystring追加ブロックをカンマ区切りで指定: idsdepthsettlement
limitqueryinteger1から1000。デフォルトは500です。

上記のカタログ用パラメータはこのビューにも適用され、statussortinclude は同じ働きをします(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 は、venue手数料を差し引く前の、ask同士のグロスリターンです。これはスナップショットの観測値であり、ベストエフォート型でキャッシュ由来です。outcomes[].kalshi.polymarket は各venueのask価格(0から1)で、cheaper はそのoutcomeでaskがより安いvenueを示します。RESTでは priced_at はライブのスナップショット時刻ではなく updated_at(そのペアの最終更新)を反映しますが、WebSocketフィードは、すべての価格ティックに実際の板読み取り時刻を載せます。

Candidates: GET /v2/markets?signal=candidates

レビュー待ち行です。マッチングエンジンが形成したものの、まだ確定していないマッチです。candidates:{sport} WebSocketチャンネル(Pro)を支える同じチャンネル履歴から、ベストエフォート型で価格付けされます。レビュー状態のmarketは、どんな価格が付いていても常に spread に解決されます。このビューが signal: "arb" 行を返すことはありません。

パラメータ場所意味
sportquerystring1つの大分類スポーツに絞り込みます。
leaguequerystringスポーツ内で1つのリーグに絞り込みます。
includequerystring追加ブロックをカンマ区切りで指定: idsdepthsettlement
limitqueryinteger1から1000。デフォルトは500です。
curl -s "https://api.dino.markets/v2/markets?signal=candidates&sport=baseball" \
  -H "Authorization: Bearer sk_live_..."

上記のカタログ用パラメータはこのビューにも適用され、statussortinclude は同じ働きをします。

行はカタログビューと同じ正規の形状で返ります。candidateに価格付きマッチがある場合、outcomescoverage はアービトラージビューと同じ方法で埋められます。価格がまだ利用できない場合は null のままです。

Includes

include は、各marketオブジェクトに追加ブロックを付与するオプトイン指定です。指定していないブロックは、フィールドが null になるのではなく、そもそもキー自体が存在しません。必要なものだけをリクエストしてください。

追加されるフィールド意味
idsvenuesconfidencevenueのハンドル(kalshi.event_tickerpolymarket.condition_id)と、マッチングエンジンのエンティティ/解決確信度(0から1)。
depthoutcomes[].kalshi_bookoutcomes[].polymarket_bookoutcomeごとの板の厚み(デプス)詳細(ask、depth、ティッカー/トークンid)。スカラーのask価格に加えて付与されます。並列フィールドであり、outcomes[].kalshi.polymarket を置き換えるものではありません。
settlementsettlementparity(bool)、risks[]、venueのテキスト、確定後の verdict

GET /v2/pairs/{market_id}

idで指定した1つの正規marketオブジェクトを、デフォルトで include=ids,depth,settlement を適用した状態で返します。これが詳細ビューです。dino_<uuid>(/v2/marketsid フィールド)または裸のUUIDを受け付けます。

パラメータ場所意味
market_idpathstring/v2/markets からのmarket 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のスプレッド(venue間の解決リスクあり)

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 を決める4つのゲートの1つで、そのペアが持つ完全な内部リスクセット全体に対して判定されます。返される risks[] には、キャンセル(cancel_*)イベントが含まれることはなく、サーバー側でフィルターされています。arb であれ spread であれ、どの行に対して行動する前でも settlement.risks を確認してください。idが解決しない場合、レスポンスは 404{ "error": "pair not found" } になります。

GET /v2/leagues

現在シーズン中のスポーツとリーグを、アクティブなフィードから導出し、スポーツごとのライフサイクル件数とともに返します。

leagues 配列は、そのスポーツで観測されたnullでないリーグを列挙します。count は、リーグがnullの行も含めた、マッチング済みゲームの総数です。open は今のところ count と同じ値になります。livesettled は常に 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

venueカバレッジ・センサス、つまりKalshiに上場している対戦形式のリーグすべてを、マッチング済みフィードに組み込まれているかどうかとその集約ステータスとともに列挙します。マッチングエンジンはこれをパスごとに、約1時間おきに再構築します。ステータスの値: 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専用で、社内のcoverageビューも同じデータを参照しています。

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

おかしいと思う機会を通報します。社内レビューキューにレポートを送信します。以下のフィールドのうち少なくとも1つを含めてください。opp_id には、/v2/markets のmarketの id 値を渡します。

フィールド意味
opp_idstringmarketの id 値(dino_<uuid>)。
reasonstring短い理由やメモ。
sportstringopp_id がない場合のスポーツ。
marketstring市場または試合。
detailstringその他の詳細。
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_idreasonsportmarketdetail のうち少なくとも1つを送信してください。空のボディは 400 を返します。