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 Twitch Esports Overlay with Live Odds
Show real-time esports odds directly on your stream. Viewers see odds updating live as the game progresses.
What You’ll Use
SDK Method Endpoint Purpose getEvents()GET /v1/eventsFind esports events getLive()GET /v1/liveGet live esports matches getEventOdds()GET /v1/events/{id}/oddsReal-time odds getScores()GET /v1/scoresCurrent map/round scores getSports()GET /v1/sportsList esports categories
How Twitch Overlays Work
OBS Studio has a “Browser Source” that renders any URL as a transparent overlay on your stream. You build a web page → OBS renders it on top of your game.
Step 1: Find Esports Events
FieldFunded covers esports under specific sport keys. Check available esports:
const sports = await client . getSports ();
const esports = sports . sports . filter ( s => s . is_esport );
// e.g. 'esports-csgo', 'esports-lol', 'esports-dota2', 'esports-valorant'
Get live esports matches:
const liveEsports = await client . getLive ({
sport: 'esports-csgo' , // CS2
});
Step 2: Build the Overlay Page
<! DOCTYPE html >
< html >
< head >
< style >
* { margin : 0 ; padding : 0 ; box-sizing : border-box ; }
body {
background : transparent ;
font-family : 'Inter' , sans-serif ;
color : #fff ;
}
.overlay {
position : fixed ;
bottom : 20 px ;
right : 20 px ;
background : rgba ( 10 , 10 , 30 , 0.85 );
border : 1 px solid #53FC18 ;
border-radius : 12 px ;
padding : 16 px ;
min-width : 280 px ;
backdrop-filter : blur ( 10 px );
}
.match-title {
font-size : 14 px ;
font-weight : 600 ;
margin-bottom : 8 px ;
color : #53FC18 ;
}
.teams {
display : flex ;
justify-content : space-between ;
margin-bottom : 12 px ;
}
.team {
text-align : center ;
flex : 1 ;
}
.team-name { font-size : 13 px ; font-weight : 500 ; }
.odds {
font-size : 18 px ;
font-weight : 700 ;
padding : 4 px 8 px ;
background : rgba ( 83 , 252 , 24 , 0.15 );
border-radius : 6 px ;
margin-top : 4 px ;
display : inline-block ;
}
.score {
text-align : center ;
font-size : 24 px ;
font-weight : 700 ;
color : #53FC18 ;
}
.map-score { font-size : 11 px ; color : #aaa ; margin-top : 2 px ; }
.vs { color : #666 ; font-size : 12 px ; }
@keyframes pulse {
0% , 100% { opacity : 1 ; }
50% { opacity : 0.7 ; }
}
.live-dot {
width : 8 px ;
height : 8 px ;
background : #ff4444 ;
border-radius : 50 % ;
display : inline-block ;
animation : pulse 1.5 s infinite ;
margin-right : 6 px ;
}
</ style >
</ head >
< body >
< div class = "overlay" id = "overlay" >
< div class = "match-title" >
< span class = "live-dot" ></ span >
< span id = "league" > Loading... </ span >
</ div >
< div class = "teams" >
< div class = "team" >
< div class = "team-name" id = "team1" > — </ div >
< div class = "odds" id = "odds1" > — </ div >
</ div >
< div class = "score" >
< span id = "score1" > 0 </ span >
< span class = "vs" > - </ span >
< span id = "score2" > 0 </ span >
< div class = "map-score" id = "mapScore" ></ div >
</ div >
< div class = "team" >
< div class = "team-name" id = "team2" > — </ div >
< div class = "odds" id = "odds2" > — </ div >
</ div >
</ div >
</ div >
< script >
const API_KEY = 'YOUR_API_KEY' ;
const BASE = 'https://api.fieldfunded.com/v1' ;
const SPORT = 'esports-csgo' ; // Change for LoL, Dota, Valorant
const POLL_INTERVAL = 15000 ; // 15 seconds
async function api ( path ) {
const res = await fetch ( ` ${ BASE }${ path } ` , {
headers: { 'X-API-Key' : API_KEY },
});
return res . json ();
}
async function update () {
try {
const live = await api ( `/live?sport= ${ SPORT } ` );
if ( ! live . events || live . events . length === 0 ) {
document . getElementById ( 'league' ). textContent = 'No live match' ;
return ;
}
const event = live . events [ 0 ]; // First live match
const odds = await api ( `/events/ ${ event . id } /odds` );
document . getElementById ( 'league' ). textContent = event . league ;
document . getElementById ( 'team1' ). textContent = event . home_team ;
document . getElementById ( 'team2' ). textContent = event . away_team ;
// Score
if ( event . scoreboard ) {
document . getElementById ( 'score1' ). textContent = event . scoreboard . home || '0' ;
document . getElementById ( 'score2' ). textContent = event . scoreboard . away || '0' ;
}
// Main market odds
if ( odds . markets && odds . markets . length > 0 ) {
const main = odds . markets [ 0 ];
if ( main . selections . length >= 2 ) {
document . getElementById ( 'odds1' ). textContent = main . selections [ 0 ]. odds ;
document . getElementById ( 'odds2' ). textContent = main . selections [ 1 ]. odds ;
}
}
} catch ( err ) {
console . error ( 'Update failed:' , err );
}
}
update ();
setInterval ( update , POLL_INTERVAL );
</ script >
</ body >
</ html >
Step 3: Add to OBS
Open OBS Studio
Sources → Add → Browser Source
Point to http://localhost:3000/overlay.html (or host it online)
Set width/height (300×120 works well)
Check “Shutdown source when not visible”
Rate Limit Math
Polling every 15 seconds = 2 requests per poll (live + odds)
Per hour: 240 requests
4-hour stream: ~960 requests
Free tier (10K/month) supports ~10 full streams per month
Starter ($29): ~300 streams/month — more than enough
Live Events Reference See live endpoint docs →
Get Your Free API Key Start building in 5 minutes — 10,000 free requests/month