Esports line gaps API.
Same prop. Different DFS lines.

What does the line gaps API return?

The line gaps API returns the spread between DFS books for the same player, event and market, as line_min, line_max and line_gap in one row. It is GET /v6/esports/{sport}/gaps on Hobby and above. If one book posts 31.5, another 32.5 and a third 30.5, the gap is 2.

FieldMeaning
line_minThe lowest line any book posts for that player, event and market
line_maxThe highest line any book posts for it
line_gapThe spread between them: 2 for lines of 30.5, 31.5 and 32.5

Updated

PrizePicks posts 31.5. Underdog posts 32.5. Sleeper posts 30.5. That two-kill spread is the product — not a model projection, not a consensus moneyline. A line gaps API joins the same player, event, and market across DFS books and returns line_min, line_max, and line_gap in one row.

Why book-vs-book gaps matter

DFS apps do not share a clearing price. The same kill market on the same map window can sit a full kill (or more) apart. If you only read one book, you never see the softest line. If you scrape five apps, you rebuild player/event joins forever.

Practical rule: line_gap is arithmetic on posted floats — max minus min. We do not invent lines or average books into a fake “true” number.

What we normalize

One gap row = one player, one event, one exact stat_type, two or more DFS books with parseable lines. Over/under pairs on the same book collapse to one book entry (prefer over).

What does line mean?

line is the median of the DFS lines in that row. Soft and hard prints stay explicit as line_min / line_max.

Core endpoint

Path-style GET /v6/esports/{sport}/gaps. Default min_gap=0.5. Filter with player, market, market_contains, or book (book must appear in the row; full books[] still returned).

EndpointPurposeKey filters
GET /v6/esports/{sport}/gapsDFS book-vs-book line spreads (Hobby+)min_gap, player, market, book, limit
GET /v6/esports/{sport}/propsFull live board per bookbook=prizepicks|underdog|…
GET /v6/esports/{sport}/linesConsensus mainlines (not DFS gaps)Hobby+
MCP get_gapsSame surface from Cursor/ClaudeHobby+

Identity and join keys

  • —player_key prefers canonical player id, then slug, then name
  • —event_key prefers sorted matchup_key so books still join when event ids diverge
  • —exact canonicalize_stat_type — Map 1 does not merge into Maps 1–2
  • —gap_id = sha1(sport|event_key|player_key|stat_type)[:12]

Sample JSON (live DFS board)

Live CS2 maps 1–2 kills for khaN: Sleeper 30.5 through Underdog 32.5 → line_gap: 2.0 from /v6/esports/cs2/gaps.

FieldExampleUsed for
line_gap2.0line_max − line_min across DFS books
line31.5Median of the DFS lines in the row
line_min / line_max30.5 / 32.5Softest and hardest posted lines
books[]sleeper…underdogOne entry per book, sorted by line
stat_typeCS2_KILLS_MAPS_1_2Exact market — map1 ≠ maps 1–2
gap_idgap_ce3fbab1ef1eStable hash of sport|event|player|stat
GET /v6/esports/cs2/gaps?min_gap=0.5&limit=1
{
  "source": "kashrock",
  "sport": "cs2",
  "min_gap": 0.5,
  "total": 70,
  "returned": 1,
  "offset": 0,
  "limit": 1,
  "has_more": true,
  "gaps": [
    {
      "gap_id": "gap_ce3fbab1ef1e",
      "player_id": "kr_pl_6b8fc7792bfe",
      "player_name": "khaN",
      "team": "Nemiga",
      "opponent": "Just_Players",
      "event_id": "kr_ev_5886cc9220e5",
      "event_time": "2026-09-12T17:00:00.000Z",
      "stat_type": "CS2_KILLS_MAPS_1_2",
      "market": "kills",
      "line": 31.5,
      "line_min": 30.5,
      "line_max": 32.5,
      "line_gap": 2,
      "book_count": 5,
      "books": [
        {
          "book": "sleeper",
          "line": 30.5,
          "propId": "kr_prop_aa230791ff25",
          "direction": "over"
        },
        {
          "book": "betr",
          "line": 31.5,
          "propId": "kr_prop_0a7fec48daa2",
          "direction": "over"
        },
        {
          "book": "boom",
          "line": 31.5,
          "propId": "kr_prop_0a7fec48daa2",
          "direction": "over"
        },
        {
          "book": "prizepicks",
          "line": 31.5,
          "propId": "kr_prop_0a7fec48daa2",
          "direction": "over"
        },
        {
          "book": "underdog",
          "line": 32.5,
          "propId": "kr_prop_67030b9dbc0f",
          "direction": "over"
        }
      ]
    }
  ]
}

Which books count

Only DFS apps with float player props. Zero or null lines (including moneyline rows) never enter the gap math. Promo sentinel lines ≤ 0 are excluded.

SourceSchemaBest use
Scrape each DFS appFragile, blocked, driftDIY line shopping
Props-only APIYou join books yourselfCustom scanners
KashRock /gapsJoined + line_gap readyBoards, bots, research

Using gaps responsibly

A large line_gap is a shopping signal, not automatic edge. Grade against settled results and your own model — do not confuse this with stack gap (model − app line).

Practical rule: sort is line_gap desc, then book_count desc — softest spreads surface first.

Operational practices

  • —Hobby+ required; sandbox returns 403 on /gaps
  • —Computed on-request from Redis prop boards — no upstream scrape
  • —Prefer MCP get_gaps so agents do not invent endpoints
  • —Empty board → gaps: [] — never mock rows

Quick reference

Curl: /v6/esports/cs2/gaps?min_gap=0.5. Docs: /docs/endpoints/gaps. DFS hub: /dfs-esports-api.

If you need a normalized feed instead of another UI wrapper, the Esports API exposes live boards, schedules, and history on one schema — with the IDs and outcome patterns that keep backtests and grading honest. Start free on Sandbox, or see published pricing.

Frequently asked questions

What is an esports line gaps API?

An API that finds the same DFS player prop priced at different lines across books and returns the spread (line_gap = max − min) with every book’s line in one object.

Is line_gap the same as stack/edge gap?

No. Edge/stack gap is model projection minus one app line. This endpoint is book-vs-book only. Field name is always line_gap.

Which books are included?

DFS apps: PrizePicks, Underdog, Dabble, ParlayPlay, Sleeper, Betr, Boom, Pick6. Kalshi, Polymarket, and Thunderpick moneylines are not in this join.

What plan do I need?

Hobby or higher. Sandbox stays on props schema checks. Prefer MCP get_gaps after Google login.

How is a gap row keyed?

gap_id = sha1(sport|event_key|player_key|stat_type)[:12] — stable across calls, so you can dedupe or cache on it.

Is there a free tier for line gaps?

Sandbox covers the props schema checks only — /gaps returns 403 there. Line gaps start on Hobby at $29/mo.