Gestion des erreurs
L'API Infoparcelle utilise les codes de statut HTTP standards et retourne des messages d'erreur détaillés en JSON.
Codes de statut HTTP
Codes de succès
| Code | Nom | Description |
|---|---|---|
200 | OK | Requête réussie, données retournées dans le corps de la réponse |
201 | Created | Ressource créée avec succès |
204 | No Content | Requête réussie, pas de contenu à retourner |
Codes d'erreur client (4xx)
| Code | Nom | Description |
|---|---|---|
400 | Bad Request | Requête malformée ou paramètres invalides |
401 | Unauthorized | Authentification manquante ou invalide |
403 | Forbidden | Accès refusé (permissions insuffisantes ou IP bloquée) |
404 | Not Found | Ressource introuvable |
429 | Too Many Requests | Trop de requêtes (limite de débit dépassée) |
432 | Subscription Required | Aucun abonnement API actif |
433 | Invalid Payment Method | Moyen de paiement invalide ou manquant |
434 | Quota Exceeded | Quota de crédits API épuisé |
435 | Upgrade Required | Fonctionnalité nécessitant un plan supérieur |
Codes d'erreur serveur (5xx)
| Code | Nom | Description |
|---|---|---|
500 | Internal Server Error | Erreur interne du serveur |
503 | Service Unavailable | Service temporairement indisponible |
Format des erreurs
Toutes les erreurs retournent un objet JSON avec cette structure :
{
"error": "Nom de l'erreur",
"message": "Description détaillée de l'erreur"
}
Exemples d'erreurs
400 - Requête invalide
{
"error": "bad_request",
"message": "Le paramètre 'recherche' est requis"
}
Causes courantes :
- Paramètre requis manquant
- Format de paramètre invalide
- Valeur hors limites
Solution : Vérifiez la documentation de l'endpoint et corrigez les paramètres.
401 - Non authentifié
{
"error": "invalid_api_key",
"message": "Token d'authentification invalide",
}
Causes courantes :
- Header
Authorizationmanquant - Clé API invalide ou supprimée
- Format du token incorrect
Solution : Vérifiez votre clé API et le format du header.
404 - Ressource non trouvée
{
"error": "not_found",
"message": "Parcelle introuvable avec l'identifiant '123456789'",
}
Causes courantes :
- Identifiant incorrect
- Ressource supprimée ou inexistante
- Endpoint mal formé
Solution : Vérifiez l'identifiant et l'endpoint.
429 - Trop de requêtes
{
"error": "rate_limit_exceeded",
"message": "Limite de débit dépassée. Maximum 20 requêtes par seconde.",
"retry_after": 30
}
Causes courantes :
- Plus de 1200 requêtes en 1 minute (soit 20 requêtes par seconde)
- Boucle infinie de requêtes
Solution : Implémentez un rate limiter et respectez le retry_after ou le header Retry-After.
432 - Abonnement requis
{
"error": "no_subscription",
"message": "Aucun abonnement API actif détecté. Veuillez souscrire à un plan.",
}
Solution : Souscrivez à un plan API depuis votre espace compte.
434 - Quota dépassé
{
"error": "quota_unavailable",
"message": "Quota mensuel de 5 000 crédits épuisé",
}
Solution : Activez les dépassements ou passez à un plan supérieur.
500 - Erreur serveur
{
"error": "server_error",
"message": "Une erreur interne s'est produite. Veuillez réessayer plus tard.",
}
Solution : Réessayez la requête. Si le problème persiste, contactez le support en fournissant l'error_id.
Gestion des erreurs par langage
- JavaScript
- Python
- PHP
async function fetchApi(url, options = {}) {
try {
const response = await fetch(url, {
...options,
headers: {
'Authorization': `Bearer ${apiKey}`,
'Accept': 'application/json',
...options.headers,
},
});
// Erreur HTTP
if (!response.ok) {
const error = await response.json();
switch (response.status) {
case 400:
throw new Error(`Requête invalide: ${error.message}`);
case 401:
throw new Error(`Authentification échouée: ${error.message}`);
case 404:
throw new Error(`Ressource introuvable: ${error.message}`);
case 429:
const retryAfter = error.retry_after || 60;
throw new Error(`Rate limit dépassé. Réessayez dans ${retryAfter}s`);
case 432:
throw new Error(`Abonnement requis: ${error.message}`);
case 434:
throw new Error(`Quota dépassé: ${error.message}`);
case 500:
case 503:
throw new Error(`Erreur serveur: ${error.message}`);
default:
throw new Error(`Erreur ${response.status}: ${error.message}`);
}
}
return await response.json();
} catch (error) {
// Erreur réseau
if (error instanceof TypeError) {
throw new Error('Erreur de connexion. Vérifiez votre connexion internet.');
}
// Rethrow les autres erreurs
throw error;
}
}
// Utilisation avec gestion d'erreur
try {
const data = await fetchApi(
'https://app.infoparcelle.fr/api/v1/geocoder/search?recherche=1+Rue+de+Rivoli'
);
console.log(data);
} catch (error) {
console.error('Erreur:', error.message);
// Logique de fallback ou notification utilisateur
}
import requests
from requests.exceptions import RequestException
class InfoparcelleAPIError(Exception):
"""Exception de base pour les erreurs API"""
pass
class AuthenticationError(InfoparcelleAPIError):
"""Erreur d'authentification"""
pass
class NotFoundError(InfoparcelleAPIError):
"""Ressource non trouvée"""
pass
class RateLimitError(InfoparcelleAPIError):
"""Limite de débit dépassée"""
def __init__(self, message, retry_after=None):
super().__init__(message)
self.retry_after = retry_after
class QuotaExceededError(InfoparcelleAPIError):
"""Quota dépassé"""
pass
def fetch_api(url, params=None):
try:
response = requests.get(
url,
params=params,
headers={
'Authorization': f'Bearer {api_key}',
'Accept': 'application/json',
}
)
# Gestion des erreurs HTTP
if response.status_code == 400:
error = response.json()
raise InfoparcelleAPIError(f"Requête invalide: {error['message']}")
elif response.status_code == 401:
error = response.json()
raise AuthenticationError(f"Authentification échouée: {error['message']}")
elif response.status_code == 404:
error = response.json()
raise NotFoundError(f"Ressource introuvable: {error['message']}")
elif response.status_code == 429:
error = response.json()
retry_after = error.get('retry_after', 60)
raise RateLimitError(
f"Rate limit dépassé. Réessayez dans {retry_after}s",
retry_after=retry_after
)
elif response.status_code == 434:
error = response.json()
raise QuotaExceededError(f"Quota dépassé: {error['message']}")
elif response.status_code >= 500:
error = response.json()
raise InfoparcelleAPIError(f"Erreur serveur: {error['message']}")
response.raise_for_status()
return response.json()
except RequestException as e:
raise InfoparcelleAPIError(f"Erreur de connexion: {str(e)}")
# Utilisation avec gestion d'erreur
try:
data = fetch_api(
'https://app.infoparcelle.fr/api/v1/geocoder/search',
params={'recherche': '1 Rue de Rivoli'}
)
print(data)
except AuthenticationError as e:
print(f"Erreur d'authentification: {e}")
# Vérifier la clé API
except RateLimitError as e:
print(f"Rate limit: {e}")
print(f"Réessayer dans {e.retry_after}s")
# Implémenter un retry
except QuotaExceededError as e:
print(f"Quota dépassé: {e}")
# Notifier l'utilisateur de mettre à niveau
except NotFoundError as e:
print(f"Non trouvé: {e}")
# Gérer l'absence de résultat
except InfoparcelleAPIError as e:
print(f"Erreur API: {e}")
# Gestion générique
<?php
class InfoparcelleAPIException extends Exception {}
class AuthenticationException extends InfoparcelleAPIException {}
class NotFoundException extends InfoparcelleAPIException {}
class RateLimitException extends InfoparcelleAPIException {
public $retryAfter;
public function __construct($message, $retryAfter = null) {
parent::__construct($message);
$this->retryAfter = $retryAfter;
}
}
class QuotaExceededException extends InfoparcelleAPIException {}
function fetchApi($url, $params = []) {
global $apiKey;
$queryString = http_build_query($params);
$fullUrl = $url . ($queryString ? '?' . $queryString : '');
$ch = curl_init($fullUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Accept: application/json',
],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
$error = json_decode($response, true);
$message = $error['message'] ?? 'Erreur inconnue';
switch ($httpCode) {
case 400:
throw new InfoparcelleAPIException("Requête invalide: $message");
case 401:
throw new AuthenticationException("Authentification échouée: $message");
case 404:
throw new NotFoundException("Ressource introuvable: $message");
case 429:
$retryAfter = $error['retry_after'] ?? 60;
throw new RateLimitException(
"Rate limit dépassé. Réessayez dans {$retryAfter}s",
$retryAfter
);
case 434:
throw new QuotaExceededException("Quota dépassé: $message");
default:
throw new InfoparcelleAPIException("Erreur HTTP $httpCode: $message");
}
}
return json_decode($response, true);
}
// Utilisation avec gestion d'erreur
try {
$data = fetchApi(
'https://app.infoparcelle.fr/api/v1/geocoder/search',
['recherche' => '1 Rue de Rivoli']
);
echo json_encode($data, JSON_PRETTY_PRINT);
} catch (AuthenticationException $e) {
echo "Erreur d'authentification: {$e->getMessage()}\n";
// Vérifier la clé API
} catch (RateLimitException $e) {
echo "Rate limit: {$e->getMessage()}\n";
echo "Réessayer dans {$e->retryAfter}s\n";
// Implémenter un retry
} catch (QuotaExceededException $e) {
echo "Quota dépassé: {$e->getMessage()}\n";
// Notifier l'utilisateur
} catch (NotFoundException $e) {
echo "Non trouvé: {$e->getMessage()}\n";
// Gérer l'absence de résultat
} catch (InfoparcelleAPIException $e) {
echo "Erreur API: {$e->getMessage()}\n";
// Gestion générique
}
Bonnes pratiques
1. Toujours vérifier le code de statut
// ❌ Mauvais - ne vérifie pas les erreurs
const data = await fetch(url).then(r => r.json());
// ✅ Bon - vérifie le statut HTTP
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
2. Implémenter un retry pour les erreurs temporaires
Réessayez automatiquement pour les erreurs 429, 500, 503 :
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${apiKey}` },
});
if (response.status === 429) {
const error = await response.json();
const retryAfter = error.retry_after || 60;
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}
if (response.status >= 500) {
if (i < maxRetries - 1) {
await new Promise(resolve => setTimeout(resolve, 2 ** i * 1000));
continue;
}
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
if (i === maxRetries - 1) throw error;
}
}
}
3. Logger les erreurs avec contexte
function logError(error, context) {
console.error({
timestamp: new Date().toISOString(),
error: error.message,
context: context,
stack: error.stack,
});
// Envoyer vers un service de monitoring (Sentry, etc.)
}
try {
const data = await fetchApi(url);
} catch (error) {
logError(error, {
url: url,
user_id: userId,
operation: 'geocoding_search',
});
}
4. Fournir des messages d'erreur utiles
function getUserFriendlyErrorMessage(error, statusCode) {
const messages = {
400: "Les paramètres de recherche sont invalides. Veuillez vérifier votre saisie.",
401: "Votre session a expiré. Veuillez vous reconnecter.",
404: "Aucun résultat trouvé pour cette recherche.",
429: "Trop de requêtes. Veuillez patienter quelques secondes.",
434: "Votre quota mensuel est épuisé. Veuillez mettre à niveau votre plan.",
500: "Une erreur est survenue. Veuillez réessayer plus tard.",
};
return messages[statusCode] || "Une erreur inattendue est survenue.";
}
Support
Si vous rencontrez une erreur persistante :
- Vérifiez la documentation : Référence API
- Consultez la FAQ : Questions fréquentes
- Contactez le support :
- Email : contact@infoparcelle.fr
- En fournissant :
- Code d'erreur HTTP
- Message d'erreur complet
- Exemple de requête (sans clé API !)
Prochaines étapes
- Référence API - Documentation complète
- Rate Limits - Gestion des limites de débit