Prefer to chat? Query the API with natural language using our AI Skill →
Give your AI tool live Cito endpoint context before you write integration code.
Public docs assistant
Tell Cito API what you are building.
Get endpoint recommendations, exact requests, code snippets, and a free-key CTA without digging through every page.
Real-time Match Tracking
Build live match trackers with real-time updates
This guide shows you how to build a real-time match tracker that updates as games progress. We'll cover both polling and webhook approaches.
Approach 1: Polling
Poll the API at regular intervals to get the latest match data:
match-tracker.js
class MatchTracker {
constructor(apiKey, matchId) {
this.apiKey = apiKey;
this.matchId = matchId;
this.lastUpdate = null;
this.listeners = [];
}
subscribe(callback) {
this.listeners.push(callback);
return () => {
this.listeners = this.listeners.filter(l => l !== callback);
};
}
emit(event, data) {
this.listeners.forEach(cb => cb(event, data));
}
async start() {
this.interval = setInterval(async () => {
try {
const response = await fetch(`https://api.citoapi.com/api/v1/cod/matches/${this.matchId}`, {
headers: { 'x-api-key': this.apiKey }
});
const match = await response.json();
if (this.hasChanged(match)) {
this.emit('update', match);
this.lastUpdate = match;
}
} catch (error) {
this.emit('error', error);
}
}, 5000); // Poll every 5 seconds
}
hasChanged(newData) {
if (!this.lastUpdate) return true;
return JSON.stringify(newData) !== JSON.stringify(this.lastUpdate);
}
stop() {
clearInterval(this.interval);
}
}
// Usage
const tracker = new MatchTracker(process.env.CITO_API_KEY, 'bp-match-214935');
tracker.subscribe((event, data) => {
if (event === 'update') {
console.log('Match updated:', data);
updateUI(data);
}
});
tracker.start();Approach 2: Webhooks (Recommended)
Use webhooks for instant updates without polling:
// Register webhook for match events
const webhook = await cito.webhooks.create({
url: 'https://yourapp.com/webhook',
events: ['match.updated', 'match.ended', 'player.elimination']
});
// Handle incoming webhooks
app.post('/webhook', (req, res) => {
const { event, data } = req.body;
// Broadcast to connected clients via WebSocket
io.emit('match-update', { event, data });
res.sendStatus(200);
});React Integration
useMatchTracker.ts
import { useState, useEffect } from 'react';
import { io } from 'socket.io-client';
export function useMatchTracker(matchId: string) {
const [match, setMatch] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
// Initial fetch
fetch(`/api/matches/${matchId}`)
.then(res => res.json())
.then(data => {
setMatch(data);
setLoading(false);
})
.catch(setError);
// Subscribe to real-time updates
const socket = io();
socket.on('match-update', ({ event, data }) => {
if (data.match_id === matchId) {
setMatch(prev => ({ ...prev, ...data }));
}
});
return () => socket.disconnect();
}, [matchId]);
return { match, loading, error };
}
// Usage in component
function MatchView({ matchId }) {
const { match, loading, error } = useMatchTracker(matchId);
if (loading) return <Spinner />;
if (error) return <Error message={error.message} />;
return (
<div>
<h1>{match.tournament}</h1>
<div>Game {match.current_game} of {match.total_games}</div>
<Leaderboard players={match.players} />
</div>
);
}Best Practices
Cache aggressively
Store match data locally and only update changed fields
Use diff updates
Only re-render components that have changed data
Handle reconnection
Implement reconnection logic for WebSocket disconnects