Piloterr

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'appel
  • You have open invoices: … — une facture impayée bloque le compte
  • Insufficient credits: X required, Y available — un point d'accès par lignes renverrait plus de lignes que vous ne pouvez en payer

Que faire :

  1. 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.
  2. 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

StatutRéessayer ?Stratégie
400NonCorriger la requête d'abord
401 (limite de débit)OuiAttendre 2–5 s, puis réessayer
401 (auth)NonCorriger la clé API
402NonAjouter des crédits ou régler les factures d'abord
403NonVérifier les permissions
404NonTraiter comme résultat vide
500OuiBackoff exponentiel (max 3 tentatives)

Résumé de facturation

StatutFacturé
200Oui
201Oui
404Spécifique au point d'accès (voir la documentation du point d'accès)
Tous les autres codesNon

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.

Sur cette page