JavaScript/TypeScript SDK Guide
Complete guide for integrating AltSportsLeagues.ai into your JavaScript or TypeScript application. Works with React, Next.js, Node.js, and any JavaScript runtime.
Installation
npm install axios
# Or use built-in fetch (Node.js 18+)Basic Setup
Create API Client
// lib/altsports-client.ts
export class AltSportsClient {
private baseURL: string;
private apiKey: string;
constructor(apiKey: string, baseURL?: string) {
this.apiKey = apiKey;
this.baseURL = baseURL || 'https://api.altsportsleagues.ai';
}
private async request<T>(
endpoint: string,
options?: RequestInit
): Promise<T> {
const response = await fetch(`${this.baseURL}${endpoint}`, {
...options,
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
...options?.headers,
},
});
if (!response.ok) {
const error = await response.json().catch(() => ({ detail: 'Unknown error' }));
throw new Error(error.detail || `HTTP ${response.status}`);
}
return response.json();
}
// League methods
async getLeagues(filters?: {
sport?: string;
tier?: string;
minBettingScore?: number;
}) {
const params = new URLSearchParams();
if (filters?.sport) params.append('sport', filters.sport);
if (filters?.tier) params.append('tier', filters.tier);
if (filters?.minBettingScore) params.append('min_betting_score', filters.minBettingScore.toString());
return this.request(`/v1/leagues?${params}`);
}
async getLeague(leagueId: string) {
return this.request(`/v1/leagues/${leagueId}`);
}
// Contract methods
async generateContract(params: {
league_name: string;
partnership_type: string;
pricing_tier: string;
}) {
return this.request('/v1/contracts/generate', {
method: 'POST',
body: JSON.stringify(params)
});
}
// Schema methods
async listSchemas(filters?: {
category?: string;
format?: string;
}) {
const params = new URLSearchParams();
if (filters?.category) params.append('category', filters.category);
if (filters?.format) params.append('format', filters.format);
return this.request(`/v1/docs/schemas?${params}`);
}
async getSchemaDoc(schemaPath: string) {
return this.request('/v1/docs/schemas/generate', {
method: 'POST',
body: JSON.stringify({
schema_path: schemaPath,
include_examples: true
})
});
}
}
// Export singleton instance
export const altsports = new AltSportsClient(
process.env.ALTSPORTS_API_KEY || '',
process.env.ALTSPORTS_BASE_URL
);React Integration
Using React Hooks
// hooks/use-altsports.ts
import { useState, useEffect } from 'react';
import { altsports } from '@/lib/altsports-client';
export function useLeagues(filters?: {
sport?: string;
tier?: string;
}) {
const [leagues, setLeagues] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchLeagues = async () => {
try {
setLoading(true);
const data = await altsports.getLeagues(filters);
setLeagues(data.leagues);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to fetch leagues');
} finally {
setLoading(false);
}
};
fetchLeagues();
}, [filters?.sport, filters?.tier]);
return { leagues, loading, error };
}
export function useContractGeneration() {
const [generating, setGenerating] = useState(false);
const [contract, setContract] = useState(null);
const [error, setError] = useState<string | null>(null);
const generate = async (params: any) => {
try {
setGenerating(true);
const result = await altsports.generateContract(params);
setContract(result);
return result;
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to generate contract');
throw err;
} finally {
setGenerating(false);
}
};
return { generate, generating, contract, error };
}Example Component
// components/league-list.tsx
'use client';
import { useLeagues } from '@/hooks/use-altsports';
export function LeagueList() {
const { leagues, loading, error } = useLeagues({ tier: 'premium' });
if (loading) return <div>Loading leagues...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{leagues.map((league: any) => (
<div key={league.id} className="border rounded-lg p-4">
<h3 className="font-bold text-lg">{league.name}</h3>
<p className="text-sm text-muted-foreground">{league.sport}</p>
<div className="mt-2 flex items-center gap-2">
<span className="text-xs bg-blue-100 px-2 py-1 rounded">{league.tier}</span>
<span className="text-xs">Betting: {league.betting_potential}/10</span>
</div>
</div>
))}
</div>
);
}Next.js Integration
Server Component
// app/leagues/page.tsx
import { altsports } from '@/lib/altsports-client';
export default async function LeaguesPage() {
// Fetch on server
const data = await altsports.getLeagues({ tier: 'premium' });
return (
<div>
<h1>Premium Leagues</h1>
{data.leagues.map((league: any) => (
<div key={league.id}>
<h2>{league.name}</h2>
<p>Betting Potential: {league.betting_potential}/10</p>
</div>
))}
</div>
);
}API Route
// app/api/leagues/route.ts
import { NextResponse } from 'next/server';
import { altsports } from '@/lib/altsports-client';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const sport = searchParams.get('sport');
try {
const data = await altsports.getLeagues({ sport: sport || undefined });
return NextResponse.json(data);
} catch (error) {
return NextResponse.json(
{ error: 'Failed to fetch leagues' },
{ status: 500 }
);
}
}Node.js Backend Integration
// server.ts
import express from 'express';
import { AltSportsClient } from './lib/altsports-client';
const app = express();
const altsports = new AltSportsClient(process.env.ALTSPORTS_API_KEY!);
app.get('/api/leagues', async (req, res) => {
try {
const data = await altsports.getLeagues({
sport: req.query.sport as string,
tier: req.query.tier as string
});
res.json(data);
} catch (error) {
res.status(500).json({ error: 'Failed to fetch leagues' });
}
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});TypeScript Types
// types/altsports.ts
export interface League {
id: string;
name: string;
sport: string;
tier: 'premium' | 'growth' | 'standard' | 'emerging';
betting_potential: number;
fan_engagement: number;
market_size: string;
founded?: number;
website?: string;
}
export interface LeaguesResponse {
leagues: League[];
total: number;
page: number;
per_page: number;
}
export interface Contract {
contract_id: string;
pipeline_id: string;
status: string;
reasoning_steps: string[];
documents: {
contract_pdf: string;
term_sheet: string;
};
generated_at: string;
}
export interface SchemaMetadata {
path: string;
category: string;
format: 'json' | 'typescript' | 'python' | 'graphql';
version: string;
name: string;
}Error Handling Best Practices
// lib/api-error-handler.ts
export class AltSportsAPIError extends Error {
constructor(
public statusCode: number,
public detail: string,
public response?: any
) {
super(detail);
this.name = 'AltSportsAPIError';
}
}
export async function handleAPIError(error: any): Promise<never> {
if (error.response) {
// API returned error response
throw new AltSportsAPIError(
error.response.status,
error.response.data.detail || 'API error',
error.response.data
);
} else if (error.request) {
// Request made but no response
throw new AltSportsAPIError(0, 'No response from API');
} else {
// Error setting up request
throw new AltSportsAPIError(0, error.message);
}
}
// Usage with retry logic
export async function withRetry<T>(
fn: () => Promise<T>,
maxRetries: number = 3,
delay: number = 1000
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (i === maxRetries - 1) throw error;
// Exponential backoff
await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, i)));
}
}
throw new Error('Max retries exceeded');
}Advanced Examples
Batch Processing
// Process multiple leagues in parallel
async function analyzeMultipleLeagues(leagueIds: string[]) {
const results = await Promise.all(
leagueIds.map(id => altsports.getLeague(id))
);
return results.map(league => ({
id: league.id,
name: league.name,
recommendation: league.betting_potential > 7.5 ? 'Partner' : 'Monitor'
}));
}Caching Strategy
// lib/cache.ts
const cache = new Map<string, { data: any; expiry: number }>();
export async function cachedRequest<T>(
key: string,
fn: () => Promise<T>,
ttl: number = 300000 // 5 minutes
): Promise<T> {
const cached = cache.get(key);
if (cached && Date.now() < cached.expiry) {
return cached.data as T;
}
const data = await fn();
cache.set(key, { data, expiry: Date.now() + ttl });
return data;
}
// Usage
const leagues = await cachedRequest(
'premium-leagues',
() => altsports.getLeagues({ tier: 'premium' }),
300000
);Testing
// __tests__/altsports-client.test.ts
import { AltSportsClient } from '@/lib/altsports-client';
describe('AltSportsClient', () => {
const client = new AltSportsClient('test_api_key');
it('fetches leagues successfully', async () => {
const data = await client.getLeagues();
expect(data.leagues).toBeInstanceOf(Array);
});
it('handles errors gracefully', async () => {
const badClient = new AltSportsClient('invalid_key');
await expect(badClient.getLeagues()).rejects.toThrow();
});
});Next Steps
- API Reference: Complete endpoint documentation
- MCP Integration: Connect AI agents
- Schema Explorer: Browse all 150+ data schemas
- Quick Start Guide: Basic integration guide