openapi: 3.2.0 info: title: Parlay Calculators API description: Real-time sports odds aggregation from **33 books and data sources** updated every 2-120 seconds depending on source cadence. version: 3.2.0 x-credit-currency: credits x-credit-cost-catalogue-url: /v1/meta/credit-costs x-pricing-url: /v1/pricing x-usage-url: /v1/usage contact: name: ParlayAPI support url: https://parlay-api.com/support email: support@parlay-api.com license: name: ParlayAPI Terms of Service url: https://parlay-api.com/terms termsOfService: https://parlay-api.com/terms servers: - url: https://parlay-api.com description: Production (primary; HTTP/2, TLS 1.3). - url: https://api.parlay-api.com description: Production (high-volume; bypasses Cloudflare edge for trading bots above 30 req/min). Same origin, same auth, same endpoints. tags: - name: Calculators description: Parlay pricing, CLV grading, Kelly / hedge / edge / free-bet math. paths: /v1/calc/kelly: get: summary: Calc Kelly description: 'Fractional Kelly stake. FREE. iter-75 deploy / #456. Returns the optimal stake size given a bankroll, the price you can bet at, your estimated win probability, and a fraction-of-Kelly multiplier (most bettors use 0.25-0.5 Kelly to avoid overbetting on noisy win-prob estimates). `expected_value_usd` is the +EV in dollars (positive means the bet is +EV at your win_prob; negative means -EV). If the Kelly stake is negative, the math says don''t bet.' operationId: calc_kelly_v1_calc_kelly_get parameters: - name: bankroll in: query required: true schema: type: number exclusiveMinimum: 0 description: Total bankroll in USD title: Bankroll description: Total bankroll in USD - name: odds in: query required: true schema: type: string description: Bet price (American or decimal, e.g. '-110' or '1.91') title: Odds description: Bet price (American or decimal, e.g. '-110' or '1.91') - name: win_prob in: query required: true schema: type: number exclusiveMaximum: 1 exclusiveMinimum: 0 description: Your estimated win probability (0 < p < 1) title: Win Prob description: Your estimated win probability (0 < p < 1) - name: fraction in: query required: false schema: type: number maximum: 1.0 exclusiveMinimum: 0 description: Kelly fraction multiplier (0.25 = quarter Kelly) default: 0.25 title: Fraction description: Kelly fraction multiplier (0.25 = quarter Kelly) responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' tags: - Calculators /v1/calc/hedge: get: summary: Calc Hedge description: 'Compute the hedge stake. FREE. iter-75 deploy / #456. Two-outcome hedge against an existing position. `original_stake` is what you placed on side A at `original_odds`. `hedge_odds` is what the OTHER side is currently quoted at. Returns the hedge stake + profit-if-A-wins and profit-if-B-wins.' operationId: calc_hedge_v1_calc_hedge_get parameters: - name: original_stake in: query required: true schema: type: number exclusiveMinimum: 0 description: Stake you already placed title: Original Stake description: Stake you already placed - name: original_odds in: query required: true schema: type: string description: Odds you took (American or decimal) title: Original Odds description: Odds you took (American or decimal) - name: hedge_odds in: query required: true schema: type: string description: Current available odds on the other side title: Hedge Odds description: Current available odds on the other side - name: target in: query required: false schema: type: string description: 'One of: equal_profit (lock in identical profit either side), guaranteed_minimum (max guaranteed return), free_roll (bet just enough to recover original_stake)' default: equal_profit title: Target description: 'One of: equal_profit (lock in identical profit either side), guaranteed_minimum (max guaranteed return), free_roll (bet just enough to recover original_stake)' responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' tags: - Calculators /v1/calc/edge: get: summary: Calc Edge description: '+EV / fair-line / no-vig calculator. FREE. iter-75 deploy / #456. Two modes: 1. Pass `true_prob` directly: returns EV vs your stated win prob. 2. Pass `sharp_over_odds` + `sharp_under_odds`: derives the no-vig fair probability from the two-sided sharp market, then computes EV against that fair line. This is the canonical EV-scan formula. `edge_pct` is in percent (positive = +EV).' operationId: calc_edge_v1_calc_edge_get parameters: - name: odds in: query required: true schema: type: string description: The price you can bet at (American or decimal) title: Odds description: The price you can bet at (American or decimal) - name: true_prob in: query required: false schema: anyOf: - type: number exclusiveMaximum: 1 exclusiveMinimum: 0 - type: 'null' description: Your estimated true win probability. Either this OR (sharp_over_odds + sharp_under_odds) required. title: True Prob description: Your estimated true win probability. Either this OR (sharp_over_odds + sharp_under_odds) required. - name: sharp_over_odds in: query required: false schema: anyOf: - type: string - type: 'null' description: Sharp book's price on the SAME side as `odds`. Used with sharp_under_odds for no-vig fair-line derivation. title: Sharp Over Odds description: Sharp book's price on the SAME side as `odds`. Used with sharp_under_odds for no-vig fair-line derivation. - name: sharp_under_odds in: query required: false schema: anyOf: - type: string - type: 'null' description: Sharp book's price on the OPPOSITE side. Used with sharp_over_odds for no-vig. title: Sharp Under Odds description: Sharp book's price on the OPPOSITE side. Used with sharp_over_odds for no-vig. - name: stake in: query required: false schema: type: number exclusiveMinimum: 0 description: Stake to compute EV-in-dollars (default $100) default: 100 title: Stake description: Stake to compute EV-in-dollars (default $100) responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' tags: - Calculators /v1/calc/free-bet: get: summary: Calc Free Bet description: 'Convert a sportsbook free-bet promo to guaranteed cash. FREE. iter-75 deploy / #456. The free-bet pays out as STAKE-FREE-WINNINGS (the original stake is NOT returned). So on a $50 free bet at +200, win → $100 returned (not $150). Hedge math accounts for this: hedge_stake = free_bet * b where b = bet_odds_decimal - 1.' operationId: calc_free_bet_v1_calc_free_bet_get parameters: - name: free_bet_usd in: query required: true schema: type: number exclusiveMinimum: 0 description: Face value of the free bet title: Free Bet Usd description: Face value of the free bet - name: bet_odds in: query required: true schema: type: string description: Odds you'd take on side A using the free bet title: Bet Odds description: Odds you'd take on side A using the free bet - name: hedge_odds in: query required: true schema: type: string description: Odds on side B at a different book for the hedge title: Hedge Odds description: Odds on side B at a different book for the hedge responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' tags: - Calculators /v1/parlay/verdict: post: summary: Parlay Verdict description: 'Grade a multi-leg parlay in one call. 10 credits. POST body: {"legs": [ {sport, market, side, home, away | team, player, line}, ... ], "region"?, "books"?, "book"?, "stake"?, "sharpBook"?} Returns each leg''s fair-vs-best, the combined no-vig fair price, the single BEST BOOK to place the whole parlay at (a real parlay is one slip at one book, not best-of-each), the parlay''s EV, the weakest leg, same-game correlation warnings, and (with `stake`) the payout. Reuses the /v1/verdict engine so single-bet and parlay verdicts agree, and scopes to the books you can bet at (region/books, same as /v1/verdict).' operationId: parlay_verdict_v1_parlay_verdict_post responses: '200': description: Successful Response content: application/json: schema: {} tags: - Calculators /v1/parlay/price: post: summary: Price Parlay description: 'Combine multiple legs into a parlay and return per-bookmaker combined odds. iteration_022 #209: in a product called ParlayAPI, callers had to client-side multiply decimal odds across N /odds calls themselves; this endpoint does that work server-side. Cost: 2 credits per leg (min 4). Request body: ``` { "legs": [ {"sport_key":"basketball_nba","event_id":"", "market":"h2h","outcome":"Cleveland Cavaliers"}, {"sport_key":"soccer_epl","event_id":"", "market":"h2h","outcome":"Tottenham Hotspur"}, {"sport_key":"baseball_mlb","event_id":"", "market":"totals","outcome":"Over","point":9.0} ], "bookmakers": ["fanduel","draftkings","betmgm"] } ``` Returns one entry per bookmaker that prices ALL legs, sorted by combined decimal odds DESCending (best to worst). Books missing even one leg appear in `missing_books` with which legs they couldn''t price. SGP flag set when 2+ legs share the same event_id; raw multiplication is the LOWER bound for SGP (real books apply a correlation discount we don''t replicate).' operationId: price_parlay_v1_parlay_price_post responses: '200': description: Successful Response content: application/json: schema: {} x-credit-cost-formula: max(4, 2 x len(legs)) x-credit-cost-floor: 4 x-credit-cost-type: variable x-credit-cost-example: 3-leg parlay = max(4, 6) = 6 credits x-credit-cost-description: Multi-leg parlay pricing security: - apiKeyHeader: [] - apiKeyQuery: [] - bearerAuth: [] tags: - Calculators /v1/clv: post: summary: Grade Clv description: 'Closing-line-value scoring for a list of bets. Accepts a bet slip and returns per-bet CLV vs the closing line at a sharp book (default pinnacle, falls back to novig if pinnacle didn''t price the market). CLV is the +EV-volume bettor''s primary validation metric: positive CLV means you beat the closing line, which over a large sample size is the most reliable signal that your strategy is actually +EV regardless of individual-bet win/loss outcomes. Cost: 2 credits per bet (min 5). Request body: ``` { "bets": [ { "sport_key": "baseball_mlb", "game_date": "2026-05-12", "player": "Nico Hoerner", // omit for game-line bets "home_team": "Atlanta Braves", // required for game-line bets "away_team": "Chicago Cubs", "market": "player_runs", // or h2h, spreads, totals "outcome": "over", // over/under for props/totals; // team name for h2h/spreads "line": 0.5, // null for h2h "taken_odds": -110, // your fill in American odds "taken_at": "2026-05-12T18:00:00Z" // optional } ], "sharp_book": "pinnacle" // optional; defaults to pinnacle } ``` Response: per-bet `clv_cents`, `clv_pct`, no-vig adjusted CLV when both sides have a closing price, plus a `summary` with aggregate stats.' operationId: grade_clv_v1_clv_post responses: '200': description: Successful Response content: application/json: schema: {} x-credit-cost-formula: max(5, 2 x len(bets)) x-credit-cost-floor: 5 x-credit-cost-type: variable x-credit-cost-example: 10-bet batch = max(5, 20) = 20 credits x-credit-cost-description: Closing-line-value batch grader security: - apiKeyHeader: [] - apiKeyQuery: [] - bearerAuth: [] tags: - Calculators /v1/clv/history: post: summary: Clv History description: 'Batch CLV history grader with date-range + period-market coverage. Body: ``` { "bets": [, ...], # same shape as /v1/clv "date_from": "YYYY-MM-DD", # optional, inclusive "date_to": "YYYY-MM-DD", # optional, inclusive "sharp_book": "pinnacle", # optional, default pinnacle "include_period_archive": false, # optional, default false "period_key": "Q1", # required when include_period_archive # AND any bet''s market is a period market } ``` Cost: max(15, 10 + 3 * len(bets)). Gated by `CLV_HISTORY_ENABLED=1`. Default OFF; returns 503 with explanatory body when disabled.' operationId: clv_history_v1_clv_history_post responses: '200': description: Successful Response content: application/json: schema: {} x-credit-cost-formula: max(15, 10 + 3 x len(bets)) x-credit-cost-floor: 15 x-credit-cost-type: variable x-credit-cost-example: 50-bet history grade = max(15, 160) = 160 credits x-credit-cost-description: Batch CLV grader with date-range + period-market coverage security: - apiKeyHeader: [] - apiKeyQuery: [] - bearerAuth: [] tags: - Calculators components: schemas: HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError ValidationError: properties: loc: items: anyOf: - type: string - type: integer type: array title: Location msg: type: string title: Message type: type: string title: Error Type input: title: Input ctx: type: object title: Context type: object required: - loc - msg - type title: ValidationError securitySchemes: apiKeyHeader: type: apiKey in: header name: X-API-Key description: API key passed in the X-API-Key header. Recommended. apiKeyQuery: type: apiKey in: query name: apiKey description: API key passed as the ?apiKey= query parameter. Useful for browser fetch() and webhooks where header control is limited. Equivalent to X-API-Key. bearerAuth: type: http scheme: bearer bearerFormat: APIKey description: 'API key passed via Authorization: Bearer . Equivalent to X-API-Key for compatibility with auth libraries that expect bearer tokens.'