SportMonks TypeScript SDK
A comprehensive, production-ready TypeScript SDK for the SportMonks Football API v3. Built with modern TypeScript, featuring complete type safety, intuitive method chaining, automatic retries, real-time polling, and extensive test coverage.
Features
- ๐ Full TypeScript Support - Complete type definitions for all 50+ entities and responses
- ๐ Intuitive Method Chaining - Fluent API design for building complex queries naturally
- ๐ฆ Comprehensive Coverage - 10 resources with 56 endpoints covering all major football data
- ๐ Smart Retry Logic - Automatic retry with exponential backoff and rate limit awareness
- ๐ Real-time Updates - Built-in polling utilities for livescores and transfer monitoring
- โ Input Validation - Automatic validation of dates, IDs, and search queries with helpful errors
- ๐ฏ Type-safe Includes - Full TypeScript support for relationship includes
- ๐ Performance Optimized - Efficient pagination, response caching, and minimal dependencies
- ๐งช Battle-tested - 330+ tests with 97.7% coverage and real API validation
- ๐ Extensive Documentation - Comprehensive JSDoc comments, examples, and guides
Quick Example
import { SportMonksClient } from '@withqwerty/sportmonks-typescript-sdk';
const client = new SportMonksClient('YOUR_API_KEY');
// Get fixtures for today with team and venue information
const fixtures = await client.fixtures
.byDate('2024-01-15')
.include(['participants', 'scores', 'venue'])
.get();
// Search for teams with pagination
const teams = await client.teams.search('Manchester').page(1).perPage(10).get();
Why Use This SDK?
Type Safety
Every API response is fully typed, giving you IntelliSense support and compile-time error checking.
Intuitive API
The method chaining approach makes building complex queries feel natural and readable.
Production Ready
With automatic retries, rate limit handling, and comprehensive error messages, this SDK is built for production use.
Well Tested
Over 330 tests ensure reliability, with both unit tests and integration tests against the real API.
Next Steps
- Get started with installation
- Learn about core concepts
- Explore the API resources
- Try the interactive REPL
Installation
npm install @withqwerty/sportmonks-typescript-sdk
Or with yarn:
yarn add @withqwerty/sportmonks-typescript-sdk
Requirements
- Node.js 14.0 or higher
- TypeScript 4.0 or higher (if using TypeScript)
API Key
Youโll need a SportMonks API key. Get one at SportMonks
Quick Start
Configuration
Client Setup
Method Chaining
Include Separator
Error Handling
Rate Limiting
Leagues Resource
Teams Resource
Players Resource
Fixtures Resource
Standings Resource
Livescores Resource
Transfers Resource
Coaches Resource
Referees Resource
Venues Resource
Type Helpers Guide
The SportMonks TypeScript SDK includes utility types and functions to make working with API responses even more type-safe.
Type Guards
hasInclude()
Check if an optional include is present and get proper type inference:
import { hasInclude } from '@withqwerty/sportmonks-typescript-sdk';
const team = await client.teams.byId(1).include(['country', 'venue']).get();
if (hasInclude(team.data, 'country')) {
// TypeScript now knows team.data.country is defined
console.log(team.data.country.name); // โ
No type errors
}
hasData()
Type guard for responses with data:
import { hasData } from '@withqwerty/sportmonks-typescript-sdk';
const response = await client.teams.byId(1).get();
if (hasData(response)) {
// TypeScript knows response.data exists
console.log(response.data.name);
}
isPaginatedResponse()
/ isSingleResponse()
Distinguish between response types:
import { isPaginatedResponse, isSingleResponse } from '@withqwerty/sportmonks-typescript-sdk';
const response = await client.teams.all().get();
if (isPaginatedResponse(response)) {
// response.data is Team[]
response.data.forEach(team => console.log(team.name));
} else if (isSingleResponse(response)) {
// response.data is Team
console.log(response.data.name);
}
Type Helpers
ExtractData<T>
Extract the data type from any response:
import {
ExtractData,
SingleResponse,
PaginatedResponse
} from '@withqwerty/sportmonks-typescript-sdk';
type TeamData = ExtractData<SingleResponse<Team>>; // Team
type TeamsData = ExtractData<PaginatedResponse<Team>>; // Team[]
WithRequired<T, K>
Make optional properties required when you know theyโre included:
import { WithRequired, Team } from '@withqwerty/sportmonks-typescript-sdk';
// Make country required on Team type
type TeamWithCountry = WithRequired<Team, 'country'>;
// Make multiple properties required
type TeamWithAll = WithRequired<Team, 'country' | 'venue' | 'coach'>;
Pre-defined Include Types
Common include combinations are pre-defined for convenience:
import {
TeamWithCountry,
TeamWithVenue,
TeamWithAll,
FixtureWithTeams,
FixtureWithEvents,
PlayerWithTeam
} from '@withqwerty/sportmonks-typescript-sdk';
// Use in your functions
function processTeamWithCountry(team: TeamWithCountry) {
// country is guaranteed to exist
console.log(`${team.name} from ${team.country.name}`);
}
Utility Functions
getNestedInclude()
Safely access nested include properties:
import { getNestedInclude } from '@withqwerty/sportmonks-typescript-sdk';
const team = await client.teams.byId(1).include(['country']).get();
// Safe access - returns undefined if not present
const countryName = getNestedInclude(team.data, 'country', 'name');
const countryCode = getNestedInclude(team.data, 'country', 'code');
Filter Helpers
Type-safe filter functions:
import { isNationalTeam } from '@withqwerty/sportmonks-typescript-sdk';
const teams = await client.teams.all().get();
const nationalTeams = teams.data.filter(isNationalTeam);
Sort Helpers
Type-safe sorting functions:
import { sortByName, sortByCapacity } from '@withqwerty/sportmonks-typescript-sdk';
// Sort teams by name
const sortedTeams = teams.data.sort(sortByName);
// Sort venues by capacity (descending)
const sortedVenues = venues.data.sort(sortByCapacity);
Response Transformers
Create typed transformers for responses:
import { createTransformer, PaginatedResponse, Team } from '@withqwerty/sportmonks-typescript-sdk';
// Create a transformer that extracts team names
const toTeamNames = createTransformer<PaginatedResponse<Team>, string[]>(response =>
response.data.map(team => team.name)
);
// Use it
const response = await client.teams.all().get();
const names = toTeamNames(response); // string[]
Complete Example
Hereโs how to use multiple type helpers together:
import {
SportMonksClient,
hasInclude,
isPaginatedResponse,
TeamWithCountry,
sortByName
} from '@withqwerty/sportmonks-typescript-sdk';
const client = new SportMonksClient(API_KEY);
async function getTeamsByCountry(countryName: string) {
const response = await client.teams.all().include(['country']).perPage(100).get();
if (!isPaginatedResponse(response)) {
throw new Error('Unexpected response type');
}
// Filter teams with type safety
const teamsFromCountry = response.data.filter((team): team is TeamWithCountry => {
return hasInclude(team, 'country') && team.country.name === countryName;
});
// Sort and return
return teamsFromCountry.sort(sortByName);
}
// Usage
const englishTeams = await getTeamsByCountry('England');
englishTeams.forEach(team => {
console.log(`${team.name} - ${team.country.name}`); // โ
Type safe!
});
Benefits
- Type Safety: Eliminate runtime errors from accessing undefined includes
- Better IntelliSense: Get proper autocomplete for included properties
- Cleaner Code: Use type guards instead of manual checks
- Reusability: Pre-defined types for common include patterns
Polling Utilities
Custom Includes
Validation
SportMonks SDK REPL (Interactive Console)
The SportMonks TypeScript SDK includes an interactive REPL (Read-Eval-Print Loop) for testing and exploring the API.
Installation & Usage
When installed via npm
After installing the SDK, you can use the REPL directly:
# Install the SDK
npm install @withqwerty/sportmonks-typescript-sdk
# Run the REPL
npx sportmonks-repl
# Run the advanced REPL
npx sportmonks-repl --advanced
When developing locally
If youโre working with the SDK source code:
# Simple REPL
npm run repl
# Advanced REPL
npm run repl:advanced
Features
- ๐ Interactive console with full SDK access
- ๐ Autocomplete support for resources and methods
- ๐ Command history (persisted between sessions)
- ๐จ Syntax highlighting and colored output
- ๐ Built-in examples and documentation
- ๐ ๏ธ Helper functions for data exploration
Getting Started
1. Set up your API key
Create a .env
file in the project root:
SPORTMONKS_API_KEY=your_api_key_here
Or set it as an environment variable:
export SPORTMONKS_API_KEY=your_api_key_here
2. Start the REPL
npm run repl
Basic Usage
Simple Queries
// Get all leagues (limited to 5)
await client.leagues.all().limit(5).get();
// Get a specific team with includes
await client.teams.byId(1).include(['country', 'venue']).get();
// Search for players
await client.players.search('Ronaldo').limit(10).get();
Using Includes
// Get fixtures with team information
await client.fixtures.byDate('2024-01-15').include(['localteam', 'visitorteam']).get();
// Get league with nested includes
await client.leagues.byId(8).include(['country', 'seasons.stages']).get();
Complex Queries
// Filter national teams in a season
await client.teams.bySeason(19735).include(['country']).filter('national_team', 'true').get();
// Get head-to-head with full match details
await client.fixtures.headToHead(1, 14).include(['events', 'lineups']).limit(5).get();
// Get transfers between dates
await client.transfers
.between('2024-01-01', '2024-01-31')
.include(['player', 'fromteam', 'toteam'])
.get();
Helper Functions
pp(response)
- Pretty Print
Pretty prints the entire response object with proper formatting:
const response = await client.leagues.all().limit(3).get();
pp(response);
data(response)
- Extract Data
Prints only the data array from the response:
const response = await client.teams.search('Manchester').get();
data(response);
examples()
- Show Examples
Displays example queries you can run:
sportmonks > examples();
resources()
- List Resources
Shows all available resources and their methods:
sportmonks > resources();
Available Resources
- leagues - Football leagues and competitions
- teams - Football teams
- players - Player information
- fixtures - Matches and game data
- seasons - Season information
- squads - Team squads by season
- standings - League tables and standings
- transfers - Player transfers
- venues - Stadium information
- coaches - Coach/manager data
- referees - Referee information
- livescores - Live match data
Protected Resources
The REPL automatically protects built-in resources and functions from being overwritten. If you try to use a protected name as a variable, youโll get a helpful error:
// This will trigger a protective error:
const players = await players.search('Salah').get();
// Error message will suggest alternatives:
// Cannot use 'players' as a variable name!
// 'players' is a SportMonks resource and cannot be overwritten.
// Try using a different name like:
// const playersResult = await players.search(...).get()
// const myPlayers = await players.all().get()
Protected names include:
- All resources:
leagues
,teams
,players
,fixtures
, etc. - Helper functions:
pp
,data
,type
,browse
,save
- System variables:
client
,_
Tips and Tricks
1. Use Tab Completion
Press Tab
to autocomplete resource names and methods:
sportmonks> client.lea[TAB]
sportmonks> client.leagues
2. Store Results in Variables
const leagues = await client.leagues.all().limit(10).get();
const premierLeague = leagues.data.find(l => l.name.includes('Premier'));
3. Explore Response Structure
const response = await client.teams.byId(1).get();
Object.keys(response); // See available fields
4. Use Async/Await
All API calls return promises, so use await
:
// Good
const data = await client.players.byId(580).get();
// Without await (returns Promise)
const promise = client.players.byId(580).get();
5. Chain Multiple Operations
const teams = await client.teams
.bySeason(19735)
.include(['country', 'venue'])
.filter('national_team', 'false')
.page(1)
.perPage(30)
.get();
Keyboard Shortcuts
Tab
- Autocompleteโ/โ
- Navigate command historyCtrl+C
- Cancel current inputCtrl+D
or.exit
- Exit REPLCtrl+L
- Clear screen
Error Handling
The REPL will show detailed error messages:
// API errors show full details
await client.teams.byId(999999).get();
// Error: Request failed with status code 404
// Validation errors
await client.fixtures.byDate('invalid-date').get();
// Error: Invalid date format: invalid-date. Expected YYYY-MM-DD
Environment Variables
SPORTMONKS_API_KEY
- Your SportMonks API keySPORTMONKS_TEST_API_KEY
- Alternative key for testing
Notes
- The REPL maintains a history file (
.sportmonks_repl_history
) for command persistence - All SDK features are available in the REPL
- The client is pre-initialized and available as
client
- Use
require()
to load additional modules if needed
Examples
API Documentation
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[1.1.0] - 2024-12-01
Changed
- IMPORTANT: Changed default include separator from comma (
,
) to semicolon (;
) to match SportMonks API requirements for multiple includes - Updated all unit tests to use semicolon separator for multiple includes
- Improved TypeScript types by replacing
any
with proper types in type helpers and validators
Added
- Input validation for PlayersResource:
- ID validation in
byId()
andbyCountry()
methods - Search query validation with minimum length check
- ID validation in
- Type helper utilities in
src/utils/type-helpers.ts
:hasInclude()
- Type guard to check if an include existshasData()
- Type guard for responses with dataisPaginatedResponse()
- Type guard for paginated responsesisSingleResponse()
- Type guard for single responsesWithRequired<T, K>
- Type helper to make optional properties required- Pre-defined types like
TeamWithCountry
,FixtureWithTeams
, etc.
- Documentation for type helpers (
docs/TYPE_HELPERS.md
) - ESLint configuration for test files (
tsconfig.eslint.json
) - Global REPL command accessible via
npx sportmonks-repl
when installed via npm
Fixed
- Integration test failures:
- Updated players test to use Denmark (ID: 320) instead of Brazil for European Plan compatibility
- Updated fixtures pagination test to use dates with more fixtures (2025-03-30)
- Skipped latest fixtures test due to subscription limitations
- ESLint configuration to properly lint test files
- Prettier formatting in type helpers and test files
- Test coverage improved to 97.7%
Developer Notes
- The include separator change maintains backwards compatibility for single includes
- Multiple includes now require semicolon separation (e.g.,
include: 'country;venue'
) - Field selectors within includes still use commas (e.g.,
include: 'team:name,short_code'
)
[1.0.2] - 2025-05-31
Added
- Interactive REPL (Read-Eval-Print Loop) for testing and exploring the API
- Simple REPL with direct resource access (
npm run repl
) - Advanced REPL with additional features (
npm run repl:advanced
) - Helper functions:
pp()
,data()
,examples()
,resources()
- Command history persistence
- No need to type
client.
prefix - direct access to resources
- Simple REPL with direct resource access (
Fixed
- Fixed
fixtures
resource documentation (removed non-existentlive()
method) - Clarified that live matches are accessed via
livescores.inplay()
Changed
- Moved REPL tools from
scripts/
totools/
directory for better organization
[1.0.1] - 2025-05-31
Changed
- Updated all dev dependencies to latest stable versions
- Migrated from ESLint v8 to v9 with new flat config format
- Updated husky to v9 simplified format
- Fixed CI/CD workflow issues (updated upload-artifact to v4)
Fixed
- Removed all deprecation warnings
- Fixed unused variable ESLint errors
Removed
- Deprecated
@types/dotenv
package (dotenv now includes its own types)
[1.0.0] - 2025-05-31
Added
- Initial release of SportMonks TypeScript SDK
- Full TypeScript support with comprehensive type definitions
- Support for 10 resources with 56 endpoints:
- Leagues (8 endpoints): all, byId, byCountry, search, live, byDate, byTeam, currentByTeam
- Teams (5 endpoints): all, byId, byCountry, bySeason, search
- Players (5 endpoints): all, byId, byCountry, search, latest
- Fixtures (13 endpoints): all, byId, byIds, byDate, byDateRange, byTeamAndDateRange, byTeamAndSeason, headToHead, search, byLivescores, byFixtureMulti, latest, byTvStation
- Standings (5 endpoints): all, bySeasonId, byRoundId, bySeasonIdCorrected, liveByLeagueId
- Livescores (3 endpoints): all, inplay, latest
- Transfers (6 endpoints): all, byId, latest, byDateRange, byPlayerId, byTeamId
- Coaches (5 endpoints): all, byId, byCountryId, byTeamId, search
- Referees (5 endpoints): all, byId, byCountryId, bySeasonId, search
- Venues (4 endpoints): all, byId, bySeasonId, search
- Method chaining for intuitive query building
- Automatic retry logic with exponential backoff
- Real-time polling utilities for livescores and transfers
- Input validation for dates, IDs, and search queries
- Rate limit information in responses
- Comprehensive error handling with detailed messages
- Support for includes, filters, pagination, and sorting
- Custom include separator support (for transfers endpoint)
- Enhanced support for SportMonksโ advanced query syntax
includeFields()
method for field selection on includeswithIncludes()
method for complex include configurations- Support for multiple filter values using arrays
SportMonksSyntaxBuilder
utility for programmatic query building- Full TypeScript types for SportMonks syntax patterns
- Comprehensive test coverage improvements (97.62% coverage)
Features
- Type Safety: Strong TypeScript types for all entities and API responses
- Method Chaining: Fluent API design for building complex queries
- Error Handling: Detailed error messages with context
- Retry Logic: Automatic retries with exponential backoff for failed requests
- Polling Utilities: Built-in support for real-time data updates
- Validation: Input validation for common parameters
- Flexible Configuration: Customizable timeout, base URL, and include separator
Testing
- Comprehensive test suite with 330+ tests
- Unit tests for all resources and utilities
- Integration tests with real API (when API key provided)
- 97.62% code coverage
Documentation
- Complete README with installation and usage instructions
- JSDoc comments on all public methods
- Examples for all major use cases
- Migration guide for future versions