> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sahlfinancial.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Erreurs

> Chaque corps d'erreur que renvoie l'API Partenaire, avec statut, cause et correctif.

## Formes d'erreur

Il y a trois formes. Lisez d'abord le statut, puis le corps.

**1. `detail` est une chaîne** (la plupart des erreurs).

```json theme={null}
{ "detail": "Invalid or revoked API key" }
```

**2. `detail` est un objet avec un `code` stable** (faites correspondre sur `code`, pas sur le message).

```json theme={null}
{
  "detail": {
    "code": "kyc_extract_cap_reached",
    "message": "Monthly document-read limit of 2000 reached.",
    "used": 2000,
    "limit": 2000
  }
}
```

**3. `code` et `message` au niveau supérieur, sans `detail`.** Ces erreurs viennent du limiteur de débit, du gestionnaire de route inconnue et du filet de sécurité pour les erreurs inattendues.

```json theme={null}
{ "code": "rate_limit_exceeded", "message": "Too many requests. Please slow down." }
```

Une erreur de schéma 422 a une liste dans `detail`, une entrée par champ invalide :

```json theme={null}
{
  "detail": [
    { "type": "string_pattern_mismatch", "loc": ["body", "reference"], "msg": "String should match pattern '^[A-Za-z0-9_.:-]+$'", "input": "client 1", "ctx": { "pattern": "^[A-Za-z0-9_.:-]+$" } }
  ]
}
```

`loc` indique où : `["body", "reference"]` pour un corps JSON, `["query", "environment"]` ou `["path", "key"]`. Pour un champ de formulaire multipart, le premier élément est aussi `body`. Gérez les trois formes : un client qui suppose que `detail` est toujours un objet échouera à la première 422.

## Identifiant de requête

Chaque réponse porte `X-Request-ID`. Si vous envoyez le vôtre (1 à 64 caractères parmi `A-Z a-z 0-9 . _ : -`), Sahl le renvoie ; sinon Sahl en crée un. Chaque appel de clé est listé dans **Developers, Call log** dans la console sous cet identifiant. Citez-le quand vous écrivez à Sahl.

## Catalogue

### 400 Requête invalide

| Message | Cause | Correctif |
| - | - | - |
| `Send between 1 and 5 files.` | `/extract` n'a reçu aucun fichier ou plus de 5. | Envoyez 1 à 5 parties `files`. |
| `Unsupported file type '<mime>'. Allowed types: application/pdf, image/jpeg, image/png, image/tiff, image/webp` | Le `Content-Type` de la partie n'est pas l'un des cinq. `image/jpg` est accepté comme JPEG. | Convertissez le fichier ou définissez le bon type de contenu sur la partie. |
| `File content does not match declared MIME type.` | Les premiers octets ne correspondent pas au type de contenu déclaré (un PNG envoyé comme `application/pdf`, ou un fichier qui n'est ni une image ni un PDF). | Envoyez le vrai fichier avec son vrai type. Un PDF peut avoir jusqu'à 1 Ko avant `%PDF-`. |

### 401 Non autorisé

| Message | Cause | Correctif |
| - | - | - |
| `Missing API key` | Pas d'en-tête `Authorization: Bearer ...`. | Envoyez-le. |
| `Invalid or revoked API key` | Clé incorrecte, mal formée ou révoquée. | Vérifiez la clé. Créez-en une nouvelle si elle a été révoquée. |
| `API key expired` | Une clé renouvelée dont la période de grâce est terminée. | Utilisez la nouvelle clé. |
| `Partner identity could not be verified` | La clé est liée à un compte de service et `X-Partner-Identity` est absent ou incorrect. | Envoyez un jeton d'identité Google valide pour le compte lié et l'audience indiquée dans le formulaire de la clé. |

### 403 Interdit

| Corps | Cause | Correctif |
| - | - | - |
| `"API key lacks the kyc:verify scope"` (chaîne, le nom du scope varie) | La clé ne détient pas le scope de l'endpoint. | Créez une clé avec ce scope. Voir [scopes](/fr/authentication). |
| `{"code": "kyc_scope_not_allowed", "message": "This workspace is not enabled for the partner KYC API."}` | La clé a un scope `kyc:` mais l'espace de travail n'est pas activé (l'accès à l'API partenaire est par espace de travail). | [Demandez un accès bac à sable](https://sahlfinancial.com/contact?type=demo). |
| `{"code": "direct_access_refused", "message": "Call the API at https://app.sahlfinancial.com/api."}` | Vous avez appelé l'adresse interne de Sahl. | Utilisez l'hôte public. |

### 404 Introuvable

| Corps | Cause | Correctif |
| - | - | - |
| `{"detail": "identity verification is not set up for this tenant"}` | Un endpoint eID sur un espace de travail sans compte chez un fournisseur eID. | [Contactez Sahl](https://sahlfinancial.com/contact?type=demo) pour activer l'eID. |
| `{"detail": "Not Found"}` | `GET /v1/kyc/eid/{key}` ou son rapport : la clé n'existe pas, ou appartient à un autre espace de travail. | Utilisez le `key` que votre `POST /v1/kyc/eid` a renvoyé. |
| `{"code": "not_found", "message": "API endpoint not found: GET /api/..."}` | Le chemin ou la méthode n'existe pas. | Vérifiez le chemin. L'URL de base se termine par `/api`. |

### 413 Charge trop volumineuse

| Message | Cause | Correctif |
| - | - | - |
| `File too large. Maximum allowed size is 30 MB.` | Un fichier dépasse la limite (30 Mo par défaut). | Compressez ou découpez. |
| `Image is 9000x9000 pixels; the maximum is 50 megapixels.` | L'en-tête de l'image déclare plus de 50 mégapixels. Un petit fichier peut quand même être refusé. | Réduisez la taille. |
| `Image dimensions are too large to process.` | Pillow a signalé une bombe de décompression. | Envoyez une image normale. |

### 422 Non traitable

| Message | Cause | Correctif |
| - | - | - |
| `reference must be 1-64 characters of A-Z a-z 0-9 _ . : -` | Champ de formulaire de `/extract`. | Utilisez seulement ces caractères. |
| `environment must be 'sandbox' or 'production'` | Champ de formulaire de `/extract`. | Utilisez l'une des deux valeurs. |
| `subject must be at most 255 characters` | Champ de formulaire de `/extract`. | Raccourcissez-le. |
| `identity verification is available for Canadian clients only` | `/v1/kyc/eid` avec un `country` qui n'est ni `CA` ni `CAN`. | L'eID est réservé aux clients canadiens. |
| Une liste de `{type, loc, msg}` | Un champ JSON, de requête ou de chemin échoue au schéma : un `reference` ou `environment` invalide, `email` qui n'est pas un courriel, `documents` qui n'en contient ni 1 ni 2, `key` qui n'est pas un entier, un champ obligatoire manquant. | Lisez `loc` et `msg`. |

Un `kind` invalide n'est pas une erreur : les valeurs inconnues comptent comme `individual`.

### 429 Trop de requêtes

| Corps | Cause | Correctif |
| - | - | - |
| `{"detail": {"code": "kyc_extract_cap_reached", "message": "Monthly document-read limit of 2000 reached.", "used": 2000, "limit": 2000}}` | L'espace de travail a utilisé ses lectures du mois calendaire (UTC). Compté avant l'exécution du modèle, donc un appel refusé ne consomme rien. | Attendez le mois suivant, ou demandez à Sahl de relever la limite. Ne réessayez pas. |
| `{"code": "rate_limit_exceeded", "message": "Too many requests. Please slow down."}` | Plus de 100 requêtes par minute depuis une même IP cliente sur ces routes. En-têtes : `Retry-After` (secondes), `X-RateLimit-Limit`, `X-RateLimit-Remaining`. | Attendez `Retry-After` secondes. |

Chaque réponse réussie porte aussi `X-RateLimit-Limit` et `X-RateLimit-Remaining`. La limite est par IP cliente, pas par clé, donc plusieurs serveurs derrière une même adresse la partagent. 100 par minute est la valeur par défaut dans le code et peut changer.

### 500 et 502

| Statut | Corps | Cause | Correctif |
| - | - | - | - |
| 500 | `{"code": "internal_error", "message": "An unexpected error occurred", "details": null}` | Une défaillance inattendue du côté de Sahl. | Réessayez une fois. Si elle persiste, citez `X-Request-ID`. |
| 502 | `{"detail": "the identity verification service did not answer"}` | Le fournisseur eID n'a pas répondu. | Réessayez plus tard. |

Un lecteur injoignable n'est pas une erreur : `/extract` répond 200 avec `reader_unavailable: true`. Voir [Lire des documents](/fr/guides/ocr-documents#reader_unavailable).

## Nouvelles tentatives

L'API n'a pas de clé d'idempotence. Réfléchissez à chaque appel avant de le réessayer.

| Appel | Réessai sans risque ? | Ce que fait un réessai |
| - | - | - |
| `GET /v1/kyc/eid/{key}` et `/report` | Oui | Lit de nouveau. |
| `POST /v1/kyc/verify`, `POST /v1/kyc/assess` | Oui en pratique | Le verdict est une fonction pure du corps. Un réessai avec une `reference` classe de nouveau le verdict sur le dossier et renvoie le webhook. Dédupliquez sur `event_id`. |
| `POST /v1/kyc/extract` | Seulement après une défaillance réseau ou une 5xx | Lit de nouveau et compte de nouveau. Avec une `reference`, il classe de nouveau les documents, donc le dossier en contient alors deux copies. |
| `POST /v1/kyc/eid` | À éviter | Envoie de nouveau un courriel au client et remplace la demande enregistrée sur le dossier. |

Règles pratiques :

* Ne réessayez jamais une 4xx, sauf une 429 pour `rate_limit_exceeded`, qui a `Retry-After`. Une 4xx échouera de la même façon.
* Réessayez une 5xx et un délai d'attente réseau avec un backoff exponentiel et un plafond, par exemple 2 s, 4 s, 8 s, puis arrêtez.
* Fixez un délai d'attente client bien supérieur au temps de réponse habituel. Les exemples utilisent 120 secondes pour `/extract`.
* Après un délai d'attente sur `/extract`, vous ne savez pas si la lecture a eu lieu. Consultez **Documents** pour la `reference` avant de renvoyer, ou acceptez le doublon.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.