On the wire · 16:01:41 UTC Live 126 · Prematch 8,738 · Markets 36,256 Vol. I · No. 1 · Monday 9 November 2026 wss://pinnfeed.io/v1/stream
PinnFeed
Guide · Google Sheets · Apps Script

Les cotes Pinnacle dans Google Sheets

Mis à jour le · PinnFeed · 6 min de lecture

Ce guide écrit les cotes 1N2 de football de Pinnacle dans une feuille Google Sheets : une ligne par match, avec les cotes décimales, les cotes justes sans marge et la marge du marché. Un déclencheur horaire met l'onglet à jour toutes les 15 minutes. Le script utilise l'API REST de PinnFeed : il fonctionne donc sur le plan Free (0 €, 30 secondes de retard, 1 000 requêtes/jour).

Étape 1 — Obtenez une clé Free#

  1. Créez un compte sur pinnfeed.io et ouvrez le tableau de bord.
  2. Créez une clé et copiez-la. Les clés ont la forme ps_live_….
  3. En Free, choisissez jusqu'à deux sports dans le tableau de bord. Le script utilise le football (soccer) par défaut ; modifiez SPORT si vous en avez choisi un autre.

Builder n'est pas nécessaire pour Sheets. Builder (99 €/mois, le plan WebSocket) sert aux clients push en temps réel comme ceux du guide Python et Node.

Étape 2 — Créez la feuille de calcul#

  1. Créez une nouvelle feuille Google Sheets.
  2. Renommez le premier onglet Odds (nom exact ; c'est ce que le script recherche).
  3. Ouvrez Extensions → Apps Script. Supprimez la fonction d'exemple myFunction et laissez le projet vide pour l'étape suivante.

Étape 3 — Collez le script et définissez les propriétés#

Collez ceci dans Code.gs :

// Google Apps Script : Extensions → Apps Script, collez ce fichier.
// Propriétés du script (Paramètres du projet → Propriétés du script) :
//   PINNFEED_BASE = https://pinnfeed.io
//   PINNFEED_KEY  = ps_live_...
// Ajoutez un onglet nommé "Odds", exécutez refreshOdds une fois, puis ajoutez un déclencheur toutes les 15 minutes.

const PROPS = PropertiesService.getScriptProperties();
const BASE = PROPS.getProperty('PINNFEED_BASE') || 'https://pinnfeed.io';
const KEY = PROPS.getProperty('PINNFEED_KEY');
const SPORT = 'soccer'; // remplacez par basketball, tennis, … (doit faire partie de votre plan)

function refreshOdds() {
  if (!KEY) {
    console.error('Set script property PINNFEED_KEY first');
    return;
  }
  const url = BASE + '/v1/odds'
    + '?sport=' + encodeURIComponent(SPORT)
    + '&market=moneyline&main=true&live=false&limit=500';
  const res = UrlFetchApp.fetch(url, {
    headers: { 'x-api-key': KEY },
    muteHttpExceptions: true,
  });
  const code = res.getResponseCode();
  if (code !== 200) {
    console.warn('PinnFeed HTTP ' + code + ': ' + res.getContentText().slice(0, 300));
    return; // en cas d'échec, l'onglet reste tel quel
  }
  const data = JSON.parse(res.getContentText());
  const rows = [];
  for (const ev of data.events || []) {
    const ml = (ev.markets || []).find((m) => m.type === 'moneyline' && m.main);
    if (!ml) continue;
    const byName = {};
    for (const o of ml.outcomes || []) byName[o.name] = o;
    const home = byName.home || {};
    const draw = byName.draw || {};
    const away = byName.away || {};
    rows.push([
      ev.startTime ? new Date(ev.startTime) : '',
      (ev.league && ev.league.name) || '',
      ev.home || '',
      ev.away || '',
      home.decimal || '',
      draw.decimal || '',
      away.decimal || '',
      home.fair || '',
      draw.fair || '',
      away.fair || '',
      ml.margin != null ? ml.margin : '',
      ev.id,
    ]);
  }
  const sheet = SpreadsheetApp.getActive().getSheetByName('Odds');
  if (!sheet) {
    console.error('Create a tab named Odds first');
    return;
  }
  sheet.clearContents();
  sheet.appendRow([
    'Starts', 'League', 'Home', 'Away',
    '1', 'X', '2',
    'Fair 1', 'Fair X', 'Fair 2',
    'Margin', 'Event id',
  ]);
  if (rows.length) {
    sheet.getRange(2, 1, rows.length, 12).setValues(rows);
  }
  console.log('Wrote ' + rows.length + ' moneyline rows for ' + SPORT);
}

Ouvrez ensuite la roue dentée du projet (Paramètres du projet) et, dans Propriétés du script, ajoutez :

PropriétéValeur
PINNFEED_KEYvotre clé (ps_live_…)
PINNFEED_BASEhttps://pinnfeed.io (facultatif ; valeur par défaut)

Ne collez jamais la clé dans les cellules de la feuille et ne partagez pas publiquement le projet Apps Script.

Étape 4 — Lancez-le une fois et autorisez-le#

  1. Choisissez refreshOdds dans la liste des fonctions et cliquez sur Exécuter.
  2. Google vous demande l'autorisation de vous connecter à un service externe et de modifier la feuille. Acceptez pour votre compte.
  3. Rechargez la feuille. L'onglet Odds doit afficher les colonnes Starts, League, Home, Away, 1, X, 2, les trois cotes justes, Margin et Event id.

Si un appel échoue (mauvaise clé, limite de requêtes, sport hors de votre plan), le script enregistre un avertissement et laisse les lignes précédentes intactes : une mauvaise minute ne vide jamais le tableau.

Étape 5 — Ajoutez un déclencheur toutes les 15 minutes#

  1. Dans Apps Script, ouvrez Déclencheurs (icône de réveil) → Ajouter un déclencheur.
  2. Fonction : refreshOdds. Source de l'événement : Déclencheur horaire. Type : Minuteur. Intervalle : Toutes les 15 minutes.
  3. Enregistrez.

Cela fait 96 appels par jour pour un sport, bien en dessous des 1 000 requêtes/jour et 1 req/s du plan Free. Deux sports toutes les 30 minutes font aussi 96 appels. Voir plans et limites (en anglais).

DéclencheurAppels / jourCompatible Free ?
Toutes les 15 min, 1 sport96oui
Toutes les 30 min, 2 sports96oui
Toutes les 15 min, 2 sports192oui
Toutes les minutes, 1 sport1 440non — nécessite Hobby ou supérieur (sans quota journalier)

Apps Script a aussi ses propres quotas ; le déclencheur horaire le plus court est d'une minute.

Étape 6 — Lisez les cotes justes et les marges#

Chaque ligne 1N2 contient les champs sans marge de PinnFeed décrits dans le schéma :

  • Fair 1 / Fair X / Fair 2 — la cote décimale fair de chaque issue (marge retirée, méthode multiplicative).
  • Margin — la margin du marché (surround = somme des probabilités implicites − 1).

Utilisez ces colonnes pour comparer une cote d'un bookmaker soft dans un autre onglet : l'espérance vaut soft × (1 / fair) − 1, le même calcul que dans le guide du value bet. Pour les mouvements de steam en direct, Sheets n'est pas le bon outil : utilisez le WebSocket de Builder et le guide de détection du steam.

Questions fréquentes#

Quel plan PinnFeed me faut-il ?#

Free suffit pour un tableau différé mis à jour toutes les quelques minutes. Hobby (29 €/mois) supprime le quota journalier et les 30 secondes de retard, mais reste uniquement REST. Le push en temps réel nécessite Builder (99 €/mois).

Pourquoi le script utilise-t-il x-api-key plutôt qu'un paramètre d'URL ?#

C'est l'en-tête d'authentification recommandé dans la documentation. UrlFetchApp d'Apps Script peut envoyer des en-têtes : aucune raison de mettre la clé dans l'URL (où elle peut finir dans des logs).

Puis-je tracer l'historique des prix ?#

Oui. Gardez l'onglet Odds comme tableau en direct (il est effacé et réécrit à chaque exécution). Ajoutez un second onglet qui ne fait qu'ajouter des lignes après chaque mise à jour, et insérez un graphique en courbes. Ne videz pas l'onglet d'historique.

Ce contenu pédagogique est-il réservé aux adultes ?#

Oui. Les données de cotes et les outils de tableur sont du contenu pédagogique destiné aux plus de 18 ans. Rien ici n'est un pronostic, un pari sûr ni une promesse de gain.

Voir aussi#

Le plan WebSocket : Builder, 99 €/mois.

Les cotes Pinnacle en temps réel sur un seul WebSocket : les 13 sports, tous les marchés, cotes justes sans marge et cotes de clôture. 3 jours gratuits, résiliable en un clic.

Form K-1 · Free API key

Get your free API key.

No password. We email you a link; click it and your key is on screen.

One free key per email. Link valid for 20 minutes.