Limites et erreurs
Les quotas d’appels de chaque clé et les codes d’erreur renvoyés par l’API.
Limites d’appels
Section intitulée « Limites d’appels »Par défaut, chaque clé peut faire :
- 30 appels par minute : le compteur repart à zéro au début de chaque minute ;
- 500 appels par jour : le compteur repart à zéro à minuit UTC, soit 1 h ou 2 h du matin à l’heure de Paris selon la saison.
Ces valeurs peuvent évoluer. Les limites en vigueur sont toujours indiquées dans les en-têtes de quota de chaque réponse.
Le quota du jour ne décompte pas :
- les appels refusés pour dépassement de limite (
429) ; - les appels qui échouent à cause d’une erreur de notre côté (
500et503) ; - les appels refusés avant tout traitement : clé invalide (
401) ou abonnement inactif (403).
Un appel refusé pour abonnement inactif (403) compte toutefois dans la limite par minute.
Les autres erreurs, comme un paramètre invalide (400) ou un article introuvable (404), sont décomptées.
En-têtes de quota
Section intitulée « En-têtes de quota »Chaque réponse, sauf les erreurs 401, contient les en-têtes suivants :
| En-tête | Valeur |
|---|---|
X-RateLimit-Limit-Minute |
Nombre d’appels autorisés par minute. |
X-RateLimit-Remaining-Minute |
Appels restants dans la minute en cours. |
X-RateLimit-Limit-Day |
Nombre d’appels autorisés par jour. |
X-RateLimit-Remaining-Day |
Appels restants jusqu’à minuit UTC. |
Par exemple :
HTTP/1.1 200 OKContent-Type: application/jsonX-RateLimit-Limit-Minute: 30X-RateLimit-Remaining-Minute: 29X-RateLimit-Limit-Day: 500X-RateLimit-Remaining-Day: 468Gérer un dépassement
Section intitulée « Gérer un dépassement »Une fois une limite atteinte, l’API répond avec le statut 429 et l’un de ces codes :
RATE_LIMIT_MINUTE_EXCEEDED: la limite par minute est atteinte ;RATE_LIMIT_DAY_EXCEEDED: la limite par jour est atteinte.
L’en-tête Retry-After indique en secondes le délai à attendre avant de réessayer : jusqu’à la minute suivante, ou jusqu’à minuit UTC pour la limite par jour. Ne relancez pas d’appel avant ce délai : il serait refusé à son tour.
Les exemples ci-dessous lisent les en-têtes de la réponse et signalent un dépassement :
curl -s -D - -o /dev/null "https://beta-api.oscar-seo.ai/v1/articles?pageSize=1" \ -H "Authorization: Bearer $OSCAR_API_KEY"-D - affiche les en-têtes de la réponse et -o /dev/null masque son contenu.
<?php$apiKey = getenv('OSCAR_API_KEY');$headers = [];
$curl = curl_init('https://beta-api.oscar-seo.ai/v1/articles?pageSize=1');curl_setopt_array($curl, [ CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey], CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADERFUNCTION => function ($curl, $line) use (&$headers) { $parts = explode(':', $line, 2); if (count($parts) === 2) { $headers[strtolower(trim($parts[0]))] = trim($parts[1]); } return strlen($line); },]);$body = json_decode(curl_exec($curl), true);$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
if ($status === 429) { exit('Limite atteinte (' . $body['error'] . '), réessayez dans ' . $headers['retry-after'] . ' secondes' . PHP_EOL);}if ($status !== 200) { exit('Erreur ' . $status . ' : ' . $body['error'] . PHP_EOL);}
echo 'Appels restants aujourd’hui : ' . $headers['x-ratelimit-remaining-day'] . PHP_EOL;const apiKey = process.env.OSCAR_API_KEY
const response = await fetch('https://beta-api.oscar-seo.ai/v1/articles?pageSize=1', { headers: { Authorization: `Bearer ${apiKey}` }})const body = await response.json()
if (response.status === 429) { const retryAfter = response.headers.get('Retry-After') throw new Error(`Limite atteinte (${body.error}), réessayez dans ${retryAfter} secondes`)}if (!response.ok) { throw new Error(`Erreur ${response.status} : ${body.error}`)}
console.log('Appels restants aujourd’hui :', response.headers.get('X-RateLimit-Remaining-Day'))Format des erreurs
Section intitulée « Format des erreurs »En cas d’erreur, l’API répond avec un statut HTTP 4xx ou 5xx et un corps JSON qui contient le code de l’erreur :
{ "error": "ARTICLE_NOT_FOUND" }Pour l’erreur INVALID_REQUEST, le champ details indique les paramètres en cause :
{ "error": "INVALID_REQUEST", "details": { "errors": [], "properties": { "pageSize": { "errors": ["Too big: expected number to be <=50"] } } }}Les messages de details sont en anglais et servent au diagnostic : leur texte peut changer. Basez le traitement des erreurs dans votre code sur le statut HTTP et sur le champ error.
Codes d’erreur
Section intitulée « Codes d’erreur »| Statut | Code | Cause | Que faire |
|---|---|---|---|
| 400 | INVALID_REQUEST |
Un paramètre est invalide : details indique lequel. |
Corrigez le paramètre. Pour un cursor refusé, renvoyez le dernier nextCursor reçu, sans le modifier. |
| 401 | INVALID_API_KEY |
La clé est absente, mal formée, inconnue ou révoquée. | Vérifiez l’en-tête Authorization. Si la clé a été révoquée, créez-en une autre. |
| 403 | SUBSCRIPTION_INACTIVE |
Aucun Oscar du site n’a d’abonnement actif. | Réactivez l’abonnement d’un Oscar du site : la clé fonctionne de nouveau, sans changement de votre côté. |
| 404 | OSCAR_NOT_FOUND |
oscarId ne correspond à aucun Oscar du site de la clé. |
Vérifiez l’identifiant, par exemple à partir du champ oscarId des articles. |
| 404 | ARTICLE_NOT_FOUND |
L’article n’existe pas, appartient à un autre site, n’a pas encore été généré ou son Oscar a été supprimé. | Vérifiez l’identifiant. Inutile de réessayer avec le même. |
| 429 | RATE_LIMIT_MINUTE_EXCEEDED |
La limite d’appels par minute est atteinte. | Attendez le délai indiqué par Retry-After. |
| 429 | RATE_LIMIT_DAY_EXCEEDED |
La limite d’appels par jour est atteinte. | Reprenez après minuit UTC, selon le délai indiqué par Retry-After. |
| 500 | INTERNAL_ERROR |
Une erreur inattendue s’est produite de notre côté. | Réessayez plus tard. Si l’erreur persiste, contactez support@oscar-seo.ai. |
| 503 | ARTICLE_CONTENT_UNAVAILABLE |
Le contenu des articles est momentanément indisponible. | Réessayez après le délai indiqué par Retry-After. |
Une réponse 401 contient aussi l’en-tête WWW-Authenticate: Bearer.