Examples

Node.js: keep a live book#

// npm install ws
import WebSocket from 'ws';

const events = new Map();
const markets = new Map();

function connect(attempt = 0) {
  const ws = new WebSocket('wss://pinnfeed.io/v1/stream', {
    headers: { 'x-api-key': process.env.PINNSOCKET_KEY },
    perMessageDeflate: true,
  });
  ws.on('open', () => {
    attempt = 0;
    ws.send(JSON.stringify({ type: 'subscribe', sports: ['soccer'], markets: ['moneyline', 'total'], main: true }));
  });
  ws.on('message', (buf) => {
    const msg = JSON.parse(buf);
    if (msg.type === 'ping') return ws.send('{"type":"pong"}');
    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.type === 'delta') {
      for (const c of msg.changes) {
        if (c.kind === 'event') c.op === 'remove' ? events.delete(c.id) : events.set(c.event.id, c.event);
        else c.op === 'remove' ? markets.delete(c.id) : markets.set(c.market.id, c.market);
      }
    }
  });
  ws.on('close', () => setTimeout(() => connect(attempt + 1), Math.min(30000, 1000 * 2 ** attempt)));
}
connect();

Python: +EV finder against a soft book#

import requests, os

API = "https://pinnfeed.io/v1/odds"
r = requests.get(API, params={"sport": "soccer", "market": "moneyline", "main": "true"},
                 headers={"x-api-key": os.environ["PINNSOCKET_KEY"]}, timeout=10)
r.raise_for_status()

def soft_price(event, outcome):
    """Return the price your other bookmaker offers (your own scraper/API)."""
    return None

for ev in r.json()["events"]:
    for m in ev["markets"]:
        for o in m["outcomes"]:
            soft = soft_price(ev, o["name"])
            if soft and soft > o["fair"]:
                edge = soft / o["fair"] - 1
                print(f'{ev["home"]} v {ev["away"]} {o["name"]}: {soft} vs fair {o["fair"]} (+{edge:.1%})')

Python: closing-line value of your bets#

import requests, os
H = {"x-api-key": os.environ["PINNSOCKET_KEY"]}

def clv(event_id, market_key, outcome, price_taken):
    r = requests.get(f"https://pinnfeed.io/v1/closing/{event_id}", headers=H, timeout=10).json()
    m = next(x["market"] for x in r["markets"] if x["market"]["key"] == market_key)
    fair_close = next(o["fair"] for o in m["outcomes"] if o["name"] == outcome)
    return price_taken / fair_close - 1   # > 0 means you beat the closing line

print(clv(1639922643, "s;0;m", "home", 2.10))

Browser#

<script>
  // Keys in browsers are visible to users: use a dedicated key, or proxy through your backend.
  const ws = new WebSocket('wss://pinnfeed.io/v1/stream?key=YOUR_KEY&sports=tennis');
  ws.onmessage = (e) => {
    const msg = JSON.parse(e.data);
    if (msg.type === 'ping') ws.send('{"type":"pong"}');
    if (msg.type === 'delta') console.log(msg.changes.length, 'changes');
  };
</script>

curl#

# Live tennis main lines
curl -s -H "x-api-key: $PINNSOCKET_KEY" "https://pinnfeed.io/v1/odds?sport=tennis&live=true&main=true" | jq '.events[] | {home, away, markets: [.markets[] | {type, outcomes: [.outcomes[] | {name, decimal, fair}]}]}'