Gestion des erreurs
Comprenez les réponses d'erreur de l'API Piloterr et apprenez à gérer chaque cas correctement.
Chaque requête à l'API Piloterr retourne un code de statut HTTP standard. Ce guide explique la signification de chaque code, quand les crédits sont consommés et comment gérer les échecs dans votre intégration.
Format de réponse
Les réponses réussies retournent un objet JSON avec les données du point d'accès. Les réponses d'erreur suivent une structure cohérente :
{
"error": "Human-readable description of what went wrong"
}Vérifiez toujours le code de statut HTTP avant de lire le corps.
Codes de statut
200 Succès
Facturé. La requête s'est terminée avec succès. Les crédits sont déduits de votre solde.
const res = await fetch(url, { headers: { "x-api-key": API_KEY } })
if (res.status === 200) {
const data = await res.json()
// process data
}201 Tâche créée
Facturé. Une tâche asynchrone a été créée et acceptée. Votre solde est vérifié avant la mise en file d'attente : une tâche ne démarre jamais sans les crédits nécessaires pour la payer.
202 Accepté (async)
Non facturé. La requête a été acceptée et mise en file d'attente. Utilisez l'ID de tâche retourné pour interroger le résultat : consulter le statut d'une tâche est gratuit.
400 Requête incorrecte
Non facturé. Votre requête contient des paramètres invalides ou manquants.
Causes courantes :
- Un paramètre de requête obligatoire est manquant
- Une valeur de paramètre a le mauvais type ou format
- Le corps de la requête est malformé
Que faire : Relisez la documentation du point d'accès et vérifiez chaque paramètre obligatoire. Enregistrez l'URL complète de la requête pour repérer les fautes de frappe.
if (res.status === 400) {
const { error } = await res.json()
console.error("Bad request:", error)
// do not retry, fix the parameters first
}401 Non autorisé
Non facturé. Retourné pour les problèmes d'authentification et la limitation de débit. Vérifiez le message d'erreur pour les distinguer.
Votre en-tête x-api-key est manquant ou contient une valeur non reconnue.
Correction : Copiez votre clé depuis votre tableau de bord → Clés API et assurez-vous que l'en-tête x-api-key est présent sur chaque requête.
La clé existe mais a été désactivée.
Correction : Accédez à votre tableau de bord → Clés API et activez la clé, ou générez-en une nouvelle.
La clé a dépassé sa date d'expiration.
Correction : Générez une nouvelle clé ou prolongez la date d'expiration depuis votre tableau de bord.
Vous avez envoyé trop de requêtes dans un court laps de temps. Les limites du plan ressemblent à Rate limit exceeded: You've exceeded the … rate limit on your subscription. Les quotas par clé ressemblent à Rate limit exceeded for the API key: quota daily (ou total / weekly / monthly).
Correction : Attendez et réessayez après un délai. Si cela se produit régulièrement, mettez à niveau votre plan ou augmentez les quotas de la clé. Ces limites retournent 401, pas 429.
if (res.status === 401) {
const { error } = await res.json()
if (error.toLowerCase().includes("rate limit")) {
await new Promise(r => setTimeout(r, 2000))
// retry
}
}402 Payment required
Non facturé. La requête n'a pas été exécutée. La chaîne error indique la raison :
Payment required— le quota API et les crédits pay-as-you-go ne peuvent pas couvrir l'appelYou have open invoices: …— une facture impayée bloque le compteInsufficient credits: X required, Y available— un point d'accès par lignes renverrait plus de lignes que vous ne pouvez en payer
Que faire :
- Achetez un pack ponctuel ou mettez à niveau votre plan depuis votre tableau de bord, ou réglez les factures en attente sous Paramètres → Factures.
- Ou activez le Rechargement automatique pour éviter que l'épuisement du solde ne se reproduise.
Le rechargement automatique ne se déclenche que lorsque votre solde passe sous le seuil configuré. Il ne s'exécute jamais selon un calendrier fixe ou à une heure précise. Un délai de 72 heures intégré empêche également plusieurs charges en peu de temps : une fois un rechargement effectué, il ne peut pas se déclencher à nouveau pendant 72 heures quelle que soit l'évolution de votre solde. En cas d'échec de paiement, le rechargement automatique est automatiquement désactivé pour protéger votre compte.
Ne réessayez pas immédiatement une réponse 402. L'appel échouera à nouveau jusqu'à ce que vous ajoutiez des crédits. Configurez une alerte pour que votre équipe soit notifiée lorsque cela se produit.
if (res.status === 402) {
// alert your team or trigger an auto top-up flow
throw new Error("Insufficient credits. Top up at https://app.piloterr.com")
}403 Interdit
Non facturé. La requête a été refusée avant d'être exécutée. Les causes habituelles sont un point d'accès indisponible sur votre plan, un compte désactivé ou une IP temporairement bloquée après plusieurs échecs d'authentification.
Que faire : Vérifiez le chemin du point d'accès dans la référence, puis confirmez que votre compte est actif dans le tableau de bord. Contactez le support si vous pensez que c'est une erreur.
404 Introuvable
Peut être facturé (spécifique au point d'accès). La ressource n'a pas été trouvée. Consultez la documentation du point d'accès concerné pour confirmer si cette réponse est facturée.
if (res.status === 404) {
// handle "no result" gracefully, not as a fatal error
return null
}500 Erreur interne du serveur
Non facturé. Une erreur inattendue s'est produite de notre côté.
Que faire : Réessayez avec un backoff exponentiel. Si le problème persiste, contactez le support.
async function fetchWithRetry(url: string, options: RequestInit, maxRetries = 3) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const res = await fetch(url, options)
if (res.status !== 500 || attempt === maxRetries) return res
const delay = 500 * 2 ** attempt
console.warn(`500 error, retrying in ${delay}ms (attempt ${attempt + 1}/${maxRetries})`)
await new Promise(r => setTimeout(r, delay))
}
}Gestionnaire d'erreurs complet
Une fonction unique qui couvre chaque code de statut :
interface ApiResult<T> {
data: T | null
error: string | null
status: number
billed: boolean
}
async function apiCall<T>(url: string, apiKey: string): Promise<ApiResult<T>> {
const res = await fetch(url, {
headers: { "x-api-key": apiKey },
})
// 200 and 201 are always billed; 404 billing is endpoint-specific
const billed = res.status === 200 || res.status === 201
if (res.status === 200) {
return { data: await res.json() as T, error: null, status: 200, billed }
}
const body = await res.json().catch(() => ({ error: "Unknown error" }))
const error = body?.error ?? "Unknown error"
switch (res.status) {
case 400:
console.error("[400] Bad request, fix your parameters:", error)
break
case 401:
if (error.toLowerCase().includes("rate limit")) {
console.warn("[401] Rate limit, back off and retry")
} else {
console.error("[401] Auth error, check your API key:", error)
}
break
case 402:
console.error("[402] No credits remaining. Top up at https://app.piloterr.com")
break
case 403:
console.error("[403] Forbidden, check your key permissions")
break
case 404:
console.warn("[404] Not found, no result for this request")
break
case 500:
console.error("[500] Server error, retry with backoff")
break
default:
console.error(`[${res.status}] Unexpected status:`, error)
}
return { data: null, error, status: res.status, billed }
}Stratégie de nouvelle tentative
| Statut | Réessayer ? | Stratégie |
|---|---|---|
400 | Non | Corriger la requête d'abord |
401 (limite de débit) | Oui | Attendre 2–5 s, puis réessayer |
401 (auth) | Non | Corriger la clé API |
402 | Non | Ajouter des crédits ou régler les factures d'abord |
403 | Non | Vérifier les permissions |
404 | Non | Traiter comme résultat vide |
500 | Oui | Backoff exponentiel (max 3 tentatives) |
Résumé de facturation
| Statut | Facturé |
|---|---|
200 | Oui |
201 | Oui |
404 | Spécifique au point d'accès (voir la documentation du point d'accès) |
| Tous les autres codes | Non |
Consultez la page Crédits pour un détail complet des coûts par point d'accès. Pour des conseils d'intégration plus larges, voir Bonnes pratiques.