Download OpenAPI specification:
Live events, full market depth, and the latest bindable prices.
The Pinnacle API gives you real-time sports betting markets: live events, full market depth, and the latest bindable prices — served over clean, typed JSON and grouped into a small, predictable set of endpoints.
The surface mirrors the well-known Pinnacle line API, so if you have integrated against it before the request and response shapes will feel familiar:
/v4/odds)./v3/fixtures)./v2/inrunning)./v1/client/balance).The odds and fixtures endpoints use a long-poll delta model. Each response
carries a last version cursor; pass it back as ?since=<last> on the next call
and you receive only what has changed. When nothing has advanced, the list comes
back empty — that is the idle response, not an error.
Every request must be authenticated with HTTP Basic credentials — the
username and password issued to you by pinc000. Send them on every call using the
standard Authorization: Basic <base64(username:password)> header; most HTTP
clients do this for you when you supply a username and password.
Requests without valid credentials receive 401 Unauthorized. In the
interactive docs, click Authorize and enter your credentials to try the
endpoints directly from this page.
If you need credentials, or believe yours have been compromised, contact pinc000 to have them issued or rotated.
Live odds for a sport, OddsResponse (Odds_Straight_V4)-shaped.
The core endpoint: reads the warm OddsBook and projects each event's periods
into spreads/totals/moneyline. last is the book's per-sport version cursor —
poll with ?since=last for the long-poll delta model (empty leagues while
nothing has changed). Prices are decimal; oddsFormat=American converts.
| sportId required | integer (Sportid) |
| oddsFormat | string (OddsFormat) Default: "Decimal" Enum: "American" "Decimal" "HongKong" "Indonesian" "Malay"
|
Since (integer) or Since (null) (Since) | |
Islive (integer) or Islive (null) (Islive) | |
Array of Eventids (strings) or Eventids (null) (Eventids) |
{- "sportId": 0,
- "last": 0,
- "leagues": [
- {
- "id": 0,
- "events": [
- {
- "id": 0,
- "homeScore": 0,
- "awayScore": 0,
- "periods": [
- {
- "lineId": 0,
- "number": 0,
- "cutoff": "string",
- "status": 1,
- "spreads": [
- {
- "altLineId": 0,
- "hdp": 0,
- "home": 0,
- "away": 0
}
], - "moneyline": {
- "home": 0,
- "away": 0,
- "draw": 0
}, - "totals": [
- {
- "altLineId": 0,
- "points": 0,
- "over": 0,
- "under": 0
}
]
}
]
}
]
}
]
}The current price + line id for one selection, GetLineResponse-shaped.
Resolves the market coordinate against the warm book, then quotes it via the
bet-slip path — so the returned lineId/altLineId and price are exactly
what POST /v4/bets/straight will bind to (the freshest bindable price, ahead
of the streamed feed). status is NOT_EXISTS when the line is not on offer.
| sportId required | integer (Sportid) |
| eventId required | integer (Eventid) |
| betType required | string (BetType) Enum: "MONEYLINE" "SPREAD" "TOTAL_POINTS" "TEAM_TOTAL_POINTS"
|
| periodNumber | integer (Periodnumber) Default: 0 |
TeamSide (string) or Team (null) (Team) | |
OverUnder (string) or Side (null) (Side) | |
Handicap (number) or Handicap (null) (Handicap) | |
| oddsFormat | string (OddsFormat) Default: "Decimal" Enum: "American" "Decimal" "HongKong" "Indonesian" "Malay"
|
{- "status": "string",
- "price": 0,
- "lineId": 0,
- "altLineId": 0,
- "minRiskStake": 0,
- "maxRiskStake": 0,
- "minWinStake": 0,
- "maxWinStake": 0,
- "maxPayout": 0,
- "effectiveAsOf": "string"
}Events (leagues + fixtures) for a sport, FixturesResponse-shaped.
Reads the same warm book as /sports/{sport}/events; the first call for a
cold sport warms it and may return few/no events until it fills. last is the
book's live version cursor — poll again with ?since=last; when nothing has
advanced the league list comes back empty (the long-poll idle response).
| sportId required | integer (Sportid) |
Since (integer) or Since (null) (Since) | |
Islive (integer) or Islive (null) (Islive) | |
Array of Eventids (strings) or Eventids (null) (Eventids) |
{- "sportId": 0,
- "last": 0,
- "league": [
- {
- "id": 0,
- "name": "string",
- "events": [
- {
- "id": 0,
- "parentId": 0,
- "starts": "string",
- "home": "string",
- "away": "string",
- "rotNum": "string",
- "liveStatus": 0,
- "status": "O"
}
]
}
]
}Leagues currently on offer for a sport, LeaguesResponse-shaped.
Derived from the same warm book as /v3/fixtures: every league carrying at
least one event in the feed, with its live event count. Warms a cold sport on
the first call (few/no leagues until it fills).
| sportId required | integer (Sportid) |
{- "sportId": 0,
- "leagues": [
- {
- "id": 0,
- "name": "string",
- "eventCount": 0,
- "hasOfferings": true
}
]
}The betting periods a sport currently offers, PeriodsResponse-shaped.
Derived from the distinct period numbers present in the warm book (0=Match, 1=1st half, …) with best-effort descriptions. Not the full provider period dictionary — only the periods actually on offer right now.
| sportId required | integer (Sportid) |
{- "sportId": 0,
- "periods": [
- {
- "number": 0,
- "description": "string"
}
]
}Live game states across the sports whose feeds are already warm,
InRunningResponse-shaped. Reports only started sports — it never opens a new
feed — so it is a cheap read over whatever /v4/odds//sports already warmed.
state/elapsed are derived best-effort from the live period label + clock.
{- "sports": [
- {
- "id": 0,
- "leagues": [
- {
- "id": 0,
- "events": [
- {
- "id": 0,
- "state": 0,
- "elapsed": 0
}
]
}
]
}
]
}Current funded-account balance, ClientBalanceResponse-shaped.
availableBalance / currency come straight from the Pinnacle account-balance
call; outstandingTransactions / givenCredit are surfaced only when the
provider payload carries them.
{- "availableBalance": 0,
- "outstandingTransactions": 0,
- "givenCredit": 0,
- "currency": "string"
}Alias of /v1/client/balance at the v2 path — identical payload, for
clients pinned to the newer version string.
{- "availableBalance": 0,
- "outstandingTransactions": 0,
- "givenCredit": 0,
- "currency": "string"
}Browse sports and their live events, expand the full market set for one event, and price a single selection.
Return the latest feed for a sport: every event currently on, each with its main markets (moneyline, handicap, totals).
| sport required | integer (Sport) Enum: 29 3 33 4 19 12 |
[- {
- "id": 0,
- "sport_id": 0,
- "sport_name": "string",
- "league_id": 0,
- "league_name": "string",
- "home": "string",
- "away": "string",
- "starts_ms": 0,
- "live": true,
- "score_home": 0,
- "score_away": 0,
- "period_label": "string",
- "clock": "string",
- "periods": [
- {
- "number": 0,
- "spreads": [
- {
- "hdp": 0,
- "home": 0,
- "away": 0,
- "line_id": 0,
- "main": true
}
], - "totals": [
- {
- "points": 0,
- "over": 0,
- "under": 0,
- "line_id": 0,
- "main": true
}
], - "moneyline": {
- "home": 0,
- "draw": 0,
- "away": 0,
- "line_id": 0
}
}
]
}
]Return every market for one event: all alternate handicap and total lines, team totals, the corners and bookings markets, and the specials (correct score, both teams to score, goalscorer, half-time/full-time, …). Depth is fetched on demand, so the first request for a new event may take a moment.
| event_id required | integer (Event Id) |
{- "event_id": 0,
- "goals": {
- "id": 0,
- "sport_id": 0,
- "home": "string",
- "away": "string",
- "category": "string",
- "periods": [
- {
- "number": 0,
- "moneyline": {
- "home": 0,
- "draw": 0,
- "away": 0,
- "line_id": 0
}, - "handicaps": [
- {
- "hdp": 0,
- "home": 0,
- "away": 0,
- "line_id": 0,
- "main": true
}
], - "totals": [
- {
- "points": 0,
- "over": 0,
- "under": 0,
- "line_id": 0,
- "main": true
}
], - "team_totals_home": [
- {
- "points": 0,
- "over": 0,
- "under": 0,
- "line_id": 0,
- "main": true
}
], - "team_totals_away": [
- {
- "points": 0,
- "over": 0,
- "under": 0,
- "line_id": 0,
- "main": true
}
], - "specials": [
- {
- "selection_id": 0,
- "name": "string",
- "category": "string",
- "bet_type": "string",
- "period": 0,
- "max_stake": 0,
- "selections": [
- {
- "id": 0,
- "line_id": 0,
- "name": "string",
- "price": 0,
- "handicap": 0
}
]
}
]
}
]
}, - "corners": {
- "id": 0,
- "sport_id": 0,
- "home": "string",
- "away": "string",
- "category": "string",
- "periods": [
- {
- "number": 0,
- "moneyline": {
- "home": 0,
- "draw": 0,
- "away": 0,
- "line_id": 0
}, - "handicaps": [
- {
- "hdp": 0,
- "home": 0,
- "away": 0,
- "line_id": 0,
- "main": true
}
], - "totals": [
- {
- "points": 0,
- "over": 0,
- "under": 0,
- "line_id": 0,
- "main": true
}
], - "team_totals_home": [
- {
- "points": 0,
- "over": 0,
- "under": 0,
- "line_id": 0,
- "main": true
}
], - "team_totals_away": [
- {
- "points": 0,
- "over": 0,
- "under": 0,
- "line_id": 0,
- "main": true
}
], - "specials": [
- {
- "selection_id": 0,
- "name": "string",
- "category": "string",
- "bet_type": "string",
- "period": 0,
- "max_stake": 0,
- "selections": [
- {
- "id": 0,
- "line_id": 0,
- "name": "string",
- "price": 0,
- "handicap": 0
}
]
}
]
}
]
}, - "bookings": {
- "id": 0,
- "sport_id": 0,
- "home": "string",
- "away": "string",
- "category": "string",
- "periods": [
- {
- "number": 0,
- "moneyline": {
- "home": 0,
- "draw": 0,
- "away": 0,
- "line_id": 0
}, - "handicaps": [
- {
- "hdp": 0,
- "home": 0,
- "away": 0,
- "line_id": 0,
- "main": true
}
], - "totals": [
- {
- "points": 0,
- "over": 0,
- "under": 0,
- "line_id": 0,
- "main": true
}
], - "team_totals_home": [
- {
- "points": 0,
- "over": 0,
- "under": 0,
- "line_id": 0,
- "main": true
}
], - "team_totals_away": [
- {
- "points": 0,
- "over": 0,
- "under": 0,
- "line_id": 0,
- "main": true
}
], - "specials": [
- {
- "selection_id": 0,
- "name": "string",
- "category": "string",
- "bet_type": "string",
- "period": 0,
- "max_stake": 0,
- "selections": [
- {
- "id": 0,
- "line_id": 0,
- "name": "string",
- "price": 0,
- "handicap": 0
}
]
}
]
}
]
}
}The latest bindable price for one selection.
Pick a market from the events or more-bets structure and send the selection (market, side, line and line id). The returned price is the freshest one — slightly ahead of the streamed feed — with stake limits and a status.
| event_id required | integer (Event Id) |
| market required | string (Market) Value: "moneyline" |
| period | integer (Period) Default: 0 |
| side required | string (Side) Enum: "home" "away" "draw" |
| line_id required | integer (Line Id) |
{- "market": "moneyline",
- "period": 0,
- "side": "home",
- "line_id": 0
}{- "status": "",
- "odds": 0,
- "lineId": 0,
- "altLineId": 0,
- "minStake": 0,
- "maxStake": 0,
- "maxStakeWin": 0,
- "maxPayout": 0,
- "originalOdds": 0,
- "lastOdds": 0,
- "betType": 0,
- "betTypeDisp": "string",
- "periodNum": 0,
- "handicap": 0,
- "eventId": 0,
- "homeTeam": "string",
- "awayTeam": "string",
- "selection": "string",
- "contestantName": "string",
- "eventName": "string",
- "category": "string",
- "inplay": true
}Place a single straight bet, PlaceStraightBetRequest/...ResponseV4-shaped.
Builds the selection from the body, RE-PRICES it via the bet-slip path (the
authoritative bindable price, ahead of the feed), then places it through the
provider buy. A stale/closed line comes back as PROCESSED_WITH_ERROR without
a placement attempt.
SAFETY: a real call spends money and debits the funded account. Pass
?dryRun=true to run the FULL build-and-price path and return what would be
sent WITHOUT placing a wager — the way to smoke-test this endpoint. A live
placement needs owner sign-off and a funded account.
| dryRun | boolean (Dryrun) Default: false |
| oddsFormat | string (OddsFormat) Default: "Decimal" Enum: "American" "Decimal" "HongKong" "Indonesian" "Malay"
|
Uniquerequestid (string) or Uniquerequestid (null) (Uniquerequestid) | |
| acceptBetterLine | boolean (Acceptbetterline) Default: true |
| stake required | number (Stake) |
| winRiskStake | string (WinRiskType) Default: "RISK" Enum: "WIN" "RISK" Whether |
| lineId required | integer (Lineid) |
Altlineid (integer) or Altlineid (null) (Altlineid) | |
FillType (string) or null | |
| sportId required | integer (Sportid) |
| eventId required | integer (Eventid) |
| periodNumber | integer (Periodnumber) Default: 0 |
| betType required | string (BetType) Enum: "MONEYLINE" "SPREAD" "TOTAL_POINTS" "TEAM_TOTAL_POINTS"
|
TeamSide (string) or null | |
OverUnder (string) or null | |
Handicap (number) or Handicap (null) (Handicap) |
{- "oddsFormat": "American",
- "uniqueRequestId": "string",
- "acceptBetterLine": true,
- "stake": 0,
- "winRiskStake": "WIN",
- "lineId": 0,
- "altLineId": 0,
- "fillType": "NORMAL",
- "sportId": 0,
- "eventId": 0,
- "periodNumber": 0,
- "betType": "MONEYLINE",
- "team": "TEAM1",
- "side": "OVER",
- "handicap": 0
}{- "status": "string",
- "errorCode": "string",
- "uniqueRequestId": "string",
- "betId": 0,
- "betStatus": "string",
- "betterLineWasAccepted": true,
- "price": 0,
- "dryRun": true
}The account's placed bets, GetBetsResponse-shaped, from the provider
my-bets. Field mapping is best-effort (unknown provider keys are preserved
on each entry rather than dropped).
{- "straightBets": [
- {
- "betId": 0,
- "wagerNumber": 0,
- "betStatus": "string",
- "betType": "string",
- "sportId": 0,
- "leagueId": 0,
- "eventId": 0,
- "placedAt": "string",
- "periodNumber": 0,
- "team1": "string",
- "team2": "string",
- "stake": 0,
- "win": 0,
- "risk": 0,
- "price": 0
}
]
}Alias of /v4/bets at the v1 path — identical payload.
{- "straightBets": [
- {
- "betId": 0,
- "wagerNumber": 0,
- "betStatus": "string",
- "betType": "string",
- "sportId": 0,
- "leagueId": 0,
- "eventId": 0,
- "placedAt": "string",
- "periodNumber": 0,
- "team1": "string",
- "team2": "string",
- "stake": 0,
- "win": 0,
- "risk": 0,
- "price": 0
}
]
}