Skip to main content
Two endpoints turn a list of oddsIds into a multi-leg price: Both take the same oddsIds parameter and return the same fixture view you already know — they only add a section. For the workflow around these endpoints — choosing between them, keeping a live slip priced, degrading when a leg suspends — see Building a betslip.

Selecting legs

A leg is identified by its oddsId:
which is exactly the key you already get back from /fixtures/odds. Pass them comma- or space-separated:
  • Duplicates are removed and the list sorted, so the same selection always produces the same request.
  • Max 20 legs per request.
  • Legs are grouped by bookmaker — request the same selections at several books to price them side by side.
parlayId, the key inside the parlay / sgp section, is that sorted list joined by ,. It is built the same way on both endpoints, so a /parlay and an /sgp entry for the same selections are directly comparable.

What comes back

Both endpoints return a normal fixture view, with one section added. An empty parlay / sgp section is normal: see suspended vs missing legs. /fixtures/odds/parlay returns an array — one object per fixture a leg belongs to, ordered by fixtureId. /fixtures/odds/sgp returns a single object, because all its legs share one fixture.

Parlay: priced locally

The added section, for two legs at 3.8 and 2.1:
price is 3.8 × 2.1, and singlesPrice equals it while the parlay is active. A cross-fixture parlay comes back on every involved fixture with the same entry, so read it off whichever one you were already looking at.

SGP: priced by the bookmaker

All legs must belong to one fixture. Requesting legs from two fixtures is a 400:
The sgp section carries the bookmaker’s own quote:
The correlation margin. singlesPrice (7.98) is what the naive product would pay; price (6.5) is what the bookmaker actually offers once it accounts for the legs being correlated. The gap between the two is the margin the book charges for the correlation — the number most clients are after.
SGP-only fields:
  • limit — max stake at this price. Optional; absent means no stated cap, not zero.
  • bookmakerParlayId — the book’s own id for the parlay.
  • bookmakerChangedAt — the book’s quote timestamp (epoch ms). Optional; falls back to changedAt.
  • betslip — deep link that opens the wager with every leg pre-loaded.
  • meta.offers — exchanges only: the price-ladder rungs below the best one, as [{ price, limit }, ...].

Suspended vs missing legs

This is the distinction to build against, and it is the same on both endpoints. A suspended leg still exists, so it comes back in odds with active: false and the parlay keeps an inactive entry carrying the reason:
price: 1 means stake back; singlesPrice still shows what it would have paid, so you can keep the selection on screen. A leg that cannot be found — unknown bookmaker, unknown or expired oddsId — gets that bookmaker no entry at all, and is named in missingOddsIds.
sgp: {} without missingOddsIds. On /fixtures/odds/sgp the bookmaker is also dropped when we hold every leg but the bookmaker’s own pricing service could not resolve the parlay — it does not know the fixture, it rate limited us, or it errored. Your legs are all present in odds, there is no missingOddsIds, and sgp is simply {}. Treat an empty sgp as “no correlated price available right now” rather than “your selection was wrong”, and fall back to /fixtures/odds/parlay for an uncorrelated price.

meta.inactiveReason values


Rate limits

Both sit in the odds bucket with the rest of the odds surface. See Rate Limits.

Errors

A leg you are not entitled to makes the whole request fail with 403 — it is not silently dropped, so filter selections against your key’s access before requesting a price. Both endpoints are opt-in per API key. If yours is not enabled you get 403 channel_not_allowed — contact us to have them added.