# LazyEdge API: Agent Guide

LazyEdge publishes model probabilities beside the Kalshi and Polymarket price
for NFL, NBA and MLB games, before the start and live during play.  This guide tells
your agent what each endpoint returns and how to read it.  LazyEdge provides
the data; your agent brings its own rules.

## What the numbers are
- NFL live engine: a possession simulator that plays out the rest of the game
  from the live state about every ten seconds.  One effect it has measured in
  play: after a turnover the market lagged the simulation, moving about 7
  points toward it within two minutes (129 turnovers, 98 games).
- NFL pregame board: every lane carries a `label` and a `record`, the measured
  result for that kind of number on 2022 to 2025, so your agent can see what
  each kind of number has done before it uses one.
- NBA live engine: a scoring model (a Skellam distribution on the margin, with
  pace, momentum and injury inputs) that reprices every game from the
  play-by-play, before the tip and in play.  The 2026-27 season is graded game
  by game as it is played.
- MLB: live win probability and totals come from tables measured on five
  years of play.
- The graded record for the published numbers is public at
  https://lazyedge.net/results and through `GET /v1/nfl/results`, and how each
  model is built is at https://lazyedge.net/methodology.

## Your rules, not ours
LazyEdge publishes a number for every game and every line it covers, and
nobody is meant to act on all of them.  The data is built to be filtered: your
agent chooses the games, the lines and the labels it acts on, sets a minimum
gap and a price band, decides when to enter and when to exit, and sizes to its
own bankroll.  The fields in this guide are the inputs for those rules.

The `ledger` and `the_play` in `/v1/nfl/results` stake every published pick at
a flat $5, every game, with no filter.  They grade the raw numbers in the
open; they are a measurement, not a strategy, and a selective approach reads
very differently from them.

## Connection
- Base URL: `https://api.lazyedge.net`
- This guide: `GET /v1/skill` (public, no key needed).  The full reference,
  every endpoint with its parameters: https://lazyedge.net/api-docs
- Auth: `Authorization: Bearer <your_key>` on every request.
- Get a key in the LazyEdge terminal → Settings → API Access.  Requires the Quant
  Node plan ($49.99) OR 5+ Lazy Lions in your linked wallet(s).
- Rate limits: recon 30 · basic 60 · pro 240 · elite 1000 req/min.
- A path that is not an endpoint answers 404 with `did_you_mean` (the closest
  real endpoints) and links back to this guide and to the full reference at
  https://lazyedge.net/api-docs.

## Conventions
- Times (`kickoff`, `as_of`, `book_ts` and the like) are ISO 8601 in UTC.  A
  slate day (today's MLB games, the MLB `date`) is the US Eastern date.
- The NFL week: with no `season` or `week`, the NFL endpoints return the
  current week, the earliest week with a game still to play, or the latest
  once every game is final.  It rolls over on its own when a week's last game
  goes final.
- NFL game `status` is `SCHEDULED`, `IN_PROGRESS`, `HALFTIME` or `FINAL`.
- Probabilities and prices are 0 to 1, including the MLB fields named `_pct`
  (`comeback_pct`, `kalshi_implied_pct`); the weather's `precip_prob` is the
  one field in percent.  Fields ending `_pp` are percentage points (ours minus
  the market's, times 100), and `price_c` is in cents.
- Errors are JSON, `{"detail": "..."}`: 401 a missing, invalid or replaced
  key; 402 the account behind the key has no active plan (the same key works
  again once it does); 403 the key's tier is below the endpoint's; 404 an
  unknown path or id; 429 over the per-minute limit, with `Retry-After: 60`;
  503 data briefly unavailable, so retry after a few seconds.
- Polling: the pregame boards change when the model republishes or a line
  moves, so every few minutes is plenty.  The live engine writes about every
  ten seconds, so polling `/v1/nfl/live` or `/v1/nfl/live-plays` faster than
  that returns the same row.  At one call every ten seconds a single endpoint
  uses 6 of a basic key's 60 calls a minute.
- An empty array is an answer: no game in the window, or nothing met the
  rule.  Null is no reading, never zero.
- `GET /v1/account/usage` shows the calls your key made today, counted from
  midnight US Eastern.

## Endpoints
- MLB pregame: `GET /v1/mlb/edges` — per game: moneyline signal + edge, the
  MEASURED totals board (`our_p_over`, `main_line`, `market_total`,
  `total_edge_pp`, `total_seam`, `total_line_ok`, `total_pick`), the daily-alpha
  pick, Kelly sizing, starting pitchers, park/weather, opener flags, and the
  exact Kalshi/Polymarket tickers.
- MLB live: `GET /v1/mlb/live` — every in-progress game with the live model:
  `p_home_win`, the moneyline edge and side, `p_over_live`, `projected_total`,
  `ou_line`, `leverage`, `comeback_pct`, and the live totals ladder.  Updates as
  the game moves.
- NBA slate: `GET /v1/games/today` — today's games (US Eastern date) with
  `game_id`, `tip_time` and every market identifier: `kalshi_home_ticker`,
  `kalshi_away_ticker`, `kalshi_event_prefix`, `polymarket_condition_id`,
  `polymarket_slug`.
- NBA live edges: `GET /v1/edges/live` — the engine's latest row for each game:
  score, `period`, `clock` (`PRE` before the tip), `our_prob`,
  `kalshi_implied`, `edge_score`, `trade_signal`, the contract the signal
  names (`target_kalshi_ticker`, `target_side`, `target_polymarket_id`), top of
  book, `edge_velocity`, momentum, `signal_stale` and `signal_age_s`.
  Filters: `min_edge`, `include_stale`.
- NBA one game: `GET /v1/edges/game/{game_id}` — that game's engine rows,
  newest first, with the edge change between rows (`limit` up to 100).
- NBA spread ladder: `GET /v1/spread-ladder/{game_id}` — every spread rung
  priced against the model's margin distribution: `ticker`, `team`, `line`,
  `model_prob`, `market_bid`, `market_ask`, `market_price`, `edge`, `side`
  (`COVER` or `NOT_COVER`), `depth_at_ask`, and `best_edge` on the widest.
  `venue=kalshi` (default) or `polymarket`.  Empty until the game's book and
  the engine's margin are both in.
- NBA injuries: `GET /v1/injuries/live` — the league report as of the latest
  poll, biggest usage first: `status`, `usage_share`, `pmm_impact`, `signal`,
  `comment`, `updated_at`.  Filter: `team`.
- NBA order books (pro tier): `GET /v1/market/depth` — the newest quote per
  contract with top-five depth, `exchange=kalshi` (every NBA series) or
  `polymarket`.  Filters: `game_id`, `limit`.
- NBA signal history (pro tier): `GET /v1/signals/history` — the engine's
  recent `BUY` and `SELL` rows, newest first, covering about the last day.
  Filters: `team` (either side), `limit`, `offset`.
- NBA stream: `wss://api.lazyedge.net/v1/ws/edges` — new engine rows as
  `EDGE_UPDATE` messages, checked every two seconds.  Within 10 seconds of
  connecting, send `{"type": "AUTH", "key": "<your key>"}`; the text `ping`
  is answered with `pong`.
- World Cup 2026: `GET /v1/wc/edges` (pregame 1X2 + totals) · `GET /v1/wc/live`.
  The tournament is over, so both return empty arrays.
- NFL pregame: `GET /v1/nfl/edges` — per game: the moneyline signal + edge, win
  probability and fair American line, the expected HOME margin AND its sigma
  (the distribution a spread price depends on), the market spread in
  sportsbook convention (`spread_home`, home favourite negative) alongside
  the raw model
  `exp_margin` (a HOME MARGIN, positive = home favoured — the two are opposite
  signs on purpose and both are labelled), our P(over) and P(cover) at the
  market lines, the FULL `p_over_ladder` / `p_cover_ladder` so you can price any
  alternate rung, THE PLAY (`play_*`, see below; prefer it to the older
  `best_market`/`best_side`), the model breakdown (`qb_edge_pts`, `hfa_scale`,
  `wx_pen`), and the exact Kalshi contracts.  Pass `include_no_edge=true` to
  get every game, since the default keeps only games with a moneyline edge.
  The current week by default; `all_weeks=true` for every published week.
  `market_p_home`, `spread_home` and `total_line` are the sportsbook
  consensus, not a venue price; the venue price behind THE PLAY is
  `play_market_p` on `play_venue`.
- NFL board: `GET /v1/nfl/board/{game_id}` — every lane for one game (spread,
  total, moneyline and every player-prop rung) ranked on one scale: `ref`,
  `line`, `our_p`, `market_p`, `edge_pp`, `price_c`, `label`, `record`, `rank`,
  `is_top` (THE PLAY).  Filters: `lane=SPREAD|TOTAL|ML|PROP`, `ranked_only=true`.
- NFL props: `GET /v1/nfl/props` — every starter's prop: our mean and median
  projection, `proj_sigma`, `p_over_ladder`, and where a venue lists it the
  main `line`, the ask on the over (`market_p_over`), ours at that line
  (`our_p_over_line`), `venue_edge_pp`, every rung (`market_rungs`), the
  market's fitted `market_median`/`market_sigma`, and `role_q`.  The current
  week by default.  Filters: `season`, `week`, `game_id`, `stat`,
  `with_line=true`.
- NFL live: `GET /v1/nfl/live` — in-game score, quarter, clock, possession,
  down/distance, red zone and two-minute flags, the live engine's row (win
  probability, margin and total with their spreads, both full ladders, the
  venue prices with the AGE of each, edges only against a price that changed
  in the last 180s), and `live.qb_exit` when a starting quarterback is off.
  Empty outside game windows rather than stale.
- NFL live props: `GET /v1/nfl/live-props` — for every game in the air, per
  player and stat: `current_value`, the measured value of the rest
  (`exp_rest`), the projection and its spread over the snaps still to come,
  the pregame line and its source, our P(over), and `availability`.  Where
  Kalshi lists the prop, the LIVE book: `ladder` (every rung with bid, ask,
  mid, our probability, the edge and the edge at the price you would pay; a
  rung quoted wider than ten cents is marked `thin` and carries no edge),
  `book_line` (the rung the book prices nearest 50c), `best_*` (the widest
  usable disagreement), `book_ts` and `moved_sd`.  The prop model has not yet
  been graded against live books.  Filter: `game_id`.
- NFL hot plays: `GET /v1/nfl/live-plays`: the live edges that met the hot
  plays rule across the slate.  Game lines from the live engine where the
  edge is at least 4 points against a price read in the last 120 seconds,
  within 300 seconds of a touchdown, field goal, turnover or big play
  (standing disagreements stay on `/v1/nfl/live`); the market's
  under-reaction after a turnover (the one measured in-game edge) marked
  `measured`; and props that moved at least 0.5 pregame SD (or absorbed
  volume, or a ruling of out), only at the book's current line priced 25c to
  75c, with an edge of at least 8 points at a tight rung that is still
  positive at the price you would pay, a book read in the last 120 seconds,
  on the side the game moved the player, at most three a game
  (`basis: prop_model`, `graded: false`).  Every play carries `why` and an
  `id` built from the game, market, side, line, player and stat, so the same
  play reads the same `id` from one call to the next and a client can tell a
  new play from one it has already seen.  The rule in force is echoed
  in `thresholds`.  Filters: `game_id`, `include_props`, `limit`.
- NFL results: `GET /v1/nfl/results` — the graded record, one game at a time,
  the same payload as the public results page.  Per game: `pregame` (our
  winner, spread and total calls against the final), `the_play` and `ledger`
  (every published pick staked at a flat $5 with no filter, at the price it
  showed: a measurement of the raw numbers, not a strategy), and `live` (the live win
  probability's Brier beside the incumbent and the market by quarter; every
  live edge episode and hot play priced on its own contract, held to the
  final and sold at 2, 5 and 15 minutes after fees; the live props against
  the final box score).  `totals` combines the graded games.  Overtime is
  left out of the in-game grade.  Filters: `season`, `week`, or `game_id` for
  one game in full.
- NFL injuries: `GET /v1/nfl/injuries` — the five-source consensus board, worst
  first: `status`, `severity` 0-4, `p_play`, `pre_report`, `conflict` with each
  source's own status, body part, return week.  Filters: `team`, `game_id`,
  `status`, `include_available=true` (starters with no designation).
- NFL teams: `GET /v1/nfl/teams` — all 32 ratings (`pass_off`, `run_off`,
  `pass_def`, `run_def`, `finishing`, `hfa_scale`, `starter`, `qb_rating`) and
  the quarterback exit input: `qb1`, `qb2`, `qb_backup_delta_pts` (the
  full-game spread change if the starter leaves; negative = worse).
- $LAZY economy (the NFL pick'em token economy, which is fully transparent
  because every figure derives from one ledger, so the API can never disagree
  with the chain).  A player appears everywhere as `player`, a stable public
  reference, and a public name; no user id, email or wallet is exposed:
  - `GET /v1/lazy/economy`: a one-call snapshot of total entered, prizes,
    burned, rake, house balance and the active pot.
  - `GET /v1/lazy/burns?season=&week=`: burn history and running total, each
    with its on-chain `tx_hash`; a burn without a tx_hash is `pending` and is
    not counted as confirmed.
  - `GET /v1/lazy/leaderboard?scope=week|season|alltime`: standings (points,
    weekly wins, `lazy_won_total`).
  - `GET /v1/lazy/rewards?season=&contest_id=&status=`: who won what and
    whether it settled on chain (`paid_on_chain`).
  - `GET /v1/lazy/contests?status=&season=`: the schedule of the economy: pot,
    burned, prize config, entry counts, status.
  - `GET /v1/lazy/player/{player}`: a player's lifetime rollups, weekly
    history, $LAZY balance and ledger movements (basic tier).
  - `GET /v1/lazy/picks?contest_id=`: the field's picks including
    `model_home_prob_at_pick`, for studying the crowd against the model.
    Sealed until the contest locks (basic tier).
- Account (any valid key): `GET /v1/account/usage` — your key's prefix, tier,
  calls today and rate limit.  `POST /v1/account/rotate-key` — issues a new key
  with the same tier; the old one keeps working for 24 hours
  (`previous_key_valid_until`) so you can switch without a gap, and the new key
  is shown once, so store it.  `POST /v1/billing/apply_promo` with
  `{"code": "..."}`.
- Keys do not expire on a calendar.  A key works while the account's plan is
  active; a 402 means the plan is not active right now, and the same key works
  again as soon as it is.  Keys are issued, listed and revoked at
  https://lazyedge.net/settings.

## How to read NFL
- THE PLAY (`play_*` on `/v1/nfl/edges`, `is_top` on the board) is the
  best-ranked CLEAN row on a main line for the game.  It is not always rank 1:
  a tail rung or a role question can outrank it and is never the headline.
- `play_edge_pp` and the board's `edge_pp` are PROBABILITY points (ours minus
  the market's number at the line the row is graded against).  `best_edge_pp`
  is the older moneyline field and is a different unit on spreads and totals.
- The LABEL is part of the number.  `RATING_Q` = our number and the eleven-book
  consensus disagree by 5+ total or 4+ spread points: a disagreement with the
  books, not a price gap.  `PRICE_GAP` = our probability clears the venue's ask
  by 3+ points on a tight quote.  `LEAN`, `NONE` = smaller or no gap.
  `TAIL_RUNG` = off the venue's main line (ranked, never the headline).
  `ROLE_Q` = we and the venue disagree on the player's role, a depth-chart
  question.  `ILLIQUID`, `ROLE_PRICED`, `UNPRICED` are shown and never ranked.
- `driver` says WHY our margin sits away from the line: `QB`, `FINISHING` or
  `RATING` (the unit ratings).  It is the game's, so it rides every spread and
  moneyline row on `/v1/nfl/board/{game_id}`, Kalshi rungs included, and
  `/v1/nfl/edges`; totals and props have none.  It splits a `RATING_Q`
  spread's record: on
  2024-25, 4+ point gaps driven by the QB or finishing covered 61%, driven by
  the unit ratings 39-49%.
- Read `record` beside every number: it is what that lane measured on 2022-25.
- Pregame numbers FREEZE at kickoff.  Once a game is live, read `/v1/nfl/live`;
  a pregame edge against a moving price is not a live edge.
- A starting quarterback's exit (`live.qb_exit`): `delta` is the full-game
  spread change for his team's own backup (negative = the team gets worse).
  The line moves only once `status` is `fired` (an out ruling, two full
  drives, eight backup dropbacks or five minutes with the backup in), and
  moves back if he returns.  `line_if_out` is the line waiting if it sticks.

## How to read NBA
- `our_prob` is the HOME team's win probability, `kalshi_implied` the home
  contract's price, and `edge_score` their difference as a probability
  (0.034 is 3.4 points).
- `trade_signal` `BUY` means our home probability is above the home
  contract's price and names the home YES contract; `SELL` means it is below
  and names the away YES contract, the other side of the same game; `HOLD`
  is inside the threshold.  Those are field values, not instructions.
- `signal_stale` true means the engine stopped updating that game while it is
  in play; such rows are left out unless `include_stale=true`, and the number
  on them is old.
- Other Kalshi markets for a game: replace `KXNBAGAME` in
  `kalshi_event_prefix` with `KXNBATOTAL` (game total, one contract per line:
  `-226` is over 225.5, YES is the over) or `KXNBASPREAD` (`-ORL27` is
  Orlando winning by more than 26.5, YES covers).  The number in the ticker
  is the line plus a half; the market's own title states the line.
  `/v1/market/depth?exchange=kalshi&game_id=` returns all of them.
- Rows with `clock` `PRE` are before the tip.  Once a game starts the engine
  reprices it from each play, so read `/v1/edges/live` during play rather
  than a row from before the tip.
- Comeback (`comeback_*` on every edge row): from the third quarter on, when
  a team trails by 5 or more, the row carries that team's measured record
  from the same spot (deficit and time bucket, `Q3_EARLY` to `FINAL_2MIN`).
  `comeback_win_prob` is how often a team in that spot went on to win;
  `comeback_cover_prob` is how often it got back within 3 points at some
  later moment, which is a measure of a run back into the game, not of a
  final margin against a line.  The figures come from the play-by-play of
  5,294 games and are the trailing team's; `comeback_tier` says whether
  the team's own games carry weight (`BLEND`) or the league's record stands
  in (`LEAGUE_FALLBACK`).  They are not part of `our_prob` or `edge_score`,
  and every field is null outside that window.
- Line cover (`spread_*` on every edge row): the engine's live chance that
  each side covers the game's pregame line.  `spread_fav_team` must win by
  more than `spread_fav_line`; `spread_fav_cover_prob` and
  `spread_dog_cover_prob` are the two sides, and `spread_trailing_team` with
  `spread_trailing_cover_prob` is the team behind now covering (null when
  level).  It is recomputed every play from the score and the engine's
  margin distribution for the rest of the game, filled all game when the
  game has a line, and is the same math as `/v1/spread-ladder/{game_id}`.
  A whole-number line can push, so the two sides can sum to less than 1.

## How to read MLB
- `signal` names the moneyline side the model prices above the market:
  `BUY_HOME`, `BUY_AWAY`, or `NO_EDGE` when the gap is inside the threshold.
  Those are field values, not instructions.  The value side can differ from
  the side the model expects to win: a 40% team priced at 30 cents is the
  value side even though the model expects it to lose.
- Totals edge = `our_p_over` minus `market_p_over`, in probability points.
- `total_seam` true means the total cleared the validated threshold.
  `total_line_ok` true means an independent sportsbook confirmed the market
  line within a run; when it is false the market price itself is suspect, so
  read the total as information only.
- `sp_tbd` true means the starting pitcher is unconfirmed, so the pregame
  total carries more uncertainty than its spread suggests.
- `pen_status` of `exposed_pen` flags a bullpen game with a thin or tired pen.

## Reading the data safely
1. Every edge sits beside the price it was measured against and that price's
   age.  An edge measured against a price that has not changed for 180 seconds
   is null by design.  Treat null as no reading, never as zero.
2. Pregame numbers freeze at kickoff.  In play, read the live endpoints.
3. The label is part of the number.  Never compare a `RATING_Q` row with a
   `PRICE_GAP` row as if they measured the same thing.
4. Kelly fields (`kelly`, `single_kelly`, and similar) are the model's own
   sizing arithmetic on its own probability, published for transparency.
5. Markets are thin.  The price you could trade at is the ask on your side,
   not the mid, and the venue fee applies: 0.07 * p * (1 - p) per contract on
   Kalshi.
6. A gap between our number and the market's is a disagreement to weigh, not
   an order.  The label, the size of the gap and the price on your side are
   what your agent's rules decide on; acting on every gap is not how the data
   is meant to be used.

## Limits
LazyEdge provides data, not financial advice.  Probabilities are estimates and
prices move, so give your agent its own thresholds and sizing, and judge any
use of the data over weeks rather than nights.
