Sports-1
A grounded, multimodal model for sports and betting: settlement rules injected on every request, live data fetched server-side mid-response, and betslip screenshots extracted into one canonical JSON schema. Model id infersia/sports-1.
Calling the model
Sports-1 is an ordinary OpenAI-compatible chat model. There is no tools array to build and no special parameter — grounding, the rulebook and the extraction schema are applied by the gateway. Anything that speaks the OpenAI API can call it.
curl https://api.infersia.com/v1/chat/completions \
-H "Authorization: Bearer $INFERSIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "infersia/sports-1",
"stream": true,
"messages": [
{"role": "user", "content": "What are the current lines for Chiefs vs Bills?"}
]
}'stream: trueis recommended — reasoning and answer tokens are forwarded as they arrive.- Context window is 1M tokens. Vision is supported via standard
image_urlcontent parts. - Reasoning defaults to high effort, which the settlement benchmarks require. Pass your own
reasoningobject to override it. - Responses carry
x-infersia-grounded-tool-calls(how many live lookups ran) andx-infersia-cost-usdheaders.
tools array and it takes precedence: your tools are always honoured and your system prompt is never overwritten, while the rulebook and betslip schema still ride along. When a question asks for odds, scores or other live data, the gateway also merges its own data tools in and executes them server-side — your agent gets the grounded answer without lifting a finger, and any call to one of your tools is forwarded to you untouched.Settlement questions
Ask what a bet pays and the model applies the correct convention — American odds, dead heats, pushes on the number, void legs in a parlay, each-way place terms — showing its working and the intermediate numbers.
from openai import OpenAI
client = OpenAI(
base_url="https://api.infersia.com/v1",
api_key=os.environ["INFERSIA_API_KEY"],
)
resp = client.chat.completions.create(
model="infersia/sports-1",
messages=[{
"role": "user",
"content": "I had $50 on Josh Allen over 249.5 passing yards at -115. "
"He threw for 261. What does the bet return?",
}],
)
print(resp.choices[0].message.content)Settlement-shaped questions run tool-free for exact arithmetic. If the question needs a result the message doesn’t state (“did my Lakers bet win last night?”), the live tools attach automatically.
Live data
When the model needs a fact, it calls gateway-side tools: betting lines (moneyline, spread, totals) and player props (anytime and first touchdown scorer, passing, rushing and receiving yards, points, rebounds, assists, home runs, strikeouts, goals and more) from named bookmakers including Pinnacle, plus live scores, standings, results, form and roster lookups across the NFL, NBA, MLB, NHL, college sports, soccer leagues worldwide, tennis, golf, MMA and more. Prices are quoted in each market’s native odds format — American for US sports — and never converted by the model.
Betslip extraction
Send one or more betslip screenshots with a prompt like Read this betslip. and the response is a single JSON object. The schema is bookmaker-agnostic: it describes the algebra every slip shares rather than any vendor’s layout, so nested same-game parlays, boosted prices, each-way splits and multi-bet screenshots are all just shapes of the same tree.
resp = client.chat.completions.create(
model="infersia/sports-1",
messages=[{"role": "user", "content": [
{"type": "text", "text": "Read this betslip."},
{"type": "image_url", "image_url": {"url": betslip_data_url}},
]}],
)
slip = json.loads(resp.choices[0].message.content)The response tree
screenshot → bets[] → components[] → selections[]. One bets[] entry per fully-visible bet — a My-Bets screenshot with three complete bets returns three entries, and multiple images in one request merge into one bets[]. Partially visible fragments are treated as noise, never guessed at.
Top level
| Parameter | Type | Description |
|---|---|---|
is_betslip | boolean | false — with no other fields — when the image is not a bet record (fixture list, odds board, tracker widget). |
bookmaker | string | null | Brand as printed, including recognisable logos and monograms, or the visible domain. Null when unsure — never guessed from UI styling. |
bets | array | One entry per fully-visible bet. |
Each bet
| Parameter | Type | Description |
|---|---|---|
bet_id | string | null | Ticket / receipt / transaction id as printed. |
bet_type | enum | single · multi (parlay/accumulator) · same_game_multi (SGP/bet builder) · each_way · system (Lucky 15, Yankee, Trixie…) · exotic (trifecta, quinella, First 4…) · pool (quaddie, pick 6, placepot) · market_quote (odds shown but no bet struck). |
placed | boolean | null | Evidence-based: a receipt, bet id, "Bet Placed" or a settled record → true; a "Place bet" button, an editable stake or "Deposit to place" → false. Unplaced bets carry status unknown. On an unplaced slip a card with no stake entered is not a bet. |
variant | string | null | A printed structural badge that changes settlement — Teaser, Round Robin, Lose-to-Win, Same Race Multi — verbatim. |
placed_at / settled_at | string | null | Bet strike time and settlement time, each exactly as printed. Distinct from the event date, which lives on each selection. |
stake | number | null | Total stake for this bet as printed. For systems, exotics and pools this is the total; the unit stake lives in the block. |
currency | string | null | ISO-style code: USD, GBP, AUD… |
combined_odds | number | null | Decimal odds for the whole bet. |
odds_pre_boost | number | null | The struck-through pre-boost price when a boost was applied. |
status | enum | open · won · lost · void · cashed_out · unknown. |
return_shown | number | null | The headline money-out figure as printed. On a lost bet the printed would-be figure is NOT a return — this is 0. |
return_kind | enum | total_return (includes the stake) · profit (excludes it) · none. Decided by arithmetic against stake × odds, never by the label wording — books disagree about what "potential winnings" means. |
cash_out_offer | number | null | A live cash-out figure if one is printed. |
reconciles | boolean | null | Whether stake × odds matches the printed return within rounding. False means the slip carries settlement the image alone cannot explain. |
anomaly_note | string | null | When reconciles is false: candidate causes from the settlement rulebook — dead heat, Rule 4, commission, void leg, partial cash-out — without asserting one. Surface these to a human instead of ingesting silently. |
boost_printed / return_range | string | object | null | The boost badge verbatim ("20% profit boost"); and, when a slip prints avg/max/min potential returns (fixed-odds exotics), {min, max, avg} — return_shown stays null. |
truncated | boolean | True when the slip prints more legs or selections than are visible ("8 Bet Builder", four shown). The counts below describe what is visible. |
system | object | null | For bet_type system: {name, combos, unit_stake, each_way}. Combos and unit stake are read as printed, never computed — an each-way Lucky 15 prints 30 bets. One component per pick. |
exotic | object | null | For bet_type exotic: {type, boxed, mystery, positions, runners, combos, unit_stake, flexi_pct, tote}. Standouts carry positions by runner number per finishing place; boxes carry the runner set; one component whose selections are the distinct runners. |
pool | object | null | For bet_type pool (quaddie, big 6, pick 6, placepot): {name, combos, unit_stake, flexi_pct, tote}. One component per leg with mode "any". |
n_components / n_selections | number | Derived from the tree, never from the slip’s "N Legs" badge — books disagree about whether that counts components or leaf selections. |
components | array | What the odds multiply across. A single is one component with one selection; an SGP is one component with several; an each-way is two components (win and place) carrying their own odds and stakes. A component may carry mode "any" — a pool leg where one of its selections must land. |
Each selection
| Parameter | Type | Description |
|---|---|---|
sport | string | american_football, basketball, horse_racing, soccer, tennis, golf… |
competition | string | null | League or competition exactly as printed (NFL, NBA…). Always present; null when the slip doesn’t print one — never inferred. |
event | object | name, date, time, venue, race_number — one shape for every sport. Team sports use name/date/time; racing carries venue plus race_number (US/AU) or race time (UK/IRE). |
market | string | Moneyline, Spread, Total Points, player prop markets, Win… Qualifiers like "(1st Half)" belong here, never inside team or event names. |
line | number | string | null | The number bet on: -3.5, 249.5, 6, or a range like "2-3". |
selection | string | The picked outcome, character-for-character as printed — names are never "corrected". |
odds / odds_place / odds_printed | number | string | null | This selection’s own odds as a decimal when printed (SGP legs often have none); a second printed price ("4.50 / 1.75") goes to odds_place; the original notation — "-110", "+260", "3/1", "4.50 / 1.75" — is preserved in odds_printed. |
place_terms | string | null | Each-way or place terms printed on the leg, verbatim: "1/5 Odds, 3 Places", "Paying 4 Places instead of 3". |
status | enum | open · won · lost · void · unknown — per leg, so partially settled parlays are readable. |
Worked example
A $20 two-leg parlay: an NFL same-game parlay (Chiefs -3.5 plus a Travis Kelce receptions prop) alongside an NBA moneyline. Note the SGP legs carry no individual odds — only the component’s 3.10 — and the counts come from the tree: 2 components, 3 selections.
{
"is_betslip": true,
"bookmaker": "DraftKings",
"bets": [
{
"bet_id": "DK-8827734",
"bet_type": "multi",
"placed_at": "Sep 1, 2026 11:42 AM",
"settled_at": null,
"stake": 20.00,
"currency": "USD",
"combined_odds": 5.92,
"odds_pre_boost": null,
"status": "open",
"return_shown": 118.40,
"return_kind": "total_return",
"cash_out_offer": 17.10,
"reconciles": true,
"anomaly_note": null,
"n_components": 2,
"n_selections": 3,
"components": [
{
"odds": 3.10,
"stake": null,
"selections": [
{
"sport": "american_football",
"competition": "NFL",
"event": {
"name": "Kansas City Chiefs @ Buffalo Bills",
"date": "Sun 9/7", "time": "1:00 PM",
"venue": null, "race_number": null
},
"market": "Spread",
"line": -3.5,
"selection": "Kansas City Chiefs -3.5",
"odds": null,
"odds_printed": "-110",
"status": "open"
},
{
"sport": "american_football",
"competition": "NFL",
"event": {
"name": "Kansas City Chiefs @ Buffalo Bills",
"date": "Sun 9/7", "time": "1:00 PM",
"venue": null, "race_number": null
},
"market": "Receptions",
"line": 6,
"selection": "Travis Kelce 6+ Receptions",
"odds": null,
"odds_printed": null,
"status": "open"
}
]
},
{
"odds": 1.91,
"stake": null,
"selections": [
{
"sport": "basketball",
"competition": "NBA",
"event": {
"name": "Los Angeles Lakers @ Boston Celtics",
"date": "Sun 9/7", "time": "7:30 PM",
"venue": null, "race_number": null
},
"market": "Moneyline",
"line": null,
"selection": "Los Angeles Lakers",
"odds": null,
"odds_printed": "-110",
"status": "open"
}
]
}
]
}
]
}Pricing & variants
Current per-token pricing is on the model page. infersia/sports-2 is a sibling model — the identical grounding stack on a dense vision base — exposed for side-by-side evaluation and answering to everything on this page; see the Sports-2 reference for what differs.