pinnacle odds api / google sheets / apps script
Pinnacle odds API in Google Sheets
loop[every 15 minutes, 96 calls a day]
GET/kit/v1/markets?event_type=prematch&sport_id=1
rows written to the Odds tab200 OK
A short Apps Script calls the Pinnacle odds API for the prematch soccer board and writes one row per match: kick-off, league, teams and the 1X2 prices. A time trigger reruns it every 15 minutes, which is 96 calls a day and fits inside a free key.
Create a free key$0 · 100 calls a day · no card
| Row | A | B | C | D | E | F | G |
|---|---|---|---|---|---|---|---|
| 1 | Starts | League | Home | Away | 1 | X | 2 |
| 2 | 4 May 16:30 | Italy - Serie A | Cremonese | Lazio | 2.45 | 3.30 | 2.90 |
| 3 | one row for every match on the prematch board | ||||||
The script
It reads your base URL and key from the script's properties, so neither sits in the code. It asks for event_type=prematch and sport_id=1, soccer, then flattens each event's full-match money line into columns E to G.
A failed call writes nothing and logs the response, so a bad minute never blanks the tab. Change SPORT_ID for another sport; the IDs are on the home page.
// Extensions > Apps Script, then paste.
const PROPS = PropertiesService
.getScriptProperties();
const BASE = PROPS.getProperty('BASE');
const KEY = PROPS.getProperty('KEY');
const SPORT_ID = 1; // 1 = soccer
function refreshOdds() {
const url = BASE + '/kit/v1/markets' +
'?event_type=prematch&sport_id=' +
SPORT_ID;
const res = UrlFetchApp.fetch(url, {
headers: { 'x-portal-apikey': KEY },
muteHttpExceptions: true,
});
if (res.getResponseCode() !== 200) {
console.warn(res.getContentText());
return;
}
const data = JSON.parse(
res.getContentText());
const rows = data.events.map((ev) => {
const p = ev.periods || {};
const ml = (p.num_0 || {})
.money_line || {};
return [new Date(ev.starts),
ev.league_name, ev.home, ev.away,
ml.home || '', ml.draw || '',
ml.away || ''];
});
const sheet = SpreadsheetApp
.getActive().getSheetByName('Odds');
sheet.clearContents();
sheet.appendRow(['Starts', 'League',
'Home', 'Away', '1', 'X', '2']);
if (rows.length) {
sheet.getRange(2, 1, rows.length, 7)
.setValues(rows);
}
}
Select the code to copy it.
set it up once
Five steps, then it runs by itself
- Add a tab named
Oddsto your spreadsheet. - Open Extensions, then Apps Script, and paste the script over the empty function.
- In Project Settings, add two script properties:
BASE, the API address from the docs, andKEY, your key. - Run
refreshOddsonce and allow the permissions Google asks for. - Under Triggers, add a time-driven trigger for
refreshOddson a 15-minute timer.
What a trigger costs against the daily limit.
| Trigger | Calls a day | Plan |
|---|---|---|
| Every 15 minutes, one sport | 96 | Free key |
| Every 30 minutes, two sports | 96 | Free key |
| Every 15 minutes, two sports | 192 | poll |
| Every minute, one sport | 1,440 | poll |
Apps Script's own quotas apply on top; the shortest time trigger is one minute.
NEXTrefreshOdds()
A key, a tab, a trigger
The free key covers a 15-minute sheet for one sport. If the sheet becomes a model that needs every sport every minute, poll's 10 calls a second is the next step; the pricing page has the numbers.