チュートリアル · Supabase · REST
Edge FunctionでピナクルオッズをSupabaseへ
回答: APIキーをSupabaseシークレットに置き、GET /v1/drops(または /v1/odds)を呼んで @supabase/server のadminクライアントでupsertするEdge Functionを書き、pg_cron + pg_net で毎分Vaultの秘密鍵付きで呼び出します。Edge Functionは短命なのでRESTポーリングであり、WebSocketリスナーではありません。Free(30秒遅延、2スポーツ)から、Hobby以上でリアルタイム。
1. テーブル#
create table if not exists pinnacle_drops (
event_id bigint, market_id text, outcome text,
price_from numeric, price_to numeric, drop_pct numeric,
moved_at timestamptz, home text, away text,
primary key (market_id, outcome, moved_at)
);
2. シークレット#
supabase secrets set PINNFEED_KEY=ps_live_your_key
3. Function supabase/functions/pinnfeed-drops/index.ts#
import { withSupabase } from 'npm:@supabase/server@1';
// auth: 'secret' accepts only callers that send your project's secret key on the apikey header
export default {
fetch: withSupabase({ auth: 'secret' }, async (_req, ctx) => {
const r = await fetch('https://pinnfeed.io/v1/drops?sport=soccer&minutes=5&min_pct=3&limit=100', {
headers: { 'x-api-key': Deno.env.get('PINNFEED_KEY')! },
});
if (!r.ok) return new Response(await r.text(), { status: r.status });
const { drops } = await r.json();
const rows = drops.map((d: any) => ({
event_id: d.eventId, market_id: d.marketId, outcome: d.outcome,
price_from: d.from, price_to: d.to, drop_pct: d.dropPct,
moved_at: d.movedAt, home: d.home, away: d.away,
}));
const { error } = await ctx.supabaseAdmin.from('pinnacle_drops').upsert(rows, { ignoreDuplicates: true });
return Response.json({ saved: rows.length, error: error?.message ?? null });
}),
};
4. デプロイ#
関数をデプロイし、プロジェクトURLとservice roleをVaultへ。pg_cron で毎分 net.http_post(apikey 認証)。cron詳細はEN Supabase Edge。関連:Cloudflare Worker、CORS。
CTA#
Builder(99€/月)。3日間トライアル、カード必須。無料REST:signup。
よくある質問#
Edge FunctionでWebSocketをストリームできますか?#
いいえ。短すぎます。ここではRESTポーリング、WSは常時サーバー(Builder)。
Freeで足りますか?#
試作なら可(30秒遅延、2スポーツ、1,000/日)。
成人向けの教育コンテンツですか?#
はい(18+)。
18歳以上の方を対象とした教育目的のコンテンツです。予想や利益の約束ではありません。日本では刑法により賭博は原則として禁止されています。