L'API Syvel utilise des codes HTTP standard. Chaque réponse d'erreur inclut un corps JSON avec trois champs.

## Structure de réponse

```json
{
  "error": "string",    // code court lisible par la machine
  "message": "string",  // explication lisible par un humain
  "detail": "string | null"  // contexte additionnel optionnel
}
```

## Récapitulatif des codes HTTP

| Code | Nom | Quand il survient |
|------|-----|-------------------|
| `200` | OK | Requête réussie |
| `401` | Unauthorized | Clé API manquante ou invalide |
| `403` | Forbidden | Clé valide, mais origine non autorisée |
| `422` | Unprocessable Entity | Format d'email/domaine invalide |
| `429` | Too Many Requests | Quota mensuel dépassé |
| `500` | Internal Server Error | Erreur inattendue côté serveur |

---

## 200 — Succès

Réponse standard. Voir [Vérification email](/fr/docs/api/check) pour le schéma complet.

---

## 401 — Non autorisé

Le header `Authorization` est absent, malformé, ou contient une clé qui ne correspond à aucune clé active.

```json
{
  "error": "unauthorized",
  "message": "Missing or invalid API key.",
  "detail": null
}
```

---

## 403 — Interdit

La clé API est valide, mais le header `Origin` de la requête ne figure pas dans la liste des origines autorisées de la clé.

```json
{
  "error": "forbidden",
  "message": "This origin is not authorised for this API key.",
  "detail": "Origin: https://example.com"
}
```

**401 vs 403 — quelle différence ?**

| | 401 | 403 |
|---|---|---|
| La clé existe ? | Non (ou invalide) | Oui |
| Restriction d'origine ? | N/A | Oui — origine bloquée |
| Solution | Vérifier/régénérer la clé | Ajouter l'origine dans le dashboard |

---

## 422 — Entité non traitable

La valeur passée dans `{email_ou_domaine}` ne respecte pas les règles de validation des entrées.

```json
{
  "error": "validation_error",
  "message": "Invalid email or domain format.",
  "detail": "Value must be a valid email address or hostname."
}
```

Causes fréquentes : chaîne vide, adresse IP, préfixe URL (`http://`), plus d'un `@`, partie locale de plus de 64 caractères. Voir [Validation des entrées](/fr/docs/api/check#validation-des-entrees) pour la liste complète.

---

## 429 — Trop de requêtes

Le quota mensuel du compte a été atteint.

```json
{
  "error": "quota_exceeded",
  "message": "Monthly quota reached. Upgrade your plan or wait for the reset.",
  "detail": null,
  "reset_at": "2026-04-01T00:00:00Z"
}
```

Le champ `reset_at` est un timestamp ISO 8601 indiquant la prochaine remise à zéro du quota (toujours le 1er du mois suivant à 00:00 UTC).

:::caution[Fail open sur 429]
Ne bloquez jamais un utilisateur parce que le quota est dépassé. Traitez un `429` comme une erreur réseau et laissez l'utilisateur passer.
:::

---

## 500 — Erreur interne

Une erreur inattendue s'est produite côté Syvel. C'est rare et transitoire.

```json
{
  "error": "internal_error",
  "message": "An unexpected error occurred. Please try again.",
  "detail": null
}
```

:::caution[Toujours fail open sur 500]
Ne bloquez pas les utilisateurs sur une `500`. Attrapez-la comme n'importe quelle autre exception et laissez la requête réussir de votre côté.
:::