Documentation Index Fetch the complete documentation index at: https://docs.fieldfunded.com/llms.txt
Use this file to discover all available pages before exploring further.
Build a Sports Betting Platform from Scratch
This guide walks through the full architecture of a betting platform: odds ingestion, bet placement, balance management, and automatic settlement.
What You’ll Use
Every major endpoint group:
SDK Method Purpose getSports() / getLeagues()Build the sports navigation getEvents()List games for each sport getEvent()Get 1,000+ markets for a game getLive() / getScores()Real-time scores and live event tracking search()Find events by team name getEventOdds()Current odds for display checkBet()Validate bet before placement checkParlay()Validate parlay combinations getSettlements()Automatic resolution after game ends getEventResult()Final score getUsage()Monitor API consumption
Architecture Overview
┌──────────────┐ ┌───────────────┐ ┌──────────────┐
│ Frontend │────▶│ Backend │────▶│ FieldFunded │
│ (React) │◀────│ (Node.js) │◀────│ API │
└──────────────┘ └───────┬───────┘ └──────────────┘
│
┌───────▼───────┐
│ Database │
│ (Postgres) │
└───────────────┘
Never expose your API key in frontend code. All FieldFunded API calls should go through your backend. The frontend calls your backend, and your backend calls FieldFunded.
Step 1: Sports Navigation
// Backend route
app . get ( '/api/sports' , async ( req , res ) => {
const data = await client . getSports ();
res . json ( data . sports . filter ( s => s . active_events > 0 ));
});
app . get ( '/api/leagues/:sport' , async ( req , res ) => {
const data = await client . getLeagues ({ sport: req . params . sport });
res . json ( data . leagues );
});
Step 2: Event Listing
app . get ( '/api/events' , async ( req , res ) => {
const events = await client . getEvents ({
sport: req . query . sport as string ,
league: req . query . league as string ,
status: req . query . status as string , // 'prematch', 'live', 'ended'
starts_within: '24h' ,
});
res . json ( events . events );
});
// Event detail with ALL markets (1,000+)
app . get ( '/api/events/:id' , async ( req , res ) => {
const detail = await client . getEvent ( req . params . id );
res . json ( detail );
});
Step 3: Bet Placement
The golden rule: lock odds at time of placement , not at time of display.
app . post ( '/api/bets/place' , async ( req , res ) => {
const { userId , eventId , market , outcome , odds , stake , marketId , selectionId } = req . body ;
// 1. Validate user has sufficient balance
const user = await db . query ( 'SELECT balance FROM users WHERE id = $1' , [ userId ]);
if ( user . balance < stake ) {
return res . status ( 400 ). json ({ error: 'Insufficient balance' });
}
// 2. Deduct stake atomically
await db . query ( 'BEGIN' );
try {
await db . query (
'UPDATE users SET balance = balance - $1 WHERE id = $2 AND balance >= $1' ,
[ stake , userId ]
);
// 3. Store bet with the odds at time of placement
await db . query (
`INSERT INTO bets (user_id, event_id, market_name, outcome, odds, stake, market_id, selection_id, status)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, 'pending')` ,
[ userId , eventId , market , outcome , odds , stake , marketId , selectionId ]
);
await db . query ( 'COMMIT' );
res . json ({ success: true });
} catch ( err ) {
await db . query ( 'ROLLBACK' );
res . status ( 500 ). json ({ error: 'Bet placement failed' });
}
});
Step 4: Settlement (the magic)
This is where FieldFunded saves you weeks of development. See the dedicated Settlement Engine guide for the full implementation.
The short version:
import cron from 'node-cron' ;
// Poll every 60 seconds
cron . schedule ( '* * * * *' , async () => {
const settlements = await client . getSettlements ({ limit: 20 });
for ( const s of settlements . settlements ) {
const pendingBets = await db . query (
'SELECT * FROM bets WHERE event_id = $1 AND status = $2' ,
[ s . event_id , 'pending' ]
);
for ( const bet of pendingBets ) {
const result = await client . checkBet ({
selections: [{
event_id: bet . event_id ,
market: bet . market_name ,
outcome: bet . outcome ,
odds: bet . odds ,
stake: bet . stake ,
market_id: bet . market_id ,
selection_id: bet . selection_id ,
}],
});
if ( result . results [ 0 ]. result !== 'pending' ) {
// Process win/loss/refund — see Settlement Engine guide
}
}
}
});
Step 5: Live Scores
Use getScores() for efficient live score polling:
// Lightweight endpoint — optimized for frequent polling
app . get ( '/api/scores' , async ( req , res ) => {
const data = await client . getScores ({
sport: req . query . sport as string ,
});
res . json ( data . scores );
});
Tech Stack Summary
Layer Recommendation Why Frontend Next.js / React SSR for SEO, React for interactivity Backend Node.js + Express SDK is TypeScript-native Database PostgreSQL (via Supabase) ACID transactions for balances Odds Data FieldFunded API 1,000+ markets, auto settlement Hosting Vercel (frontend) + Railway (backend) Both have free tiers Total infrastructure cost $0/month
MVP Timeline
Week What to build 1 User auth + sports navigation + event listing 2 Event detail page with markets + bet slip 3 Bet placement + balance management 4 Settlement integration + bet history
Settlement Engine Guide Deep dive into automatic settlement →
SDK Reference All 25 SDK methods →
Get Your Free API Key Start building in 5 minutes — 10,000 free requests/month