WebSocket de odds da Pinnacle: exemplo em Python
Resposta: instale websockets, defina PINNFEED_KEY, conecte em wss://pinnfeed.io/v1/stream com o header x-api-key, envie uma mensagem subscribe, aplique cada snapshot/delta, responda ao ping com {"type":"pong"} e reconecte com backoff exponencial. Você precisa do plano Builder (€99/mês): chaves Free e Hobby recebem 403 plan_lacks_ws.
Cliente mínimo#
pip install websockets
export PINNFEED_KEY="ps_live_..."
import asyncio, json, os, random
import websockets
WS = "wss://pinnfeed.io/v1/stream"
KEY = os.environ["PINNFEED_KEY"]
async def main():
delay = 1
while True:
try:
async with websockets.connect(WS, additional_headers={"x-api-key": KEY}, max_size=None) as ws:
await ws.send(json.dumps({
"type": "subscribe",
"sports": ["soccer", "tennis"],
"markets": ["moneyline"],
"main": True,
"specials": False,
}))
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "ping":
await ws.send('{"type":"pong"}')
elif msg["type"] == "snapshot" and msg.get("final"):
print("snapshot pronto")
delay = 1
elif msg["type"] == "delta":
for c in msg["changes"]:
if c["kind"] == "market" and c["op"] == "upsert":
m = c["market"]
if (m["maxStake"] or 0) >= 100:
print(m["id"], [(o["name"], o["decimal"], o["fair"]) for o in m["outcomes"]])
except (OSError, websockets.ConnectionClosed) as e:
print("desconectado", e, "nova tentativa em", delay, "s")
await asyncio.sleep(delay + random.random())
delay = min(delay * 2, 30)
asyncio.run(main())
Campos de cada resultado: decimal, american, fair (sem margem), fairProb. O id do mercado é eventId:key. O filtro maxStake >= 100 descarta mercados com pouca liquidez. Lista completa de frames: docs do WebSocket.
Códigos de fechamento#
| Código | Significado |
|---|---|
4002 no_subscription | Nenhum subscribe em 30 s |
4008 slow_consumer | Cliente lento demais (buffer do servidor acima de 16 MB) |
4001 key_revoked | Chave revogada: não reconecte em loop |
Builder: teste de 3 dias em preços; é preciso cartão, cobrado após o dia 3 se você não cancelar. Ou comece com uma chave REST grátis. Veja também push ou polling e bootstrap de conta em Python.
Conteúdo educativo para maiores de 18 anos: documentação técnica, não palpites nem promessa de lucro.
Perguntas frequentes#
Por que minha chave Free recebe 403 no WebSocket?#
Free e Hobby são só REST. Passe para o Builder para ter push, ou consulte /v1/odds no Free (30 s de atraso) ou Hobby (tempo real).
Preciso responder aos ping?#
Sim. O servidor envia ping a cada 20 segundos; sem pong por 60 s, a conexão é encerrada.
Quantas conexões?#
O Builder permite 3 simultâneas e o Pro 10. Acima disso: 429 connection_limit.