Proxy quote Pinnacle con FastAPI
Risposta: esegui una piccola app FastAPI che legge PINNFEED_KEY dall'ambiente, chiama /v1/odds con httpx, mette in cache il risultato per pochi secondi e restituisce solo i campi utili. Il browser parla alla tua API; la chiave non lascia il server e la cache tiene molti visitatori dentro il rate limit.
app.py#
import os, time
import httpx
from fastapi import FastAPI, HTTPException
KEY = os.environ["PINNFEED_KEY"] # ps_live_...
API = "https://pinnfeed.io/v1"
TTL = 5 # seconds
cache: dict[str, tuple[float, list]] = {}
app = FastAPI()
client = httpx.AsyncClient(headers={"x-api-key": KEY}, timeout=10)
@app.get("/odds/{sport}")
async def odds(sport: str, q: str | None = None):
ck = f"{sport}|{q}"
hit = cache.get(ck)
if hit and time.time() - hit[0] < TTL:
return hit[1]
params = {"sport": sport, "market": "moneyline", "main": "true", "limit": 100}
if q:
params["q"] = q
r = await client.get(f"{API}/odds", params=params)
if r.status_code != 200:
raise HTTPException(r.status_code, r.json().get("error", {}).get("message", "upstream error"))
rows = [
{"id": e["id"], "home": e["home"], "away": e["away"], "start": e["startTime"], "live": e["live"],
"prices": {o["name"]: o["decimal"] for m in e["markets"] for o in m["outcomes"]},
"maxStake": max((m["maxStake"] or 0) for m in e["markets"]) if e["markets"] else None}
for e in r.json()["events"]
]
cache[ck] = (time.time(), rows)
return rows
Avvia con pip install fastapi uvicorn httpx e uvicorn app:app --port 8000, poi chiama /odds/soccer?q=arsenal.
Note prod#
- Aggiungi auth o rate limit sul proxy se è pubblico.
- Rispetta
429conRetry-Afterda PinnFeed; piani: 1 (Free), 2 (Hobby), 10 (Builder) o 30 (Pro) req/s. - Per board live, un WebSocket server (Builder) e fan-out: WebSocket Python.
CTA#
Builder (99 €/mese). Prova 3 giorni; carta richiesta. REST gratis: signup. Altri host: Cloudflare Worker, Supabase. Correlato: JS browser / CORS.
Domande frequenti#
Perché non chiamare PinnFeed da JavaScript?#
CORS lo consente, ma la chiave sarebbe pubblica: JS browser e CORS.
La cache rende le quote stale?#
Fino a TTL secondi. 1–5 s per prematch; WebSocket per il live.
Posso usare Flask?#
Sì; stesso pattern con requests e un dict cache.
Contenuto educativo per maggiorenni (18+): non pronostici né promesse di guadagno. In Italia scommetti solo con operatori autorizzati ADM.