MoneyLine AI

MoneyLine AI lets you make one API call to get both MoneyLine betting data and an AI-generated response grounded in that data. It is designed for sports betting products, not for general-purpose chat.

Every request resolves one controlled MoneyLine context, pulls a capped dataset, sends only that dataset to the model, and returns a response you can render directly or use inside your own application logic. The response also includes a stable presentation layer so app teams can rely on one consistent payload shape.

How Integration Works

1. Send chat-style input

Post a messages array plus context, scope, responseFormat, and optional safe filters.

2. MoneyLine resolves one context

The request is mapped to best bets, EV bets, or arbitrage. No open-ended database querying is allowed.

3. MoneyLine fetches the dataset

A controlled set of records is selected based on the chosen context and requested scope.

4. You receive answer + UI contract

The response includes grounded AI output, normalized records, a deterministic presentation object, and credit usage metadata.

Endpoint

POST/v1/ai/chat

Generate a MoneyLine-grounded AI response from a stateless chat request.

ParameterTypeRequiredDescription
messagesarrayYes1 to 6 chat messages. The last message must be from the user.
contextstringNobest_bets, ev_bets, arbitrage, or event_best_available_bet. If omitted, MoneyLine uses deterministic context inference.
scopestringNosmall, medium, or large. Controls how many records are retrieved. Default: small.
responseFormatstringNonatural, hybrid, or structured. Default: hybrid.
filtersobjectNoOptional safe filters limited to league, leagues, market, sourceType, bookmaker, and bookmakers.

Response

{
  "success": true,
  "data": {
    "answer": "The strongest EV spots right now are concentrated in NBA moneyline markets, with FanDuel posting the best price on Boston relative to the current consensus.",
    "records": [
      {
        "recordType": "ev_bet",
        "eventId": "nba-ev-311286",
        "leagueId": "nba",
        "sport": "basketball",
        "calculatedAt": "2026-03-26T14:05:00.000Z",
        "market": "h2h",
        "outcome": "Boston Celtics",
        "sourceType": "sportsbook",
        "sourceRegion": "us",
        "bookmakerName": "FanDuel",
        "bookmakerId": "fanduel",
        "odds": 185,
        "ev": 0.0412,
        "evPct": 4.12
      }
    ],
    "context": {
      "requestedContext": "ev_bets",
      "resolvedContext": "ev_bets",
      "inferred": false,
      "scope": "small",
      "responseFormat": "hybrid",
      "filters": {
        "league": "nba"
      }
    },
    "sources": {
      "primary": "edge.ev",
      "label": "EV Bets",
      "filters": {
        "league": "nba"
      }
    },
    "presentation": {
      "version": "v1",
      "responseType": "surface_summary",
      "headline": "EV Bets Summary",
      "summary": "Top EV Bets signal right now: Boston Celtics in the moneyline market at +185 from FanDuel. At the current price, MoneyLine expects this bet to return about +4.12% per bet over a large sample.",
      "confidence": "medium",
      "primaryPick": {
        "signalType": "ev_bet",
        "signalLabel": "EV Bet",
        "selection": "Boston Celtics",
        "market": "h2h",
        "marketLabel": "Moneyline",
        "odds": 185,
        "oddsDisplay": "+185",
        "bookmakerName": "FanDuel",
        "humanInsight": {
          "summary": "At the current price, MoneyLine expects this bet to return about +4.12% per bet over a large sample.",
          "confidenceReason": "The current price still projects positive long-run return.",
          "keyNumbers": [
            { "label": "Current Line", "value": "+185", "detail": "FanDuel" },
            { "label": "Expected Value", "value": "+4.12%" },
            { "label": "Projected Units", "value": "+0.041", "detail": "Expected profit per 1 unit staked" }
          ],
          "supportingPoints": [
            "Projected long-run return: +4.12% per bet.",
            "Expected profit per 1 unit staked: +0.041."
          ]
        }
      },
      "cards": [
        {
          "recordIndex": 0,
          "signalType": "ev_bet",
          "signalLabel": "EV Bet",
          "selection": "Boston Celtics",
          "market": "h2h",
          "marketLabel": "Moneyline",
          "odds": 185,
          "oddsDisplay": "+185",
          "bookmakerName": "FanDuel",
          "confidence": "medium",
          "reason": "Positive EV opportunity with 4.12% expected value.",
          "humanInsight": {
            "summary": "At the current price, MoneyLine expects this bet to return about +4.12% per bet over a large sample.",
            "confidenceReason": "The current price still projects positive long-run return.",
            "keyNumbers": [
              { "label": "Current Line", "value": "+185", "detail": "FanDuel" },
              { "label": "Expected Value", "value": "+4.12%" },
              { "label": "Projected Units", "value": "+0.041", "detail": "Expected profit per 1 unit staked" }
            ],
            "supportingPoints": [
              "Projected long-run return: +4.12% per bet.",
              "Expected profit per 1 unit staked: +0.041."
            ]
          }
        }
      ]
    }
  },
  "meta": {
    "creditUsage": {
      "total": 27,
      "retrieval": 9,
      "generation": 18
    }
  }
}

Quick Start

Pass your API key in the x-api-key header and send a JSON body to /v1/ai/chat.

For most integrations, the best default is to omit bothcontext andfilters.league /filters.leagues. Let MoneyLine infer the intent from the latest user message so prompts like"basketball","hoops","football","I want to bet on hockey this weekend" or"What's the best bet for the Braves game today?"just work without app-side routing.

Broad sport prompts automatically map to supported league families. For example,"basketball" and"hoops" search acrossnba andncaa_basketball, while"football" and"pigskin" search acrossnfl andncaa_football. If your app already knows that multi-league scope, you can sendfilters.leagues directly.

Recommended auto-infer example
curl -X POST https://mlapi.bet/v1/ai/chat \
  -H "content-type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "scope": "small",
    "responseFormat": "hybrid",
    "messages": [
      { "role": "user", "content": "I want to bet on hockey this weekend and I am only using FanDuel. What is the best bet for me?" }
    ]
  }'

You can constrain AI results to one or more sportsbooks either by sendingfilters.bookmaker orfilters.bookmakers, or by saying it naturally in the latest user message, like"only show FanDuel". If both are present, the structured filter wins.

Choose A Context

ContextMaps ToBest For
best_betsBest bets dataFeatured picks, recommendation cards, daily summaries
ev_betsPositive EV edge dataExplaining value, surfacing mathematically favorable bets
arbitrageArbitrage edge dataGuaranteed-profit workflows and cross-book comparison tools
event_best_available_betEvent-specific recommendation workflow“If I have to bet this game, what should I choose?” plus a better same-league alternative

If you omit context, MoneyLine will try to infer it from the last user prompt. If the prompt is ambiguous, the API returns a400 response and asks for an explicit context.

Choose A Response Format

natural

Returns a prose answer plus the stable presentation object, without machine-analysis fields.

hybrid

Returns prose, normalized records, and the stable presentation object. Best default for production UI.

structured

Returns normalized records, the same stable presentation object, and deterministic analysis fields for downstream logic.

Expected Result Shape

The key integration detail is that data.presentationis the stable UI contract. It is built by the MoneyLine API itself, so client teams do not have to parse the model's freeform wording to render cards, hero copy, or recommendation summaries.

Always present

records, context, sources, and presentation are returned on successful AI responses regardless of format.

Natural + Hybrid

Use answer for plain copy, but render from presentation when you need consistent UI sections.

Structured

Use analysis for machine-readable summaries and highlights, but keep presentation as the canonical render layer.

Event-specific requests

event_best_available_bet may also include primaryRecommendation, alternativeRecommendation, alternativeRecords, reasoningMode, and entityResolution.

Stable payload contract
{
  "success": true,
  "data": {
    "records": [...],
    "context": {
      "requestedContext": null,
      "resolvedContext": "event_best_available_bet",
      "inferred": true,
      "scope": "small",
      "responseFormat": "hybrid",
      "filters": {}
    },
    "sources": {
      "primary": "event_recommendation",
      "label": "Event Recommendation",
      "filters": {}
    },
    "presentation": {
      "version": "v1",
      "responseType": "event_recommendation",
      "headline": "MoneyLine AI Recommendation for Boston Celtics at Atlanta Hawks",
      "summary": "For Boston Celtics at Atlanta Hawks, MoneyLine recommends Atlanta Hawks +4.5 in the spread market at -108 from FanDuel.",
      "confidence": "high",
      "entity": { "...": "..." },
      "primaryPick": { "...": "..." },
      "alternativePick": { "...": "..." },
      "cards": [{ "...": "..." }]
    },
    "answer": "Only for natural and hybrid formats.",
    "analysis": "Only for structured format.",
    "primaryRecommendation": "Present on event-specific workflows.",
    "alternativeRecommendation": "Present when a stronger same-league option exists."
  },
  "meta": {
    "creditUsage": {
      "total": 41,
      "retrieval": 14,
      "generation": 27
    }
  }
}

Suggested UI Display Guide

If you are building your own UI or handing this response to another LLM for formatting, treat data.presentation as the source of truth. It is the clean, deterministic layer meant for cards, hero copy, recommendation grouping, and readable summaries.

Use presentation first

Render headline, summary, primaryPick, alternativePick, and cards directly from data.presentation.

Use narrative second

Use answer or analysis only as supporting explanation below the main recommendation blocks.

Hide internal metadata

Do not surface context, sources, records, requestId, or creditUsage in the main end-user experience.

Preserve API order

Keep cards in the order returned by MoneyLine instead of re-ranking them in the client.

Recommended Render Order

  1. Render data.presentation.headline as the title.
  2. Render data.presentation.summary as the short overview directly under it.
  3. Render data.presentation.primaryPick as the featured recommendation.
  4. Render data.presentation.alternativePick only when it exists.
  5. Render data.presentation.cards as supporting evidence blocks in the exact order returned.
  6. Render data.answer or data.analysis.summary below the picks as optional expanded explanation.

Field Meaning Guide

FieldHow To Use It
presentation.responseTypeUse this to decide whether the response is a general surface summary or a specific event recommendation.
presentation.headlineReady-to-render title for the entire AI module.
presentation.summaryPrimary plain-English summary. This should be your default overview copy.
presentation.primaryPickThe single most important recommendation to feature first.
presentation.alternativePickOptional backup recommendation. Omit the section entirely when it is absent.
presentation.cardsSupporting cards. Use these for evidence, secondary rows, or stacked recommendation tiles.
primaryPick.event.matchup + primaryPick.event.startTimeUse these as the source of truth for the game label and scheduled date/time tied to the suggested bet whenever they are present.
primaryPick.selection + marketLabel + oddsDisplay + bookmakerNameThis is the core readable recommendation tuple. If selection is short like Over 8.5, pair it with marketLabel so the user knows whether it means Total Runs, Total Points, Total Goals, or a prop label.
primaryPick.rationale and cards[].reasonUse these as the short “why this bet” explanation. Do not invent your own rationale if these are missing.
primaryPick.humanInsight and cards[].humanInsightDeterministic non-expert explanation layer. Use summary for the plain-English sentence, keyNumbers for stat chips, and riskNote when present.
primaryPick.metrics and cards[].metricsUse structured support data such as edgePct, evPct, impliedProb, modelProb, profitPct, or guaranteedProfit when present.
answer / analysis.summaryOptional narrative layer. Use it below the featured picks, not as the canonical display contract.

Fields To Keep Out Of The Main UI

  • meta.creditUsage, meta.requestId, and meta.degraded should be treated as operational metadata.
  • data.context, data.sources, and data.records are useful for logging, traceability, and drill-down, but not for the primary end-user presentation.
  • data.primaryRecommendation, data.alternativeRecommendation, and data.entityResolution are workflow-level details. Prefer the normalized fields already exposed in data.presentation.
Copy/paste instructions for another LLM
Use MoneyLine's data.presentation object as the authoritative UI contract.

Ignore these fields for end-user presentation:
- meta.creditUsage
- meta.requestId
- meta.degraded
- data.context
- data.sources
- data.records
- data.primaryRecommendation
- data.alternativeRecommendation
- data.alternativeRecords
- data.entityResolution

Only use those ignored fields for logging, debugging, support, or drill-down.

Render order:
1. data.presentation.headline as the top title.
2. data.presentation.summary as the short plain-English overview.
3. data.presentation.primaryPick as the main recommendation block.
4. data.presentation.alternativePick as a secondary option only if present.
5. data.presentation.cards as supporting evidence cards in the order provided.
6. data.answer or data.analysis.summary as optional expanded explanation below the main recommendation.

Field meanings:
- data.presentation.responseType
  - surface_summary: general best-bet, EV, value, or arbitrage summary across surfaced MoneyLine records.
  - event_recommendation: recommendation for a specific game, matchup, or player-linked event.
- data.presentation.headline: ready-to-render title.
- data.presentation.summary: ready-to-render short summary; use this as the default explanatory sentence.
- data.presentation.confidence: high, medium, or low; reflect this in wording and emphasis, but do not invent stronger certainty.
- data.presentation.entity: event context for event-specific flows.
- data.presentation.entity.matchup: human-readable event label.
- data.presentation.primaryPick: the single most important bet to show first.
- data.presentation.alternativePick: backup option if present.
- data.presentation.cards: supporting picks or evidence; preserve order and do not re-rank.
- data.presentation.sourceLabel: human-readable MoneyLine source label such as Best Bets, EV Bets, or Event Recommendation.

Primary pick and alternative pick meanings:
- signalType: machine type such as best_bet, value_bet, ev_bet, arbitrage, hit_rate, or fallback.
- hit_rate signalType: indicates a player prop chosen primarily on recent L5/L10/L25 hit-rate strength. humanInsight.summary cites the hits-per-games fragments and any concurrent EV or edge enrichment. metrics.hitRate carries the L5/L10/L25/season windows for chip rendering.
- signalLabel: human label for the signal type.
- selection: the cleanest label for what to bet; use this as the main pick text.
- market: betting market such as moneyline, spread, total, or prop market.
- marketLabel: human-readable market label such as Moneyline, Run Line, Puck Line, Total Runs, Total Goals, Total Points, or Points. Use this whenever selection alone is ambiguous.
- event: normalized game or matchup context for the suggested bet.
- event.matchup: human-readable matchup label tied to the suggested bet.
- event.startTime: ISO start time for the game or matchup tied to the suggested bet.
- outcome: raw side, team, or player outcome.
- point: line value when applicable.
- odds: numeric American odds.
- oddsDisplay: preformatted American odds string; prefer this for display.
- bookmakerName: sportsbook or source name.
- bookmakerId: internal source id; not necessary for end-user display.
- sourceType: sportsbook, exchange, or dfs; useful as supporting metadata.
- confidence: confidence for this pick.
- rationale: concise reason to show under the pick.
- humanInsight: deterministic explanation layer written for non-expert users.
- humanInsight.summary: the default plain-English sentence to show under the pick.
- humanInsight.confidenceReason: one short line explaining why MoneyLine is confident in this signal.
- humanInsight.keyNumbers: labeled stats ready for chips, badges, or small comparison rows.
- humanInsight.supportingPoints: optional extra lines expanding the case for the bet.
- humanInsight.riskNote: optional caution line, mainly for narrow fallback scenarios where no positive edge exists.
- metrics: structured supporting stats.

Metrics meanings:
- edgePct: model edge versus market consensus.
- evPct: expected value percentage.
- ev: expected value per unit stake.
- profitPct: guaranteed arbitrage return percentage.
- guaranteedProfit: guaranteed profit amount from arbitrage math.
- impliedProb: probability implied by the market odds.
- modelProb: MoneyLine projected probability.

Card meanings:
- recordIndex: index into data.records; use only for traceability.
- signalType, signalLabel, selection, market, marketLabel, event, oddsDisplay, bookmakerName, confidence, reason, and metrics should be rendered similarly to the main pick, but as supporting evidence rather than the featured pick.

Narrative fields:
- If data.answer exists, it is a prose explanation for natural and hybrid responses.
- If data.analysis exists, use data.analysis.summary and data.analysis.highlights for structured responses.
- Never let data.answer or data.analysis override data.presentation. If there is any mismatch, trust data.presentation.

Formatting rules:
- Show exactly one featured recommendation from primaryPick.
- Show alternativePick only if present.
- Show all returned cards, preserving API order.
- Do not invent odds, books, confidence, or metrics when fields are missing.
- Omit empty sections entirely.
- Keep explanation text grounded in summary, rationale, reason, and metrics.
- Prefer primaryPick.humanInsight.summary over ad-libbed explanatory copy when you want a confident, non-expert-friendly explanation.
- Render humanInsight.keyNumbers in the order returned and do not invent additional stat chips.
- Treat selection + marketLabel + oddsDisplay + bookmakerName as the core readable recommendation tuple.
- If selection is a short value like Over 8.5 or Under 2.5, always pair it with marketLabel so the end user knows what the total or prop refers to.
- When available, use primaryPick.event.matchup and primaryPick.event.startTime as the source of truth for the game label and scheduled date/time.

Date And Time Display

  • Use primaryPick.event.matchup as the game label tied to the recommendation.
  • Use primaryPick.event.startTime as the source-of-truth ISO timestamp for that matchup.
  • If primaryPick.event is absent, fall back to cards[0].event if present.
  • Do not infer the game label or time from summary, answer, or other narrative fields.
  • Format the ISO timestamp in the client with the user's timezone or a chosen display timezone such as Eastern Time.
Client Date Formatting Example
const event = data.presentation.primaryPick?.event ?? data.presentation.cards?.[0]?.event;

const matchup = event?.matchup ?? null;
const startTime = event?.startTime ?? null;

const formattedStartTime = startTime
  ? new Intl.DateTimeFormat("en-US", {
      weekday: "short",
      month: "short",
      day: "numeric",
      hour: "numeric",
      minute: "2-digit",
      timeZone: "America/New_York",
      timeZoneName: "short",
    }).format(new Date(startTime))
  : null;

// Example output:
// matchup => "Cleveland Guardians at Atlanta Braves"
// formattedStartTime => "Fri, Apr 10, 7:20 PM EDT"

Scope And Credit Usage

ScopeRecordsNaturalHybridStructured
smallTop 5202717
mediumTop 12476040
largeTop 259311373

Every AI response includes meta.creditUsage, so you can show cost to your team, monitor usage internally, or make product decisions around when to request larger scopes.

Common Integration Patterns

Daily bet summaries

Use best_bets or ev_bets with small or medium scope to generate cards, newsletters, and notifications.

Explainable recommendation UI

Use hybrid responses and render against presentation, while keeping records for source rows, links, and odds metadata.

Chat interfaces

Keep the experience stateless by passing recent messages in each call, but let retrieval be driven by the latest user turn. MoneyLine does not store server-side threads in the MVP.

Internal tooling and automation

Use structured responses when your app needs records plus machine-readable analysis, but keep presentation as the render-safe contract.

Example Structured Request

Structured response example
const res = await fetch("https://mlapi.bet/v1/ai/chat", {
  method: "POST",
  headers: {
    "content-type": "application/json",
    "x-api-key": "YOUR_API_KEY"
  },
  body: JSON.stringify({
    context: "arbitrage",
    scope: "small",
    responseFormat: "structured",
    filters: { league: "nba", sourceType: "all" },
    messages: [
      { role: "user", content: "Rank the top arbitrage spots and tell me which records are most actionable." }
    ]
  })
})

const payload = await res.json()
console.log(payload.data.analysis)
console.log(payload.data.records)

Best Practices

Default to auto-infer

In most apps, omit explicit context and league filters. Let the latest user message drive context and league inference.

Use explicit filters sparingly

Add explicit league, market, or sportsbook filters only when your product already knows those constraints ahead of time.

Send the full visible thread

Keep requests stateless by sending recent chat messages, but phrase the newest user message clearly when switching sports or games.

Prefer hybrid for shipping features

Hybrid gives you both rendered copy and the underlying records, which is the best default for most production integrations.

Game-Specific Recommendation Example

Event recommendation example
const res = await fetch("https://mlapi.bet/v1/ai/chat", {
  method: "POST",
  headers: {
    "content-type": "application/json",
    "x-api-key": "YOUR_API_KEY"
  },
  body: JSON.stringify({
    context: "event_best_available_bet",
    scope: "small",
    responseFormat: "hybrid",
    messages: [
      { role: "user", content: "Show me the best bet for the Hawks game tonight. If that game is weak, tell me what I should bet in the NBA instead." }
    ]
  })
})

const payload = await res.json()
console.log(payload.data.primaryRecommendation)
console.log(payload.data.alternativeRecommendation)
console.log(payload.data.answer)

Example AI Response

This is a representative hybrid response from MoneyLine AI. It shows the display-ready answer, normalized records, stable presentation contract, recommendation objects, resolution metadata, and credit usage that a front end can use to render cards, source rows, and usage details.

Hybrid response payload
{
  "success": true,
  "data": {
    "answer": "For the Braves game, the strongest current option on FanDuel is Atlanta Braves moneyline at +118. If you want the better overall MLB spot instead, look at the Cubs moneyline at +132.",
    "records": [
      {
        "recordType": "best_bet",
        "eventId": "mlb-ev-1329189120",
        "leagueId": "mlb",
        "sport": "baseball",
        "calculatedAt": "2026-04-07T01:18:16.945Z",
        "market": "moneyline",
        "outcome": "Atlanta Braves",
        "bestOdds": 118,
        "bookmakerId": "fanduel",
        "bookmakerName": "FanDuel",
        "sourceType": "sportsbook",
        "sourceRegion": "us"
      }
    ],
    "context": {
      "requestedContext": null,
      "resolvedContext": "event_best_available_bet",
      "inferred": true,
      "scope": "small",
      "responseFormat": "hybrid",
      "filters": {
        "bookmakers": ["fanduel"]
      }
    },
    "sources": {
      "primary": "event_recommendation",
      "label": "Event Recommendation",
      "filters": {
        "bookmakers": ["fanduel"]
      }
    },
    "presentation": {
      "version": "v1",
      "responseType": "event_recommendation",
      "headline": "MoneyLine AI Recommendation for Atlanta Braves at New York Mets",
      "summary": "For Atlanta Braves at New York Mets, MoneyLine recommends Atlanta Braves in the moneyline market at +118 from FanDuel. Best available line surfaced from MoneyLine best-bets data. If you want the stronger same-league alternative, look at Chicago Cubs in the moneyline market at +132 from FanDuel.",
      "confidence": "medium",
      "entity": {
        "resolvedEntityType": "event",
        "resolvedEventId": "mlb-ev-1329189120",
        "resolvedLeagueId": "mlb",
        "resolutionConfidence": "medium",
        "resolutionReason": "Resolved from team/game language in the prompt.",
        "matchup": "Atlanta Braves at New York Mets"
      },
      "primaryPick": {
        "signalType": "best_bet",
        "signalLabel": "Best Bet",
        "type": "surface",
        "eventId": "mlb-ev-1329189120",
        "leagueId": "mlb",
        "market": "moneyline",
        "marketLabel": "Moneyline",
        "selection": "Atlanta Braves",
        "outcome": "Atlanta Braves",
        "odds": 118,
        "oddsDisplay": "+118",
        "bookmakerName": "FanDuel",
        "bookmakerId": "fanduel",
        "sourceType": "sportsbook",
        "confidence": "medium",
        "rationale": "Best available line surfaced from MoneyLine best-bets data.",
        "metrics": {}
      },
      "alternativePick": {
        "signalType": "ev_bet",
        "signalLabel": "EV Bet",
        "type": "surface",
        "eventId": "mlb-ev-1329189109",
        "leagueId": "mlb",
        "market": "moneyline",
        "marketLabel": "Moneyline",
        "selection": "Chicago Cubs",
        "outcome": "Chicago Cubs",
        "odds": 132,
        "oddsDisplay": "+132",
        "bookmakerName": "FanDuel",
        "bookmakerId": "fanduel",
        "sourceType": "sportsbook",
        "confidence": "high",
        "rationale": "Positive EV opportunity with 6.4% expected value.",
        "metrics": {
          "ev": 0.064,
          "evPct": 6.4
        }
      },
      "cards": [
        {
          "recordIndex": 0,
          "signalType": "best_bet",
          "signalLabel": "Best Bet",
          "selection": "Atlanta Braves",
          "market": "moneyline",
          "marketLabel": "Moneyline",
          "odds": 118,
          "oddsDisplay": "+118",
          "bookmakerName": "FanDuel",
          "confidence": "medium",
          "reason": "Best currently available market price from FanDuel.",
          "metrics": {}
        }
      ],
      "reasoningMode": "hybrid_surface_plus_fallback",
      "sourceLabel": "Event Recommendation"
    },
    "primaryRecommendation": {
      "type": "surface",
      "premiumSignalType": "best_bet",
      "eventId": "mlb-ev-1329189120",
      "leagueId": "mlb",
      "market": "moneyline",
      "selection": "Atlanta Braves",
      "outcome": "Atlanta Braves",
      "bookmakerId": "fanduel",
      "bookmakerName": "FanDuel",
      "sourceType": "sportsbook",
      "sourceRegion": "us",
      "odds": 118,
      "confidence": "medium",
      "why": "Best available line surfaced from MoneyLine best-bets data.",
      "metrics": {}
    },
    "alternativeRecommendation": {
      "type": "surface",
      "premiumSignalType": "ev_bet",
      "eventId": "mlb-ev-1329189109",
      "leagueId": "mlb",
      "market": "moneyline",
      "selection": "Chicago Cubs",
      "outcome": "Chicago Cubs",
      "bookmakerId": "fanduel",
      "bookmakerName": "FanDuel",
      "sourceType": "sportsbook",
      "sourceRegion": "us",
      "odds": 132,
      "confidence": "high",
      "why": "Positive EV opportunity with 6.4% expected value.",
      "whyBetterThanPrimary": "This same-league option has a stronger surfaced MoneyLine edge than the requested game.",
      "metrics": {
        "ev": 0.064,
        "evPct": 6.4
      }
    },
    "alternativeRecords": [
      {
        "recordType": "ev_bet",
        "eventId": "mlb-ev-1329189109",
        "leagueId": "mlb",
        "sport": "baseball",
        "calculatedAt": "2026-04-07T01:18:13.912Z",
        "edgeId": "ev-1775523493902-fanduel",
        "market": "moneyline",
        "outcome": "Chicago Cubs",
        "sourceType": "sportsbook",
        "sourceRegion": "us",
        "bookmakerName": "FanDuel",
        "bookmakerId": "fanduel",
        "odds": 132,
        "ev": 0.064,
        "evPct": 6.4
      }
    ],
    "reasoningMode": "hybrid_surface_plus_fallback",
    "entityResolution": {
      "resolvedEntityType": "event",
      "resolvedEventId": "mlb-ev-1329189120",
      "resolvedLeagueId": "mlb",
      "resolutionConfidence": "medium",
      "resolutionReason": "Resolved from team/game language in the prompt."
    }
  },
  "meta": {
    "creditUsage": {
      "total": 41,
      "retrieval": 14,
      "generation": 27
    },
    "requestId": "ml_req_example123"
  },
  "error": null
}

Limits And Errors

  • Requests may contain up to 6 messages and 8,000 total input characters.
  • Only one MoneyLine context is allowed per request.
  • If no supported context can be inferred, the API returns 400.
  • For ambiguous event prompts where no specific game can be resolved (or the resolved game has no odds yet), MoneyLine AI degrades to a same-league surface fallback instead of returning a 404. The response stays 200 with data.entityResolution.resolutionFallback: true and data.reasoningMode: "event_resolution_fallback_surface".
  • For surface contexts (best_bets / ev_bets / arbitrage) where the inferred filters yield zero records, MoneyLine AI broadens once before returning 404. The broadened response sets data.context.broadened: true and meta.degraded: true.
  • If the model provider is unavailable, the API returns a 502 or 503.
400 — ambiguous context
{
  "success": false,
  "data": null,
  "meta": {
    "requestId": "ml_req_ab12cd34ef56"
  },
  "error": {
    "message": "Your request appears to match multiple MoneyLine AI contexts. Resend with an explicit \"context\" value.",
    "statusCode": 400
  }
}