Rate limit | API 3.0

Rate limit | API 3.0

docs.sportmonks.com

Copy

<?php

class RateLimiter {
private $maxRequests;
private $windowSeconds;
private $requests = [];

public function __construct($maxRequests = 3000, $windowSeconds = 3600) {
$this->maxRequests = $maxRequests;
$this->windowSeconds = $windowSeconds;
}

public function throttle($entity = 'default') {
$now = time();

// Initialise entity if needed
if (!isset($this->requests[$entity])) {
$this->requests[$entity] = [];
}

// Remove old requests outside the window
$this->requests[$entity] = array_filter(
$this->requests[$entity],
function($timestamp) use ($now) {
return ($now - $timestamp) < $this->windowSeconds;
}
);

// Check if at limit
if (count($this->requests[$entity]) >= $this->maxRequests) {
$oldestRequest = min($this->requests[$entity]);
$waitTime = $this->windowSeconds - ($now - $oldestRequest);

echo "Throttling {$entity}: waiting {$waitTime}s\n";
sleep($waitTime);

// Try again recursively
return $this->throttle($entity);
}

// Add this request to history
$this->requests[$entity][] = $now;
}
}

class SportmonksAPI {
private $token;
private $baseUrl = 'https://api.sportmonks.com/v3/football';
private $cache = [];
private $limiter;

public function __construct($apiToken, $maxRequests = 2800) {
$this->token = $apiToken;
$this->limiter = new RateLimiter($maxRequests);
}

public function request($endpoint, $params = [], $entity = 'default', $maxRetries = 3) {
// Throttle request
$this->limiter->throttle($entity);

// Build URL
$params['api_token'] = $this->token;
$url = $this->baseUrl . $endpoint . '?' . http_build_query($params);

// Make request with retry logic
for ($attempt = 0; $attempt < $maxRetries; $attempt++) {
try {
$response = $this->fetchWithRetry($url, $attempt);
$data = json_decode($response, true);

// Log rate limit info
if (isset($data['rate_limit'])) {
$this->logRateLimit($data['rate_limit']);
}

return $data;

} catch (Exception $e) {
if ($attempt === $maxRetries - 1) {
throw $e;
}

// Exponential backoff
$waitTime = pow(2, $attempt);
echo "Request failed. Retrying after {$waitTime}s...\n";
sleep($waitTime);
}
}
}

private function fetchWithRetry($url, $attempt) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 429) {
$data = json_decode($response, true);
$retryAfter = $data['retry_after'] ?? pow(2, $attempt);

echo "Rate limited. Retrying after {$retryAfter}s...\n";
sleep($retryAfter);

// Retry recursively
return $this->fetchWithRetry($url, $attempt);
}

if ($httpCode !== 200) {
throw new Exception("HTTP {$httpCode}: {$response}");
}

return $response;
}

private function logRateLimit($rateLimit) {
$remaining = $rateLimit['remaining'] ?? '?';
$entity = $rateLimit['requested_entity'] ?? 'Unknown';

echo "{$entity}: {$remaining} requests remaining\n";

if ($remaining < 200) {
echo "⚠️ Low on {$entity} requests! Optimize your calls.\n";
}
}

// Cached method for types
public function getTypes() {
$cacheKey = 'types';
$cacheDuration = 7 * 24 * 60 * 60; // 1 week

if (isset($this->cache[$cacheKey])) {
$cached = $this->cache[$cacheKey];
if (time() - $cached['timestamp'] < $cacheDuration) {
echo "Using cached types\n";
return $cached['data'];
}
}

echo "Fetching fresh types\n";
$response = $this->request('/core/types', [], 'Type');

$this->cache[$cacheKey] = [
'data' => $response['data'],
'timestamp' => time()
];

return $response['data'];
}

// Helper method for batched requests
public function getFixturesByIds($ids) {
if (empty($ids)) {
return [];
}

$idsString = implode(',', $ids);
return $this->request("/fixtures/multi/{$idsString}", [], 'Fixture');
}
}

// Usage Example
try {
$api = new SportmonksAPI('YOUR_TOKEN_HERE');

// Single fixture with includes
$fixture = $api->request('/fixtures/123', [
'include' => 'participants;scores;events'
], 'Fixture');

echo "Fixture: {$fixture['data']['name']}\n";

// Batched request
$multipleFixtures = $api->getFixturesByIds([123, 456, 789]);
echo "Fetched " . count($multipleFixtures['data']) . " fixtures\n";

// Cached types (only fetches once)
$types = $api->getTypes();
echo "Got " . count($types) . " types\n";

// Types from cache (0 API calls)
$typesAgain = $api->getTypes();

} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>

Report Page