REST reference

The read API — leagues, participants, contests, markets, liquidity, orderbook depth, and live game state, normalized across every connected venue. Authenticate with an API key. Use the “Try it” panel under each endpoint to send live requests right from this page.

Base URL

text
https://api.openmarkets.ai/flow/v1

All endpoints below are read-only GETs (one batch POST for fan-out reads). Pass your key as the X-API-Key header on every request.

Response envelope

Every successful response uses the same top-level structure: data, optional pagination, and meta.

json
{
  "data": [...] | {...},
  "pagination": {
    "next_cursor": "2026-04-17T22:00:00.000Z" | null,
    "has_more": true,
    "limit": 50
  },
  "meta": {
    "timestamp": "2026-04-17T22:00:00Z",
    "api_version": "v1"
  }
}

Catalog

Leagues, participants, contests, and markets.

GET/flow/v1/leagues

List leagues you have access to.

NameInTypeRequiredDescription
limitqueryintegernoMax items (default 50, max 200)
Try it
GET/flow/v1/leagues

Max items (default 50, max 200)

GET/flow/v1/leagues/:id

Retrieve a single league. Returns 404 with not_found if the league ID does not exist.

NameInTypeRequiredDescription
idpathstringyesLeague ID returned from /leagues
Try it
GET/flow/v1/leagues/lg_nfl

League ID returned from /leagues

GET/flow/v1/participants

List participants (teams or athletes) in a league. Requires league_id. Returns a slim shape suited to dropdowns and lookups.

NameInTypeRequiredDescription
league_idquerystringyesLeague to scope to (required)
limitqueryintegernoMax items (default 50, max 200)
Try it
GET/flow/v1/participants

League to scope to (required)

Max items (default 50, max 200)

GET/flow/v1/participants/:id

Retrieve a single participant. Returns 404 not_found if the participant ID does not exist.

NameInTypeRequiredDescription
idpathstringyes
Try it
GET/flow/v1/participants/p_lakers
GET/flow/v1/contests

List contests, filtered and paginated by scheduled start.

NameInTypeRequiredDescription
league_idquerystringnoScope to a specific league
statusqueryenumnoDefault: open
start_afterqueryiso8601noOnly contests starting at or after this timestamp
start_beforequeryiso8601noOnly contests starting at or before this timestamp
parent_contest_idquerystringnoChildren of a parent (e.g. matches in a tournament)
cursorqueryiso8601noPass the previous pagination.next_cursor to fetch the next page
limitqueryintegernoMax items (default 50, max 200)
Try it
GET/flow/v1/contests?status=open

Scope to a specific league

Default: open

Only contests starting at or after this timestamp

Only contests starting at or before this timestamp

Children of a parent (e.g. matches in a tournament)

Pass the previous pagination.next_cursor to fetch the next page

Max items (default 50, max 200)

GET/flow/v1/contests/:id

Retrieve a single contest.

NameInTypeRequiredDescription
idpathstringyes
Try it
GET/flow/v1/contests/ct_abc123
Example response.data
{
  "id": "ct_abc123",
  "league_id": "lg_nfl",
  "title": "Kansas City Chiefs vs. San Francisco 49ers",
  "type": "match",
  "starts_at": "2026-09-07T20:20:00Z",
  "status": "open",
  "tags": { "home_team": "KC", "away_team": "SF" },
  "created_at": "2026-08-01T12:00:00Z",
  "updated_at": "2026-08-15T18:30:00Z"
}
GET/flow/v1/contests/:id/markets

List all markets (moneyline, spread, total, etc.) available on a contest.

NameInTypeRequiredDescription
idpathstringyes
Try it
GET/flow/v1/contests/ct_abc123/markets
GET/flow/v1/markets/:id

Retrieve a single market definition (not specific to any contest).

NameInTypeRequiredDescription
idpathstringyes
Try it
GET/flow/v1/markets/mk_ml

Liquidity & depth

Best-available prices per position, and full per-partner orderbook depth.

GET/flow/v1/contests/:id/liquidity

Current aggregated liquidity positions for the contest, with per-partner prices and distribution-model fair values.

NameInTypeRequiredDescription
idpathstringyes
Try it
GET/flow/v1/contests/ct_abc123/liquidity
Position shape
{
  "position_hash": "ct_abc123:mk_ml:side_home:var_0:p_kc:tf_full",
  "contest_id": "ct_abc123",
  "title": "Kansas City Chiefs — Moneyline",
  "market_key": "moneyline",
  "side_key": "home",
  "participant_id": "p_kc",
  "consensus_price": 0.52,
  "partner_liquidities": [
    {
      "partner_id": "kalshi",
      "partner_name": "Kalshi",
      "price": 0.49,
      "american_odds": "+104",
      "available": 5400
    }
  ]
}
GET/flow/v1/depth/:position_hash

Full orderbook depth across all partners for a single 6-part position hash. Bulk depth lookup is planned but not yet available — query one hash at a time.

NameInTypeRequiredDescription
position_hashpathstringyesSame value returned by /contests/:id/liquidity
Try it
GET/flow/v1/depth/ct_abc123%3Amk_ml%3Aside_home%3Avar_0%3Ap_kc%3Atf_full

Same value returned by /contests/:id/liquidity

Response.data
{
  "position_hash": "ct_abc123:mk_ml:side_home:var_0:p_kc:tf_full",
  "partners": [
    {
      "partner_id": "kalshi",
      "partner_name": "Kalshi",
      "levels": [
        { "price": 0.49, "available": 2100 },
        { "price": 0.48, "available": 3300 }
      ],
      "total_available": 5400,
      "best_price": 0.49,
      "fetched_at": "2026-04-17T22:00:00Z"
    }
  ],
  "fetched_at": "2026-04-17T22:00:00Z"
}

Live contest state

Live game state — score, clock, period, box score — churns on a different cadence than contest metadata, so it lives on its own endpoints. Available where we have a sports-data feed for the league. For real-time updates, subscribe to the contest_state channel on the WebSocket stream instead of polling.

GET/flow/v1/contests/:id/state

Live game state for a contest — game_status, clock, period, scores or leaderboard, and a sport-specific situation block. Returns 404 if no state has been cached for the contest yet.

NameInTypeRequiredDescription
idpathstringyes
Try it
GET/flow/v1/contests/ct_abc123/state
Response.data
{
  "contest_id": "ct_abc123",
  "state": {
    "game_status": "in_progress",
    "clock": { "display": "7:42", "remaining_seconds": 462, "is_running": true },
    "period": { "number": 3, "label": "3rd Quarter", "type": "quarter" },
    "contest_result": "pending",
    "winner_participant_id": null,
    "scores": { "home": 71, "away": 68 },
    "situation": null
  },
  "refreshed_at": "2026-05-26T02:14:30Z",
  "cached_at": "2026-05-26T02:14:31Z"
}
POST/flow/v1/contest-state/batch

Fan-out read: live state for many contests in one request (max 200). Body is { contest_ids: string[] }. Returns a map keyed by contest_id — contests with no cached state are simply absent (no 404). Use this to hydrate a multi-game scoreboard without N round-trips.

Try it
POST/flow/v1/contest-state/batch
Request + Response
// Request body
{ "contest_ids": ["ct_abc123", "ct_def456"] }

// Response.data — keyed by contest_id; misses are omitted
{
  "ct_abc123": {
    "contest_id": "ct_abc123",
    "state": { "game_status": "in_progress", "scores": { "home": 71, "away": 68 } },
    "refreshed_at": "2026-05-26T02:14:30Z"
  }
}

Partners catalog

The exchange partners OpenMarkets aggregates, and the credential fields each expects.

GET/flow/v1/partners

The catalog of exchange partners OpenMarkets supports, each with the exact credential fields it expects (key, label, input type). New partners appear without a client release.

Try it
GET/flow/v1/partners
Response.data[]
{
  "data": [
    {
      "partner_id": "p_kalshi",
      "name": "Kalshi",
      "status": "active",
      "credential_fields": [
        { "key": "api_key",         "label": "API Key",           "type": "text",     "required": true },
        { "key": "private_key_pem", "label": "Private Key (PEM)", "type": "textarea", "required": true }
      ]
    }
  ]
}
GET/flow/v1/partners/:partner_id

Retrieve a single partner descriptor (same shape as an item from /flow/v1/partners). Returns 404 not_found if the partner ID does not exist.

NameInTypeRequiredDescription
partner_idpathstringyes
Try it
GET/flow/v1/partners/p_kalshi

Pagination

List endpoints return a pagination object. When has_more is true, pass next_cursor back as the cursor query param to fetch the next page. Cursors are opaque but stable — don't construct them yourself.

Coming soon

Planned but not yet available:

  • Batch depth lookup — multiple position hashes in one request
  • Historical price queries — tick-level archive for backtesting and research
  • Webhooks for liquidity and settlement events