# ComboBuilder ✨

{% hint style="success" %}
🆕 **New** — Now available for Football, Basketball, and Baseball.
{% endhint %}

### Overview <a href="#overview" id="overview"></a>

The LSports ComboBuilder API enables operators to offer Combo Bet functionality — allowing bettors to combine multiple selections from a single fixture into one bet with a correlation-aware combined price.

Unlike naive parlay pricing that simply multiplies individual odds, the ComboBuilder engine accounts for statistical dependencies between selections (e.g., "Home Win" and "Over 2.5 Goals" are correlated events), producing a fair margined price that reflects joint probabilities.

#### Authentication <a href="#authentication" id="authentication"></a>

All ComboBuilder API endpoints require authentication via JWT access tokens. To obtain your credentials and authenticate, see the [Authentication Guide](/u/trade/combo-builder/authentication.md).

#### Integration Workflow <a href="#integration-workflow" id="integration-workflow"></a>

The API consists of two endpoints designed to be used together:

**1. Resolve market dependencies** — For each selection the end user wants to include, call `/v1/markets` to determine which market data the pricing engine requires. Markets often have dependencies - for example, pricing a "Player Total Shots" selection may require you to also provide "Shots on Target" and "Assists" data in the same request. This endpoint tells you exactly what to supply.

**2. Build the combined price** — Call `/v1/combobuilder` with the fixture's market data (as determined in step 1), the user's selections, and participant/player information. The API returns a single combined decimal odds value along with metadata indicating which selections are required vs. redundant.

**Coverage:** ComboBuilder is available for all Football leagues. No coverage check is required.

#### Key Principle <a href="#key-principle" id="key-principle"></a>

The operator is responsible for supplying the underlying market odds data to the pricing engine. The ComboBuilder does not source odds - it derives the combined price from the data you provide. The richer and more complete the market data you supply (more lines, more periods), the more accurate the combined pricing will be.

Refer to the full API specification below for request/response schemas, supported market keys, period definitions, and worked examples for Football.

{% hint style="info" %}
**Previous endpoint URLs** — `POST /v1/betbuilder` and `POST /v1/betbuilder/markets` are still active and will be supported until **June 7, 2026**. New integrations should use the updated endpoints documented below.
{% endhint %}

## Derive combined combo price

> Calculates a margined combined price for two or more selections on a fixture.\
> \
> The \`markets\` object uses actual LSports market IDs as string keys. Each market ID value contains the source odds payload for that market. For example, Football market \`"1"\` is Match Result, \`"2"\` is Total Goals, and \`"13"\` is European Handicap.\
> \
> \`IncomingRequest\` logs preserve this ID-keyed request shape; \`UpstreamRequest\` logs show the normalized internal shape used by the pricing engine.

```json
{"openapi":"3.0.1","info":{"title":"ComboBuilder Customers API","version":"v1.0"},"tags":[{"name":"ComboBuilder","description":"Core bet price derivation endpoints"}],"servers":[{"url":"https://combo-builder-gw.lsports.eu","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT Bearer token issued by the authentication provider (Frontegg).\nInclude the token in the `Authorization` header as `Bearer <token>`.\n"}},"schemas":{"ComboBuilderRequest":{"required":["sportId","participants","selections","markets"],"type":"object","additionalProperties":false,"properties":{"sportId":{"type":"integer","description":"LSports sport ID","enum":[6046,48242,154914]},"leagueId":{"type":"integer","nullable":true,"description":"LSports league/tournament ID. Required for Basketball to select the\ncorrect pricing model format.\n\n**Known values**\n| League | ID |\n|---|---|\n| NBA | 64 |\n| WNBA | 761 |\n| NCAA Basketball | 4045 |\n| Euroleague | 33249 |\n| MLB | 183 |\n"},"fixtureId":{"type":"integer","nullable":true,"description":"LSports fixture ID. Each request must use a unique value so the engine treats it\nas an independent event. Reusing the same ID across requests can cause state\ncaching issues on the engine side.\n"},"participants":{"type":"array","minItems":2,"maxItems":2,"description":"Home (index 0) and Away (index 1) teams with optional player rosters.","items":{"$ref":"#/components/schemas/Participant"}},"selections":{"type":"array","minItems":2,"description":"List of bet selections to be combined. **A ComboBuilder slip requires\nat least two selections** — single-leg slips are rejected by the\nengine with `InvalidBetslip: Minimum 2 selections required`.\n\nEach selection references an LSports `marketId`. For player props,\ninclude `playerId` and optionally `metricType`.\n","items":{"$ref":"#/components/schemas/Selection"}},"markets":{"type":"object","description":"Source market odds keyed by LSports market ID as a string. The value shape depends on the market. For fixed-line markets such as Football `1` or Baseball `235`, send the odds object directly. For line-based markets such as totals and handicaps, key the payload by the line value. The service normalizes this ID-keyed shape into internal sport/period fields before pricing.","additionalProperties":{"type":"object"}},"scoreboard":{"$ref":"#/components/schemas/Scoreboard","nullable":true,"description":"Live match scoreboard. Required for in-play requests."},"eventId":{"type":"string","nullable":true,"description":"Optional external event reference ID."},"viewId":{"type":"string","nullable":true,"description":"Optional view/session reference ID."}},"description":"ComboBuilder request using ID-keyed source markets."},"Participant":{"required":["id"],"type":"object","additionalProperties":false,"properties":{"id":{"type":"integer","description":"LSports participant (team) ID"},"name":{"type":"string","nullable":true,"description":"Team name (used for display only)"},"players":{"type":"array","nullable":true,"description":"Player roster. Required when sending player prop selections.\nPlayer IDs here must match IDs used as keys in `markets` sub-fields\n(e.g. `101`, `201`).\n","items":{"$ref":"#/components/schemas/Player"}}}},"Player":{"required":["id"],"type":"object","additionalProperties":false,"properties":{"id":{"type":"integer","description":"LSports player ID. Use the same ID as keys in market data fields."},"name":{"type":"string","nullable":true},"position":{"type":"string","nullable":true,"description":"Player position (sport-specific, e.g. `M` for midfielder in football)."},"starting":{"type":"string","nullable":true,"description":"Whether the player is in the starting lineup. Use `\"1\"` for starter.\n"}}},"Selection":{"required":["marketId"],"type":"object","additionalProperties":false,"properties":{"marketId":{"type":"integer","description":"LSports market ID.\n\n**Common Football market IDs**\n| ID | Market |\n|---|---|\n| 1 | Match Result (1X2) |\n| 2 | Total Goals |\n| 3 | Asian Handicap |\n| 4 | Half Time / Full Time |\n| 6 | Correct Score |\n| 11 | Corner Kicks |\n| 13 | European Handicap |\n| 16 | First Team to Score |\n| 214 | Total Cards |\n| 711 | Player to Score (Anytime) |\n| 714 | Player to Score 2+ Goals |\n| 715 | Player Hat-Trick |\n| 941 | First Goal Scorer |\n| 942 | Last Goal Scorer |\n| 1071 | Under/Over Player Assists |\n| 1397 | Under/Over Player Shots |\n| 2351 | Under/Over Player Shots On Target |\n| 2352 | Under/Over Player Tackles |\n| 2734 | Under/Over Player Passes |\n| 3201 | Player Over Shots |\n"},"outcome":{"type":"string","nullable":true,"description":"Selection outcome.\n- Standard markets: `\"1\"` (Home), `\"X\"` (Draw), `\"2\"` (Away)\n- Totals: `\"O\"` (Over), `\"U\"` (Under)\n- Player props (binary): `\"1\"` or `\"Y\"` (yes/over), `\"2\"` or `\"N\"` (no/under)\n"},"line":{"type":"number","format":"double","nullable":true,"description":"Handicap or total line value (e.g. `2.5`, `0.5`, `289.5`)."},"playerId":{"type":"integer","nullable":true,"description":"LSports player ID. Required for all player prop markets.\nMust match a player listed in `participants[].players[].id`.\n"},"period":{"type":"string","nullable":true,"description":"Optional period override. If omitted, the default full-game period is used.\nFootball: `RT`, `H1`, `H2`. Basketball: `*`, `H1`, `Q1`–`Q4`.\n"},"metricType":{"type":"string","nullable":true,"description":"Explicit metric type override. Required when the `marketId` is not in the\npre-configured mapping.\n\n**Football values**: `goals`, `shots`, `shotsOnTarget`, `assists`, `passes`, `tackles`, `cards`, `fouls`\n**Basketball values**: `points`, `assists`, `rebounds`, `steals`, `blocks`, `points{value=3}`\n"}}},"Scoreboard":{"type":"object","nullable":true,"description":"Live match scoreboard for in-play requests.\nSupports **both** LSports format (`CurrentPeriod` / `periods`) and\nengine format (`current_phase` / `phases`).\n","properties":{"CurrentPeriod":{"$ref":"#/components/schemas/LsportsCurrentPeriod","nullable":true},"periods":{"$ref":"#/components/schemas/LsportsPeriods","nullable":true},"current_phase":{"$ref":"#/components/schemas/EngineCurrentPhase","nullable":true},"phases":{"$ref":"#/components/schemas/EnginePhases","nullable":true}}},"LsportsCurrentPeriod":{"type":"object","properties":{"name":{"type":"string","nullable":true},"status":{"type":"integer","nullable":true,"description":"LSports fixture status ID:\n1=NotStartedYet, 2=InProgress, 3=Finished, 4=Canceled,\n5=Postponed, 6=Interrupted, 7=Abandoned, 8=CoverageLost, 9=AboutToStart\n"},"current_state":{"$ref":"#/components/schemas/LsportsCurrentState","nullable":true}}},"LsportsCurrentState":{"type":"object","properties":{"possession":{"type":"string","nullable":true},"first_possession":{"type":"string","nullable":true},"period":{"type":"string","nullable":true},"time":{"type":"integer","nullable":true,"description":"Time elapsed in seconds (converted to MM:SS internally)."}}},"LsportsPeriods":{"type":"object","properties":{"time_interval":{"$ref":"#/components/schemas/LsportsTimeInterval","nullable":true}}},"LsportsTimeInterval":{"type":"object","properties":{"type":{"type":"string","nullable":true},"time":{"type":"integer","nullable":true,"description":"Time in seconds."},"incidents":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/LsportsIncident"}}}},"LsportsIncident":{"type":"object","properties":{"IncidentType":{"type":"string","nullable":true,"description":"LSports incident type (e.g. `goals`, `corners`, `cards`)."},"time":{"type":"integer","nullable":true,"description":"Time of incident in seconds."},"period":{"type":"string","nullable":true},"team":{"type":"string","nullable":true},"player":{"type":"string","nullable":true},"type":{"type":"string","nullable":true},"value":{"type":"string","nullable":true}}},"EngineCurrentPhase":{"type":"object","properties":{"name":{"type":"string","nullable":true},"status":{"type":"string","nullable":true,"description":"e.g. `\"Started\"`, `\"NotStarted\"`, `\"Finished\"`"},"current_state":{"$ref":"#/components/schemas/EngineCurrentState","nullable":true}}},"EngineCurrentState":{"type":"object","properties":{"possession":{"type":"string","nullable":true},"first_possession":{"type":"string","nullable":true},"period":{"type":"string","nullable":true},"time":{"type":"string","nullable":true,"description":"Time as string (e.g. `\"35:00\"`)."}}},"EnginePhases":{"type":"object","properties":{"time_interval":{"$ref":"#/components/schemas/EngineTimeInterval","nullable":true}}},"EngineTimeInterval":{"type":"object","properties":{"type":{"type":"string","nullable":true},"time":{"type":"string","nullable":true,"description":"Time as string with period prefix (e.g. `\"RT/35:00\"`)."},"incidents":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/EngineIncident"}}}},"EngineIncident":{"type":"object","properties":{"group":{"type":"string","nullable":true,"description":"Incident type (`\"group\"`)."},"time":{"type":"string","nullable":true,"description":"e.g. `\"H1/09:38\"`"},"team":{"type":"string","nullable":true},"player":{"type":"string","nullable":true}}},"ComboBuilderResponse":{"type":"object","properties":{"correlationId":{"type":"string","nullable":true,"description":"Internal correlation ID for tracing."},"price":{"type":"number","format":"double","description":"Combined margined decimal odds for all selections."},"requiredSelections":{"type":"array","nullable":true,"description":"Indices of selections that are required for the bet to be valid.","items":{"type":"integer"}},"selections":{"type":"array","nullable":true,"description":"Per-selection details echoed back with `isRequired` flag.","items":{"$ref":"#/components/schemas/SelectionResponse"}}}},"SelectionResponse":{"type":"object","properties":{"bet":{"$ref":"#/components/schemas/SelectionBet","nullable":true},"isRequired":{"type":"boolean","description":"Whether this selection is required for the combined bet to win."}}},"SelectionBet":{"type":"object","properties":{"marketId":{"type":"integer"},"outcome":{"type":"string","nullable":true},"line":{"type":"number","format":"double","nullable":true},"playerId":{"type":"integer","nullable":true},"period":{"type":"string","nullable":true}}},"ComboBuilderErrorResponse":{"type":"object","description":"Standardized error response returned by all ComboBuilder API endpoints.\n\n**Error Code Ranges:**\n| Range | Category | Description |\n|-------|----------|-------------|\n| 1000-1999 | Pricing Errors | Errors from the pricing engine (422 responses) |\n| 2000-2999 | Validation Errors | Request validation failures (400/501 responses) |\n| 5000-5999 | Server Errors | Internal server errors (500/503 responses) |\n| 6000-6999 | Integration Errors | Upstream service failures (502/504 responses) |\n\n**Complete Error Code Reference:**\n| errorCode | errorType | HTTP Status | Description |\n|-----------|-----------|-------------|-------------|\n| 1001 | UnprocessableEntity | 422 | Missing source markets or state data |\n| 1002 | InvalidBetslip | 422 | Invalid combination of selections |\n| 1003 | UnwinnableBet | 422 | Zero-win probability combination |\n| 1004 | CalculationError | 422 | Calculation processing error |\n| 2001 | ValidationError | 400 | Request validation failed |\n| 2002 | UnsupportedSelection | 501 | Selection type not supported |\n| 5000 | InternalServerError | 500 | Unexpected internal error |\n| 5003 | ServiceUnavailable | 503 | Service temporarily unavailable |\n| 6001 | PricingConnectionError | 502 | Pricing service connection failure |\n| 6002 | PricingTimeout | 504 | Pricing service request timeout |\n| 6003 | InvalidPricingResponse | 502 | Invalid response from pricing service |\n","required":["errorCode","errorType","message"],"properties":{"errorCode":{"type":"integer","description":"Numeric error code for programmatic error handling.\nSee the table above for the complete list of error codes.\n"},"errorType":{"type":"string","description":"Human-readable error type identifier.\nCorresponds to the errorCode and can be used for display or logging.\n","enum":["UnprocessableEntity","InvalidBetslip","UnwinnableBet","CalculationError","ValidationError","UnsupportedSelection","InternalServerError","ServiceUnavailable","PricingConnectionError","PricingTimeout","InvalidPricingResponse","Unknown"]},"message":{"type":"string","description":"Human-readable error message describing the error."},"correlationId":{"type":"string","nullable":true,"description":"Unique identifier for request tracing. Use this when contacting support."},"details":{"type":"string","nullable":true,"description":"Additional technical details about the error (when available)."}}},"ForbiddenError":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable error message explaining the 403 rejection."}}}}},"paths":{"/v1/combobuilder":{"post":{"tags":["ComboBuilder"],"summary":"Derive combined combo price","parameters":[{"name":"customerId","in":"header","required":true,"schema":{"type":"integer"},"description":"Customer ID. Must match the `tenantId` claim in the JWT token.\nUsed for authorization — the customer must be registered for ComboBuilder access.\n"}],"description":"Calculates a margined combined price for two or more selections on a fixture.\n\nThe `markets` object uses actual LSports market IDs as string keys. Each market ID value contains the source odds payload for that market. For example, Football market `\"1\"` is Match Result, `\"2\"` is Total Goals, and `\"13\"` is European Handicap.\n\n`IncomingRequest` logs preserve this ID-keyed request shape; `UpstreamRequest` logs show the normalized internal shape used by the pricing engine.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboBuilderRequest"}}}},"responses":{"200":{"description":"Combined bet price successfully derived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboBuilderResponse"}}}},"400":{"description":"Bad request — missing required fields or invalid format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboBuilderErrorResponse"}}}},"401":{"description":"Unauthorized — missing or invalid JWT Bearer token"},"403":{"description":"Forbidden — the customer is not authorized for ComboBuilder.\nReturned when the `customerId` header is missing/invalid or the customer\ndoes not have ComboBuilder access.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"422":{"description":"Unprocessable Entity — pricing engine cannot process the request.\n\n**Error Types:**\n| errorCode | errorType | Description |\n|-----------|-----------|-------------|\n| 1001 | UnprocessableEntity | Missing source markets or state data to calculate the selection |\n| 1002 | InvalidBetslip | The combination of selections on the betslip is invalid (e.g., mutually exclusive) |\n| 1003 | UnwinnableBet | The combination of selections results in zero-win probability |\n| 1004 | CalculationError | An error occurred while calculating the betslip |\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboBuilderErrorResponse"}}}},"500":{"description":"Internal server error — unexpected error occurred","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboBuilderErrorResponse"}}}},"501":{"description":"Not Implemented — selection type is not supported","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboBuilderErrorResponse"}}}},"502":{"description":"Bad Gateway — failed to connect to pricing service","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboBuilderErrorResponse"}}}},"503":{"description":"Service Unavailable — pricing service is temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboBuilderErrorResponse"}}}},"504":{"description":"Gateway Timeout — pricing service request timed out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboBuilderErrorResponse"}}}}}}}}}
```

## Get supported markets for a sport

> Returns the list of LSports markets supported by ComboBuilder for the requested\
> sport, together with the source markets that should be provided in the pricing\
> request to price each market with full calibration.\
> \
> Supported sports:\
> &#x20; \* Football (\`sportId: 6046\`)\
> &#x20; \* Basketball (\`sportId: 48242\`)\
> &#x20; \* Baseball (\`sportId: 154914\`)\
> \
> \`dependedMarketIds\` lists the \*\*other\*\* markets that should be present in the\
> \`markets\` payload of the \`pricelsports\` request alongside the requested\
> market.\
> \
> \### Football (sportId 6046)\
> \
> Markets are grouped into the following dependency buckets, mirroring\
> the LSports ComboBuilder dependency contract:\
> \
> &#x20; \* \*\*Group A — Goal-based / full-match\*\* markets (1X2, Double Chance, HT/FT,\
> &#x20;   Correct Score, Both Teams To Score, totals, team totals, etc.) depend on\
> &#x20;   \`European Handicap (13)\`, \`1X2 (1)\`, \`Under/Over (2)\`, \`Asian Handicap (3)\`.\
> &#x20; \* \*\*Group B — Half-period\*\* markets (1st Period Winner, 2nd Period Winner,\
> &#x20;   U/O 1st/2nd Period, Correct Score 1st/2nd Period, halftime DC, etc.)\
> &#x20;   depend on \`European Handicap (13)\`, \`1X2 (1)\`, \`Under/Over 1st Period (21)\`,\
> &#x20;   \`Asian Handicap (3)\`, \`1st Period Winner (41)\`, \`Under/Over (2)\`.\
> &#x20; \* \*\*Group C — Corners\*\* markets depend on\
> &#x20;   \`Team With Most Corners (259)\`, \`Total Corners (11)\`.\
> &#x20; \* \*\*Group D — Cards\*\* market \`Under/Over Cards (214)\` is self-contained and\
> &#x20;   returns \`dependedMarketIds: null\`. \`Will A Red Card Be Shown? (82)\`\
> &#x20;   depends on \`Under/Over Cards (214)\`.\
> &#x20; \* \*\*Group F — Player\*\* markets depend on \`Player To Score In Anytime (711)\`.\
> &#x20;   \`Player To Score In Anytime\` itself returns \`null\`. Per-player odds\
> &#x20;   (\`asianPlayerTotals\`) are passed via the corresponding\
> &#x20;   \`players\[].sourceMarkets\` block, not via \`markets\`.\
> \
> \### Basketball (sportId 48242)\
> \
> Markets fall into the following groups, mirroring the LSports ComboBuilder\
> dependency contract for basketball:\
> \
> &#x20; \* \*\*Halftime-derived (H1)\*\* markets (1st/2nd Period Winner, U/O 1st/2nd Period —\
> &#x20;   Home/Away Team, 12 Halftime, 1st/2nd Period Odd/Even, 1st/2nd Period\
> &#x20;   Odd/Even — Home/Away Team) depend on \`1X2 Halftime (282)\`. The engine\
> &#x20;   consumes 282's odds to calibrate the halftime home/away points split.\
> &#x20;   \`282\` itself returns \`dependedMarketIds: null\` because it is the\
> &#x20;   source for this group.\
> &#x20; \* \*\*2nd-Half-derived (H2)\*\* markets (3rd/4th Period Winner, 3rd/4th Period\
> &#x20;   Odd/Even, U/O 3rd/4th Period — Home/Away Team, 12 2nd Half, U/O 2nd\
> &#x20;   Half markets including incl-OT variants) depend on both\
> &#x20;   \`Asian Handicap 2nd Half (283)\` and \`1X2 2nd Half (284)\`.\
> &#x20;   The engine consumes the joint (ML, spread) signal via\
> &#x20;   \`compute\_basketball\_h2\_means\` to calibrate the Q3+Q4 home/away\
> &#x20;   points split — the AH line sharpens the H2 sigma\_diff vs ML alone.\
> &#x20;   \`283\` and \`284\` themselves return \`dependedMarketIds: null\`.\
> &#x20; \* \*\*Odd/Even (5)\*\* depends on \`Under/Over (2)\` — the engine reads the\
> &#x20;   implied total mean from market 2 to price 5.\
> &#x20; \* \*\*Double Chance (7)\*\* depends on \`1X2 (1)\` — Double Chance is\
> &#x20;   analytically derivable from 1X2 outcome probabilities.\
> &#x20; \* \*\*HT/FT (4)\*\* depends on both \`1X2 (1)\` and \`1X2 Halftime (282)\`.\
> &#x20; \* \*\*To Win Both Halves (84)\*\* depends on \`1X2 Halftime (282)\`,\
> &#x20;   \`Asian Handicap 2nd Half (283)\` and \`1X2 2nd Half (284)\` since\
> &#x20;   the outcome is the joint event of winning both halves and the\
> &#x20;   engine consumes all three sources to calibrate per-half lambdas.\
> &#x20; \* \*\*OT-related\*\* markets (\`Will The Game Go To Overtime? (69)\`,\
> &#x20;   \`12 Including Overtime (226)\`) depend on \`1X2 (1)\` since the engine\
> &#x20;   extends the full-game ML simulation into overtime.\
> &#x20; \* \*\*Full-game team totals\*\* (\`U/O - Home Team (101)\`, \`U/O - Away Team (102)\`)\
> &#x20;   depend on \`Under/Over (2)\` since the engine extracts home/away expected\
> &#x20;   points from the game total.\
> &#x20; \* \*\*Including-OT team totals\*\* (\`U/O Home incl. OT (221)\`, \`U/O Away incl. OT (220)\`)\
> &#x20;   depend on their regulation counterparts (101, 102 respectively).\
> &#x20; \* Full-game source markets (\`1X2 (1)\`, \`Under/Over (2)\`, \`Asian Handicap (3)\`)\
> &#x20;   and the H1/H2 source anchors (\`282\`, \`283\`, \`284\`) themselves return\
> &#x20;   \`dependedMarketIds: null\`.\
> \
> \### Baseball (sportId 154914)\
> \
> Baseball markets are grouped into eight dependency buckets, mirroring\
> the LSports ComboBuilder dependency contract:\
> \
> &#x20; \* \*\*Group A — Full-game core\*\* sources (every full-game market depends on\
> &#x20;   these): \`1X2 (1)\`, \`Over/Under Total Points (2)\`, \`Both Teams to Score (17)\`,\
> &#x20;   \`Money Line incl. Overtime (226)\`. Markets in this group (Correct Score,\
> &#x20;   Total Odd/Even, Highest Scoring Inning, Match to go to Overtime,\
> &#x20;   First/Last Team to Score, combo markets, …) only return Group A as\
> &#x20;   their dependency list.\
> &#x20; \* \*\*Group A′ — Half-Time/Full-Time\*\* (\`HT/FT (4)\`, \`HT/FT (incl. overtime) (390)\`)\
> &#x20;   additionally depends on \`First-Half Result (Team based) (282)\` since the\
> &#x20;   engine consumes the halftime moneyline to calibrate the F5 home/away\
> &#x20;   lambdas that drive the HT outcome.\
> &#x20; \* \*\*Group B — Run line / Handicap\*\* (\`Handicap incl. OT (3, 342)\`)\
> &#x20;   additionally depends on \`Handicap (incl. Overtime) (3)\`.\
> &#x20; \* \*\*Group C — Team-specific\*\* (Home/Away O/U Team Total, team Odd/Even,\
> &#x20;   Race to X Runs) additionally depends on \`Over/Under Home Total Points (101)\`\
> &#x20;   and \`Over/Under Away Total Points (102)\`. \`Under/Over - Home Team Including Overtime (221)\`\
> &#x20;   and \`Under/Over - Away Team Including Overtime (220)\` additionally cross-reference each\
> &#x20;   other so a bet on either side carries both team totals in the payload.\
> &#x20; \* \*\*Group D — First-3 innings\*\* (\`First 3 Innings Winner (1561)\`,\
> &#x20;   \`3 Full Innings Total (1562)\`) additionally depends on the F3 sources\
> &#x20;   \`1561, 1562\`.\
> &#x20; \* \*\*Group E — First-5 innings / First-half\*\* (\`5 Full Innings Winner (235)\`,\
> &#x20;   \`5 Full Innings Total (236)\`, \`5 Full Innings Run Line (281)\`,\
> &#x20;   \`5 Full Innings Winner (Draw No Bet) (1618)\`, \`First-Half Result (Team based) (282)\`,\
> &#x20;   \`Asian Handicap Half-Time Betting (53)\`) additionally depends on the\
> &#x20;   F5 sources \`53, 235, 236, 281, 282\` — the engine consumes both the\
> &#x20;   5-full-innings markets and the halftime ML/AH to calibrate per-inning\
> &#x20;   F5 lambdas via \`compute\_baseball\_halftime\_lambdas\`.\
> &#x20; \* \*\*Group F — First-7 innings\*\* (\`First 7 Innings Winner (524)\`,\
> &#x20;   \`7 Full Innings Total (525)\`, \`7 Full Innings Handicap (526)\`)\
> &#x20;   additionally depends on the F7 sources \`524, 525, 526\`.\
> &#x20; \* \*\*Group G — Per-inning\*\* (every winner / total / handicap / team total /\
> &#x20;   odd-even market scoped to a specific inning) additionally depends on\
> &#x20;   that inning's own marketIds (e.g. inning 4 → \`47, 44, 205, 67\`).\
> &#x20; \* \*\*Group H — Player props\*\* (\`Player Total Runs Over/Under (1624)\`,\
> &#x20;   \`Player Total Home Runs Over/Under (1626)\`, \`Player Total Earned Runs Over/Under (1635)\`,\
> &#x20;   \`Player Total Hits Allowed Over/Under (1636)\`, \`Player Total Strikeouts Over/Under (1637)\`)\
> &#x20;   additionally depends on the player prop's own marketId.\
> \
> A market is never listed as its own dependency. \`dependedMarketIds: null\`\
> means the market either has no source-market dependencies in the LSports\
> contract, or it is itself the sole source of its group (e.g. \`Under/Over\
> Cards\`, \`Player To Score In Anytime\`, \`First-Half Result (Team based)\`).\
> \
> \*\*\`null\` semantics\*\*\
> \
> \`dependedMarketIds: null\` is the contract for "no source markets needed\
> for this market id" and is \*\*semantically equivalent to an empty list\
> \`\[]\`\*\*. Clients should treat both shapes identically; the API\
> deliberately uses \`null\` to make the absence explicit (rather than an\
> empty array, which can be ambiguous on some deserialisers). This is\
> consistent across all supported sports (Football, Basketball, Baseball).<br>

```json
{"openapi":"3.0.1","info":{"title":"ComboBuilder Customers API","version":"v1.0"},"tags":[{"name":"Markets","description":"Discover supported markets per sport"}],"servers":[{"url":"https://combo-builder-gw.lsports.eu","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT Bearer token issued by the authentication provider (Frontegg).\nInclude the token in the `Authorization` header as `Bearer <token>`.\n"}},"schemas":{"MarketsRequest":{"required":["sportId"],"type":"object","additionalProperties":false,"properties":{"sportId":{"type":"integer","description":"LSports sport ID. Football (`6046`), Basketball (`48242`) and Baseball (`154914`) are supported.","enum":[6046,48242,154914]},"marketId":{"type":"integer","nullable":true,"description":"Optional filter — return data for a single market only."}}},"MarketsResponse":{"type":"object","properties":{"result":{"type":"array","items":{"$ref":"#/components/schemas/MarketResult"}}}},"MarketResult":{"type":"object","properties":{"sport":{"$ref":"#/components/schemas/SportIdName"},"market":{"$ref":"#/components/schemas/MarketIdName"},"dependedMarketIds":{"type":"array","nullable":true,"description":"Markets that should be present in the `markets` payload of the\n`pricelsports` request alongside this market for full pricing calibration\n(excluding the market itself). Markets are grouped by type:\ngoal-based / full-match → European Handicap, 1X2, Under/Over, Asian\nHandicap; half-period → adds Under/Over 1st Period and 1st Period Winner;\ncorners → Team With Most Corners, Total Corners; cards → Under/Over Cards\n(with Will A Red Card Be Shown? when applicable); player → Player To\nScore In Anytime. `null` indicates the market has no further dependencies\n(e.g. a market that is itself the sole source of its group).\n","items":{"$ref":"#/components/schemas/MarketIdName"}}}},"SportIdName":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","nullable":true}}},"MarketIdName":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","nullable":true}}},"ForbiddenError":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable error message explaining the 403 rejection."}}}}},"paths":{"/v1/markets":{"post":{"tags":["Markets"],"summary":"Get supported markets for a sport","parameters":[{"name":"customerId","in":"header","required":true,"schema":{"type":"integer"},"description":"Customer ID. Must match the `tenantId` claim in the JWT token.\nUsed for authorization — the customer must be registered for ComboBuilder access.\n"}],"description":"Returns the list of LSports markets supported by ComboBuilder for the requested\nsport, together with the source markets that should be provided in the pricing\nrequest to price each market with full calibration.\n\nSupported sports:\n  * Football (`sportId: 6046`)\n  * Basketball (`sportId: 48242`)\n  * Baseball (`sportId: 154914`)\n\n`dependedMarketIds` lists the **other** markets that should be present in the\n`markets` payload of the `pricelsports` request alongside the requested\nmarket.\n\n### Football (sportId 6046)\n\nMarkets are grouped into the following dependency buckets, mirroring\nthe LSports ComboBuilder dependency contract:\n\n  * **Group A — Goal-based / full-match** markets (1X2, Double Chance, HT/FT,\n    Correct Score, Both Teams To Score, totals, team totals, etc.) depend on\n    `European Handicap (13)`, `1X2 (1)`, `Under/Over (2)`, `Asian Handicap (3)`.\n  * **Group B — Half-period** markets (1st Period Winner, 2nd Period Winner,\n    U/O 1st/2nd Period, Correct Score 1st/2nd Period, halftime DC, etc.)\n    depend on `European Handicap (13)`, `1X2 (1)`, `Under/Over 1st Period (21)`,\n    `Asian Handicap (3)`, `1st Period Winner (41)`, `Under/Over (2)`.\n  * **Group C — Corners** markets depend on\n    `Team With Most Corners (259)`, `Total Corners (11)`.\n  * **Group D — Cards** market `Under/Over Cards (214)` is self-contained and\n    returns `dependedMarketIds: null`. `Will A Red Card Be Shown? (82)`\n    depends on `Under/Over Cards (214)`.\n  * **Group F — Player** markets depend on `Player To Score In Anytime (711)`.\n    `Player To Score In Anytime` itself returns `null`. Per-player odds\n    (`asianPlayerTotals`) are passed via the corresponding\n    `players[].sourceMarkets` block, not via `markets`.\n\n### Basketball (sportId 48242)\n\nMarkets fall into the following groups, mirroring the LSports ComboBuilder\ndependency contract for basketball:\n\n  * **Halftime-derived (H1)** markets (1st/2nd Period Winner, U/O 1st/2nd Period —\n    Home/Away Team, 12 Halftime, 1st/2nd Period Odd/Even, 1st/2nd Period\n    Odd/Even — Home/Away Team) depend on `1X2 Halftime (282)`. The engine\n    consumes 282's odds to calibrate the halftime home/away points split.\n    `282` itself returns `dependedMarketIds: null` because it is the\n    source for this group.\n  * **2nd-Half-derived (H2)** markets (3rd/4th Period Winner, 3rd/4th Period\n    Odd/Even, U/O 3rd/4th Period — Home/Away Team, 12 2nd Half, U/O 2nd\n    Half markets including incl-OT variants) depend on both\n    `Asian Handicap 2nd Half (283)` and `1X2 2nd Half (284)`.\n    The engine consumes the joint (ML, spread) signal via\n    `compute_basketball_h2_means` to calibrate the Q3+Q4 home/away\n    points split — the AH line sharpens the H2 sigma_diff vs ML alone.\n    `283` and `284` themselves return `dependedMarketIds: null`.\n  * **Odd/Even (5)** depends on `Under/Over (2)` — the engine reads the\n    implied total mean from market 2 to price 5.\n  * **Double Chance (7)** depends on `1X2 (1)` — Double Chance is\n    analytically derivable from 1X2 outcome probabilities.\n  * **HT/FT (4)** depends on both `1X2 (1)` and `1X2 Halftime (282)`.\n  * **To Win Both Halves (84)** depends on `1X2 Halftime (282)`,\n    `Asian Handicap 2nd Half (283)` and `1X2 2nd Half (284)` since\n    the outcome is the joint event of winning both halves and the\n    engine consumes all three sources to calibrate per-half lambdas.\n  * **OT-related** markets (`Will The Game Go To Overtime? (69)`,\n    `12 Including Overtime (226)`) depend on `1X2 (1)` since the engine\n    extends the full-game ML simulation into overtime.\n  * **Full-game team totals** (`U/O - Home Team (101)`, `U/O - Away Team (102)`)\n    depend on `Under/Over (2)` since the engine extracts home/away expected\n    points from the game total.\n  * **Including-OT team totals** (`U/O Home incl. OT (221)`, `U/O Away incl. OT (220)`)\n    depend on their regulation counterparts (101, 102 respectively).\n  * Full-game source markets (`1X2 (1)`, `Under/Over (2)`, `Asian Handicap (3)`)\n    and the H1/H2 source anchors (`282`, `283`, `284`) themselves return\n    `dependedMarketIds: null`.\n\n### Baseball (sportId 154914)\n\nBaseball markets are grouped into eight dependency buckets, mirroring\nthe LSports ComboBuilder dependency contract:\n\n  * **Group A — Full-game core** sources (every full-game market depends on\n    these): `1X2 (1)`, `Over/Under Total Points (2)`, `Both Teams to Score (17)`,\n    `Money Line incl. Overtime (226)`. Markets in this group (Correct Score,\n    Total Odd/Even, Highest Scoring Inning, Match to go to Overtime,\n    First/Last Team to Score, combo markets, …) only return Group A as\n    their dependency list.\n  * **Group A′ — Half-Time/Full-Time** (`HT/FT (4)`, `HT/FT (incl. overtime) (390)`)\n    additionally depends on `First-Half Result (Team based) (282)` since the\n    engine consumes the halftime moneyline to calibrate the F5 home/away\n    lambdas that drive the HT outcome.\n  * **Group B — Run line / Handicap** (`Handicap incl. OT (3, 342)`)\n    additionally depends on `Handicap (incl. Overtime) (3)`.\n  * **Group C — Team-specific** (Home/Away O/U Team Total, team Odd/Even,\n    Race to X Runs) additionally depends on `Over/Under Home Total Points (101)`\n    and `Over/Under Away Total Points (102)`. `Under/Over - Home Team Including Overtime (221)`\n    and `Under/Over - Away Team Including Overtime (220)` additionally cross-reference each\n    other so a bet on either side carries both team totals in the payload.\n  * **Group D — First-3 innings** (`First 3 Innings Winner (1561)`,\n    `3 Full Innings Total (1562)`) additionally depends on the F3 sources\n    `1561, 1562`.\n  * **Group E — First-5 innings / First-half** (`5 Full Innings Winner (235)`,\n    `5 Full Innings Total (236)`, `5 Full Innings Run Line (281)`,\n    `5 Full Innings Winner (Draw No Bet) (1618)`, `First-Half Result (Team based) (282)`,\n    `Asian Handicap Half-Time Betting (53)`) additionally depends on the\n    F5 sources `53, 235, 236, 281, 282` — the engine consumes both the\n    5-full-innings markets and the halftime ML/AH to calibrate per-inning\n    F5 lambdas via `compute_baseball_halftime_lambdas`.\n  * **Group F — First-7 innings** (`First 7 Innings Winner (524)`,\n    `7 Full Innings Total (525)`, `7 Full Innings Handicap (526)`)\n    additionally depends on the F7 sources `524, 525, 526`.\n  * **Group G — Per-inning** (every winner / total / handicap / team total /\n    odd-even market scoped to a specific inning) additionally depends on\n    that inning's own marketIds (e.g. inning 4 → `47, 44, 205, 67`).\n  * **Group H — Player props** (`Player Total Runs Over/Under (1624)`,\n    `Player Total Home Runs Over/Under (1626)`, `Player Total Earned Runs Over/Under (1635)`,\n    `Player Total Hits Allowed Over/Under (1636)`, `Player Total Strikeouts Over/Under (1637)`)\n    additionally depends on the player prop's own marketId.\n\nA market is never listed as its own dependency. `dependedMarketIds: null`\nmeans the market either has no source-market dependencies in the LSports\ncontract, or it is itself the sole source of its group (e.g. `Under/Over\nCards`, `Player To Score In Anytime`, `First-Half Result (Team based)`).\n\n**`null` semantics**\n\n`dependedMarketIds: null` is the contract for \"no source markets needed\nfor this market id\" and is **semantically equivalent to an empty list\n`[]`**. Clients should treat both shapes identically; the API\ndeliberately uses `null` to make the absence explicit (rather than an\nempty array, which can be ambiguous on some deserialisers). This is\nconsistent across all supported sports (Football, Basketball, Baseball).\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketsRequest"}}}},"responses":{"200":{"description":"List of supported markets with dependencies","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketsResponse"}}}},"401":{"description":"Unauthorized — missing or invalid JWT Bearer token"},"403":{"description":"Forbidden — the customer is not authorized for ComboBuilder.\nReturned when the `customerId` header is missing/invalid or the customer\ndoes not have ComboBuilder access.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}}}}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.lsports.eu/u/trade/combo-builder.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
