Erreurs API

Comment gérer les erreurs de l'API FourA.

Format des réponses d'erreur

L'API renvoie des objets JSON plats pour toutes les erreurs. Il n'y a pas d'objet error imbriqué ni de codes d'erreur.

{
  "error": "Invalid API key"
}

Certaines erreurs incluent des champs supplémentaires comme status, service, retryAfter, current ou limits au premier niveau :

{
  "error": "Rate limit exceeded",
  "status": 429,
  "service": "single",
  "retryAfter": 5,
  "current": { "concurrency": 12, "rpm": 3000 },
  "limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}

Suivi d'une request

Chaque response API (succès ou erreur) inclut un header X-Foura-Request-Id contenant un UUID pour cet appel. Enregistrez-le de votre côté. Si vous devez demander au support ce qui est arrivé à une request spécifique, cet ID nous permet de la retrouver.

curl -i -X POST https://eu.api.foura.ai/api/single/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"method": "GET", "url": "https://example.com"}'
# HTTP/1.1 200 OK
# X-Foura-Request-Id: 9f1c4e6c-7b2a-4d3e-8a1f-2c9d8e4a3b15
# Content-Type: application/json
# ...

Types d'erreurs

400: Bad Request

Le corps de la request ne contient pas les champs requis, contient des valeurs invalides ou nomme une cible que l'API refuse de récupérer.

{
  "error": "Invalid request body format"
}

Ce même code 400 couvre également la protection SSRF. Si votre url résout vers une plage IP privée, de loopback ou autrement réservée (RFC 5735, RFC 6598, blocs réservés IPv6), la request est rejetée avant de quitter le réseau de FourA :

{
  "error": "Target <ip> resolves to a private/reserved IP"
}

Correction : Vérifiez que votre request inclut tous les champs requis, que les URL utilisent http:// ou https:// et que l'hôte résout vers une adresse publique.

401: Unauthorized

Votre clé API est manquante ou invalide.

Clé manquante :

{
  "error": "Missing API key. Include X-API-Key header."
}

Clé invalide :

{
  "error": "Invalid API key"
}

Correction : Vérifiez que votre header X-API-Key contient une clé valide. Générez une nouvelle clé depuis le Dashboard si nécessaire.

429: Rate Limited

Vous avez envoyé trop de requests dans un court intervalle de temps.

{
  "error": "Rate limit exceeded",
  "status": 429,
  "service": "single",
  "retryAfter": 5,
  "current": { "concurrency": 12, "rpm": 3000 },
  "limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}

Correction : Attendez le nombre de secondes indiqué dans retryAfter avant d'envoyer d'autres requests. Consultez Rate Limits pour plus de détails.

500: Server Error

Une erreur est survenue de notre côté.

Correction : Réessayez la request après un court délai. Si l'erreur persiste, consultez la page de statut ou contactez le support en fournissant l'identifiant X-Foura-Request-Id de la response en échec.

503: Service désactivé ou à pleine capacité

Une erreur 503 signifie soit que le service est temporairement indisponible pour maintenance, soit que vous avez atteint la limite de concurrence. Les deux responses incluent un champ retryAfter. Le format lié à la concurrence inclut également current et limits.

{
  "error": "Service disabled",
  "status": 503,
  "retryAfter": 60
}

Correction : Attendez le nombre de secondes spécifié dans retryAfter, puis réessayez. La page de statut répertorie les fenêtres de maintenance actives.

Échecs côté cible avec un statut 200 OK

Tous les échecs ne se manifestent pas sous la forme d'un statut HTTP autre que 2xx. Lorsque le site cible renvoie un statut HTTP 200 avec un contenu d'erreur, FourA vous transmet tout de même le corps du message mais classifie la request comme application_error. Lorsque la cible renvoie un statut non-2xx que vos règles validate n'acceptent pas, le résultat est application_fail et le corps est transmis sans modification.

Dans les deux cas, la facturation s'applique comme si la request avait réussi au niveau réseau. La référence des Outcomes présente la taxonomie complète.

Encodage des responses

FourA décode automatiquement le corps des responses en UTF-8. Si la cible utilise windows-1251, gbk, shift_jis, iso-8859-* ou tout autre jeu de caractères déclaré dans le header Content-Type ou dans une balise HTML <meta charset>, vous recevez une chaîne UTF-8 propre dans le champ data (single, proxy) ou body (browser).

Pour les contenus binaires (images, protobuf, audio brut), définissez returnBuffer: true sur la request. Le corps est renvoyé sous forme de buffer base64 sans aucune conversion de jeu de caractères.

Stratégie de retry

Une stratégie de retry pratique :

import time
import requests

def make_request(url, payload, api_key, max_retries=3):
    for attempt in range(max_retries):
        resp = requests.post(
            url,
            headers={"X-API-Key": api_key, "Content-Type": "application/json"},
            json=payload,
        )
        if resp.status_code == 200:
            return resp.json()

        body = resp.json() if resp.headers.get("content-type", "").startswith("application/json") else {}
        retry_after = body.get("retryAfter", 2 ** attempt)
        request_id = resp.headers.get("X-Foura-Request-Id", "?")

        if resp.status_code in (429, 503):
            time.sleep(retry_after)
            continue
        if resp.status_code >= 500:
            time.sleep(2 ** attempt)
            continue

        # 400/401/404 won't fix themselves
        raise RuntimeError(f"{resp.status_code} (request {request_id}): {body.get('error')}")

    raise RuntimeError(f"Exhausted {max_retries} retries")

Voir aussi

Mis à jour : 18 juin 2026