Chaque erreur, expliquée à une adresse stable.
Cette page est une référence d'exploitation, pas un argumentaire. Chaque classe d'erreur de l'API Connect y possède une ancre pérenne ; les réponses d'erreur de l'API renverront vers ces adresses. Vous y trouvez la cause probable et le geste qui corrige — dans cet ordre. Retour à la documentation développeurs.
Clé absente, mal formée ou inconnue
L'API s'authentifie exclusivement par l'en-tête Authorization: Bearer vgk_… — jamais par cookie de session. Une clé révoquée redevient inconnue à l'instant de sa révocation.
Ce même 401 porte "motif": "fin_option_api" quand la clé a été arrêtée parce que l'API ne fait plus partie de l'abonnement du cabinet. La date de cet arrêt a été donnée dans un courriel aux administrateurs du cabinet ou, à défaut, à son adresse de facturation, puis annoncée dans l'en-tête Sunset de chaque réponse à un appel accepté (calendrier à #cle-expiree). Sans motif, il peut aussi venir d'un abonnement suspendu : la suspension coupe les clés sur-le-champ.
Le geste. Vérifiez que l'en-tête part bien (les proxys le retirent parfois), que la clé commence par vgk_ et qu'elle n'a pas été révoquée depuis la console du cabinet. Le secret n'étant montré qu'à la création, une clé perdue se remplace, elle ne se retrouve pas. Avec "motif": "fin_option_api", ni l'en-tête ni la clé ne sont en cause : l'administrateur du cabinet nous écrit à contact@vigilae.org pour que l'API revienne dans l'abonnement, et la même clé est de nouveau acceptée dès que c'est fait, jusqu'à sa propre échéance.
Clé expirée
Chaque clé expire un an après sa création — la date expire_le est visible dans la console du cabinet dès la création. Le 401 d'expiration est explicite : il dit que la clé a existé et n'est plus valide.
Une clé d'API peut aussi cesser d'être acceptée avant cette date, quand l'API ne fait plus partie de l'abonnement du cabinet. L'arrêt tombe alors 30 jours au moins après un premier courriel, à la date que donne un second, envoyé 7 jours au moins avant ; l'un et l'autre partent aux administrateurs du cabinet ou, à défaut, à son adresse de facturation. Dès qu'elle est fixée, cette date se lit dans la console du cabinet (champ coupure_le de GET /connect/cles), et chaque réponse à un appel accepté l'annonce dans l'en-tête Sunset jusqu'à ce qu'elle tombe. Passé cette date, l'appel reçoit le 401 de #authentification, avec "motif": "fin_option_api" ; si l'API revient dans l'abonnement, la clé est de nouveau acceptée, jusqu'à sa propre échéance.
Le geste. Créez une nouvelle clé, basculez vos appels, révoquez l'ancienne. Pour une clé d'API, encore faut-il que l'API fasse partie de l'abonnement du cabinet : sans elle, la console refuse d'en créer une. Prévoyez ce remplacement dans votre exploitation plutôt que de le découvrir.
Scope insuffisant
Les clés portent les portées cochées à leur création : les générales lecture (défaut) et ecriture, ou des portées fines par ressource (clients:lecture, pieces:ecriture, origine-fonds:lecture, journal:lecture…).
L'héritage est suffixal, dans un seul sens : lecture couvre tout *:lecture, ecriture tout *:ecriture — l'inverse est faux, une portée fine n'ouvre qu'elle-même.
Six portées sortent de ce couple et ne s'héritent d'aucune clé générale : alertes:qualifier, embed:emettre, adversemedia:consulter, conformite:consulter, dispositif:consulter, integrite:consulter. Qualifier un événement, émettre un jeton d'embed, lire la presse défavorable d'un dossier ou une note de tenue ne découle jamais d'un droit de lecture général : chacune se coche à part.
Le geste. Créez une clé portant le scope nécessaire — et seulement lui. Le moindre privilège est voulu : une intégration qui ne fait que lire n'a aucune raison de détenir une clé d'écriture, et une clé large ne rattrapera jamais l'absence d'une portée déléguée explicitement.
Introuvable — ou d'un autre cabinet
Un 404 signifie que la ressource n'existe pas ou qu'elle appartient à un autre cabinet. L'API ne distingue jamais les deux cas : distinguer reviendrait à révéler ce qui existe ailleurs. Le cloisonnement est appliqué au niveau de la base de données, pas seulement dans le code.
Le geste. Vérifiez le seq contre le journal du cabinet dont la clé est issue (GET /api/v1/evenements). Si vous intégrez plusieurs cabinets, chaque cabinet a ses clés : un seq ne voyage pas d'un cabinet à l'autre.
Ce compte existe déjà
Un POST /scim/v2/Users sur un userName déjà provisionné pour ce cabinet répond 409 avec scimType: uniqueness. L'unicité est tenue par une contrainte de base de données, pas par un cache : deux créations simultanées ne peuvent pas produire deux comptes.
Le geste. Traitez le 409 comme un succès idempotent, pas comme une erreur : relisez le compte par ?filter=userName eq "…" et poursuivez avec l'identifiant rendu. Un connecteur qui réessaie en boucle sur un 409 ne créera jamais rien de plus.
Ce compte échappe à l'annuaire
Un annuaire ne peut ni rétrograder ni désactiver un compte portant un pouvoir d'administration du cabinet : la demande est refusée avec scimType: mutability et journalisée. Sans cette limite, un connecteur qui adopte l'adresse du responsable de la conformité fermerait le cabinet à celui qui en répond.
Le geste. Retirez cette personne du périmètre synchronisé, ou changez son rôle depuis Vigilae. Le refus ne porte que sur ce compte : le reste du lot est appliqué normalement.
Débit dépassé
60 requêtes par minute et par clé, par défaut (surchargeable par clé). La réponse porte Retry-After et les en-têtes X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.
Le geste. Respectez Retry-After — pas de retry immédiat. Si vous atteignez la limite en polling, c'est presque toujours le signe d'un re-balayage complet : le curseur depuisSeq ne relit jamais ce qui a déjà été lu.
La signature ne se vérifie pas chez vous
Votre récepteur doit recalculer v1 = HMAC-SHA256(secret, t + "." + corps) depuis le corps brut reçu, et rejeter tout t au-delà de 5 minutes. Les échecs classiques : le corps re-sérialisé avant vérification (un JSON reformaté n'a plus les mêmes octets), une horloge qui dérive au-delà de la tolérance, et une rotation ignorée — pendant 24 h, l'en-tête porte un v1 par secret encore valide, il faut accepter si l'un correspond.
Le geste. Vérifiez sur les octets bruts, synchronisez l'horloge (NTP), testez votre vérification pendant une rotation. Les extraits Node et Python de la documentation font exactement cela — copiez-les plutôt que de les réécrire.
Un événement arrive deux fois
La livraison est at-least-once, par lots de 100 au maximum, dans l'ordre du journal ; le curseur n'avance que sur votre réponse 2xx, lot par lot. Un échec après réception mais avant l'avance du curseur provoque une relivraison — c'est le contrat, pas un défaut.
Le geste. Le seq est votre identifiant d'idempotence : traitez chaque séquence une seule fois, et ne répondez 2xx qu'après avoir persisté. Un 2xx anticipé suivi d'un crash est le seul moyen de perdre un événement.
Le journal semble incomplet ou se répète
depuisSeq est strictement exclusif : seuls les événements de seq supérieur sont rendus, triés croissant, au plus 500 par page. La réponse rend prochainSeq, à repasser tel quel. Une page plus courte que limite signifie la fin du journal.
Le geste. Persistez prochainSeq entre deux passages et ne le recalculez pas vous-même. Si vous voyez des doublons, vous repartez d'un curseur trop ancien ; si vous voyez des trous, vous avez sauté une page en erreur sans la rejouer.
Paramètre hors schéma
Un statut inconnu, une disposition hors liste (planifie, traite, ecarte), une limite non entière : la réponse nomme le champ en cause, et rien d'autre — les messages d'erreur ne transportent jamais de contenu de dossier.
Le geste. La spécification OpenAPI est la source : les énumérations et bornes qu'elle déclare sont celles que le serveur applique, puisqu'elle est servie par lui.
Nationalité trop longue
Une nationalité tient en 60 caractères au plus : sur une fiche client (nationalite), sur la contrepartie d'un dossier (contrepartie.nationalite), sur la nationalité du client d'un dossier (clientNationalite) et sur chaque ligne de bénéficiaires effectifs (detentions[i].nationalite). On compte les caractères de ce que vous avez envoyé, espaces de début et de fin retirés. Au-delà, rien n'est écrit, et la réponse dit où et de combien dans champ, limite et longueur ; elle ne recopie jamais la valeur reçue, qui décrit une personne. Le refus vaut à compter du 9 novembre 2026. D'ici là, la saisie passe encore : si sa forme rangée dépasse 60 caractères, elle est coupée, et la réponse le signale dans avertissements, où coupee dit si la coupe a vraiment eu lieu. Une liste de codes noyée dans les espaces mesure plus de 60 caractères mais se range en quelques-uns : elle s'écrit entière. Seule clientNationalite n'a jamais été coupée : refusée au-delà de 60 caractères bien avant cette carte, elle le reste, sous #validation jusqu'au 9 novembre.
Le geste. Envoyez la nationalité en codes ISO 3166-1 alpha-2, trois au plus (FR, DZ) : c'est la forme que le serveur range et lit, et elle tient toujours dans la limite. Une précision plus longue, comme les circonstances d'une naturalisation, n'a pas sa place dans ce champ.
Scope insuffisant (API de ressources)
Les endpoints de ressources (/clients, /dossiers, pièces, criblage, alertes) exigent un scope fin : clients:*, dossiers:*, pieces:*, criblage:* ou le scope dédié alertes:qualifier. Une clé historique lecture vaut chaque *:lecture et ecriture chaque *:ecriture — mais alertes:qualifier ne s'hérite jamais : qualifier une alerte est un acte de responsable, délégué en cochant ce scope à la création de la clé.
Le geste. Créez une clé portant exactement les scopes dont votre intégration a besoin — et seulement eux. Le detail de la réponse nomme le scope manquant.
Ressource introuvable — ou d'un autre cabinet
Même règle que #cloisonnement, appliquée aux ressources : un client, un dossier, une pièce ou une alerte qui n'existe pas ou qui appartient à un autre cabinet répond le même 404. L'API ne distingue jamais les deux cas.
Le geste. Vérifiez l'identifiant contre les listes du cabinet dont la clé est issue. Un identifiant ne voyage pas d'un cabinet à l'autre.
En-tête Idempotency-Key absent
Tout POST de création ou de déclenchement (client, dossier, pièce, criblage, bénéficiaires effectifs) exige l'en-tête Idempotency-Key : une chaîne stable de 200 caractères au plus, une par opération. Rejouer la même clé avec le même corps rend la même réponse, sans effet — c'est votre protection contre les doublons sur incident réseau.
Le geste. Générez la clé avant le premier essai (un UUID par opération métier) et réutilisez-la telle quelle pour chaque retry de la même opération.
Clé d'idempotence réutilisée pour une autre requête
Cette Idempotency-Key a déjà servi pour une autre requête dans les dernières 24 heures : un autre corps, ou bien le même corps sur une autre route ou un autre dossier. La clé est propre à UNE requête — méthode, chemin, ressource et corps — et non au seul corps : c'est ce qui empêche qu'une clé dérivée du sha256 d'un fichier, déposée sur deux dossiers, resserve la réponse du premier. La clé rejoue une réponse, elle n'en écrase jamais une : la réutiliser pour une opération nouvelle est presque toujours le signe d'une clé fabriquée depuis un compteur ou une date tronquée.
Le geste. Une clé nouvelle par opération nouvelle. Ne dérivez jamais la clé de données qui se répètent d'une opération à l'autre.
Une autre tentative sous cette clé s'exécute encore
Deux requêtes portant la même Idempotency-Key sont arrivées ensemble : la première s'exécute, la seconde est refusée avant tout effet. C'est ce refus qui empêche le doublon. Le cas courant : un proxy rend 502 ou 504 pendant que le serveur travaille encore, et votre client rejoue. L'en-tête Retry-After dit au bout de combien de secondes rejouer.
Le geste. Rejouez la même requête, telle quelle, avec la même clé, passé le délai annoncé : vous recevrez la réponse de la première tentative. Ne fabriquez jamais une clé neuve pour « débloquer » — ce serait créer le doublon que la clé évite.
Environnement d'essai : quota atteint
Un environnement d'essai garde des limites fixes : 200 fiches clients, 50 dossiers et 40 pièces par dossier. La création ou le dépôt qui dépasserait l'une d'elles est refusé avant toute écriture, et le refus dit laquelle : les membres ressource, quota et courant portent la ressource, le plafond et le compte au moment du refus. Deux créations simultanées pour la dernière place n'en laissent passer qu'une. Modifier une fiche ou un dossier existant ne consomme rien.
Le geste. Ces quotas ne se négocient pas, et rejouer la requête rendra le même refus. Réinitialisez l'environnement d'essai depuis votre espace — il repart du jeu de démonstration — ou souscrivez un abonnement : ces quotas ne s'appliquent qu'aux environnements d'essai.
Dossier scellé : le registre est figé
Le scellement fige la chaîne d'intégrité du dossier — c'est sa valeur de preuve. Un dossier scellé ne s'édite plus, ne reçoit plus de pièce et ne se re-crible plus par ce canal. Seule la qualification d'une alerte reste possible : elle s'écrit hors chaîne, la tête scellée ne bouge pas.
Le geste. Rien à « corriger » : c'est l'immuabilité voulue. Si une donnée doit évoluer, c'est une nouvelle opération de vigilance dans l'application, pas une mutation du dossier scellé.
Dossier clos : la relation d'affaires est terminée
La relation a été clôturée dans l'application : le dossier ne reçoit plus d'écriture par l'API — ni édition, ni pièce, ni criblage, ni bénéficiaires effectifs. Les lectures restent ouvertes : un dossier clos se consulte et s'exporte pendant toute la durée de conservation.
Le geste. Rouvrir la relation est un geste humain, tracé, dans l'application ; l'API ne le fait pas à votre place. Si l'opération est nouvelle, ouvrez un dossier nouveau plutôt que de ranimer l'ancien.
Dossier purgé : les données ont été effacées
L'échéance de conservation est passée et les données du dossier ont été effacées. Il ne reste que la trace d'audit, qui atteste qu'un dossier a existé et qu'il a été purgé à la date dite ; elle ne reçoit plus aucune écriture.
Le geste. Rien à corriger et rien à rejouer : l'effacement est définitif et voulu. Un identifiant de dossier purgé conservé dans vos systèmes se traite comme un historique, jamais comme une cible d'écriture.
Format de pièce non accepté
Les pièces justificatives acceptent PDF, JPG, JPEG, PNG et WEBP — les mêmes formats que l'application. Le contrôle porte sur l'extension du filename, obligatoire : une pièce sans nom de fichier valide est refusée, quel que soit son contenu.
Le geste. Convertissez avant l'envoi (un scan TIFF ou HEIC se convertit en PDF ou JPEG) et envoyez le contenu en base64 standard dans contenu, avec un type parmi les codes stables a_doc_*.
Pièce au-delà de 6 Mo
La borne s'applique au fichier décodé (6 Mo), la même que dans l'application et le portail de collecte. Le base64 ajoutant un tiers d'encodage, le corps de requête accepte jusqu'à 9 Mo.
Le geste. Compressez le document (un PDF scanné en 300 dpi couleur descend presque toujours sous la borne en niveaux de gris) plutôt que de le découper.
Source de criblage indisponible
Aucune des entités du dossier n'a pu être confrontée aux listes : la source (index de listes officielles ou fournisseur) n'a pas répondu. L'API refuse de conclure — un rapport « propre » au-dessus d'une source morte serait le pire faux négatif possible. L'échec est tracé au dossier (erreurSource). Une panne partielle ne produit pas ce 502 : la réponse 200 conserve les correspondances des entités qui ont répondu et nomme celles en échec dans erreurSourceEntites.
Le geste. Rejouez le même appel plus tard, même Idempotency-Key : seules les réponses de succès sont mémorisées par l'idempotence — le rejeu après une erreur relance un criblage réel.
Widgets embarqués non activés sur cette instance
Le mint POST /api/v1/embed/jetons s'appuie sur les origines déclarées de votre cabinet — c'est cette liste qui pilote la CSP frame-ancestors du shell embarqué. Ce 501 dit que l'instance appelée ne porte pas ce stockage : la surface d'embed y est inerte par construction, et elle le dit plutôt que d'émettre un jeton qu'aucune origine ne pourrait afficher. À ne pas confondre avec le 400 rendu à un cabinet dont les origines ne sont pas encore déclarées.
Le geste. Ce 501 parle de l'instance, pas de votre requête. Sur vigilae.org, l'administrateur du cabinet déclare lui-même les origines, écran « Intégrations & sécurité » (l'encadré de la section widgets dit où) ; rejouez ensuite le même appel. Rien à corriger dans votre code : la requête était bonne, l'instance n'était pas prête.
Surface indisponible sur ce dépôt
Deux lectures du socle — GET /api/v1/dossiers/{id}/origine-fonds et GET /api/v1/dossiers/{id}/exigences — s'appuient sur des stockages que toutes les instances ne portent pas. Quand l'un manque, l'API le dit au lieu de servir une liste vide : « rien à signaler » et « rien n'a été lu » sont deux faits opposés, et les confondre ferait passer un dossier jamais consulté pour un dossier sans réserve. Ce 501 parle donc de l'instance appelée, jamais de votre requête ni du dossier.
Le geste. Ne rejouez pas en boucle : rien ne changera tant que l'instance ne portera pas ce stockage. Traitez ce code comme « donnée indisponible ici » et surtout ne le comptez pas comme un zéro dans vos tableaux de bord — c'est ainsi qu'une absence de mesure devient un mauvais chiffre. Sur vigilae.org, ces deux lectures sont servies ; sur un déploiement dédié, la mise à niveau du dépôt revient à votre exploitant.
Cette page évoluera avec l'API ; les ancres existantes, elles, ne changent pas d'adresse — vous pouvez les stocker dans vos journaux d'exploitation.