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 WhatsApp Sports Alert System
Automate sports alerts for your friend group: game kickoffs, significant odds shifts, and final scores with settlement results.
What You’ll Use
SDK Method Endpoint Purpose getEvents()GET /v1/eventsFind upcoming games getEventOdds()GET /v1/events/{id}/oddsTrack odds changes getScores()GET /v1/scoresGet live scores getEventResult()GET /v1/events/{id}/resultGet final result
Prerequisites
Twilio account (free trial works)
Twilio WhatsApp Sandbox activated
Node.js 18+
npm install @fieldfunded/sdk twilio node-cron
Step 1: Initialize
import { FieldFundedSDK } from '@fieldfunded/sdk' ;
import twilio from 'twilio' ;
import cron from 'node-cron' ;
const ff = new FieldFundedSDK ({
apiKey: process . env . FIELDFUNDED_API_KEY ! ,
baseUrl: 'https://api.fieldfunded.com/v1' ,
});
const sms = twilio ( process . env . TWILIO_SID ! , process . env . TWILIO_AUTH ! );
const WHATSAPP_FROM = 'whatsapp:+14155238886' ; // Twilio sandbox
const GROUP_NUMBERS = [ 'whatsapp:+351912345678' ]; // Your friends
Step 2: Alert Type 1 — Game Starting Soon
async function checkKickoffs () {
const events = await ff . getEvents ({
sport: 'soccer' ,
starts_within: '15m' , // Games starting in 15 minutes
status: 'prematch' ,
});
for ( const event of events . events ) {
const odds = await ff . getEventOdds ( event . id );
const main = odds . markets ?.[ 0 ];
let message = `⚽ *Starting Soon!* \n ` ;
message += ` ${ event . home_team } vs ${ event . away_team } \n ` ;
message += `🏟️ ${ event . league } \n ` ;
message += `⏰ ${ new Date ( event . start_time ). toLocaleTimeString () } \n ` ;
if ( main ) {
const oddsStr = main . selections
. map (( s : any ) => ` ${ s . name } : ${ s . odds } ` )
. join ( ' | ' );
message += `📊 ${ oddsStr } ` ;
}
await sendToGroup ( message );
}
}
Step 3: Alert Type 2 — Odds Movement
// Store previous odds in memory (or database for persistence)
const previousOdds = new Map < string , number >();
async function checkOddsMovement () {
const live = await ff . getEvents ({ status: 'live' , sport: 'soccer' });
for ( const event of live . events . slice ( 0 , 10 )) {
const odds = await ff . getEventOdds ( event . id );
const main = odds . markets ?.[ 0 ];
if ( ! main ) continue ;
for ( const sel of main . selections ) {
const key = ` ${ event . id } - ${ sel . name } ` ;
const prev = previousOdds . get ( key );
if ( prev ) {
const change = Math . abs ( sel . odds - prev ) / prev ;
if ( change > 0.1 ) { // 10% shift
const direction = sel . odds > prev ? '📈' : '📉' ;
await sendToGroup (
` ${ direction } *Odds Alert* \n ` +
` ${ event . home_team } vs ${ event . away_team } \n ` +
` ${ sel . name } : ${ prev . toFixed ( 2 ) } → ${ sel . odds . toFixed ( 2 ) } ( ${ ( change * 100 ). toFixed ( 0 ) } % shift)`
);
}
}
previousOdds . set ( key , sel . odds );
}
}
}
Step 4: Alert Type 3 — Final Score
async function checkFinalScores () {
// Track events we've already alerted
const alerted = new Set < string >();
const events = await ff . getEvents ({ status: 'ended' , sport: 'soccer' });
for ( const event of events . events . slice ( 0 , 5 )) {
if ( alerted . has ( event . id )) continue ;
const result = await ff . getEventResult ( event . id );
if ( result . status === 'ended' && result . score ) {
await sendToGroup (
`🏁 *Full Time* \n ` +
` ${ event . home_team } * ${ result . score . home } * - * ${ result . score . away } * ${ event . away_team } \n ` +
`🏟️ ${ event . league } `
);
alerted . add ( event . id );
}
}
}
Step 5: Send to Group
async function sendToGroup ( message : string ) {
for ( const number of GROUP_NUMBERS ) {
await sms . messages . create ({
from: WHATSAPP_FROM ,
to: number ,
body: message ,
});
}
}
Step 6: Schedule Everything
// Check for kickoffs every 5 minutes
cron . schedule ( '*/5 * * * *' , checkKickoffs );
// Check odds movement every 2 minutes during live games
cron . schedule ( '*/2 * * * *' , checkOddsMovement );
// Check final scores every 3 minutes
cron . schedule ( '*/3 * * * *' , checkFinalScores );
Rate Limit Math
Check Frequency Requests/hour Monthly Kickoffs Every 5 min 24 ~17,280 Odds movement Every 2 min 60 ~43,200 Final scores Every 3 min 40 ~28,800
Total: ~89,000/month → Pro plan ($59/mo) covers it.
To fit in the free tier, reduce to checking only your favorite leagues and extend intervals.
Events API Reference See event filters (starts_within, status) →
Get Your Free API Key Start building in 5 minutes — 10,000 free requests/month