Erreurs
Chaque code d'erreur de l'API Certivant expliqué — forme de la réponse, correspondance avec les statuts HTTP, consignes de traitement par code, et un wrapper de nouvelle tentative robuste que vous pouvez intégrer à votre implémentation.
Chaque réponse d'erreur de l'API Certivant suit la même forme. Écrivez un seul gestionnaire d'erreurs qui exploite cette forme, et vous pourrez traiter uniformément chaque point de terminaison.
Forme de la réponse
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Body validation failed.",
"fields": {
"applicant.dateOfBirth": "Invalid date format. Expected YYYY-MM-DD.",
"applicant.nationality": "Must be a 2-character ISO 3166-1 alpha-2 code."
}
}
}
| Champ | Type | Remarques |
|---|---|---|
success | booléen | Toujours false en cas d'erreur |
error.code | chaîne | Lisible par une machine. Basez votre logique de contrôle sur ce champ |
error.message | chaîne | Lisible par un humain. Peut être journalisé ; ne doit pas être affiché tel quel aux demandeurs |
error.fields | objet | Présent uniquement pour VALIDATION_ERROR. Associe les chemins de champs en notation pointée à des messages d'erreur par champ |
Les chaînes error.message ne sont pas garanties stables d'une version à l'autre. Utilisez code pour toute
logique ; considérez message comme une aide à la journalisation et au développement.
Code de statut HTTP → code d'erreur
| HTTP | error.code habituel | Signification |
|---|---|---|
400 | VALIDATION_ERROR | Le corps de la requête n'a pas passé la validation Zod. Consultez fields |
400 | BAD_REQUEST | Requête incorrecte générique (par exemple soumettre avant que tous les documents soient envoyés) |
401 | UNAUTHORIZED | Clé d'API absente, mal formée, révoquée ou expirée |
402 | verification_unavailable | L'organisation n'a plus de crédit et n'est pas configurée pour continuer sans crédit |
403 | FORBIDDEN | La clé est valide mais ne possède pas la portée requise, provient d'une adresse hors de sa liste d'adresses IP autorisées, est restreinte à d'autres formulaires, ou la ressource appartient à une autre organisation |
404 | NOT_FOUND | La ressource (req_…, doc_…, etc.) n'existe pas ou n'est pas visible par l'organisation de cette clé |
409 | CONFLICT | Transition d'état non autorisée (par exemple soumettre une demande deux fois), ou violation d'une contrainte d'unicité (externalRef déjà utilisée) |
413 | BAD_REQUEST | Envoi de fichier supérieur à 10 Mo |
415 | BAD_REQUEST | Content-Type non pris en charge par le point de terminaison (par exemple un corps JSON envoyé à un point de terminaison multipart) |
429 | RATE_LIMITED | Limite de débit par minute dépassée. Voir Limites de débit |
500 | INTERNAL_ERROR | Erreur serveur inattendue. Toujours journalisée de notre côté ; une nouvelle tentative est sans risque |
502 | BAD_GATEWAY | Un service amont (fournisseur de sanctions, passerelle de paiement, registre) est indisponible. Réessayez après un délai |
503 | SERVICE_UNAVAILABLE | Base de données dégradée. Réessayez avec un espacement progressif |
Catalogue des codes d'erreur
UNAUTHORIZED
La clé d'API figurant dans l'en-tête Authorization est absente, mal formée ou révoquée.
{ "success": false, "error": { "code": "UNAUTHORIZED", "message": "Invalid or revoked API key." } }
error.reason indique le cas précis : missing_api_key, invalid_api_key, api_key_revoked, api_key_expired ou api_key_rotated (la clé a fait l'objet d'une rotation et sa période de chevauchement est terminée). La liste complète figure dans Authentification.
Comment gérer : Vérifiez que l'en-tête est bien Authorization: Bearer ck_live_… (ou ck_test_… ; les anciennes clés commencent par kyk_). Consultez le statut de la clé dans le tableau de bord. Si elle est indiquée comme révoquée ou expirée, créez une nouvelle clé ou effectuez une rotation.
FORBIDDEN
La clé est valide mais ne possède pas la portée requise, ou la ressource appartient à une organisation différente de celle de la clé.
{ "success": false, "error": { "code": "FORBIDDEN", "message": "This API key does not include the kyc:manage scope required for this endpoint." } }
error.reason vaut insufficient_scope (la clé ne possède pas une portée), ip_not_allowed (l'adresse de l'appelant ne figure pas dans la liste d'adresses IP autorisées de la clé) ou form_not_allowed (la clé est restreinte à d'autres formulaires).
Comment gérer : Vérifiez les portées et restrictions de votre clé dans le tableau de bord (KYC → Développeur, l'icône en forme de crayon). Vous pouvez modifier les permissions d'une clé, ses restrictions de formulaires et de workflows, sa liste d'adresses IP autorisées et son expiration sans changer son secret ; le secret et l'environnement (production ou test) ne peuvent pas être modifiés.
verification_unavailable (HTTP 402)
Votre organisation n'a plus de crédit et n'est pas configurée pour continuer sans crédit : Certivant ne peut donc pas accepter une nouvelle vérification. La réponse utilise le code verification_unavailable :
{ "success": false, "error": { "code": "verification_unavailable", "message": "This organization is temporarily unable to accept new verifications. Please contact them to continue." } }
Comment gérer : Rechargez le solde de crédits dans Paramètres → Crédits et utilisation (vos propriétaires et administrateurs reçoivent aussi une notification et un courriel, au plus une fois par jour). Les demandeurs qui rencontrent la même situation dans un formulaire ou une page hébergée voient une page leur demandant de contacter votre organisation ; cette page ne mentionne jamais le crédit ni l'argent. Voir Facturation et crédits.
NOT_FOUND
{ "success": false, "error": { "code": "NOT_FOUND", "message": "Request not found." } }
Comment gérer : Vérifiez l'identifiant de la ressource. Une cause fréquente est l'utilisation d'un identifiant issu d'un autre environnement : les identifiants de préproduction n'existent pas en production, et inversement.
VALIDATION_ERROR
Le corps de la requête n'a pas passé la validation de schéma. La table fields liste chaque champ en échec avec un message propre à ce champ.
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Body validation failed.",
"fields": {
"type": "Required",
"applicant.email": "Invalid email format"
}
}
}
Comment gérer : Affichez fields à côté des champs de votre formulaire. Les chemins de champs utilisent la notation pointée pour les champs imbriqués et [N] pour les index de tableaux (directors[0].dateOfBirth).
BAD_REQUEST
Requête incorrecte générique, qui ne correspond à aucune autre catégorie.
{ "success": false, "error": { "code": "BAD_REQUEST", "message": "Cannot submit a request with pending documents. Upload the remaining documents first." } }
Comment gérer : Lisez le message. Ces erreurs indiquent en général un problème d'ordre des opérations : appelez d'abord le point de terminaison prérequis.
CONFLICT
Une transition d'état illégale depuis l'état actuel, ou une violation de contrainte d'unicité.
{ "success": false, "error": { "code": "CONFLICT", "message": "externalRef already in use by request req_…" } }
Comment gérer : Consultez l'état actuel de la demande via GET /requests/:id et adaptez votre appel. Pour une violation d'unicité de référence, récupérez la demande existante (avec ?externalRef=… sur le point de terminaison de liste) ou choisissez une autre référence.
RATE_LIMITED
{ "success": false, "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded. Max 120 requests per 60s. Retry in 14s." } }
Les en-têtes de cette réponse comprennent X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset (secondes avant que le quota ne se recharge). Voir Limites de débit pour la stratégie de nouvelle tentative.
INTERNAL_ERROR
Une défaillance s'est produite de notre côté. Certivant journalise chaque erreur 500 avec son contexte complet.
{ "success": false, "error": { "code": "INTERNAL_ERROR", "message": "An unexpected error occurred. Please try again." } }
Comment gérer : Réessayez une fois après un court délai. Si l'erreur persiste, consultez la page d'état et contactez le support en indiquant l'identifiant de la requête.
BAD_GATEWAY et SERVICE_UNAVAILABLE
Une dépendance amont est indisponible (API du registre du commerce, fournisseur de données de sanctions, stockage) ou la base de données est dégradée.
{ "success": false, "error": { "code": "BAD_GATEWAY", "message": "Sanctions screening provider is unreachable. The request remains in PENDING state — Certivant will retry automatically." } }
Comment gérer : Traitez ces erreurs comme transitoires. Mettez en place un espacement exponentiel (1 s, 2 s, 4 s, 8 s, 16 s) et arrêtez après environ 5 tentatives. La demande n'est pas perdue : la file d'attente de Certivant reprendra le traitement dès que l'amont sera rétabli.
Un gestionnaire d'erreurs robuste
async function callCertivant<T>(
fn: () => Promise<Response>,
options: { maxRetries?: number } = {},
): Promise<T> {
const maxRetries = options.maxRetries ?? 3;
let attempt = 0;
let delay = 500;
while (true) {
const res = await fn();
if (res.ok) return (await res.json()) as T;
const body = (await res.json().catch(() => null)) as
| { error?: { code: string; message: string } }
| null;
const code = body?.error?.code ?? "INTERNAL_ERROR";
// Retry on transient errors
if (
attempt < maxRetries &&
(res.status === 429 || res.status >= 500)
) {
const retryAfter =
res.status === 429
? Number(res.headers.get("X-RateLimit-Reset") ?? 60) * 1000
: delay;
await sleep(retryAfter);
delay *= 2;
attempt += 1;
continue;
}
// Bubble everything else up
throw new CertivantError(code, body?.error?.message ?? "Unknown error", res.status);
}
}
Ce modèle gère toutes les erreurs documentées ci-dessus :
- Classe
200→ analyser et renvoyer le résultat. 429→ attendreX-RateLimit-Reset, puis réessayer.5xx→ espacement exponentiel, puis nouvelle tentative.4xx→ lever l'erreur immédiatement (votre code est en faute ; aucune nouvelle tentative ne la corrigera).
Référence de l'API (OpenAPI)
L'API REST complète de Certivant sous forme de document OpenAPI 3.1 — une spécification JSON publique que vous pouvez importer dans Postman ou fournir à un générateur de code, ainsi qu'une référence interactive avec chaque point de terminaison, schéma, portée et événement webhook.
Limites de débit
Certivant applique une limite de débit de l'API par minute, selon le forfait — apprenez à lire les en-têtes de limite de débit, à traiter les réponses 429, à réessayer correctement et à concevoir votre intégration pour rester sous la limite.