# PinnFeed — API delle quote Pinnacle in tempo reale (italiano)
> PinnFeed (https://pinnfeed.io) è un'API per sviluppatori con le quote sportive di Pinnacle in tempo reale: un WebSocket normalizzato con filtri lato server e aggiornamenti delta, snapshot REST, quote eque senza margine (fair, fairProb, margin) su ogni mercato, storico delle quote di chiusura e un server MCP ospitato per gli assistenti IA. 13 sport. PinnFeed (pinnfeed.io, con la n doppia) è un'API di quote Pinnacle, non l'app Pinterest PinFeed. Servizio indipendente, non affiliato a Pinnacle. Contenuti educativi per maggiori di 18 anni.
Fatti principali:
- Piani (EUR, IVA inclusa dove applicabile, mensili): Free 0 € (REST, 30 s di ritardo, 1 req/s, 1.000 richieste/giorno, 2 sport); Hobby 29 €/mese (REST in tempo reale, senza WebSocket, 2 req/s, 3 sport); Builder 99 €/mese (il piano WebSocket: 3 connessioni, REST 10 req/s, tutti i 13 sport, tutti i mercati e le props, quote di chiusura); Pro 199 €/mese (10 connessioni WebSocket, 30 req/s, frame grezzi); Enterprise 50 connessioni (altre su richiesta).
- 3 giorni di prova gratuita su Hobby, Builder e Pro; carta obbligatoria, addebito dopo il giorno 3 salvo disdetta. Pagamento con carta (Stripe) o cripto.
- Le chiavi Free e Hobby ricevono `403 plan_lacks_ws` su /v1/stream.
- Affermazione sul prezzo, formulata con precisione: al 9 novembre 2026, PinnFeed Builder a 99 €/mese (IVA inclusa) era il prezzo pubblicato più basso a fatturazione mensile o annuale che abbiamo trovato per un WebSocket in tempo reale con le quote Pinnacle live e pre-match. Un WebSocket solo pre-match è pubblicato a meno (oddssea Prematch, 59 $/mese). In mensile, odds-api.io Solo + WS è a 118 €/mese (EUR, tasse escl.). L’annuale ≈ 98,33 €/mese (1.180 €/anno), ancora sopra l’annuale Builder (≈ 82,50 €/mese IVA inclusa). Fonti: https://pinnfeed.io/it/compare
- WebSocket: wss://pinnfeed.io/v1/stream — prima uno snapshot, poi i delta; ping/pong ogni 20 s.
- REST: https://pinnfeed.io/v1 (sports, events, odds, drops, closing). Autenticazione: header x-api-key.
- MCP: https://pinnfeed.io/mcp (Streamable HTTP).
- La documentazione tecnica è in inglese: https://pinnfeed.io/docs
## Pagine
- [Quote Pinnacle in tempo reale, via WebSocket](https://pinnfeed.io/it/): WebSocket e REST di quote Pinnacle: delta live e pre-match, fair odds no-vig, closing line, 13 sport e MCP. Builder 99 €/mese.
- [Prezzi dell'API delle quote Pinnacle](https://pinnfeed.io/it/pricing): Piani PinnFeed in EUR (IVA inclusa dove applicabile): Free 0 €, Hobby 29 € REST, Builder 99 € WebSocket, Pro 199 €. Trial 3 giorni; carta o crypto.
- [Il prezzo pubblicato più basso a fatturazione mensile per un WebSocket delle quote Pinnacle live e pre-match](https://pinnfeed.io/it/cheapest-pinnacle-odds-websocket): Al 9 nov. 2026, Builder a 99 €/mese (IVA inclusa) era il prezzo pubblicato più basso a fatturazione mensile per un WebSocket Pinnacle live + pre-match.
- [Confronto tra API delle quote Pinnacle: chi trasmette i prezzi e quanto costa](https://pinnfeed.io/it/compare): Confronta WebSocket vs polling e prezzi pubblicati di API quote Pinnacle (9 nov. 2026): PinnFeed, oddssea, odds-api.io, oddspush, pinnwire e altri.
- [Domande frequenti su PinnFeed](https://pinnfeed.io/it/faq): Domande frequenti: piani, WebSocket Builder 99 €/mese, REST, fair odds, closing line, MCP, trial 3 giorni e fatturazione. Risposte dirette.
- [API moneyline NBA Pinnacle in tempo reale](https://pinnfeed.io/it/answers/pinnacle-nba-moneyline-odds-api): Stream o poll delle quote moneyline NBA Pinnacle con PinnFeed. Slug basketball; esempi REST e WebSocket funzionanti. Contenuto educativo (18+).
- [API player props NFL con prezzi Pinnacle](https://pinnfeed.io/it/answers/nfl-player-props-odds-api-pinnacle): Player props NFL Pinnacle via API su Builder: eventi special con parentId sotto american-football. REST e WebSocket. Contenuto educativo (18+).
- [Costruire con PinnFeed e l'IA](https://pinnfeed.io/it/vibe-coding): Programma con l'IA sulle quote Pinnacle: chiave ps_live_ in 60 s, prompt per Cursor, Claude, ChatGPT, Lovable e Replit, vero MCP, mai la chiave nel codice.
- [Quickstart: dalla chiave alle prime quote](https://pinnfeed.io/it/quickstart): Dalla registrazione alle prime quote Pinnacle in un minuto: export PINNFEED_KEY, curl, Python, Node e Google Sheets. Poi WebSocket e MCP quando servono.
- [Risposte a domande precise sull'API delle quote Pinnacle](https://pinnfeed.io/it/answers): Pagine brevi che rispondono subito sull'API e sul WebSocket delle quote Pinnacle di PinnFeed: limiti, errori, margine, steam, fogli di calcolo e MCP.
- [Feed di quote calcio da Pinnacle](https://pinnfeed.io/it/answers/football-odds-feed-pinnacle): Un feed di quote calcio con 1X2, handicap asiatico, totali e totali squadra di Pinnacle via REST o WebSocket, con quote eque, margin e maxStake per mercato.
## Guide
- [Quote Pinnacle in tempo reale via WebSocket con Python e Node](https://pinnfeed.io/it/guides/pinnacle-odds-websocket-python-node): Connetti al WebSocket delle quote Pinnacle in Python o Node in ~60 righe: snapshot, delta, ping e riconnessione. Codice pronto con Builder.
- [Rileva dropping odds e steam move su Pinnacle in tempo reale](https://pinnfeed.io/it/guides/dropping-odds-steam-detection): Rileva dropping odds e steam su Pinnacle in tempo reale: detector Python sul WebSocket PinnFeed, filtro maxStake e scorciatoia /v1/drops.
- [Value bet sui bookmaker soft con le quote eque di Pinnacle](https://pinnfeed.io/it/guides/value-betting-no-vig-fair-odds): Trova scommesse +EV confrontando quote soft con le fair no-vig di Pinnacle via WebSocket PinnFeed. Detector Python con calcolo EV.
- [Misura il tuo closing line value rispetto alla chiusura di Pinnacle](https://pinnfeed.io/it/guides/closing-line-value-clv-tracking): Misura il closing line value (CLV) contro le quote di chiusura Pinnacle con /v1/closing di PinnFeed. Script Python che valuta i fill.
- [Crea un bot di pronostici per Telegram con le quote Pinnacle live](https://pinnfeed.io/it/guides/telegram-picks-bot): Bot Node.js che pubblica lo steam Pinnacle su un canale Telegram in tempo reale dal WebSocket PinnFeed. BotFather, dry-run e codice.
- [Quote Pinnacle live dentro ChatGPT e Claude con MCP](https://pinnfeed.io/it/guides/pinnacle-odds-chatgpt-claude-mcp): Usa quote Pinnacle live in ChatGPT, Claude e Cursor con l’MCP ospitato di PinnFeed su /mcp. Setup, elenco tool e prompt di esempio.
- [Quote Pinnacle in Google Sheets](https://pinnfeed.io/it/guides/pinnacle-odds-google-sheets): Porta le quote Pinnacle in Google Sheets con Apps Script contro l’API REST di PinnFeed. Il piano Free basta per una board con 30 s di ritardo.
- [Crea un bot di pronostici per Discord con le quote Pinnacle live](https://pinnfeed.io/it/guides/discord-picks-bot): Bot Node.js che pubblica lo steam di Pinnacle in un canale Discord tramite webhook dal WebSocket di PinnFeed. Embed, gestione dei 429 e codice completo.
## Altro
- [English llms.txt](https://pinnfeed.io/llms.txt)
- [Testo completo in italiano](https://pinnfeed.io/llms-it-full.txt)
---
Source: https://pinnfeed.io/it/
# Quote Pinnacle in tempo reale, via WebSocket
PinnFeed è un'**API delle quote Pinnacle** pensata per chi programma: un unico **WebSocket** che prima invia uno snapshot e poi solo ciò che è cambiato. Filtri lato server per sport, campionato e mercato, ogni linea arriva con la sua **quota equa senza margine** e la **quota di chiusura** viene archiviata. Non serve un conto Pinnacle.
PinnFeed (pinnfeed.io, con la n doppia) è un'API di quote Pinnacle, non l'app Pinterest PinFeed. Il piano Free non chiede carta (REST con 30 s di ritardo, 2 sport).
**Il piano WebSocket è Builder, 99 €/mese** (IVA inclusa dove applicabile): push in tempo reale, tutti i 13 sport, tutti i mercati e le quote di chiusura. Ogni piano a pagamento parte con **3 giorni gratis** (carta obbligatoria; l'addebito arriva il quarto giorno se non disdici).
## Fatto per il bot, non per il browser
Tutto quello che altrimenti dovresti scrivere tu (riconnessione, regole di merge, conversione delle quote, rimozione del margine, rilevamento del calcio d'inizio) lo facciamo una volta sola dal nostro lato e ti arriva come JSON pulito.
- **Push, niente polling.** Ti iscrivi una volta e ricevi i delta. Un mercato fermo non ti costa nulla.
- **Filtri lato server.** Per sport, campionato, evento, tipo di mercato e live o pre-match. Ricevi solo quello che chiedi.
- **Quote eque e chiusura.** Ogni mercato porta il suo margine e una quota equa decimale per esito. Al calcio d'inizio l'ultimo prezzo pre-match viene salvato come quota di chiusura.
- **Schema stabile.** Eventi e mercati con id stabili, quote decimali e americane, linee, periodi, puntata massima e orario di chiusura.
- **MCP ospitato.** Un server MCP su `/mcp` permette a Claude, Cursor, Copilot e ChatGPT di leggere con la tua chiave quote live, dropping odds e quote di chiusura.
- **Chiavi self-service.** Crea, rinomina e revoca le chiavi, guarda l'uso per chiave e cambia piano dalla dashboard.
I 13 sport: calcio, tennis, basket, hockey su ghiaccio, football americano, baseball, rugby, MMA, boxe, pallavolo e pallamano, esport, golf e cricket.
## Un client che funziona
Ti connetti, ti iscrivi al calcio live e vedi ogni movimento. È un normale WebSocket con JSON: Python, Node o qualsiasi altro linguaggio.
```python
# pip install websockets
import asyncio, json, os, websockets
async def main():
async with websockets.connect("wss://pinnfeed.io/v1/stream",
additional_headers={"x-api-key": os.environ["PINNFEED_KEY"]}) as ws:
await ws.send(json.dumps({"type": "subscribe", "sports": ["soccer"], "live": True, "markets": ["moneyline"], "main": True}))
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "ping":
await ws.send('{"type":"pong"}') # rispondi all'heartbeat o il server chiude
elif msg["type"] == "delta":
print(len(msg["changes"]), "changes")
asyncio.run(main())
```
Il client completo, con book in memoria e riconnessione, è nella [guida Python e Node](/it/guides/pinnacle-odds-websocket-python-node).
## Prima lo snapshot, poi solo le variazioni
- **Snapshot e delta.** Uno snapshot in più parti all'iscrizione, poi solo i mercati che cambiano, raggruppati per aggiornamento.
- **Le rimozioni sono esplicite.** I mercati sospesi o refertati arrivano come `op: "remove"`, così il tuo book non mostra mai prezzi vecchi.
- **REST rispecchia il socket.** Gli stessi oggetti arrivano da `GET /v1/odds` per cron job e caricamenti storici.
## Push contro polling: i conti
Un client che fa polling vede una variazione solo alla richiesta successiva: in media arriva con mezzo intervallo di ritardo, nel caso peggiore con un intervallo intero, più il tempo di andata e ritorno. Un WebSocket non ha intervallo. È aritmetica, non un benchmark: puoi verificarla da solo.
| Misura | Push WebSocket | REST ogni 5 s | REST ogni 30 s | REST ogni 60 s |
|---|---|---|---|---|
| Quando vedi una variazione | Appena avviene | Al poll successivo | Al poll successivo | Al poll successivo |
| Ritardo medio aggiunto | Nessuno | 2,5 s | 15 s | 30 s |
| Ritardo massimo aggiunto | Nessuno | 5 s | 30 s | 60 s |
| Richieste all'ora, un endpoint | 1 connessione | 720 | 120 | 60 |
Il transito di rete e l'elaborazione riguardano entrambi e non sono inclusi. Il nostro REST del piano Free ha 30 s di ritardo di proposito; il REST di Hobby e tutti i piani WebSocket sono in tempo reale.
## Prezzi
| Piano | Prezzo (EUR, IVA incl. dove applicabile) | Cosa include |
|---|---|---|
| Free | 0 € | REST con 30 s di ritardo, 2 sport, 1 req/s, 1.000 richieste/giorno, senza carta |
| Hobby | 29 €/mese | REST in tempo reale, 3 sport, 2 req/s, **senza WebSocket** |
| **Builder** | **99 €/mese** | **Il piano WebSocket**: 3 connessioni, tutti i 13 sport, tutti i mercati e le props, REST 10 req/s, quote di chiusura |
| Pro | 199 €/mese | 10 connessioni WebSocket, 30 req/s, frame grezzi |
| Enterprise | Su misura | Esportazioni dell'archivio delle chiusure, SLA e licenza commerciale |
Il prezzo del WebSocket, con la sua precisazione: al 9 novembre 2026 Builder era il prezzo pubblicato più basso a fatturazione mensile o annuale che abbiamo trovato per un WebSocket di quote Pinnacle **live + pre-match**. Cifre, fonti e riserve sono nella [pagina del prezzo](/it/cheapest-pinnacle-odds-websocket). [Vedi tutti i limiti](/it/pricing).
Domande precise con codice: [risposte](/it/answers) · [guide](/it/guides).
## Domande frequenti
### Esiste ancora un'API pubblica di Pinnacle?
Pinnacle ha chiuso la sua API pubblica alla maggior parte degli utenti a luglio 2025. PinnFeed è un servizio indipendente che distribuisce i prezzi di Pinnacle agli sviluppatori tramite un WebSocket normalizzato e un'API REST. Non serve un conto Pinnacle.
### Perché un WebSocket invece del polling di un'API REST?
Un client che fa polling vede una variazione solo alla richiesta successiva, quindi in media con mezzo intervallo di ritardo. Con il WebSocket, PinnFeed invia ogni variazione appena arriva al nostro server, filtrata su ciò a cui sei iscritto e con le quote eque. Builder (99 €/mese) è il piano WebSocket.
### Cos'è una quota equa (senza margine)?
I prezzi di Pinnacle includono un margine. Lo togliamo con il metodo moltiplicativo e restituiamo per ogni esito la probabilità equa e la quota decimale equa, così confronti qualsiasi bookmaker con la linea più affilata senza fare conti.
### C'è un piano gratuito?
Sì. Il piano Free dà accesso REST a due sport con 30 secondi di ritardo e 1.000 richieste al giorno, senza carta. Hobby (29 €/mese) rende il REST in tempo reale; Builder (99 €/mese) aggiunge il WebSocket in tempo reale.
### Posso disdire quando voglio?
Sì. Ogni piano a pagamento parte con 3 giorni gratis (carta obbligatoria, addebito il quarto giorno se non disdici) ed è mensile tramite Stripe; disdici o cambi piano dalla dashboard con un clic. I piani in cripto sono prepagati per 1, 3 o 12 mesi e non si rinnovano mai da soli.
### I contenuti sono riservati ai maggiorenni?
PinnFeed è un’API self-serve di quote Pinnacle in tempo reale: un WebSocket normalizzato (Builder 99 €/mese) più REST, fair odds no-vig, storico delle closing line, 13 sport e un server MCP ospitato. Free 0 € (REST, 30 s di ritardo); Hobby 29 €/mese solo REST; Pro 199 €/mese. 3 giorni di trial sui piani a pagamento. Al 9 novembre 2026, Builder era il prezzo pubblicato più basso a fatturazione mensile o annuale che abbiamo trovato per un WebSocket di quote Pinnacle live + pre-match (fonti).
- Piano WebSocket
- Builder · 99 €/mese · 3 connessioni · live + pre-match · i 13 sport
- Anche
- Free 0 € · Hobby 29 €/mese (senza WS) · Pro 199 €/mese · Enterprise su misura
- Trial
- 3 giorni su Hobby, Builder e Pro (carta richiesta)
- Stack
- WebSocket + REST · fair odds no-vig · closing line · MCP
Sì. PinnFeed è uno strumento di dati e i suoi contenuti sono educativi, per maggiori di 18 anni. Niente qui è un pronostico o una promessa di guadagno. Gioca responsabilmente e solo dove è legale.
---
Source: https://pinnfeed.io/it/pricing
# Prezzi dell'API delle quote Pinnacle
Parti gratis con dati REST in ritardo oppure prova qualsiasi piano a pagamento **3 giorni gratis**. **Builder è il piano WebSocket** (99 €/mese): push delle quote Pinnacle in tempo reale, tutti gli sport, tutti i mercati e lo storico delle quote di chiusura. Disdici quando vuoi.
PinnFeed (pinnfeed.io, con la n doppia) è un'API di quote Pinnacle, non l'app Pinterest PinFeed.
## Piani
| Piano | Mensile (EUR, IVA incl. dove applicabile) | Cosa fa la chiave | Inizia |
|---|---|---|---|
| Free | 0 € | Snapshot REST (30 s di ritardo) · 2 sport a scelta · mercati principali · 1.000 richieste/giorno · senza carta | [Chiave gratuita](/signup) |
| Hobby | 29 €/mese | REST in tempo reale (senza ritardo) · 3 sport · mercati principali + quote eque · 2 req/s · senza WebSocket | [3 giorni gratis](/start/hobby) |
| **Builder · il piano WebSocket** | **99 €/mese** | Push WebSocket in tempo reale (3 connessioni) · tutti i 13 sport · tutti i mercati, linee alternative, props e antepost · REST 10 req/s · storico delle quote di chiusura | [3 giorni gratis](/start/builder) |
| Pro | 199 €/mese | 10 connessioni WebSocket · tutto ciò che c'è in Builder · opzione frame grezzi · REST 30 req/s · supporto prioritario | [3 giorni gratis](/start/pro) |
| Enterprise | Su misura | 50 connessioni WebSocket (altre su richiesta) · esportazioni massive delle quote di chiusura (CSV/Parquet) · SLA e licenza commerciale | [Scrivici](mailto:support@pinnfeed.io?subject=PinnFeed%20Enterprise) |
Prezzi in euro, fatturazione mensile, IVA inclusa dove applicabile; le aziende possono inserire la partita IVA al checkout. Paghi con carta tramite Stripe, oppure prepaghi 1, 3 o 12 mesi in USDC, USDT, SOL o BTC dalla dashboard.
## Tutti i limiti, fianco a fianco
| Limite | Free | Hobby | Builder | Pro | Enterprise |
|---|---|---|---|---|---|
| WebSocket in tempo reale | — | — (solo REST) | 3 connessioni | 10 connessioni | 50 (altre su richiesta) |
| API REST | 1 req/s · 1.000/giorno | 2 req/s | 10 req/s | 30 req/s | 100 req/s |
| Prova gratuita | — | 3 giorni | 3 giorni | 3 giorni | — |
| Ritardo dei dati | 30 secondi | Tempo reale | Tempo reale | Tempo reale | Tempo reale |
| Sport | 2 a scelta | 3 a scelta | Tutti i 13 | Tutti i 13 | Tutti i 13 |
| Mercati | Principali | Principali | Tutte le linee, periodi, props e antepost | Tutto + frame grezzi | Tutto + grezzi |
| Quote eque senza margine | ✓ | ✓ | ✓ | ✓ | ✓ |
| Storico delle quote di chiusura | — | — | ✓ | ✓ | Esportazioni massive |
| Server MCP per IA | ✓ con ritardo | ✓ | ✓ | ✓ | ✓ |
| Prezzo (EUR, IVA incl. dove applicabile) | 0 € | 29 €/mese | 99 €/mese | 199 €/mese | Su misura |
| Supporto | Docs | Email | Email | Prioritario | SLA |
Come si posiziona Builder? Al 9 novembre 2026, Builder a 99 €/mese era il prezzo pubblicato più basso a fatturazione mensile o annuale che abbiamo trovato per un WebSocket di quote Pinnacle **live + pre-match**; un WebSocket solo pre-match è pubblicato a meno. Dettagli e fonti nel [confronto dei prezzi](/it/cheapest-pinnacle-odds-websocket).
## Domande sulla fatturazione
### C'è una prova gratuita?
Sì. Hobby, Builder e Pro partono con 3 giorni gratis. Al checkout serve una carta, che viene addebitata automaticamente alla fine del giorno 3 se non disdici prima. Una prova a persona.
### Posso pagare in cripto o per un anno?
Sì. Dalla dashboard puoi prepagare 1, 3 o 12 mesi in USDC o USDT (Ethereum, Base, Arbitrum, Polygon, BNB Chain, Solana), SOL o BTC. Le stablecoin sono token in dollari, quindi il prezzo in euro viene convertito al tasso di riferimento BCE quando si crea la fattura. I piani in cripto si attivano con la conferma on-chain e non si rinnovano mai da soli.
### Hobby include il WebSocket?
No. Hobby è solo REST in tempo reale. Il WebSocket parte da Builder (99 €/mese), il piano WebSocket, con 3 connessioni, tutti i 13 sport e tutti i mercati.
### Cosa succede se un pagamento non va a buon fine?
Stripe riprova l'addebito. Il tuo piano resta attivo per un periodo di tolleranza di 3 giorni e poi passa a Free finché il pagamento non va a buon fine.
### Posso usare i dati a fini commerciali?
Sì, all'interno dei tuoi prodotti e nel rispetto della Acceptable Use Policy. Ridistribuire il feed grezzo come servizio dati concorrente richiede una licenza Enterprise.
### Applicate l'IVA?
- Piano WebSocket
- Builder · 99 €/mese · 3 connessioni · live + pre-match · i 13 sport
- Anche
- Free 0 € · Hobby 29 €/mese (senza WS) · Pro 199 €/mese · Enterprise 50 (altre su richiesta)
- Trial
- 3 giorni su Hobby, Builder e Pro (carta richiesta)
- Stack
- WebSocket + REST · fair odds no-vig · closing line · MCP
I prezzi sono in euro e includono l'IVA dove applicabile: i prezzi EUR elencati includono l'IVA dove applicabile, e Stripe calcola la quota IVA al checkout in base al tuo indirizzo di fatturazione. La quota può essere 0 in caso di inversione contabile o quando l'IVA non si applica.
---
Source: https://pinnfeed.io/it/cheapest-pinnacle-odds-websocket
# Il prezzo pubblicato più basso a fatturazione mensile per un WebSocket delle quote Pinnacle live e pre-match
Al 9 novembre 2026, PinnFeed Builder a **99 €/mese** (IVA inclusa) era il prezzo pubblicato più basso a fatturazione mensile o annuale che abbiamo trovato per un WebSocket in tempo reale che trasmette le quote Pinnacle **live e pre-match**. Un WebSocket solo pre-match è pubblicato a meno (oddssea Prematch, 59 $/mese). In mensile, odds-api.io Solo + WS è a 118 €/mese (EUR, tasse escl.). L’annuale ≈ 98,33 €/mese (1.180 €/anno), ancora sopra l’annuale Builder (≈ 82,50 €/mese IVA inclusa). Il [confronto completo](/it/compare) collega la pagina dei prezzi di ogni fornitore.
Se PinnFeed non fa per te, [alternative all'API delle quote Pinnacle](/alternatives) (in inglese) spiega quando conviene ciascun altro fornitore.
## Cosa ottieni con 99 € al mese
- **Push in tempo reale.** I prezzi vengono inviati quando cambiano: uno snapshot all'iscrizione, poi solo i delta. Niente polling e nessun limite di richieste sul socket.
- **3 connessioni WebSocket**, tutti i 13 sport, live e pre-match.
- **Tutti i mercati**: testa a testa (moneyline), handicap, over/under e totali squadra di ogni periodo, linee alternative, props e antepost.
- **Quote eque senza margine** e il margine del bookmaker su ogni mercato, per valutare le value bet senza fare i conti.
- **Storico delle quote di chiusura** per misurare il CLV, con `/v1/closing`.
- **REST a 10 richieste al secondo** con lo stesso schema, per snapshot e caricamenti storici.
- **Server MCP ospitato**, così ChatGPT, Claude o Cursor leggono le stesse quote.
## Come si confronta il prezzo
| Opzione | Quanto paghi al mese | Push? | Live + pre-match? |
|---|---|---|---|
| oddssea Prematch | 59 $ (≈ 53 €) | WebSocket | Solo pre-match |
| **PinnFeed Builder** | **99 €** (IVA incl. dove applicabile) | WebSocket | **Sì** |
| odds-api.io Solo + WebSocket | 98 £ al mese (≈ 117 €), oppure 980 £ all'anno (≈ 98,33 € al mese) | WebSocket | Sì (più bookmaker) |
| oddspush REST + WebSocket | 138 $ (≈ 124 €), 1 mese prepagato | WebSocket | Sì |
| oddssea Live | 149 $ (≈ 133 €) | WebSocket | Sì |
| pinnwire Pro + Raw WebSocket | 89 $ + 89 $ = 178 $ (≈ 159 €) | WebSocket | Sì |
| Rivenditori solo-Pinnacle: piano REST + add-on WebSocket | 99 $ + 99 $ = 198 $ (≈ 177 €) | WebSocket | Sì |
| Unabated Concierge | 799 $ (≈ 716 €), solo cinque leghe USA | SSE | Sport limitati |
| OpticOdds | Solo su preventivo | SSE, RabbitMQ | — |
| OddsJam API | Solo su preventivo | Push stream, protocollo non indicato | — |
| The Odds API | Da 30 $ (≈ 27 €) | No, solo polling | Sì (polling) |
Prezzi come pubblicati sulla pagina di ciascun fornitore il 9 novembre 2026. Le conversioni in euro usano il tasso di riferimento BCE del 6 novembre 2026 (1 USD = 0,89566 €, 1 GBP = 1,1988 €) e sono approssimate. Fonti: [oddssea.dev](https://oddssea.dev/), [oddspush.com](https://oddspush.com/#pricing), [pinnwire.com](https://pinnwire.com/), [odds-api.io/pricing](https://odds-api.io/pricing).
Riserve oneste: un WebSocket **solo pre-match** è pubblicato a meno (oddssea Prematch, 59 $/mese ≈ 53 €); il piano annuale di odds-api.io costa un po' meno al mese se paghi l'anno in anticipo (≈ 98,33 €); e The Odds API costa meno se ti basta il polling, ma non ha WebSocket.
## Come iniziare spendendo meno
- **Free**: 0 €, snapshot REST con 30 secondi di ritardo, 2 sport, 1.000 richieste al giorno. Abbastanza per costruire e testare il tuo parser.
- **Hobby**: 29 €/mese, REST in tempo reale senza ritardo, 3 sport. Senza WebSocket.
- **Builder**: 99 €/mese, il piano WebSocket. [Vedi Builder nella pagina dei prezzi](/it/pricing#plan-builder).
## Connettiti in poche righe
```python
# pip install websockets
import asyncio, json, os, websockets
async def main():
async with websockets.connect("wss://pinnfeed.io/v1/stream",
additional_headers={"x-api-key": os.environ["PINNFEED_KEY"]}) as ws:
await ws.send(json.dumps({"type": "subscribe", "sports": ["soccer"], "markets": ["moneyline"], "main": True}))
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "ping":
await ws.send('{"type":"pong"}')
elif msg["type"] == "delta":
print(len(msg["changes"]), "changes")
asyncio.run(main())
```
Un client completo che mantiene il book live e si riconnette è nella [guida Python e Node](/it/guides/pinnacle-odds-websocket-python-node).
## Domande frequenti
### Quanto costa un WebSocket delle quote Pinnacle live e pre-match?
Al 9 novembre 2026, PinnFeed Builder a 99 €/mese (IVA inclusa) era il prezzo pubblicato più basso a fatturazione mensile o annuale che abbiamo trovato per un WebSocket in tempo reale che trasmette le quote Pinnacle live e pre-match. Un WebSocket solo pre-match è pubblicato a meno (oddssea Prematch, 59 $/mese). In mensile, odds-api.io Solo + WS è a 118 €/mese (EUR, tasse escl.). L’annuale ≈ 98,33 €/mese (1.180 €/anno), ancora sopra l’annuale Builder (≈ 82,50 €/mese IVA inclusa).
### C'è una prova gratuita?
Sì. Tutti i piani a pagamento partono con 3 giorni gratis. Inserisci una carta al checkout e l'addebito arriva il quarto giorno se non disdici. Il piano Free non chiede la carta.
### Posso pagare in cripto?
Sì. Oltre alla carta con Stripe, puoi prepagare 1, 3 o 12 mesi in USDC, USDT, SOL o BTC dalla dashboard. I piani in cripto non si rinnovano mai da soli.
### Mi serve un conto Pinnacle?
No. Ti serve solo una chiave API di PinnFeed. PinnFeed è indipendente e non è affiliato a Pinnacle.
---
Source: https://pinnfeed.io/it/compare
# Confronto tra API delle quote Pinnacle: chi trasmette i prezzi e quanto costa
Se ti servono le quote Pinnacle nel tuo codice appena si muovono, il mercato si divide in tre gruppi: API self-service con WebSocket, rivenditori solo-Pinnacle che vendono il socket come add-on e fornitori enterprise che danno il prezzo solo in una chiamata commerciale. Ecco i prezzi pubblicati che abbiamo trovato, con i link, così puoi verificare ogni cifra.
**Risposta breve:** al 9 novembre 2026, PinnFeed Builder a **99 €/mese** (IVA inclusa) era il prezzo pubblicato più basso a fatturazione mensile o annuale che abbiamo trovato per un WebSocket in tempo reale che trasmette le quote Pinnacle **live e pre-match**. Un WebSocket solo pre-match è pubblicato a meno (oddssea Prematch, 59 $/mese). In mensile, odds-api.io Solo + WS è a 118 €/mese (EUR, tasse escl.). L’annuale ≈ 98,33 €/mese (1.180 €/anno), ancora sopra l’annuale Builder (≈ 82,50 €/mese IVA inclusa). Se ti basta il polling, The Odds API costa meno di tutti, ma non ha alcun feed push.
## La tabella di confronto
Prezzi come pubblicati sulla pagina di ciascun fornitore il 9 novembre 2026. Le conversioni in euro usano il tasso di riferimento BCE del 6 novembre 2026 (1 GBP = 1,1988 €, 1 USD = 0,89566 €) e sono approssimate.
| Fornitore | Quote Pinnacle | Push in tempo reale | Piano pubblicato più accessibile con push | ≈ € al mese | Piano gratuito | Fonte |
|---|---|---|---|---|---|---|
| oddssea Prematch | Sì (solo Pinnacle) | WebSocket | Prematch, 59 $/mese | ≈ 53 € | Sì, REST pre-match in ritardo | [oddssea.dev](https://oddssea.dev/) (verificato il 9 nov. 2026) |
| **PinnFeed** | Sì (solo Pinnacle) | WebSocket, delta normalizzati | Builder (live + pre-match) | **99 €** (IVA incl. dove applicabile) | Sì, REST con 30 s di ritardo | [prezzi](/it/pricing) |
| odds-api.io | Sì (uno dei tuoi bookmaker) | WebSocket | Solo (2 bookmaker) + WebSocket, 98 £/mese | ≈ 117 € mensile · ≈ 98,33 € in annuale | No | [odds-api.io/pricing](https://odds-api.io/pricing) |
| oddspush | Sì (solo Pinnacle) | WebSocket | REST + WebSocket, 138 $ (1 mese prepagato) | ≈ 124 € | Prova di 7 giorni (REST + WS) | [oddspush.com](https://oddspush.com/#pricing) (verificato il 9 nov. 2026) |
| oddssea Live | Sì (solo Pinnacle) | WebSocket | Live, 149 $/mese | ≈ 133 € | Sì, REST pre-match in ritardo | [oddssea.dev](https://oddssea.dev/) (verificato il 9 nov. 2026) |
| pinnwire | Sì (solo Pinnacle) | Add-on WebSocket grezzo (+ cali via SSE) | Pro 89 $ + Raw WS 89 $ = 178 $ | ≈ 159 € | Sì, 100 richieste/giorno | [pinnwire.com](https://pinnwire.com/), [docs](https://pinnwire.com/docs.html) (verificato il 9 nov. 2026) |
| Rivenditori solo-Pinnacle | Sì (solo Pinnacle) | Add-on WebSocket grezzo | Piano REST da 99 $ + add-on WebSocket da 99 $ | ≈ 177 € | Sì, 100 richieste/giorno | Pagine dei prezzi pubblicate dei tre rivenditori verificati |
| SportsGameOdds | Pinnacle da Pro in su | WebSocket via Pusher (beta); invia gli id degli eventi cambiati da richiedere via REST | AllStar o piano su misura, prezzo su richiesta | Non pubblicato | Sì (Amateur, aggiornamenti ogni 10 minuti) | [docs streaming](https://sportsgameodds.com/docs/guides/realtime-streaming-api), [prezzi](https://sportsgameodds.com/pricing/) |
| OddsPapi | Sì | WebSocket (v5) | Solo piano B2B | Non pubblicato | Sì, 250 richieste/mese | [docs WebSocket](https://oddspapi.io/en/docs/websocket-api) |
| Unabated | Non citata nella pagina dell'API; Unabated Line nel piano Concierge | SSE, niente WebSocket | Concierge, 799 $/mese (NFL, NBA, MLB, NHL, WNBA; uso personale) | ≈ 716 € | 15 secondi di ritardo, per publisher che raggiungono obiettivi di traffico via deeplink | [unabated.com/odds-api](https://unabated.com/odds-api) |
| OpticOdds | Sì (aggregatore) | SSE e RabbitMQ, niente WebSocket | Solo su preventivo | Non pubblicato | No | [prezzi](https://opticodds.com/pricing), [FAQ API](https://developer.opticodds.com/docs/api-faq) |
| OddsJam API | Non citata nella pagina dell'API | Push stream, protocollo non indicato | Solo su preventivo | Non pubblicato | Nessun piano API gratuito pubblicato | [oddsjam.com/odds-api](https://oddsjam.com/odds-api) |
| The Odds API | Sì (regione UE) | **Nessuno**, solo polling REST | Nessun piano push; polling da 30 $/mese | ≈ 27 € (polling) | Sì, 500 crediti/mese | [the-odds-api.com](https://the-odds-api.com/) |
## Come leggerla
- **Push contro polling.** Un WebSocket consegna ogni variazione di prezzo una volta, quando avviene. Il polling di un endpoint REST ogni N secondi perde i movimenti intermedi e consuma quota su prezzi che non sono cambiati. Per lo steam, i modelli live o qualsiasi cosa sensibile al tempo conta il push. Vedi [perché il push batte il polling](/odds-websocket-api) (in inglese).
- **Live + pre-match contro solo pre-match.** Diversi feed dedicati pubblicano un WebSocket solo pre-match a un prezzo più basso. L'affermazione di questa pagina riguarda solo i piani che trasmettono le quote Pinnacle **live e pre-match**. oddssea Prematch, a 59 $/mese, costa meno se non ti serve il live.
- **Solo Pinnacle contro tanti bookmaker.** PinnFeed porta solo Pinnacle, il mercato più affilato e il prezzo di riferimento abituale. Se ti servono anche le quote dei bookmaker soft nello stesso feed, è più adatto un aggregatore come odds-api.io o SportsGameOdds, e paghi per ogni bookmaker in più.
- **Cosa include il prezzo.** Builder include il WebSocket con REST a 10 richieste al secondo, tutti i 13 sport, linee alternative, props e antepost, quote eque su ogni mercato e storico delle quote di chiusura. I rivenditori solo-Pinnacle vendono il socket come add-on da 99 $ sopra un piano REST, per questo il totale è di circa 177 €. Anche pinnwire fa pagare il WebSocket grezzo come add-on da +89 $ da Pro in su.
- **Fornitori solo su preventivo.** OpticOdds, l'API di OddsJam e i livelli B2B di altri fornitori non pubblicano prezzi. Alcuni articoli di terzi citano cifre, ma le lasciamo fuori perché i fornitori non le hanno pubblicate.
## Una pagina per fornitore
Ogni fornitore ha la sua pagina (in inglese) con un giudizio, una tabella dei prezzi datata e quando sceglierlo al posto di PinnFeed: parti da [alternative all'API delle quote Pinnacle](/alternatives) o vai diretto a [oddssea](/oddssea-alternative), [odds-api.io](/odds-api-io-alternative), [oddspush](/oddspush-alternative), [pinnwire](/pinnwire-alternative), [The Odds API](/the-odds-api-alternative), [OpticOdds](/opticodds-alternative), [OddsJam](/oddsjam-alternative), [SportsDataIO](/sportsdataio-alternative) o [Sportmonks](/sportmonks-alternative).
## Cosa non affermiamo
- Non affermiamo di avere una latenza inferiore a quella di un fornitore specifico; non abbiamo fatto un test diretto.
- Non affermiamo di costare meno di The Odds API, che costa meno ma non invia dati in push.
- Non affermiamo di costare meno di un WebSocket **solo pre-match** (oddssea Prematch, 59 $/mese al 9 novembre 2026).
- «Più basso» qui significa il prezzo pubblicato più basso a fatturazione mensile o annuale che siamo riusciti a trovare il 9 novembre 2026 per un WebSocket in tempo reale che trasmette le quote Pinnacle **live e pre-match**. I prezzi cambiano. Se vedi un piano pubblicato a meno entro questo perimetro, scrivici e aggiorneremo la pagina.
## Domande frequenti
### Qual è il prezzo pubblicato più basso a fatturazione mensile per un WebSocket delle quote Pinnacle live e pre-match?
Al 9 novembre 2026, PinnFeed Builder a 99 €/mese (IVA inclusa) era il prezzo pubblicato più basso a fatturazione mensile o annuale che abbiamo trovato per un WebSocket in tempo reale che trasmette le quote Pinnacle live e pre-match. Un WebSocket solo pre-match è pubblicato a meno (oddssea Prematch, 59 $/mese). In mensile: odds-api.io Solo + WS 118 €/mese (tasse escl.). L’annuale ≈ 98,33 €/mese — ancora sopra Builder annuale (≈ 82,50 €/mese IVA inclusa).
### Esiste un WebSocket gratuito delle quote Pinnacle?
Non ne abbiamo trovati. I piani gratuiti con i prezzi di Pinnacle sono solo REST: il piano gratuito di PinnFeed ha 30 secondi di ritardo, The Odds API dà 500 crediti al mese e OddsPapi 250 richieste al mese.
### The Odds API ha un WebSocket?
No. The Odds API è solo REST; per vedere le variazioni devi fare polling. I piani partono da 30 $ al mese.
### OpticOdds ha un WebSocket?
No. La FAQ dell'API di OpticOdds dice che non offre webhook né WebSocket e che trasmette via Server-Sent Events. Il prezzo è solo su preventivo.
### PinnFeed è l'API ufficiale di Pinnacle?
No. Pinnacle ha chiuso la sua API pubblica a luglio 2025. PinnFeed è un servizio indipendente, non affiliato a Pinnacle, che ridistribuisce i prezzi osservati di Pinnacle per lo sviluppo software e la ricerca.
---
Source: https://pinnfeed.io/it/faq
# Domande frequenti su PinnFeed
Risposte dirette su PinnFeed, l'API delle quote Pinnacle in tempo reale. PinnFeed (pinnfeed.io, con la n doppia) è un'API di quote Pinnacle, non l'app Pinterest PinFeed. C'è un piano Free (senza carta, REST con 30 s di ritardo, 2 sport) e una prova gratuita di 3 giorni sui piani a pagamento (carta obbligatoria). Manca qualcosa? Scrivi a support@pinnfeed.io.
## Domande sul prodotto e sui dati
### Cos'è PinnFeed?
PinnFeed (pinnfeed.io, con la n doppia) è un'API per sviluppatori con le quote sportive di Pinnacle in tempo reale, non l'app Pinterest PinFeed. Fornisce prezzi live e pre-match su un unico WebSocket con filtri lato server e aggiornamenti delta, più snapshot REST, quote eque senza margine, storico delle quote di chiusura e un server MCP ospitato per gli assistenti IA.
### PinnFeed è l'API ufficiale di Pinnacle?
No. Pinnacle ha chiuso la sua API pubblica a luglio 2025. PinnFeed è un servizio indipendente, non affiliato a Pinnacle, e non ti serve un conto Pinnacle.
### Quali sport e mercati copre?
Tredici sport: calcio, tennis, basket, hockey, football americano, baseball, rugby, MMA, boxe, pallavolo e pallamano, esport, golf e cricket. I mercati sono testa a testa (moneyline), handicap, over/under e totali squadra di ogni periodo, più linee alternative, props e antepost da Builder in su.
### Cosa contiene ogni mercato?
Quote decimali e americane, la linea, la puntata massima di Pinnacle, il margine del bookmaker e, per ogni esito, la quota equa senza margine e la probabilità equa.
### Quanto sono freschi i dati?
I piani a pagamento sono in tempo reale: il WebSocket invia ogni variazione appena la riceve. Il piano gratuito ha 30 secondi di ritardo.
### Posso usare PinnFeed con ChatGPT o Claude?
Sì. PinnFeed ospita un server MCP su https://pinnfeed.io/mcp che funziona con Claude, Claude Code, la modalità sviluppatore di ChatGPT, Cursor, VS Code Copilot e Codex. Vedi la guida MCP.
### I contenuti sono riservati ai maggiorenni?
Sì. I dati sulle quote e le guide sono materiale educativo per maggiori di 18 anni. Niente di tutto questo è un pronostico, una scommessa sicura o una promessa di guadagno.
## Domande su prezzi e fatturazione
### Quanto costa PinnFeed?
Free 0 € (REST, 30 secondi di ritardo); Hobby 29 €/mese (REST in tempo reale, senza WebSocket); Builder 99 €/mese (il piano WebSocket); Pro 199 €/mese; Enterprise su richiesta. I prezzi includono l'IVA dove applicabile.
### Quale piano include il WebSocket?
Builder (99 €/mese) e superiori. Le chiavi Free e Hobby sono solo REST.
### C'è una prova gratuita?
Sì, 3 giorni gratis su tutti i piani a pagamento. La carta viene addebitata il quarto giorno se non disdici. Una prova per cliente.
### PinnFeed è il WebSocket Pinnacle live + pre-match più economico a fatturazione mensile?
Al 9 novembre 2026, PinnFeed Builder a 99 €/mese (IVA inclusa) era il prezzo pubblicato più basso a fatturazione mensile o annuale che abbiamo trovato per un WebSocket in tempo reale che trasmette le quote Pinnacle **live e pre-match**. Un WebSocket solo pre-match è pubblicato a meno (oddssea Prematch, 59 $/mese). In mensile, odds-api.io Solo + WS è a 118 €/mese (EUR, tasse escl.). L’annuale ≈ 98,33 €/mese (1.180 €/anno), ancora sopra l’annuale Builder (≈ 82,50 €/mese IVA inclusa). Il [confronto](/it/compare) collega tutte le fonti.
### Posso pagare in cripto?
Sì. Puoi prepagare 1, 3 o 12 mesi in USDC, USDT, SOL o BTC dalla dashboard, oppure pagare con carta tramite Stripe.
### I prezzi includono l'IVA dove applicabile e la mia azienda può inserire la partita IVA?
Sì. I prezzi sono in euro e includono l'IVA dove applicabile: i prezzi EUR elencati includono l'IVA dove applicabile, e Stripe calcola la quota IVA al checkout in base al tuo indirizzo di fatturazione. La quota può essere 0 in caso di inversione contabile o quando l'IVA non si applica. Le aziende possono inserire la partita IVA al checkout.
### Come disdico?
Dalla dashboard: Plan & billing → Manage billing → Cancel. Mantieni l'accesso fino alla fine del periodo pagato.
---
Source: https://pinnfeed.io/it/answers/pinnacle-nba-moneyline-odds-api
# API moneyline NBA Pinnacle in tempo reale
**Risposta:** lo slug PinnFeed per la NBA (e il basket) è **`basketball`**. Poll `GET /v1/odds?sport=basketball&market=moneyline&main=true` su Free/Hobby, o WebSocket `"sports":["basketball"],"markets":["moneyline"],"main":true` su Builder (€99/mese). Nessuno slug `nba` — filtra per `league.name`.
## Snapshot REST (Free, ritardo 30 s)
```bash
export PINNFEED_KEY="ps_live_..."
curl -sS -H "x-api-key: $PINNFEED_KEY" \
"https://pinnfeed.io/v1/odds?sport=basketball&market=moneyline&main=true&live=true&limit=20"
```
## Sottoscrizione WebSocket (Builder)
```javascript
// Example Node fragment — needs Builder key
const ws = new WebSocket('wss://pinnfeed.io/v1/stream', {
headers: { 'x-api-key': process.env.PINNFEED_KEY },
});
ws.on('open', () => ws.send(JSON.stringify({
type: 'subscribe',
sports: ['basketball'],
markets: ['moneyline'],
main: true,
live: true,
specials: false,
})));
ws.on('message', (buf) => {
const msg = JSON.parse(buf);
if (msg.type === 'ping') ws.send(JSON.stringify({ type: 'pong' }));
// filter NBA: if (event.league?.name?.includes('NBA')) ...
});
```
## CTA
[Builder](/it/pricing#plan-builder) (99 €/mese). Prova 3 giorni; carta richiesta. REST gratis: [signup](/signup). Vedi anche: [props NBA](/it/answers/nfl-player-props-odds-api-pinnacle), [sport ids](/it/answers/pinnacle-odds-api-sport-ids). Storico NBA (EN): [historical NBA](/answers/historical-betting-odds-pinnacle-closing).
## Domande frequenti
### Slug `nba` o `basketball`?
`basketball`.
### Contenuto educativo per adulti?
Sì (18+).
*Contenuto educativo per maggiorenni (18+): non pronostici né promesse di guadagno. In Italia scommetti solo con operatori autorizzati ADM.*
---
Source: https://pinnfeed.io/it/answers/nfl-player-props-odds-api-pinnacle
# API player props NFL con prezzi Pinnacle
**Risposta:** Pinnacle pubblica i player props NFL come eventi **special** sotto `american-football`. Su Builder/Pro, `/v1/odds?sport=american-football` li restituisce con `parentId` verso la partita. Free/Hobby sono main-only.
## Esempio
```python
import os, requests
from collections import defaultdict
H = {"x-api-key": os.environ["PINNFEED_KEY"]} # ps_live_...
# 1) find the NFL league id once (college football is a different league)
ev = requests.get("https://pinnfeed.io/v1/events", headers=H, timeout=10,
params={"sport": "american-football", "q": "nfl", "limit": 200}).json()["events"]
print({(e["league"]["id"], e["league"]["name"]) for e in ev if e["league"]})
LEAGUE = int(input("NFL league id: "))
# 2) games and props together (no main=true: that would drop the specials)
data = requests.get("https://pinnfeed.io/v1/odds", headers=H, timeout=15,
params={"sport": "american-football", "league": LEAGUE, "limit": 500}).json()["events"]
games = {e["id"]: e for e in data if not e.get("special")}
props = defaultdict(list)
for e in data:
if e.get("special") and e.get("parentId") in games:
props[e["parentId"]].append(e)
for gid, items in props.items():
g = games[gid]
print(f'{g["away"]} @ {g["home"]} ({len(items)} props)')
for p in items[:10]:
for m in p["markets"]:
line = " | ".join(f'{o["name"]} {o["decimal"]} (fair {o.get("fair")})' for o in m["outcomes"])
print(" ", p["special"]["description"], m["type"], m.get("line"), line)
```
```json
{ "type": "subscribe", "sports": ["american-football"], "leagues": [LEAGUE_ID], "specials": true }
```
Correlato: [specials](/it/answers/pinnacle-specials-props-odds-api), [API NFL](/it/answers/pinnacle-nfl-american-football-odds-api).
## CTA
[Builder](/it/pricing#plan-builder) (99 €/mese). Prova 3 giorni; carta richiesta. REST gratis: [signup](/signup).
## Domande frequenti
### Free include i props NFL?
No — Builder.
### Contenuto educativo per adulti?
Sì (18+).
*Contenuto educativo per maggiorenni (18+): non pronostici né promesse di guadagno. In Italia scommetti solo con operatori autorizzati ADM.*
---
Source: https://pinnfeed.io/it/vibe-coding
# Costruire con PinnFeed e l'IA
**Risposta:** prendi una chiave Free dalla [registrazione](/signup), esporta `PINNFEED_KEY`, incolla un prompt di questa pagina in Cursor, Claude, ChatGPT, Lovable, Replit o Bolt e dai all'agente [llms-api.txt](/llms-api.txt) o [AGENTS.md](/AGENTS.md). L'autenticazione usa `x-api-key` (oppure Bearer o `?key=`). Il WebSocket richiede [Builder](/it/pricing#plan-builder) (99 €/mese).
## 1. La chiave in un minuto
```bash
export PINNFEED_KEY="ps_live_..."
echo 'PINNFEED_KEY=ps_live_...' >> .env
echo '.env' >> .gitignore
```
Non incollare mai la chiave in una chat condivisa o in git. Free = REST con circa 30 s di ritardo, 2 sport, 1 req/s, 1.000 al giorno. Hobby = REST in tempo reale, senza WebSocket. Builder = il piano WebSocket. Dettagli: [prezzi](/it/pricing), [quickstart](/it/quickstart).
## 2. Verifica la chiave
```bash
curl -sS -H "x-api-key: $PINNFEED_KEY" \
"https://pinnfeed.io/v1/odds?sport=soccer&main=true&limit=3"
```
OpenAPI: [/openapi.json](/openapi.json). Postman / Insomnia: [collection JSON](/postman/pinnfeed.postman_collection.json) (variabile `apiKey`).
## 3. Dai all'agente la vera API
- API compatta: [llms-api.txt](/llms-api.txt)
- Convenzione Cursor / Codex: [AGENTS.md](/AGENTS.md)
- Skill del prodotto: [SKILL.md](/SKILL.md)
- Docs (in inglese): [docs](/docs) · [WebSocket](/docs/websocket) · [MCP](/docs/mcp) · [errori](/docs/errors)
## 4. MCP (trasporti reali)
MCP ospitato: **`POST https://pinnfeed.io/mcp`** (Streamable HTTP). Auth: `Authorization: Bearer`, `x-api-key`, oppure `?key=` se il client non può inviare header.
```json
{
"mcpServers": {
"pinnfeed": {
"url": "https://pinnfeed.io/mcp",
"headers": { "Authorization": "Bearer YOUR_KEY" }
}
}
}
```
```bash
claude mcp add --transport http pinnfeed https://pinnfeed.io/mcp \
--header "Authorization: Bearer YOUR_KEY"
```
Per Claude Desktop, Claude web o i connettori ChatGPT che non accettano header: `https://pinnfeed.io/mcp?key=YOUR_KEY` con una chiave dedicata che puoi revocare. Strumenti: `get_account`, `list_sports`, `search_events`, `get_live_odds`, `get_prematch_odds`, `get_event`, `get_drops`, `get_closing_odds`.
## 5. Prompt base (Cursor / Claude Code)
I prompt sono in inglese, come la documentazione che l'agente leggerà:
```text
You are building against PinnFeed (Pinnacle odds API).
1) Read https://pinnfeed.io/llms-api.txt and https://pinnfeed.io/openapi.json.
2) Use env PINNFEED_KEY only (x-api-key). Add .env to .gitignore.
3) Goal: YOUR_GOAL
4) Prefer REST on Free/Hobby; WebSocket only if I confirm Builder.
5) Educational, 18+. No betting tips, no guaranteed profit.
```
Altri prompt (ChatGPT, Lovable, Replit) e 8 idee di app: [hub vibe coding in inglese](/it/vibe-coding).
## Prova
[Builder](/it/pricing#plan-builder) (99 €/mese) per il WebSocket e lo storico delle quote di chiusura. Prova di 3 giorni; serve una carta, addebitata dopo il giorno 3 se non disdici prima. Chiave gratuita: [registrazione](/signup).
*Contenuto educativo per maggiorenni (18+). Le regole sul gioco cambiano da paese a paese; in Italia il gioco è regolato dall'ADM. Questo non è un parere legale.*
## Domande frequenti
### Serve Builder per il vibe coding?
No per prototipi REST su Free o Hobby. Sì per `/v1/stream` e `/v1/closing`.
### L'agente può inventare endpoint?
Non deve: vincolalo all'OpenAPI e a llms-api.txt.
### Il server MCP consuma quota?
Sì, ogni `tools/call` conta come una richiesta REST.
---
Source: https://pinnfeed.io/it/quickstart
# Quickstart: dalla chiave alle prime quote
**Risposta:** [registrati](/signup) → copia una volta la chiave `ps_live_...` dalla [dashboard](/dashboard) → `export PINNFEED_KEY=...` → un curl su `/v1/odds`. È il percorso da 60 secondi. Seguono Python, Node e Sheets. Il WebSocket è il passo 5 (Builder). La documentazione completa resta su [/docs](/docs) (in inglese).
## Passo 1 — La chiave
1. [Crea un account gratuito](/signup).
2. Dashboard → **Create key** → copia `ps_live_...` (mostrata una sola volta).
3. Solo nell'ambiente:
```bash
export PINNFEED_KEY="ps_live_..."
```
## Passo 2 — curl
```bash
curl -sS -H "x-api-key: $PINNFEED_KEY" \
"https://pinnfeed.io/v1/odds?sport=soccer&main=true&limit=5"
```
Ricevi eventi JSON con mercati ed esiti (`decimal`, `american`, `fair`, `fairProb`). Contratto: [openapi.json](/openapi.json).
## Passo 3 — Python
```python
import os, urllib.request, json
req = urllib.request.Request(
"https://pinnfeed.io/v1/odds?sport=soccer&main=true&limit=5",
headers={"x-api-key": os.environ["PINNFEED_KEY"]},
)
print(json.load(urllib.request.urlopen(req))["events"][0]["home"])
```
## Passo 4 — Node
```js
const key = process.env.PINNFEED_KEY;
const r = await fetch(
"https://pinnfeed.io/v1/odds?sport=soccer&main=true&limit=5",
{ headers: { "x-api-key": key } },
);
const data = await r.json();
console.log(data.events?.[0]?.home);
```
## Passo 5 — Google Sheets
`IMPORTDATA` non può inviare `x-api-key`. Usa **Estensioni → Apps Script** con la chiave nelle proprietà dello script e segui la [guida Google Sheets](/it/guides/pinnacle-odds-google-sheets).
## Quando ti serve il push
Il WebSocket `wss://pinnfeed.io/v1/stream` richiede [Builder](/it/pricing#plan-builder) (99 €/mese). Le chiavi Free e Hobby ricevono `403 plan_lacks_ws`. Client Python e Node: [guida WebSocket](/it/guides/pinnacle-odds-websocket-python-node).
## Assistenti IA
MCP: [/docs/mcp](/docs/mcp). File per agenti: [llms-api.txt](/llms-api.txt), [AGENTS.md](/AGENTS.md), [SKILL.md](/SKILL.md). Prompt pronti: [vibe coding](/it/vibe-coding).
## Prova
REST gratuito con ritardo: [registrazione](/signup). WebSocket Builder: [prezzi](/it/pricing#plan-builder), prova di 3 giorni; serve una carta, addebitata dopo il giorno 3 se non disdici prima.
*Contenuto educativo per maggiorenni (18+).*
## Domande frequenti
### Che differenza c'è con /docs?
Questa pagina è il percorso da 60 secondi. [/docs](/docs) è la guida completa per sviluppatori (WebSocket, schema, esempi).
### Posso mettere la chiave in una cella del foglio?
No. Usa le proprietà dello script o un secret: una chiave in una cella finisce copiata ed esposta.
### Devo pagare per iniziare?
No. Free costa 0 € (REST, 30 s di ritardo, 2 sport, 1.000 richieste al giorno), senza carta.
---
Source: https://pinnfeed.io/it/answers
# Risposte a domande precise sull'API delle quote Pinnacle
Ogni pagina risponde a una domanda precisa: prima la risposta, poi codice che funziona con la vera API di PinnFeed e infine le domande frequenti. Altre pagine sono nelle [risposte in inglese](/answers); per percorsi completi, vedi le [guide](/it/guides).
## Pagine in italiano
- [Alert email di drop in Google Sheets](/it/answers/google-sheets-odds-drop-email-alert)
- [API +EV con quote no-vig Pinnacle](/it/answers/ev-betting-api-no-vig)
- [Feed quote calcio (inclusi filtri per lega)](/it/answers/football-odds-feed-pinnacle)
- [API closing Pinnacle per il CLV](/it/answers/pinnacle-closing-line-api-clv)
- [Filter odds by league id (WNBA, EuroLeague, college)](/answers/pinnacle-odds-by-league-id)
- [API corner calcio Pinnacle](/it/answers/pinnacle-soccer-corners-odds-api)
- [API delle quote di tennis Pinnacle](/it/answers/pinnacle-tennis-odds-api)
- [API di dropping odds](/it/answers/dropping-odds-api)
- [API di line movement Pinnacle](/it/answers/pinnacle-line-movement-api)
- [API di quote fair senza margine (no-vig)](/it/answers/no-vig-fair-odds-api)
- [API linee alternate Pinnacle](/it/answers/pinnacle-alternate-lines-api)
- [API LoL e Dota 2 (quote Pinnacle)](/it/answers/lol-dota2-odds-api-pinnacle)
- [API max stake Pinnacle — maxStake](/it/answers/pinnacle-max-stake-api)
- [Moneyline, spread e totali NBA](/it/answers/pinnacle-nba-moneyline-odds-api)
- [API multi-book vs Pinnacle-only](/it/answers/multi-book-odds-api-vs-pinnacle-only)
- [API pallavolo e pallamano Pinnacle](/it/answers/pinnacle-volleyball-handball-odds-api)
- [API Pinnacle chiusa: quali opzioni ci sono?](/it/answers/pinnacle-api-access-closed)
- [API Pinnacle self-serve (PinnFeed)](/it/answers/pinnacle-api-self-serve)
- [Player props NFL e NBA](/it/answers/nfl-player-props-odds-api-pinnacle)
- [API quote boxing Pinnacle](/it/answers/pinnacle-boxing-odds-api)
- [API quote cricket Pinnacle](/it/answers/pinnacle-cricket-odds-api)
- [API quote esports Pinnacle](/it/answers/pinnacle-esports-odds-api)
- [API quote golf Pinnacle](/it/answers/pinnacle-golf-odds-api)
- [API quote gratis: cosa include free](/it/answers/free-odds-api)
- [API quote live Pinnacle](/it/answers/pinnacle-live-odds-api)
- [API quote MMA / UFC di Pinnacle](/it/answers/pinnacle-mma-ufc-odds-api)
- [API quote NFL Pinnacle (american-football)](/it/answers/pinnacle-nfl-american-football-odds-api)
- [API quote NHL / hockey Pinnacle](/it/answers/pinnacle-nhl-hockey-odds-api)
- [API quote Pinnacle CS:GO / CS2](/it/answers/pinnacle-csgo-odds-api)
- [API quote Pinnacle in Power BI](/it/answers/pinnacle-odds-api-power-bi)
- [API quote Pinnacle in R con httr2](/it/answers/pinnacle-odds-api-r-httr2)
- [API quote Pinnacle per Sheets ed Excel](/it/answers/pinnacle-odds-api-google-sheets-excel)
- [API quote rugby Pinnacle](/it/answers/pinnacle-rugby-odds-api)
- [API quote scommesse: come scegliere](/it/answers/betting-odds-api)
- [API specials e props Pinnacle](/it/answers/pinnacle-specials-props-odds-api)
- [Pinnacle odds API](/pinnacle-odds-api)
- [Architettura di un bot di scommesse](/it/answers/sports-betting-bot-architecture)
- [Autenticazione dell'API quote Pinnacle](/it/answers/pinnacle-odds-api-authentication)
- [Backtest contro le closing Pinnacle](/it/answers/pinnacle-odds-api-backtesting-clv)
- [Bot Discord con le quote Pinnacle](/it/answers/discord-picks-bot-pinnacle-odds)
- [Bot picks Telegram su quote Pinnacle](/it/answers/telegram-picks-bot-pinnacle)
- [Calcolatore senza margine in Excel o Sheets](/it/answers/no-vig-calculator-excel-sheets)
- [Claude MCP per le quote Pinnacle](/it/answers/claude-mcp-sports-odds)
- [Client Go per il WebSocket delle quote Pinnacle](/it/answers/pinnacle-odds-websocket-golang)
- [Client WebSocket TypeScript Pinnacle](/it/answers/pinnacle-odds-websocket-typescript)
- [Closing Pinnacle in DuckDB e Parquet](/it/answers/pinnacle-closing-odds-duckdb-parquet)
- [Closing Pinnacle — calcio europeo](/it/answers/pinnacle-closing-lines-european-football-api)
- [Codici di errore dell'API quote Pinnacle](/it/answers/pinnacle-odds-api-error-codes)
- [Compressione del WebSocket quote Pinnacle](/it/answers/pinnacle-odds-websocket-compression)
- [Disdire PinnFeed o ottenere un rimborso](/it/answers/pinnacle-odds-api-cancel-refund)
- [Fatturazione annuale e trimestrale PinnFeed](/it/answers/pinnfeed-annual-quarterly-billing)
- [Filtro EV con fairProb in Python](/it/answers/pinnacle-odds-python-fairprob-ev-screen)
- [Foglio per tracciare scommesse con CLV](/it/answers/bet-tracker-spreadsheet-clv)
- [Frame grezzi Pinnacle (Pro)](/it/answers/pinnacle-odds-websocket-raw-frames)
- [Guida Excel Power Query Pinnacle](/it/answers/pinnacle-odds-excel-power-query-guide)
- [Heartbeat ping/pong del WebSocket Pinnacle](/it/answers/pinnacle-odds-websocket-ping-pong)
- [Id e slug sport PinnFeed (13)](/it/answers/pinnacle-odds-api-sport-ids)
- [Latenza API quote: misurala tu](/it/answers/pinnacle-odds-api-latency-honesty)
- [Limiti di richieste dell'API quote Pinnacle](/it/answers/pinnacle-odds-api-rate-limits)
- [Line shopping rispetto al prezzo Pinnacle (API)](/it/answers/line-shopping-vs-pinnacle)
- [Map snapshot/delta Pinnacle in Node](/it/answers/pinnacle-odds-node-snapshot-delta-map)
- [Margine (overround) Pinnacle per mercato via API](/it/answers/pinnacle-margin-overround-api)
- [Memorizzare le quote Pinnacle in Postgres](/it/answers/pinnacle-odds-postgres-storage)
- [odds-api.io annuale vs prezzo Builder](/it/answers/odds-api-io-annual-vs-pinnfeed-builder)
- [OddsJam API preventivo vs WS self-serve](/it/answers/oddsjam-api-quote-vs-self-serve)
- [Pagamento crypto API quote PinnFeed](/it/answers/pinnacle-odds-api-crypto-payment)
- [Piano Builder di PinnFeed: cosa include](/it/answers/pinnacle-odds-api-builder-whats-included)
- [Piano Free: quote Pinnacle con 30 s di ritardo](/it/answers/pinnacle-odds-api-free-tier-delay)
- [Polling The Odds API vs push PinnFeed](/it/answers/the-odds-api-polling-vs-pinnfeed-push)
- [Prezzi API quote: a richiesta o a canone fisso](/it/answers/odds-api-pricing-per-request-vs-flat)
- [Probabilità implicita via fairProb](/it/answers/pinnacle-odds-implied-probability-api)
- [Prova gratuita dell'API quote Pinnacle](/it/answers/pinnacle-odds-api-free-trial)
- [Proxy FastAPI per quote Pinnacle](/it/answers/pinnacle-odds-fastapi-proxy)
- [Quote di chiusura Pinnacle in Python (CLV)](/it/answers/pinnacle-odds-python-closing-lines-clv)
- [Quote live: push o polling REST](/it/answers/pinnacle-live-odds-push-vs-polling)
- [Historical odds via Pinnacle closings](/answers/historical-betting-odds-pinnacle-closing)
- [Quote Pinnacle con IMPORTDATA (Sheets)](/it/answers/pinnacle-odds-google-sheets-importdata)
- [Quote Pinnacle in ChatGPT e Claude (MCP)](/it/answers/pinnacle-odds-chatgpt-mcp)
- [Quote Pinnacle in Excel Power Query](/it/answers/pinnacle-odds-excel-power-query)
- [Quote Pinnacle in JS browser (CORS)](/it/answers/pinnacle-odds-browser-javascript-cors)
- [Quote Pinnacle in Python (REST)](/it/answers/pinnacle-odds-python-rest)
- [Quote Pinnacle in Supabase (Edge Function)](/it/answers/pinnacle-odds-supabase-edge-function)
- [Quote Pinnacle in un DataFrame pandas](/it/answers/pinnacle-odds-pandas-dataframe)
- [Quote Pinnacle senza scraping](/it/answers/pinnacle-odds-without-scraping)
- [Quote Pinnacle su un Cloudflare Worker](/it/answers/pinnacle-odds-cloudflare-worker)
- [Quote Pinnacle: storico o feed live](/it/answers/pinnacle-odds-historical-vs-live)
- [Ricette curl per l'API di quote Pinnacle](/it/answers/pinnacle-odds-curl-openapi-recipes)
- [Rilevare gli steam move con l'API Pinnacle](/it/answers/detect-steam-moves-pinnacle-api)
- [Ruotare o revocare una chiave API PinnFeed](/it/answers/pinnacle-odds-api-key-rotation)
- [Solo prematch vs WS live+pre-match](/it/answers/pinnacle-prematch-vs-live-websocket)
- [SSE drop vs WebSocket Pinnacle](/it/answers/pinnacle-odds-sse-vs-websocket)
- [Steam chasing con gli alert di calo Pinnacle](/it/answers/steam-chasing-pinnacle-alerts)
- [Steam move in Python sul WebSocket](/it/answers/steam-move-detection-python-websocket)
- [Steam Pinnacle su Telegram](/it/answers/pinnacle-steam-telegram-alert)
- [Strumenti MCP di PinnFeed: riferimento](/it/answers/pinnacle-odds-mcp-tools-reference)
- [Testare il WebSocket delle quote con wscat](/it/answers/pinnacle-odds-websocket-wscat)
- [The Odds API ha un WebSocket?](/it/answers/the-odds-api-websocket)
- [Trigger temporale Sheets per quote Pinnacle](/it/answers/pinnacle-odds-sheets-time-driven-trigger)
- [Vibe-coda uno scanner +EV educativo](/it/answers/vibe-coding-ev-scanner)
- [Webhook vs WebSocket per quote Pinnacle](/it/answers/pinnacle-odds-webhook-vs-websocket)
- [WebSocket Pinnacle in Node.js: riconnessione](/it/answers/pinnacle-odds-websocket-nodejs-reconnect)
- [WebSocket Pinnacle: snapshot e delta](/it/answers/pinnacle-odds-websocket-snapshot-delta)
- [WebSocket quote Pinnacle in Kotlin (OkHttp)](/it/answers/pinnacle-odds-websocket-kotlin)
- [WebSocket quote Pinnacle: esempio Python](/it/answers/pinnacle-odds-websocket-python-example)
- [WS Pinnacle: prezzi stale e riconnessione](/it/answers/pinnacle-websocket-stale-price-reconnect)
*Contenuto educativo per maggiorenni (18+): non pronostici né promesse di guadagno. In Italia il gioco è regolato dall'ADM.*
## Domande frequenti
### Perché ci sono meno pagine che in inglese?
Traduciamo prima le domande più cercate. Il resto è nelle [risposte in inglese](/answers), con lo stesso codice.
### Da dove comincio?
Dalla [guida rapida](/it/quickstart) e da una [chiave gratuita](/signup), poi i [limiti per piano](/it/answers/pinnacle-odds-api-rate-limits).
---
Source: https://pinnfeed.io/it/answers/football-odds-feed-pinnacle
# Feed di quote calcio da Pinnacle
**Risposta:** il feed `sport=soccer` di PinnFeed porta i mercati calcio di Pinnacle: moneyline (1X2), spread (handicap asiatico), totale gol e totali squadra, per ogni periodo quotato da Pinnacle, prematch e live. Interroga `GET /v1/odds?sport=soccer` su qualsiasi piano, oppure ricevi ogni variazione in push sul WebSocket con Builder (99 €/mese).
## REST
```bash
export PINNFEED_KEY="ps_live_..."
curl -sS -H "x-api-key: $PINNFEED_KEY" \
"https://pinnfeed.io/v1/odds?sport=soccer&market=moneyline,spread,total&main=true&limit=50"
```
Filtra per id di `league` (elenco delle leghe con `GET /v1/events?sport=soccer`), `live=true` o `live=prematch`, oppure `q=` per il nome di una squadra.
## WebSocket (Builder)
```json
{ "type": "subscribe", "sports": ["soccer"], "markets": ["moneyline", "spread", "total"], "main": true }
```
Ricevi `subscribed`, poi frame `snapshot`, poi frame `delta` quando i prezzi si muovono. Il server invia un ping ogni 20 secondi; rispondi `{"type":"pong"}`. Client: [Python](/it/answers/pinnacle-odds-websocket-python-example), [riconnessione Node](/it/answers/pinnacle-odds-websocket-nodejs-reconnect).
## Piani
Free: 30 secondi di ritardo, 2 sport a scelta, mercati principali. Hobby (29 €/mese): REST in tempo reale. [Builder](/it/pricing#plan-builder): WebSocket, tutti i mercati, prop e storico delle chiusure. Prova di 3 giorni; carta richiesta, addebito dopo il giorno 3 salvo disdetta.
Pagine delle leghe: [Serie A](/it/answers/football-odds-feed-pinnacle), [Champions League](/it/answers/football-odds-feed-pinnacle).
*Contenuto educativo per maggiorenni (18+): non pronostici né promesse di guadagno. In Italia scommetti solo con operatori autorizzati ADM.*
## Domande frequenti
### Il feed include i risultati?
Gli eventi hanno `score`, `clock` e `status` quando Pinnacle li fornisce. PinnFeed è un feed di quote, non un fornitore di statistiche: niente formazioni né dati sui giocatori.
### Quali leghe sono coperte?
Tutto ciò che Pinnacle quota. Elenca leghe ed eventi attuali con `GET /v1/events?sport=soccer`.
### Altri bookmaker?
No. PinnFeed copre solo Pinnacle.
---
Source: https://pinnfeed.io/it/guides/pinnacle-odds-websocket-python-node
# Quote Pinnacle in tempo reale via WebSocket con Python e Node
In questa guida costruisci un client che tiene in memoria una copia live dei prezzi di Pinnacle: si connette, si iscrive, carica lo snapshot, applica ogni delta, risponde agli heartbeat e si riconnette da solo. Le altre guide (alert di steam, value betting, il bot Telegram) si basano su questo.
Ti serve una chiave PinnFeed sul piano **Builder** (il piano WebSocket, 99 €/mese, 3 giorni gratis). Con una chiave Free o Hobby puoi seguire gli esempi REST della [documentazione](/docs/rest) (in inglese).
## Passo 1 — Ottieni una chiave e mettila nell'ambiente
Crea una chiave nella [dashboard](/dashboard) ed esportala, così non finisce mai nel tuo codice:
```bash
export PINNFEED_KEY="ps_live_..."
```
## Passo 2 — Capire i frame
Dopo la connessione e l'invio di `subscribe`, il server manda:
1. `subscribed` e poi uno **snapshot** in parti (`part`, `parts`, `final`) con tutti gli eventi e i mercati che corrispondono ai tuoi filtri;
2. frame **delta**, ognuno con una lista `changes`: `upsert` contiene l'oggetto nuovo completo, `remove` solo il suo id;
3. un **ping** ogni 20 secondi. Rispondi con `{"type":"pong"}` o il server chiude il socket dopo 60 secondi di silenzio.
I mercati sono identificati da `id` (`eventId:key`), quindi un dizionario è tutto lo stato che ti serve. Ogni esito ha `decimal`, `american`, `fair` (quota equa senza margine) e `fairProb`. Il [riferimento del WebSocket](/docs/websocket) (in inglese) elenca tutti i campi.
## Passo 3 — Il client Python
Installa l'unica dipendenza con `pip install websockets` (Python 3.9+). Salvalo come `pinnfeed_stream.py`; le guide sullo steam e su Telegram lo importano.
```python
# pinnfeed_stream.py: mantiene una copia live del book di Pinnacle dal WebSocket di PinnFeed.
# pip install websockets (Python 3.9+)
import asyncio, json, os, random
import websockets
WS_URL = os.environ.get("PINNFEED_WS", "wss://pinnfeed.io/v1/stream")
KEY = os.environ["PINNFEED_KEY"]
SIDES = {"home", "away", "draw", "over", "under"}
class Book:
"""Eventi e mercati per id, aggiornati dai frame snapshot + delta."""
def __init__(self):
self.events, self.markets = {}, {}
def apply(self, msg, on_market=None):
if msg["type"] == "snapshot":
for e in msg["events"]:
self.events[e["id"]] = e
for m in msg["markets"]:
self.markets[m["id"]] = m
elif msg["type"] == "delta":
for c in msg["changes"]:
if c["kind"] == "event" and c["op"] == "upsert":
self.events[c["event"]["id"]] = c["event"]
elif c["kind"] == "event" and c["op"] == "remove":
self.events.pop(c["id"], None)
for mid in [k for k, m in self.markets.items() if m["eventId"] == c["id"]]:
del self.markets[mid]
elif c["kind"] == "market" and c["op"] == "upsert":
old = self.markets.get(c["market"]["id"])
self.markets[c["market"]["id"]] = c["market"]
if on_market:
on_market(old, c["market"], self.events.get(c["market"]["eventId"]))
elif c["kind"] == "market" and c["op"] == "remove":
self.markets.pop(c["id"], None)
async def stream(subscription, on_market=None, on_ready=None):
"""Si connette, si iscrive e tiene aggiornato il book; si riconnette con backoff all'infinito."""
delay = 1
while True:
book = Book()
try:
async with websockets.connect(WS_URL, additional_headers={"x-api-key": KEY}, max_size=None) as ws:
await ws.send(json.dumps({"type": "subscribe", **subscription}))
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "ping":
await ws.send('{"type":"pong"}')
elif msg["type"] == "error":
print("server error:", msg["code"], msg["message"])
elif msg["type"] in ("snapshot", "delta"):
book.apply(msg, on_market if msg["type"] == "delta" else None)
if msg["type"] == "snapshot" and msg.get("final") and on_ready:
on_ready(book)
delay = 1
except (OSError, websockets.ConnectionClosed) as e:
print(f"disconnected ({e}); reconnecting in {delay}s")
await asyncio.sleep(delay + random.random())
delay = min(delay * 2, 30)
if __name__ == "__main__":
def ready(book):
print(f"book ready: {len(book.events)} events, {len(book.markets)} markets")
def moved(old, new, event):
if old and event:
for o_old, o_new in zip(old["outcomes"], new["outcomes"]):
if o_new["name"] in SIDES and o_old["decimal"] != o_new["decimal"]:
print(f'{event["home"]} v {event["away"]} {new["type"]} {o_new["name"]}: '
f'{o_old["decimal"]} -> {o_new["decimal"]} (fair {o_new["fair"]})')
asyncio.run(stream({"sports": ["soccer"], "markets": ["moneyline"], "main": True, "specials": False}, moved, ready))
```
Eseguilo con `python pinnfeed_stream.py`. Vedrai `book ready: N events, M markets` e poi una riga per ogni movimento di prezzo.
## Passo 4 — Il client Node
La stessa logica in Node 18+ con `npm install ws`. Salvalo come `stream.mjs` ed esegui `node stream.mjs`.
```javascript
// stream.mjs: book di Pinnacle live dal WebSocket di PinnFeed (Node 18+).
// npm install ws
import WebSocket from 'ws';
const WS_URL = process.env.PINNFEED_WS || 'wss://pinnfeed.io/v1/stream';
const KEY = process.env.PINNFEED_KEY;
const SIDES = new Set(['home', 'away', 'draw', 'over', 'under']);
const events = new Map();
const markets = new Map();
function connect(delay = 1000) {
const ws = new WebSocket(WS_URL, { headers: { 'x-api-key': KEY }, perMessageDeflate: true });
ws.on('open', () => {
delay = 1000;
ws.send(JSON.stringify({ type: 'subscribe', sports: ['soccer', 'tennis'], markets: ['moneyline'], main: true, specials: false }));
});
ws.on('message', (raw) => {
const msg = JSON.parse(raw);
if (msg.type === 'ping') return ws.send('{"type":"pong"}');
if (msg.type === 'error') return console.error('server error:', msg.code, msg.message);
if (msg.type === 'snapshot') {
if (msg.part === 1) { events.clear(); markets.clear(); }
msg.events.forEach((e) => events.set(e.id, e));
msg.markets.forEach((m) => markets.set(m.id, m));
if (msg.final) console.log(`book ready: ${events.size} events, ${markets.size} markets`);
}
if (msg.type === 'delta') {
for (const c of msg.changes) {
if (c.kind === 'event') c.op === 'upsert' ? events.set(c.event.id, c.event) : events.delete(c.id);
if (c.kind === 'market' && c.op === 'remove') markets.delete(c.id);
if (c.kind === 'market' && c.op === 'upsert') {
const old = markets.get(c.market.id);
markets.set(c.market.id, c.market);
const ev = events.get(c.market.eventId);
if (!old || !ev) continue;
c.market.outcomes.forEach((o, i) => {
const prev = old.outcomes[i];
if (prev && SIDES.has(o.name) && prev.decimal !== o.decimal) console.log(`${ev.home} v ${ev.away} ${o.name}: ${prev.decimal} -> ${o.decimal} (fair ${o.fair})`);
});
}
}
}
});
ws.on('close', (code) => {
const wait = Math.min(delay * 2, 30000);
console.log(`closed (${code}); reconnecting in ${wait / 1000}s`);
setTimeout(() => connect(wait), wait + Math.random() * 1000);
});
ws.on('error', (e) => console.error('ws error:', e.message));
}
connect();
```
## Passo 5 — Restringi l'iscrizione
I filtri si applicano lato server, quindi ricevi ed elabori solo ciò che chiedi:
```json
{ "type": "subscribe", "sports": ["tennis"], "live": true, "markets": ["moneyline", "total"], "main": true }
```
- `sports`: slug o id; `leagues` ed `events`: liste di id.
- `live`: `true` solo live, `false` solo pre-match; se lo ometti, entrambi.
- `main: true` tiene solo il testa a testa, l'handicap e il totale principali di ogni evento.
- Inviare di nuovo `subscribe` sostituisce l'iscrizione e manda un nuovo snapshot.
## Checklist per la produzione
- **Riconnettiti con backoff e jitter** (entrambi i client lo fanno: 1 s, 2 s, 4 s, fino a 30 s) e ricostruisci dal nuovo snapshot.
- **Attiva la compressione**: `websockets` di Python negozia `permessage-deflate` di default; in Node passa `perMessageDeflate: true`. Gli snapshot si riducono di 5–10 volte.
- **Leggi in fretta.** Se per un client lento si accumulano più di 16 MB, il server lo chiude con il codice `4008`. Fai il lavoro pesante fuori dal ciclo del socket.
- **Usa `seq` per i log, non per rilevare buchi**: i filtri saltano i lotti a cui non sei iscritto.
## Domande frequenti
### Quale piano mi serve per il WebSocket?
Builder (99 €/mese) o superiore. Le chiavi Free e Hobby ricevono `403 plan_lacks_ws` sul WebSocket e possono usare il REST.
### Quante connessioni posso aprire?
Builder consente 3 connessioni WebSocket per account, Pro 10, Enterprise 50 (altre su richiesta).
### Perché alcuni esiti hanno id di partecipanti invece di home o away?
Gli speciali e alcuni antepost elencano partecipanti invece di squadra di casa e ospite. Iscriviti con `"specials": false` e filtra su `home`, `away`, `draw`, `over` e `under` se vuoi solo le linee delle partite, come fanno gli esempi.
---
Source: https://pinnfeed.io/it/guides/dropping-odds-steam-detection
# Rileva dropping odds e steam move su Pinnacle in tempo reale
Uno **steam move** è un calo di quota rapido e marcato presso un bookmaker che fa il mercato, come Pinnacle, di solito perché è entrato denaro sharp su un lato. I bookmaker soft spesso restano indietro di secondi o minuti, ed è per questo che gli alert di steam sono tra i segnali più utili che puoi ricavare da un feed live. In questa guida costruisci un rilevatore sul WebSocket di PinnFeed. È uno strumento statistico, non un sistema di pronostici.
## Passo 1 — Definisci cos'è uno steam
Una definizione pratica che puoi regolare:
- la quota decimale di un esito **scende almeno del 5%** rispetto al massimo degli ultimi **2 minuti**;
- la **puntata massima** del mercato è almeno 100, perché Pinnacle alza i limiti man mano che si fida di un prezzo, quindi i movimenti nei mercati poco liquidi sono più rumorosi;
- mandi un alert **una volta per esito e finestra**, non a ogni tick.
## Passo 2 — Ricevi il book in streaming
Usa il client Python della [guida Python e Node](/it/guides/pinnacle-odds-websocket-python-node). Salvalo come `pinnfeed_stream.py` accanto allo script qui sotto; chiama `on_market(old, new, event)` ogni volta che un mercato cambia.
## Passo 3 — Segui il massimo mobile di ogni esito
Tieni una deque corta di `(timestamp, price)` per mercato ed esito, scarta ciò che è più vecchio della finestra e confronta il prezzo attuale con il massimo della finestra:
```python
# steam.py: segnala gli steam move di Pinnacle (cali di quota rapidi e forti) dal WebSocket live.
# Usa pinnfeed_stream.py della guida Python/Node. pip install websockets
import asyncio, collections, os, time
from pinnfeed_stream import stream, SIDES
WINDOW_S = int(os.environ.get("WINDOW_S", 120)) # finestra di osservazione
MIN_DROP = float(os.environ.get("MIN_DROP", 0.05)) # alert quando la quota scende del 5% o più nella finestra
MIN_STAKE = float(os.environ.get("MIN_STAKE", 100)) # ignora i mercati poco liquidi: la puntata massima di Pinnacle è un segnale di fiducia
history = collections.defaultdict(collections.deque) # (id mercato, esito) -> deque[(ts, decimal)]
alerted = {}
def on_market(old, new, event):
if not event or (new.get("maxStake") or 0) < MIN_STAKE:
return
now = time.time()
for o in new["outcomes"]:
if o["name"] not in SIDES:
continue
h = history[(new["id"], o["name"])]
h.append((now, o["decimal"]))
while h and now - h[0][0] > WINDOW_S:
h.popleft()
high = max(p for _, p in h)
drop = 1 - o["decimal"] / high
key = (new["id"], o["name"])
if drop >= MIN_DROP and now - alerted.get(key, 0) > WINDOW_S:
alerted[key] = now
pts = o.get("points")
line = "" if pts is None else f" {pts:g}" if new["type"] == "total" else f" {pts:+g}"
print(f'STEAM {event["sport"]} | {event["home"]} v {event["away"]} | {new["type"]}{line} {o["name"]}: '
f'{high:.3f} -> {o["decimal"]:.3f} (-{drop:.1%} in {WINDOW_S}s) fair {o["fair"]:.3f} max stake {new["maxStake"]}')
asyncio.run(stream({"sports": ["soccer", "tennis", "basketball"], "markets": ["moneyline", "spread", "total"],
"main": True, "specials": False}, on_market))
```
Eseguilo con `python steam.py`. Le soglie sono variabili d'ambiente; per esempio `MIN_DROP=0.03 WINDOW_S=300 python steam.py` per un 3% in cinque minuti. Una riga tipica:
```text
STEAM tennis | Sebastian Baez v Daniil Glinka | moneyline away: 2.260 -> 2.050 (-9.3% in 120s) fair 2.143 max stake 975
```
## Passo 4 — Oppure interroga l'endpoint REST
Se ti basta una lista periodica, `GET /v1/drops` restituisce i cali più forti in una finestra mobile, calcolati lato server:
```bash
curl -H "x-api-key: $PINNFEED_KEY" "https://pinnfeed.io/v1/drops?sport=soccer&live=true&minutes=10&min_pct=5"
```
Ogni riga contiene evento, mercato, linea, esito, `from`, `to`, `dropPct` e `movedAt`. Funziona su tutti i piani, anche su Free con i suoi 30 secondi di ritardo.
## Passo 5 — Dagli alert ai pronostici
- **Confronta con i bookmaker soft.** Uno steam serve solo dove il prezzo soft non si è ancora mosso. La [guida al value betting](/it/guides/value-betting-no-vig-fair-odds) mostra come quantificare quel vantaggio con le quote eque di Pinnacle.
- **Preferisci il pre-match per il ritardo dei bookmaker soft**; nel live i movimenti dipendono spesso dal punteggio più che dal denaro sharp.
- **Misurati** con il [closing line value](/it/guides/closing-line-value-clv-tracking): se i tuoi pronostici di steam battono in media la chiusura, il segnale è reale.
- **Pubblicali**: il [bot di pronostici per Telegram](/it/guides/telegram-picks-bot) e il [bot di pronostici per Discord](/it/guides/discord-picks-bot) inviano questi alert a un canale.
## Domande frequenti
### Che differenza c'è tra dropping odds e steam?
Le dropping odds sono qualsiasi quota in calo. Lo steam è un calo rapido e significativo presso un bookmaker sharp, di solito provocato da denaro informato, che poi tende a propagarsi agli altri bookmaker.
### Perché usare Pinnacle per rilevare lo steam?
Pinnacle accetta limiti alti e muove i prezzi in base all'azione sharp, quindi i suoi movimenti sono il miglior segnale del mercato. I bookmaker soft li copiano o arrivano dopo.
### Posso farlo senza il WebSocket?
Sì, facendo polling su `/v1/drops`, che funziona su tutti i piani. Il WebSocket vede ogni movimento quando avviene; il polling lo vede solo alla tua richiesta successiva.
---
Source: https://pinnfeed.io/it/guides/value-betting-no-vig-fair-odds
# Value bet sui bookmaker soft con le quote eque di Pinnacle
I prezzi di Pinnacle sono quanto di più vicino a una probabilità reale offra il mercato delle scommesse. Togliendo il margine ottieni una **quota equa**; qualsiasi bookmaker soft che paga più di quella quota offre una scommessa a valore atteso positivo (+EV). PinnFeed calcola la quota equa su ogni mercato, quindi il calcolo si riduce a una moltiplicazione. Il +EV è un concetto statistico di lungo periodo, non una garanzia di vincita.
## Passo 1 — Capire la quota equa
Per un mercato con quote decimali `d_i`:
```text
implied_i = 1 / d_i
margin = Σ implied_i − 1
fairProb_i = implied_i / Σ implied_j (metodo moltiplicativo)
fair_i = 1 / fairProb_i
```
Ogni esito dell'API ha già `fair` e `fairProb`, e ogni mercato ha `margin`. Ci sono anche i prezzi grezzi, se preferisci applicare il metodo della potenza o quello di Shin.
## Passo 2 — Calcola il valore atteso
Se un bookmaker soft offre la quota decimale `S` su un esito con probabilità equa `p`:
```text
EV = S × p − 1
```
Con `S = 2.30` e `p = 0.488` (quota equa 2.049), l'EV è +12,3%: nel lungo periodo ti aspetti 12,3 centesimi per ogni euro puntato. Quasi tutti fissano una soglia dell'1–3% per assorbire il rumore e il tempo che serve a piazzare la giocata.
## Passo 3 — Calcola la puntata
Il Kelly pieno (`(S·p − 1) / (S − 1)`) è troppo aggressivo con probabilità stimate. Un quarto di Kelly è un compromesso comune ed è quello che stampa lo script.
## Passo 4 — Esegui lo script
Riempi `SOFT` con le quote raccolte da un bookmaker soft (a mano, da un comparatore o da un'altra API), con i nomi delle squadre scritti come li scrive PinnFeed. Installa `requests` ed esegui `python value.py`:
```python
# value.py: trova quote +EV su un bookmaker soft usando le quote eque senza margine di Pinnacle.
# pip install requests
import os, requests
BASE = os.environ.get("PINNFEED_BASE", "https://pinnfeed.io")
KEY = os.environ["PINNFEED_KEY"]
# Quote raccolte da un bookmaker soft: (squadra di casa, squadra ospite, esito) -> quota decimale.
SOFT = {
("Osasuna", "Malaga", "home"): 1.95,
("Colon", "Defensor Sporting", "away"): 2.30,
}
MIN_EV = 0.02 # vantaggio del 2%
def kelly(price, p, fraction=0.25):
"""Puntata di Kelly frazionario come quota del bankroll."""
return max(0.0, fraction * (price * p - 1) / (price - 1))
r = requests.get(f"{BASE}/v1/odds", headers={"x-api-key": KEY},
params={"sport": "soccer", "market": "moneyline", "main": "true", "limit": 1000}, timeout=20)
r.raise_for_status()
for ev in r.json()["events"]:
for m in ev["markets"]:
for o in m["outcomes"]:
soft = SOFT.get((ev["home"], ev["away"], o["name"]))
if not soft:
continue
ev_pct = soft * o["fairProb"] - 1 # valore atteso per unità puntata
flag = "VALUE" if ev_pct >= MIN_EV else "no edge"
print(f'{flag:8} {ev["home"]} v {ev["away"]} {o["name"]}: soft {soft} vs Pinnacle {o["decimal"]} '
f'(fair {o["fair"]:.3f}, margin {m["margin"]:.1%}) EV {ev_pct:+.1%} '
f'kelly/4 {kelly(soft, o["fairProb"]):.2%}')
```
L'output è così:
```text
VALUE Colon v Defensor Sporting away: soft 2.3 vs Pinnacle 1.8065 (fair 2.049, margin 13.4%) EV +12.3% kelly/4 2.36%
```
La chiamata REST funziona su tutti i piani; su Free i prezzi hanno 30 secondi. Per il value nel live li vuoi in diretta: fai lo stesso confronto dentro il client WebSocket della [guida Python e Node](/it/guides/pinnacle-odds-websocket-python-node), con Builder.
## Passo 5 — Verifica con il CLV
Nel breve periodo i risultati sono soprattutto varianza. La risposta onesta più rapida è il **closing line value**: il prezzo che hai preso ha battuto la quota equa di chiusura di Pinnacle? La [guida al CLV](/it/guides/closing-line-value-clv-tracking) registra ogni scommessa e la misura.
## Domande frequenti
### Perché usare Pinnacle come riferimento?
Pinnacle lavora con margini bassi e limiti alti e muove i prezzi con il denaro sharp, quindi il suo prezzo senza margine è molto usato come migliore stima pubblica della probabilità reale.
### Che metodo usa PinnFeed per togliere il margine?
Il metodo moltiplicativo (proporzionale). Ogni esito include le quote decimali e americane grezze, quindi puoi usare un altro metodo.
### PinnFeed fornisce quote dei bookmaker soft?
No. PinnFeed porta solo Pinnacle. Abbinalo alle tue quote dei bookmaker soft o a un'API multi-bookmaker come The Odds API.
---
Source: https://pinnfeed.io/it/guides/closing-line-value-clv-tracking
# Misura il tuo closing line value rispetto alla chiusura di Pinnacle
Il **closing line value (CLV)** confronta il prezzo che hai preso con l'ultimo prezzo del mercato prima del calcio d'inizio. Battere con costanza la quota equa di chiusura di Pinnacle è il segnale precoce più solido che il tuo metodo ha un vantaggio, molto prima che il tuo bilancio possa dimostrarlo, anche se non è mai una garanzia di guadagno. PinnFeed salva il prezzo di chiusura di Pinnacle di ogni mercato quando inizia l'evento e lo serve da `/v1/closing`.
## Passo 1 — La formula
```text
CLV = price_taken / closing_fair_price − 1
```
Usa il prezzo di chiusura **senza margine**, non quello grezzo: battere un prezzo che contiene ancora il margine di Pinnacle è più facile e gonfia il tuo vantaggio. Se hai preso 2.10 e il mercato ha chiuso a una quota equa di 1.95, il tuo CLV è +7,7%.
## Passo 2 — Registra ogni scommessa
Ogni scommessa richiede l'id dell'evento, la chiave del mercato e l'esito. Arrivano tutti e tre dall'API: l'`id` dell'evento, la `key` del mercato (`s;0;m` è il testa a testa della partita intera, `s;0;ou;2.5` l'over/under 2,5 della partita) e il `name` dell'esito (`home`, `away`, `draw`, `over`, `under`).
## Passo 3 — Esegui il tracker
Installa `requests`, salva lo script come `clv.py` e registra le scommesse man mano che le fai:
```python
# clv.py: registra le tue scommesse e misura il closing line value (CLV) rispetto alla chiusura senza margine di Pinnacle.
# pip install requests Uso:
# python clv.py bet es. bet 1640141281 "s;0;m" home 2.10
# python clv.py report
import os, sqlite3, sys, requests
BASE = os.environ.get("PINNFEED_BASE", "https://pinnfeed.io")
KEY = os.environ["PINNFEED_KEY"]
db = sqlite3.connect(os.environ.get("CLV_DB", "bets.db"))
db.execute("CREATE TABLE IF NOT EXISTS bets (event_id INTEGER, market_key TEXT, outcome TEXT, price REAL, "
"close_fair REAL, placed_at TEXT DEFAULT CURRENT_TIMESTAMP)")
def closing_fair(event_id, market_key, outcome):
r = requests.get(f"{BASE}/v1/closing/{event_id}", headers={"x-api-key": KEY}, timeout=20)
if r.status_code == 404:
return None # non ancora chiuso (o mai acquisito)
r.raise_for_status()
for rec in r.json()["markets"]:
if rec["market"]["key"] == market_key:
for o in rec["market"]["outcomes"]:
if o["name"] == outcome:
return o["fair"]
return None
if sys.argv[1:2] == ["bet"]:
_, _, event_id, market_key, outcome, price = sys.argv
db.execute("INSERT INTO bets (event_id, market_key, outcome, price) VALUES (?,?,?,?)",
(int(event_id), market_key, outcome, float(price)))
db.commit()
print("logged")
else:
rows = db.execute("SELECT rowid, event_id, market_key, outcome, price, close_fair FROM bets").fetchall()
clvs = []
for rowid, event_id, key, outcome, price, close in rows:
if close is None:
close = closing_fair(event_id, key, outcome)
if close:
db.execute("UPDATE bets SET close_fair=? WHERE rowid=?", (close, rowid))
if close:
clv = price / close - 1
clvs.append(clv)
print(f"{event_id} {key} {outcome}: took {price}, closed fair {close:.3f} -> CLV {clv:+.2%}")
else:
print(f"{event_id} {key} {outcome}: took {price}, waiting for close")
db.commit()
if clvs:
print(f"average CLV over {len(clvs)} bets: {sum(clvs) / len(clvs):+.2%}")
```
```bash
python clv.py bet 1640229582 "s;0;m" home 2.10
python clv.py report
```
```text
1640229582 s;0;m home: took 2.1, closed fair 3.181 -> CLV -33.99%
999 s;0;m home: took 1.9, waiting for close
average CLV over 1 bets: -33.99%
```
Lancia `report` da cron dopo i calci d'inizio; il prezzo di chiusura di ogni scommessa viene richiesto una volta e salvato.
## Passo 4 — Interpreta il risultato
- Su qualche centinaio di scommesse, un CLV medio di **+2% o più** è un indizio forte di un vantaggio reale.
- CLV negativo con profitto positivo di solito è fortuna. Tende a svanire.
- Dividi il CLV per sport, mercato e anticipo della giocata: ti dice da dove viene davvero il tuo vantaggio.
## Passo 5 — Scarica una giornata intera
Per ricerca o backtest, chiedi tutte le linee di chiusura di un giorno UTC:
```bash
curl -H "x-api-key: $PINNFEED_KEY" "https://pinnfeed.io/v1/closing?date=2026-11-08&sport=soccer&main=true"
```
## Domande frequenti
### Quale piano include le quote di chiusura?
Lo storico delle quote di chiusura è incluso da Builder (99 €/mese) e in Pro ed Enterprise.
### Quando viene acquisito il prezzo di chiusura?
All'inizio dell'evento: per ogni mercato si salva l'ultimo prezzo pre-match con l'ora di acquisizione.
### Fin dove arriva l'archivio?
Parte dal giorno di lancio del servizio e cresce ogni giorno. I piani Enterprise possono esportarlo in blocco in CSV o Parquet.
---
Source: https://pinnfeed.io/it/guides/telegram-picks-bot
# Crea un bot di pronostici per Telegram con le quote Pinnacle live
Questo bot osserva i prezzi di Pinnacle sul WebSocket di PinnFeed e pubblica un messaggio in un canale Telegram ogni volta che un mercato va in steam, cioè quando la sua quota scende del 5% o più in due minuti in un mercato con una puntata massima ragionevole. È un solo file di circa 70 righe, senza librerie Telegram: chiama direttamente la Bot API.
## Passo 1 — Crea il bot
1. Su Telegram apri **@BotFather**, invia `/newbot` e segui le istruzioni. Copia il token.
2. Crea un canale e aggiungi il bot come **amministratore** con il permesso di pubblicare.
3. Usa il nome pubblico del canale (`@mychannel`) come chat id, oppure l'id numerico per una chat privata.
## Passo 2 — Configura l'ambiente
```bash
export PINNFEED_KEY="ps_live_..." # piano Builder (WebSocket)
export TELEGRAM_TOKEN="123456:ABC..." # da @BotFather
export TELEGRAM_CHAT="@mychannel"
npm install ws
```
Se lasci `TELEGRAM_TOKEN` vuoto, il bot gira in **modalità di prova**: stampa i messaggi invece di inviarli.
## Passo 3 — Il bot
Salvalo come `telegram-picks-bot.mjs`:
```javascript
// telegram-picks-bot.mjs: pubblica gli steam move di Pinnacle in un canale Telegram come "pronostici".
// npm install ws Node 18+ (global fetch)
// ambiente: PINNFEED_KEY, TELEGRAM_TOKEN (da @BotFather), TELEGRAM_CHAT (es. @mychannel o un id chat)
import WebSocket from 'ws';
const WS_URL = process.env.PINNFEED_WS || 'wss://pinnfeed.io/v1/stream';
const { PINNFEED_KEY, TELEGRAM_TOKEN, TELEGRAM_CHAT } = process.env;
const MIN_DROP = Number(process.env.MIN_DROP || 0.05); // calo del 5%...
const WINDOW_MS = Number(process.env.WINDOW_MS || 120000); // ...entro 2 minuti
const SIDES = new Set(['home', 'away', 'draw', 'over', 'under']);
const events = new Map();
const highs = new Map(); // "marketId|outcome" -> [{t, p}]
const sent = new Map(); // "marketId|outcome" -> ora dell'ultimo alert
async function post(text) {
if (!TELEGRAM_TOKEN) return console.log('[dry run]', text);
const r = await fetch(`https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage`, {
method: 'POST', headers: { 'content-type': 'application/json' },
body: JSON.stringify({ chat_id: TELEGRAM_CHAT, text, disable_web_page_preview: true }),
});
if (!r.ok) console.error('telegram', r.status, await r.text());
}
function check(m) {
const ev = events.get(m.eventId);
if (!ev || (m.maxStake ?? 0) < 100) return;
const now = Date.now();
for (const o of m.outcomes) {
if (!SIDES.has(o.name)) continue;
const k = `${m.id}|${o.name}`;
const h = (highs.get(k) || []).filter((x) => now - x.t < WINDOW_MS);
h.push({ t: now, p: o.decimal });
highs.set(k, h);
const high = Math.max(...h.map((x) => x.p));
const drop = 1 - o.decimal / high;
if (drop < MIN_DROP || now - (sent.get(k) || 0) < WINDOW_MS) continue;
sent.set(k, now);
const pick = o.name === 'home' ? ev.home : o.name === 'away' ? ev.away : o.name;
const line = o.points == null ? '' : m.type === 'total' ? ` ${o.points}` : ` ${o.points > 0 ? '+' : ''}${o.points}`;
post(`📉 ${ev.sport.toUpperCase()} · ${ev.league?.name ?? ''}\n${ev.home} v ${ev.away}\n` +
`Pick: ${pick} (${m.type}${line})\nPinnacle ${high.toFixed(2)} → ${o.decimal.toFixed(2)} (−${(drop * 100).toFixed(1)}%)\n` +
`Fair now ${o.fair.toFixed(2)} · max stake ${m.maxStake}`);
}
}
function connect(delay = 1000) {
const ws = new WebSocket(WS_URL, { headers: { 'x-api-key': PINNFEED_KEY }, perMessageDeflate: true });
ws.on('open', () => {
delay = 1000;
ws.send(JSON.stringify({ type: 'subscribe', sports: ['soccer', 'tennis', 'basketball'], markets: ['moneyline', 'spread', 'total'], main: true, specials: false }));
});
ws.on('message', (raw) => {
const msg = JSON.parse(raw);
if (msg.type === 'ping') return ws.send('{"type":"pong"}');
if (msg.type === 'snapshot') msg.events.forEach((e) => events.set(e.id, e));
if (msg.type === 'delta') for (const c of msg.changes) {
if (c.kind === 'event') c.op === 'upsert' ? events.set(c.event.id, c.event) : events.delete(c.id);
if (c.kind === 'market' && c.op === 'upsert') check(c.market);
}
});
ws.on('close', () => setTimeout(() => connect(Math.min(delay * 2, 30000)), delay));
ws.on('error', (e) => console.error('ws error:', e.message));
}
connect();
```
## Passo 4 — Avvialo e provalo
```bash
node telegram-picks-bot.mjs
```
Un messaggio si presenta così:
```text
📉 SOCCER · Italy - Serie A
Udinese v Fiorentina
Pick: Udinese (spread +0.25)
Pinnacle 1.88 → 1.70 (−9.5%)
Fair now 1.83 · max stake 150
```
Regola il volume con `MIN_DROP` e `WINDOW_MS`; per esempio `MIN_DROP=0.08` per meno alert ma più forti.
## Passo 5 — Tienilo acceso
- Eseguilo con `systemd`, `pm2` o un container che si riavvia in caso di errore; il bot si riconnette da solo al WebSocket.
- Telegram consente circa 20 messaggi al minuto per gruppo o canale. Alza `MIN_DROP` se ricevi risposte `429`.
- Pubblica il tuo storico con onestà: registra ogni pronostico e misuralo con il [closing line value](/it/guides/closing-line-value-clv-tracking).
## Domande frequenti
### Quale piano di PinnFeed serve al bot?
Builder (99 €/mese) o superiore, perché usa il WebSocket. Per un bot più lento su Free o Hobby, fai polling su `/v1/drops` ogni minuto.
### Posso pubblicare i pronostici su Discord?
Sì. Sostituisci la funzione `post` con un POST all'URL di un webhook Discord con il body `{"content": text}`. Il bot completo (embed, coda di invio e gestione dei 429) è nella [guida al bot di pronostici per Discord](/it/guides/discord-picks-bot).
### È consentito pubblicare pronostici?
Le regole su pronostici e pubblicità del gioco cambiano da paese a paese; in Italia, per esempio, il Decreto Dignità (2018) vieta la pubblicità del gioco con vincite in denaro. Verifica le regole dove ti trovi tu e dove si trova il tuo pubblico, rivolgiti solo a maggiori di 18 anni e non presentare mai i pronostici come sicuri. Questa non è una consulenza legale.
---
Source: https://pinnfeed.io/it/guides/pinnacle-odds-chatgpt-claude-mcp
# Quote Pinnacle live dentro ChatGPT e Claude con MCP
PinnFeed ha un server [Model Context Protocol](https://modelcontextprotocol.io) ospitato. Lo aggiungi una volta al tuo assistente e questo può consultare quote Pinnacle live e pre-match, dropping odds, quote eque e quote di chiusura quando glielo chiedi. Niente dati da incollare, niente codice.
## Passo 1 — Una chiave per l'assistente
Crea una chiave dedicata nella [dashboard](/dashboard) con il nome dell'assistente (per esempio "claude"), così puoi revocarla da sola. Ogni chiamata a uno strumento conta come una richiesta REST del tuo piano; Free funziona con dati in ritardo di 30 secondi.
## Passo 2 — Aggiungi il server
**Claude Code**
```bash
claude mcp add --transport http pinnfeed https://pinnfeed.io/mcp --header "Authorization: Bearer YOUR_KEY"
```
**Claude (web e desktop):** Settings → Connectors → Add custom connector, URL `https://pinnfeed.io/mcp?key=YOUR_KEY`.
**ChatGPT:** Settings → Apps & Connectors → Advanced → attiva Developer mode e crea un connettore con l'URL del server `https://pinnfeed.io/mcp?key=YOUR_KEY` e senza autenticazione.
**Cursor** (`~/.cursor/mcp.json`):
```json
{ "mcpServers": { "pinnfeed": { "url": "https://pinnfeed.io/mcp", "headers": { "Authorization": "Bearer YOUR_KEY" } } } }
```
Gli snippet per VS Code Copilot e Codex CLI sono nella [documentazione MCP](/docs/mcp) (in inglese).
## Passo 3 — Chiedi
L'assistente sceglie lo strumento. Prompt che funzionano bene (puoi scriverli in italiano):
- «Quali quote del calcio sono scese di più su Pinnacle negli ultimi 15 minuti?» (`get_drops`)
- «Mostrami i testa a testa del tennis live con la quota equa senza margine e il margine.» (`get_live_odds`)
- «Qual è la quota equa di Inter-Milan e qual è la puntata massima?» (`search_events` e poi `get_event`)
- «Un bookmaker soft offre 2.30 sulla vittoria in trasferta in Colon-Defensor Sporting. È +EV rispetto a Pinnacle?» (`get_event`, poi l'assistente fa il conto)
- «Dammi le quote di chiusura dell'evento 1640229582.» (`get_closing_odds`, da Builder in su)
## Passo 4 — Provalo senza assistente
Il server è JSON-RPC su HTTP, quindi puoi provare qualsiasi strumento con curl:
```bash
curl -s https://pinnfeed.io/mcp -H "Authorization: Bearer $PINNFEED_KEY" \
-H "content-type: application/json" -H "accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_drops","arguments":{"sport":"soccer","minutes":15}}}'
```
Il risultato è un blocco di testo JSON con i cali: evento, mercato, linea, esito, `from`, `to`, `dropPct` e `movedAt`.
## Passo 5 — Passa al codice
Quando una domanda diventa una strategia, portala nel codice: la [guida allo steam](/it/guides/dropping-odds-steam-detection) e la [guida al value betting](/it/guides/value-betting-no-vig-fair-odds) fanno la stessa cosa in continuo sul WebSocket.
## Domande frequenti
### Quali strumenti espone il server MCP di PinnFeed?
`get_account`, `list_sports`, `search_events`, `get_live_odds`, `get_prematch_odds`, `get_event`, `get_drops` e `get_closing_odds`.
### Il server MCP richiede un piano a pagamento?
No. Funziona su tutti i piani con i rispettivi limiti: Free ha 30 secondi di ritardo e 1.000 richieste al giorno. Le quote di chiusura richiedono Builder o superiore.
### È sicuro mettere la mia chiave in un URL?
Trattala come una password. Usa una chiave dedicata per ogni assistente e revocala dalla dashboard se viene esposta.
---
Source: https://pinnfeed.io/it/guides/pinnacle-odds-google-sheets
# Quote Pinnacle in Google Sheets
Questa guida scrive le quote 1X2 del calcio di Pinnacle in un foglio Google Sheets: una riga per partita, con quote decimali, quote eque senza margine e il margine del mercato. Un attivatore a tempo aggiorna il foglio ogni 15 minuti. Lo script usa l'API REST di PinnFeed, quindi funziona sul piano **Free** (0 €, 30 secondi di ritardo, 1.000 richieste/giorno).
## Passo 1 — Ottieni una chiave Free
1. Crea un account su [pinnfeed.io](/signup) e apri la [dashboard](/dashboard).
2. Crea una chiave e copiala. Le chiavi hanno la forma `ps_live_…`.
3. Su Free, scegli fino a due sport nella dashboard. Lo script usa il calcio (`soccer`) di default; cambia `SPORT` se ne hai scelto un altro.
Per Sheets non ti serve Builder. Builder (99 €/mese, il piano WebSocket) è per client push in tempo reale come quelli della [guida Python e Node](/it/guides/pinnacle-odds-websocket-python-node).
## Passo 2 — Crea il foglio di calcolo
1. Crea un nuovo foglio Google Sheets.
2. Rinomina il primo foglio in **Odds** (nome esatto; lo script lo cerca così).
3. Apri **Estensioni → Apps Script**. Cancella la funzione di esempio `myFunction` e lascia il progetto vuoto per il passo successivo.
## Passo 3 — Incolla lo script e imposta le proprietà
Incolla questo in `Code.gs`:
```javascript
// Google Apps Script: Estensioni → Apps Script, incolla questo file.
// Proprietà dello script (Impostazioni progetto → Proprietà dello script):
// PINNFEED_BASE = https://pinnfeed.io
// PINNFEED_KEY = ps_live_...
// Crea un foglio chiamato "Odds", esegui refreshOdds una volta, poi aggiungi un attivatore ogni 15 minuti.
const PROPS = PropertiesService.getScriptProperties();
const BASE = PROPS.getProperty('PINNFEED_BASE') || 'https://pinnfeed.io';
const KEY = PROPS.getProperty('PINNFEED_KEY');
const SPORT = 'soccer'; // cambialo in basketball, tennis, … (deve essere nel tuo piano)
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; // se la chiamata fallisce, il foglio resta com'è
}
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);
}
```
Poi apri l'ingranaggio del progetto (**Impostazioni progetto**) e, in **Proprietà dello script**, aggiungi:
| Proprietà | Valore |
|---|---|
| `PINNFEED_KEY` | la tua chiave (`ps_live_…`) |
| `PINNFEED_BASE` | `https://pinnfeed.io` (opzionale; è il valore predefinito) |
Non incollare mai la chiave nelle celle del foglio e non condividere pubblicamente il progetto Apps Script.
## Passo 4 — Eseguilo una volta e autorizzalo
1. Scegli `refreshOdds` nel menu delle funzioni e premi **Esegui**.
2. Google ti chiederà il permesso di connettersi a un servizio esterno e modificare il foglio. Concedilo per il tuo account.
3. Ricarica il foglio. Il foglio Odds dovrebbe mostrare le colonne `Starts`, `League`, `Home`, `Away`, `1`, `X`, `2`, le tre quote eque, `Margin` ed `Event id`.
Se una chiamata fallisce (chiave sbagliata, limite di richieste, sport fuori dal tuo piano), lo script registra un avviso e **lascia le righe precedenti com'erano**, così un minuto storto non svuota mai la tua tabella.
## Passo 5 — Aggiungi un attivatore ogni 15 minuti
1. In Apps Script apri **Attivatori** (icona dell'orologio) → **Aggiungi attivatore**.
2. Funzione: `refreshOdds`. Origine evento: **Basato sul tempo**. Tipo: **Timer minuti**. Intervallo: **Ogni 15 minuti**.
3. Salva.
Sono 96 chiamate al giorno per uno sport, ben sotto le 1.000 richieste/giorno e 1 req/s del piano Free. Due sport ogni 30 minuti fanno sempre 96. Vedi [piani e limiti](/docs/limits) (in inglese).
| Attivatore | Chiamate / giorno | Rientra in Free? |
|---|---|---|
| Ogni 15 min, 1 sport | 96 | sì |
| Ogni 30 min, 2 sport | 96 | sì |
| Ogni 15 min, 2 sport | 192 | sì |
| Ogni minuto, 1 sport | 1.440 | no — serve Hobby o superiore (senza limite giornaliero) |
Apps Script ha anche le sue quote; l'attivatore a tempo più breve è di un minuto.
## Passo 6 — Leggi quote eque e margini
Ogni riga 1X2 riporta i campi senza margine di PinnFeed descritti nello [schema](/docs/schema):
- `Fair 1` / `Fair X` / `Fair 2` — la quota decimale `fair` di ogni esito (margine rimosso, metodo moltiplicativo).
- `Margin` — il `margin` del mercato (aggio = somma delle probabilità implicite − 1).
Usa queste colonne quando confronti la quota di un bookmaker soft in un altro foglio: il valore atteso è `soft × (1 / fair) − 1`, lo stesso calcolo della [guida al value betting](/it/guides/value-betting-no-vig-fair-odds). Per gli steam move live, Sheets non è lo strumento giusto: usa il WebSocket di Builder e la [guida al rilevamento dello steam](/it/guides/dropping-odds-steam-detection).
## Domande frequenti
### Quale piano di PinnFeed mi serve?
Free basta per una tabella in ritardo che si aggiorna ogni pochi minuti. Hobby (29 €/mese) toglie il limite giornaliero e i 30 secondi di ritardo, ma resta solo REST. Il push in tempo reale richiede [Builder](/it/pricing#plan-builder) (99 €/mese).
### Perché lo script usa `x-api-key` invece di un parametro nell'URL?
È l'header di autenticazione consigliato nella [documentazione](/docs/authentication). `UrlFetchApp` di Apps Script può inviare header, quindi non c'è motivo di mettere la chiave nell'URL (dove può finire nei log).
### Posso fare un grafico dello storico dei prezzi?
Sì. Lascia il foglio Odds come tabella live (viene svuotato e riscritto a ogni esecuzione). Aggiungi un secondo foglio che si limita ad accodare righe dopo ogni aggiornamento e inserisci un grafico a linee. Non cancellare il foglio dello storico.
### È un contenuto educativo per maggiorenni?
Sì. I dati sulle quote e gli strumenti per fogli di calcolo sono materiale educativo per maggiori di 18 anni. Niente di tutto questo è un pronostico, una scommessa sicura o una promessa di guadagno.
## Correlati
- [Riferimento dell'API REST](/docs/rest) (in inglese) — filtri e paginazione di `/v1/odds`
- [Value betting con quote eque senza margine](/it/guides/value-betting-no-vig-fair-odds)
- [Bot di pronostici per Telegram](/it/guides/telegram-picks-bot) — se il foglio non ti basta più
- [Prezzi](/it/pricing)
---
Source: https://pinnfeed.io/it/guides/discord-picks-bot
# Crea un bot di pronostici per Discord con le quote Pinnacle live
Questo bot segue i prezzi di Pinnacle sul WebSocket di PinnFeed e pubblica un embed in un canale Discord ogni volta che un mercato fa steam: la quota scende del 5% o più in due minuti in un mercato con una puntata massima di almeno 100. È un solo file di circa 90 righe. Non serve una libreria Discord né un account bot, perché pubblica tramite un **webhook in entrata** del canale.
È il gemello su Discord del [bot di pronostici per Telegram](/it/guides/telegram-picks-bot). La regola di rilevamento è quella spiegata nella [guida al rilevamento dello steam](/it/guides/dropping-odds-steam-detection). È uno strumento didattico per maggiori di 18 anni, non pronostici.
## Passo 1 — Crea il webhook
1. Nel tuo server Discord apri **Impostazioni server → Integrazioni → Webhook** e scegli **Nuovo webhook**.
2. Dagli un nome, scegli il canale in cui pubblicherà e usa **Copia URL webhook**.
3. Tratta quell'URL come una password: chi ce l'ha può pubblicare nel canale. Se trapela, elimina il webhook e creane uno nuovo.
## Passo 2 — Configura l'ambiente
```bash
export PINNFEED_KEY="ps_live_..." # piano Builder (WebSocket)
export DISCORD_WEBHOOK="https://discord.com/api/webhooks/..." # dal passo 1
npm install ws
```
Se lasci `DISCORD_WEBHOOK` vuota, il bot gira in **modalità di prova**: stampa ogni avviso invece di pubblicarlo.
Lo stream richiede **Builder** (99 €/mese) o superiore. Le chiavi Free e Hobby ricevono `403 plan_lacks_ws` su `/v1/stream`; vedi i [prezzi](/it/pricing).
## Passo 3 — Il bot
Salvalo come `discord-picks-bot.mjs`:
```javascript
// discord-picks-bot.mjs: post Pinnacle steam moves to a Discord channel through an incoming webhook.
// npm install ws Node 18+ (global fetch)
// env: PINNFEED_KEY (Builder or higher), DISCORD_WEBHOOK (channel webhook URL; unset = dry run)
import WebSocket from 'ws';
const WS_URL = process.env.PINNFEED_WS || 'wss://pinnfeed.io/v1/stream';
const { PINNFEED_KEY, DISCORD_WEBHOOK } = process.env;
const MIN_DROP = Number(process.env.MIN_DROP || 0.05); // 5% shortening...
const WINDOW_MS = Number(process.env.WINDOW_MS || 120000); // ...inside 2 minutes
const MIN_STAKE = Number(process.env.MIN_STAKE || 100); // skip thin markets
const SIDES = new Set(['home', 'away', 'draw', 'over', 'under']);
const events = new Map();
const highs = new Map(); // "marketId|outcome" -> [{t, p}]
const sent = new Map(); // "marketId|outcome" -> last alert time
const queue = []; // embeds waiting to be posted
let busy = false;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
// One worker drains the queue, so a slow or rate-limited webhook never blocks the stream.
async function drain() {
if (busy) return;
busy = true;
while (queue.length) {
const embed = queue.shift();
if (!DISCORD_WEBHOOK) { console.log('[dry run]', embed.title, '|', embed.description.replace(/\n/g, ' | ')); continue; }
for (let attempt = 0; attempt < 3; attempt++) {
const r = await fetch(DISCORD_WEBHOOK, {
method: 'POST', headers: { 'content-type': 'application/json' },
body: JSON.stringify({ embeds: [embed], allowed_mentions: { parse: [] } }),
}).catch((e) => ({ ok: false, status: 0, text: async () => e.message }));
if (r.status === 429) { const b = await r.json().catch(() => ({})); await sleep(1000 * (b.retry_after ?? 1)); continue; }
if (!r.ok) console.error('discord', r.status, await r.text());
break;
}
}
busy = false;
}
function post(embed) {
queue.push(embed);
if (queue.length > 50) queue.shift(); // an alert from minutes ago is no longer news
drain();
}
function check(m) {
const ev = events.get(m.eventId);
if (!ev || (m.maxStake ?? 0) < MIN_STAKE) return;
const now = Date.now();
for (const o of m.outcomes) {
if (!SIDES.has(o.name)) continue;
const k = `${m.id}|${o.name}`;
const h = (highs.get(k) || []).filter((x) => now - x.t < WINDOW_MS);
h.push({ t: now, p: o.decimal });
highs.set(k, h);
const high = Math.max(...h.map((x) => x.p));
const drop = 1 - o.decimal / high;
if (drop < MIN_DROP || now - (sent.get(k) || 0) < WINDOW_MS) continue;
sent.set(k, now);
const pick = o.name === 'home' ? ev.home : o.name === 'away' ? ev.away : o.name;
const line = o.points == null ? '' : m.type === 'total' ? ` ${o.points}` : ` ${o.points > 0 ? '+' : ''}${o.points}`;
post({
title: `📉 ${ev.home} v ${ev.away}`,
description: `**${pick}** (${m.type}${line})\nPinnacle ${high.toFixed(2)} → ${o.decimal.toFixed(2)} (−${(drop * 100).toFixed(1)}%)\n` +
`Fair now ${o.fair.toFixed(2)} · max stake ${m.maxStake}`,
color: 0xe8590c,
footer: { text: `${ev.sport.toUpperCase()} · ${ev.league?.name ?? ''} · 18+ · not a tip` },
timestamp: new Date(now).toISOString(),
});
}
}
function connect(delay = 1000) {
const ws = new WebSocket(WS_URL, { headers: { 'x-api-key': PINNFEED_KEY }, perMessageDeflate: true });
ws.on('open', () => {
delay = 1000;
ws.send(JSON.stringify({ type: 'subscribe', sports: ['soccer', 'tennis', 'basketball'], markets: ['moneyline', 'spread', 'total'], main: true, specials: false }));
});
ws.on('message', (raw) => {
const msg = JSON.parse(raw);
if (msg.type === 'ping') return ws.send('{"type":"pong"}');
if (msg.type === 'snapshot') msg.events.forEach((e) => events.set(e.id, e));
if (msg.type === 'delta') for (const c of msg.changes) {
if (c.kind === 'event') c.op === 'upsert' ? events.set(c.event.id, c.event) : events.delete(c.id);
if (c.kind === 'market' && c.op === 'upsert') check(c.market);
}
});
ws.on('close', () => setTimeout(() => connect(Math.min(delay * 2, 30000)), delay));
ws.on('error', (e) => console.error('ws error:', e.message));
}
connect();
```
Cosa fa, in ordine:
- **Si iscrive** alle linee principali (moneyline, spread, total) di calcio, tennis e basket. Cambia `sports` con uno qualsiasi dei 13 sport del tuo piano; il [protocollo WebSocket](/docs/websocket) (in inglese) elenca tutti i filtri.
- **Tiene una finestra di 2 minuti** per mercato ed esito e segnala un calo di `MIN_DROP` rispetto al massimo della finestra. I mercati sotto `MIN_STAKE` vengono saltati, perché un movimento con un limite basso dice poco.
- **Mette in coda la pubblicazione.** Un solo worker invia gli embed al webhook, così un webhook lento o limitato non blocca mai lo stream. Se più di 50 avvisi sono in attesa, il più vecchio viene scartato.
- **Rispetta i 429.** Discord risponde alle raffiche con `429` e un valore `retry_after` in secondi nel corpo JSON. Il bot aspetta quel tempo e riprova, fino a tre tentativi.
- **Nessuna menzione.** `allowed_mentions: { parse: [] }` impedisce che il nome di una squadra o di un giocatore menzioni qualcuno nel canale.
## Passo 4 — Avvialo e provalo
```bash
node discord-picks-bot.mjs
```
In modalità di prova un avviso viene stampato così:
```text
[dry run] 📉 Udinese v Fiorentina | **Udinese** (spread +0.25) | Pinnacle 1.88 → 1.70 (−9.6%) | Fair now 1.75 · max stake 150
```
Su Discord lo stesso avviso è un embed: la partita come titolo, il lato e il movimento di quota nel corpo, la quota equa senza margine e la puntata massima nell'ultima riga, e sport, campionato e la nota "18+ · not a tip" nel piè di pagina.
Regola il volume con variabili d'ambiente, per esempio `MIN_DROP=0.08` per meno avvisi e più forti, oppure `MIN_STAKE=500` per tenere solo i mercati più profondi.
## Passo 5 — Tienilo acceso
- Eseguilo con `systemd`, `pm2` o un container con riavvio in caso di errore. Il bot si ricollega da solo al WebSocket con backoff e ricostruisce l'elenco degli eventi dal nuovo snapshot.
- Basta un webhook per canale. Se vuoi calcio e tennis in canali separati, avvia due copie con altri `sports` e webhook; una chiave Builder consente 3 connessioni WebSocket.
- Tieni lo storico in modo onesto: registra ogni avviso e misuralo con il [closing line value](/it/guides/closing-line-value-clv-tracking), non con la percentuale di vincite.
- Per cosa pubblicare e come moderare un server, vedi il [caso d'uso dei server Discord](/use-cases/discord-servers) (in inglese).
## Domande frequenti
### Quale piano PinnFeed serve al bot Discord?
Builder (99 €/mese) o superiore, perché legge il WebSocket. Per un confronto vedi la pagina sul [prezzo del WebSocket live e pre-match](/it/cheapest-pinnacle-odds-websocket). I piani a pagamento hanno 3 giorni di prova gratuita; serve una carta, addebitata dopo il giorno 3 se non annulli.
### Posso usarlo con il piano Free?
Così com'è, no. Free è solo REST con 30 secondi di ritardo. Per un bot più lento su Free o Hobby, interroga `/v1/drops` una volta al minuto e pubblica il risultato sullo stesso webhook; vedi la [documentazione REST](/docs) (in inglese).
### Mi serve un account bot Discord o discord.js?
No. Un webhook in entrata accetta un semplice `POST` JSON, quindi al bot basta `fetch`. Usa un account bot con discord.js solo se vuoi comandi slash o risposte.
### Come evito di intasare il canale?
Alza `MIN_DROP` o `MIN_STAKE`, riduci `sports` e mantieni la pausa per esito (un avviso per lato di mercato ogni `WINDOW_MS`). Il limite della coda scarta gli avvisi vecchi invece di pubblicarli in ritardo.
### È consentito pubblicare pronostici in un server Discord?
Le regole su pronostici e pubblicità del gioco cambiano da paese a paese; in Italia, per esempio, il Decreto Dignità (2018) vieta la pubblicità del gioco con vincite in denaro. Anche Discord ha le sue linee guida della community. Verifica le regole dove ti trovi tu e dove si trovano i tuoi membri, riserva il server ai maggiori di 18 anni e non presentare mai gli avvisi come vincite sicure. Questa non è una consulenza legale.