API reference
Closing line value, batch
The same for up to 100 bets in one call, priced per distinct event.
POST
/odds/v1/clv- Cost
- 1 token per distinct event_id (5 bets on one game cost 1)
- Authentication
- X-API-Key, your own key (not the demo key)
Parameters
betsarrayrequiredUp to 100 rows across at most 25 distinct events. Each row is event_id, selection_key, book and odds, as on GET /clv.formatstringoptionaldecimal, american or fractional. Applies to every row's odds and to the prices in the response.Default:decimal
Request
The demo key (Free plan) cannot call this endpoint: it answers 403 plan_required. Set ODDS_API_KEY to your own key first.
curl -s -X POST "https://api.b337.ai/odds/v1/clv" \
-H "X-API-Key: $ODDS_API_KEY" -H "Content-Type: application/json" \
-d '{
"format": "decimal",
"bets": [
{"event_id": "baseball/us/mlb/philadelphia_phillies_v_tampa_bay_rays/2026-09-26",
"selection_key": "4ec43f065e08", "book": "betfair", "odds": 1.95},
{"event_id": "baseball/us/mlb/philadelphia_phillies_v_tampa_bay_rays/2026-09-26",
"selection_key": "4ec43f065e08", "book": "tab", "odds": 1.9}
]
}'import os
import requests
event = "baseball/us/mlb/philadelphia_phillies_v_tampa_bay_rays/2026-09-26"
resp = requests.post(
"https://api.b337.ai/odds/v1/clv",
json={"format": "decimal", "bets": [
{"event_id": event, "selection_key": "4ec43f065e08", "book": "betfair", "odds": 1.95},
{"event_id": event, "selection_key": "4ec43f065e08", "book": "tab", "odds": 1.9},
]},
headers={"X-API-Key": os.environ["ODDS_API_KEY"]},
timeout=10,
)
resp.raise_for_status()
for row in resp.json()["data"]:
print(row["book"], row["clv_pct"], row["close_reason"])// Node 18+, saved as an .mjs file
const event = "baseball/us/mlb/philadelphia_phillies_v_tampa_bay_rays/2026-09-26";
const res = await fetch("https://api.b337.ai/odds/v1/clv", {
method: "POST",
headers: { "X-API-Key": process.env.ODDS_API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
format: "decimal",
bets: [
{ event_id: event, selection_key: "4ec43f065e08", book: "betfair", odds: 1.95 },
{ event_id: event, selection_key: "4ec43f065e08", book: "tab", odds: 1.9 },
],
}),
});
const { data } = await res.json();
for (const row of data) console.log(row.book, row.clv_pct, row.close_reason);Response
200 OK
{
"schema_version": 1, "odds_format": "decimal", "count": 2,
"data": [
{"selection_key": "4ec43f065e08", "book": "betfair", "taken_odds": 1.95,
"close_odds": 1.86, "clv_pct": 4.84, "close_reason": null,
"fair_odds": null, "clv_vs_fair_pct": null, "fair_reason": "no_fair_price", "...": "..."},
{"selection_key": "4ec43f065e08", "book": "tab", "taken_odds": 1.9,
"close_odds": 1.8, "clv_pct": 5.56, "close_reason": null,
"fair_odds": null, "clv_vs_fair_pct": null, "fair_reason": "no_fair_price", "...": "..."}
],
"generated_at": "2026-10-05T03:40:12Z"
}Fields
- Up to 100 bets across at most 25 distinct events. Cost is 1 token per distinct
event_id: five bets on one game cost 1. - Each row is computed as on GET /clv, with the same formula and
close_reason/fair_reasoncodes. Rows come back in the order sent. - A malformed row rejects the whole call with a 400, and
error.indexnames the row. An unknown event is a row withclose_reason: unknown_event. - The demo key cannot call this endpoint.