LAZY EDGE NBA
Log In Get Started

How Lazy Edge Works

From raw data to actionable trading signals in under 2 seconds.

Architecture Overview

End-to-end pipeline from raw data ingestion to signal delivery.

ESPN
ESPN Play-by-Play
60s polling
DB
Live Events DB
live_events table
ML
ML Engine
HMM + Hawkes
EDGE
Edge Signals
BUY / SELL / HOLD
UI
Dashboard
API
REST API
WH
Webhooks
KAL
Kalshi Markets
5min snapshots
DB
Kalshi Snapshots
kalshi_snapshots table
Edge Calculation

Data Sources

REAL-TIME

ESPN Play-by-Play

We poll the ESPN scoreboard API every 60 seconds during game hours (6 PM – midnight ET). For every active game, we fetch possession-level play-by-play events: made/missed shots, turnovers, steals, fouls, rebounds, and timeouts.

Written to: live_events
MARKET

Kalshi Prediction Markets

Every 5 minutes we snapshot all open NBA markets from Kalshi across three series: KXNBAWIN (moneyline), KXNBASPREAD (spread), and KXNBAPTS (totals). We capture bid/ask, implied probability, spread value, and 24h volume.

Written to: kalshi_snapshots
PRE-GAME

Elo Power Ratings

Pre-game power ratings updated after every game. Factors in home-court advantage, rest days, back-to-backs, and recent form over the last 10 games. Each team carries a rolling Elo that regresses toward the mean at season boundaries.

ENRICHMENT

Coaching, Lineups, Pace

We ingest coaching profiles (timeout tendencies, adjustment windows), lineup clustering via ANC (Agglomerative Nested Clustering), and pace metrics to enrich signals with context the market often ignores.

ML Engine

HMM State Detection

A Hidden Markov Model identifies the current game state from the sequence of possession outcomes. Four states are modeled:

  • RUN Scoring burst
  • DROUGHT Scoring drought
  • EQUILIB Equilibrium
  • MOMENTUM — Shift in progress

Hawkes Process Momentum

A self-exciting point process models clustering of scoring events. When a team goes on a run, the intensity spikes—and our model detects it before the market adjusts. Decay rate is tuned per-team based on historical pace.

Pregame Feature Matrix

Five signal layers feed the pregame model:

  1. Elo differential (home vs. away)
  2. Rest & schedule context
  3. Lineup ANC cluster matchup
  4. Coaching tendency profile
  5. Pace & venue adjustment

Edge & Position Sizing

edge = our_prob - kalshi_implied

Position sizing uses quarter-Kelly criterion:

kelly = 0.25 × (p × odds - (1-p)) / odds

Where p = our probability, odds = derived from Kalshi implied. Quarter-Kelly balances growth with drawdown protection.

Signal Types

Trade Signals

BUY
Edge ≥ +3%

Our model thinks the team is underpriced. The market hasn't caught up to a momentum shift, lineup change, or coaching adjustment.

edge: +5.2% • kelly: 3.1% • conf: HIGH
SELL
Edge ≤ -3%

Our model thinks the team is overpriced. Fade the public—the market is lagging behind a drought or matchup problem.

edge: -4.8% • kelly: 2.7% • conf: MED
HOLD
Edge between -3% and +3%

No actionable edge. The market is efficiently priced for this game right now.

edge: +0.8% • kelly: 0.0% • conf: LOW

Enrichment Indicators

COACHING INACTION

Coach hasn't called a timeout during an opponent run of 8+ points. Historical data shows teams that don't break runs here lose the spread 67% of the time.

FOUL TROUBLE

A starter has 4+ fouls before the 4th quarter. Lineup degradation incoming—net rating drops ~6 pts/100 possessions on average.

LINEUP ANC

Current 5-man unit clusters into an archetype with known strengths/weaknesses. Matchup context the market rarely prices in.

VENUE EDGE

Home-court Elo boost, altitude factor (DEN/UTA), and rest-day differential create a pre-game edge layer.

API Reference

Full endpoint documentation. For an interactive explorer, see the dedicated API docs.

FREE No API key required
GET /health Service health check
curl https://api.lazyedge.net/health
{
  "status": "ok",
  "timestamp": "2026-03-21T02:15:00Z",
  "version": "2.1.0"
}
GET /games/today Today's NBA games
curl https://api.lazyedge.net/games/today
{
  "date": "2026-03-21",
  "games": [
    {
      "game_id": "401584567",
      "home": "BOS", "away": "LAL",
      "status": "in_progress",
      "quarter": 3, "clock": "4:32",
      "home_score": 78, "away_score": 72
    }
  ]
}
GET /elo/{team} Pre-game Elo rating for a team
curl https://api.lazyedge.net/elo/BOS
{
  "team": "BOS",
  "elo": 1642,
  "rank": 2,
  "last_updated": "2026-03-20T06:00:00Z"
}
BASIC $29/mo — 1,000 calls/day
GET /signal/live/{game_id} Live edge signals for a game
curl -H "X-API-Key: le_your_key_here" \
  https://api.lazyedge.net/signal/live/401584567
{
  "game_id": "401584567",
  "signal": "BUY",
  "team": "BOS",
  "edge": 0.052,
  "our_prob": 0.68,
  "kalshi_implied": 0.628,
  "timestamp": "2026-03-21T02:15:00Z"
}
GET /signal/buy All current BUY signals
curl -H "X-API-Key: le_your_key_here" \
  https://api.lazyedge.net/signal/buy
{
  "signals": [
    {
      "game_id": "401584567",
      "team": "BOS", "edge": 0.052,
      "signal": "BUY", "kelly": 0.031
    }
  ],
  "count": 1
}
GET /edge/team/{team_abbr} Team edge profile
curl -H "X-API-Key: le_your_key_here" \
  https://api.lazyedge.net/edge/team/BOS
{
  "team": "BOS",
  "elo": 1642,
  "avg_edge_30d": 0.028,
  "buy_signals_30d": 14,
  "win_rate_on_buy": 0.71
}
PRO $99/mo — 10,000 calls/day
GET /signal/live/{game_id}/full Full signals with enrichment data
curl -H "X-API-Key: le_your_key_here" \
  https://api.lazyedge.net/signal/live/401584567/full
{
  "game_id": "401584567",
  "signal": "BUY", "team": "BOS",
  "edge": 0.052, "kelly": 0.031,
  "our_prob": 0.68, "kalshi_implied": 0.628,
  "hmm_state": "momentum",
  "hawkes_intensity": 0.84,
  "enrichment": {
    "coaching_inaction": false,
    "foul_trouble": ["J. Tatum"],
    "lineup_anc_cluster": "elite_spacing",
    "venue_edge": 0.018
  },
  "timestamp": "2026-03-21T02:15:00Z"
}
GET /coaching/{team_abbr} Coaching analytics profile
curl -H "X-API-Key: le_your_key_here" \
  https://api.lazyedge.net/coaching/BOS
{
  "team": "BOS",
  "coach": "Joe Mazzulla",
  "timeout_tendency": "passive",
  "avg_timeout_delay_seconds": 142,
  "adjustment_window_q": 2,
  "challenge_success_rate": 0.48
}
GET /lineup/{team_abbr} Lineup clustering profiles
curl -H "X-API-Key: le_your_key_here" \
  https://api.lazyedge.net/lineup/BOS
{
  "team": "BOS",
  "lineups": [
    {
      "players": ["Tatum","Brown","White","Holiday","Porzingis"],
      "anc_cluster": "elite_spacing",
      "net_rating": 12.4,
      "minutes": 284
    }
  ]
}
GET /pace/{team_abbr} Pace analytics
curl -H "X-API-Key: le_your_key_here" \
  https://api.lazyedge.net/pace/BOS
{
  "team": "BOS",
  "pace": 98.7,
  "pace_rank": 14,
  "half_court_freq": 0.62,
  "transition_freq": 0.38
}
POST /webhook/register Register BUY signal webhook
curl -X POST -H "X-API-Key: le_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your-server.com/hook","secret":"your_hmac_secret"}' \
  https://api.lazyedge.net/webhook/register
{
  "id": "wh_abc123",
  "url": "https://your-server.com/hook",
  "status": "active",
  "created_at": "2026-03-21T02:15:00Z"
}
GET /webhooks List your registered webhooks
curl -H "X-API-Key: le_your_key_here" \
  https://api.lazyedge.net/webhooks
{
  "webhooks": [
    {
      "id": "wh_abc123",
      "url": "https://your-server.com/hook",
      "status": "active",
      "created_at": "2026-03-21T02:15:00Z"
    }
  ]
}
DELETE /webhook/{id} Deactivate a webhook
curl -X DELETE -H "X-API-Key: le_your_key_here" \
  https://api.lazyedge.net/webhook/wh_abc123
{
  "id": "wh_abc123",
  "status": "deactivated"
}
ELITE $299/mo — Unlimited calls
GET /historical/edges Backtested edge data (paginated)
curl -H "X-API-Key: le_your_key_here" \
  "https://api.lazyedge.net/historical/edges?page=1&per_page=50"
{
  "edges": [
    {
      "game_id": "401584100",
      "date": "2026-03-18",
      "team": "GSW", "signal": "BUY",
      "edge": 0.061, "result": "win"
    }
  ],
  "page": 1, "per_page": 50, "total": 1243
}
GET /signal/stream Server-Sent Events real-time stream
curl -N -H "X-API-Key: le_your_key_here" \
  https://api.lazyedge.net/signal/stream
event: signal
data: {"game_id":"401584567","signal":"BUY","team":"BOS","edge":0.052}

event: signal
data: {"game_id":"401584590","signal":"SELL","team":"MIA","edge":-0.041}
WS /ws/live WebSocket real-time stream
// JavaScript
const ws = new WebSocket(
  "wss://api.lazyedge.net/ws/live?api_key=le_your_key_here"
);
ws.onmessage = (e) => console.log(JSON.parse(e.data));
{
  "type": "signal_update",
  "game_id": "401584567",
  "signal": "BUY", "team": "BOS",
  "edge": 0.052, "kelly": 0.031,
  "timestamp": "2026-03-21T02:15:00Z"
}

Authentication

API Key Authentication

Pass your API key in the X-API-Key header with every request:

curl -H "X-API-Key: le_your_key_here" \
  https://api.lazyedge.net/signal/buy

Your API key is generated when you subscribe to a paid plan. You can view it on your Account page. Keys are prefixed with le_ for easy identification.

Rate Limits

TierDaily LimitRate
FREE 100 calls/day No key required
BASIC 1,000 calls/day 10 req/sec
PRO 10,000 calls/day 50 req/sec
ELITE Unlimited 100 req/sec

When rate-limited, the API returns 429 Too Many Requests with a Retry-After header in seconds.

Web Dashboard Sessions

The web dashboard uses session cookies (HttpOnly, SameSite=Lax) set at login. Sessions expire after 24 hours. No API key is needed for dashboard access—just log in.

Webhook Guide

Registering a Webhook

Pro and Elite users can register webhooks to receive BUY signals in real-time. Provide a publicly accessible HTTPS URL and an HMAC secret:

curl -X POST -H "X-API-Key: le_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhook/lazy-edge",
    "secret": "your_hmac_secret_here"
  }' \
  https://api.lazyedge.net/webhook/register

Payload Format

When a BUY signal fires, we POST the following JSON to your registered URL:

{
  "event": "signal.buy",
  "timestamp": "2026-03-21T02:15:00Z",
  "data": {
    "game_id": "401584567",
    "team": "BOS",
    "edge": 0.052,
    "kelly": 0.031,
    "our_prob": 0.68,
    "kalshi_implied": 0.628,
    "hmm_state": "momentum"
  }
}

HMAC Signature Verification

Every webhook request includes an X-LE-Signature header containing an HMAC-SHA256 signature of the request body using your secret:

# Python verification example
import hmac, hashlib

def verify_signature(payload_body, signature, secret):
    expected = hmac.new(
        secret.encode(), payload_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)

Retry Policy

If your endpoint returns a non-2xx status or times out (10s), we retry with exponential backoff:

  • Retry 1: after 30 seconds
  • Retry 2: after 2 minutes
  • Retry 3: after 10 minutes

After 3 failed retries, the webhook is marked as failing. After 24 hours of continuous failures, it is automatically deactivated. Check your webhook status via GET /webhooks.

Dashboard Guide

What Each Tier Sees

FREE

Free Dashboard

  • Tonight's game cards (teams, scores, status)
  • Pre-game Elo ratings
  • Game schedule and start times
BASIC

Basic Dashboard

  • Everything in Free
  • Live signal table (BUY / SELL / HOLD badges)
  • Edge percentage for each game
  • Team edge profile lookups
PRO

Pro Dashboard

  • Everything in Basic
  • Full signal cards with Kelly fraction
  • Enrichment indicators on each game card
  • Coaching, lineup, and pace analytics panels
ELITE

Elite Dashboard

  • Everything in Pro
  • Real-time streaming feed (auto-updates)
  • Historical edge data explorer
  • Backtest performance charts

Game Cards

Each game is shown as a card with teams, score, quarter/clock, and signal status. The signal badge (BUY/SELL/HOLD) updates in real-time for paid users. Edge percentage and Kelly fraction are shown alongside the badge for Pro+ users.

Signal Badges

Signal badges are color-coded for quick scanning:

BUY SELL HOLD

Enrichment Indicators

Pro+ game cards show contextual enrichment tags below the signal. These highlight factors like coaching inaction, foul trouble, favorable lineup matchups, and venue edge—context the market is often slow to price in.

Ready to Find Your Edge?

Start with a free account. Upgrade anytime for live signals, enrichment data, and API access.

Create Free Account Explore the API