On the wire · 04:48:15 UTC Live 550 · Prematch 14,373 · Markets 57,037 Vol. I · No. 5 · Friday 13 November 2026 wss://pinnfeed.io/v1/stream
PinnFeed
チュートリアル · Python · FastAPI

FastAPIでピナクルオッズプロキシ

更新日 · PinnFeed · 約1分で読めます

回答: 環境変数の PINNFEED_KEY を読む小さなFastAPIアプリを動かし、httpx で /v1/odds を呼び、数秒キャッシュして必要なフィールドだけ返します。ブラウザはあなたのAPIと話し、キーはサーバーから出ず、キャッシュで多数の訪問者をレート制限内に収めます。

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

pip install fastapi uvicorn httpx の後 uvicorn app:app --port 8000 で起動し、/odds/soccer?q=arsenal を呼びます。

本番メモ#

  • 公開するなら自前の認証やレート制限を追加。
  • PinnFeedの 429 と Retry-After を尊重。プランは Free 1、Hobby 2、Builder 10、Pro 30 req/s。
  • ライブボードはサーバー側WebSocket(Builder)でfan-out:Python WebSocket。

CTA#

Builder(99€/月)。3日間トライアル、カード必須。無料REST:signup。 他ホスト:Cloudflare Worker、Supabase。関連:ブラウザJS / CORS。

よくある質問#

なぜJSから直接PinnFeedを呼ばない?#

CORSは通るがキーが公開される:ブラウザJSとCORS。

キャッシュでオッズは古くなりますか?#

最大TTL秒。プレマッチは1–5秒、ライブはWebSocket。

Flaskでもできますか?#

はい。requests とdictキャッシュで同じパターンです。

18歳以上の方を対象とした教育目的のコンテンツです。予想や利益の約束ではありません。日本では刑法により賭博は原則として禁止されています。

WebSocketプラン:Builder、月額99ユーロ

ピナクルのオッズを1本のWebSocketでリアルタイムに。全13競技、全マーケット、マージンなしのフェアオッズとクロージングオッズ。3日間無料、ワンクリックで解約できます。

Form K-1 · Free API key

Get your free API key.

One field. No password, no card: enter your email, click the link we send, and your key is on screen.

By continuing you agree to the Terms and Privacy Policy.

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