Examples · Expo (React Native)
Build a Sports Odds App With React Native (Expo)
This tutorial builds a phone app that lists upcoming games with the best moneyline for each team and the book offering it, with league tabs and pull to refresh.
Cost: 18 credits per league load. The free plan includes 1,000 credits a month. Full project on GitHub.
1. Load the best price per team
odds.ts calls ml.odds() for the league's sportsbook moneylines, keeps the next 20 games, and picks the best price for each side.
2. Build the screen
App.tsx shows league chips across the top and a FlatList of game cards. Pulling down reloads the odds.
3. Move the key before you ship
The prototype reads the key from EXPO_PUBLIC_MONEYLINE_API_KEY, which ends up inside the app. Anyone who installs an app can read what's in it, so before you release, move the call in odds.ts to your own backend and keep the key there.
The code
mobile-odds-app/odds.ts, straight from the repository.
import { MoneyLine } from 'moneyline-sports-api'
// Prototype only: anything in an app bundle can be read by the people who install it.
// Before you ship, call your own backend and keep the key there.
const ml = new MoneyLine({ apiKey: process.env.EXPO_PUBLIC_MONEYLINE_API_KEY })
type Outcome = { name: string; price: number }
type Game = {
eventId: string; startTime: string; homeTeamName: string; awayTeamName: string
bookmakers: { bookmakerName: string; sourceType: string; markets: { outcomes: Outcome[] }[] }[]
}
type Side = { team: string; price: number | null; book: string | null }
export type GameLine = { eventId: string; startTime: string; books: number; away: Side; home: Side }
function best(game: Game, team: string): Side {
let side: Side = { team, price: null, book: null }
for (const book of game.bookmakers) {
const price = book.markets.flatMap((m) => m.outcomes).find((o) => o.name === team)?.price
if (price != null && (side.price == null || price > side.price)) side = { team, price, book: book.bookmakerName }
}
return side
}
// Best moneyline for each side of the next 20 games (one call, 18 credits).
export async function bestMoneylines(league: string): Promise<GameLine[]> {
const games = (await ml.odds({ league, market: 'moneyline', sourceType: 'sportsbook' })) as Game[]
const now = Date.now()
return games
.filter((g) => new Date(g.startTime).getTime() > now)
.sort((a, b) => a.startTime.localeCompare(b.startTime))
.slice(0, 20)
.map((g) => ({ eventId: g.eventId, startTime: g.startTime, books: g.bookmakers.length, away: best(g, g.awayTeamName), home: best(g, g.homeTeamName) }))
}
Run it
Get a free API key, clone the example, then run:
npm install
EXPO_PUBLIC_MONEYLINE_API_KEY=your-key npx expo start