Anatomie de la réponse
La réponse de POST /v2/email/validate a toujours la même structure : quelques champs de synthèse à la racine, le détail de chaque contrôle dans features, puis les métadonnées.
{
"result": "risky",
"score": 52,
"freeProvider": true,
"businessEmail": false,
"disposable": true,
"alias": false,
"finalDecision": "accepted",
"policy": { "decision": "accepted", "reasons": [], "rejectedByClientConfig": false },
"warnings": [
{ "code": "DISPOSABLE_EMAIL", "severity": "warning", "message": "Disposable / throwaway email provider" }
],
"features": {
"syntax": { … },
"dns": { … },
"disposable": { "result": "invalid", "score": 0, "message": "…", "reasonCode": "DISPOSABLE_DOMAIN" },
"…": { … }
},
"metadata": {
"requestId": "0192f6b4-6a1e-7c11-9d0a-3f2b8c4e1a77",
"timestamp": "2026-10-15T09:12:44.512Z",
"processingTime": 212,
"credits": { "used": 0, "remaining": 0, "breakdown": { "smtp": 0, "…": 0 } },
"apiVersion": "2.0"
}
}
Les valeurs de score et les textes message sont donnés à titre d'exemple.
Champs de synthèse
| Champ | Type | Description |
|---|---|---|
result | valid · risky · invalid · unknown | Le verdict. Voir Verdicts et score. |
score | entier 0–100 | La confiance dans l'adresse. |
freeProvider | booléen | Domaine grand public (webmail, fournisseur d'accès) ou jetable. |
businessEmail | booléen | Adresse professionnelle : l'inverse de freeProvider pour une adresse bien formée. |
disposable | booléen | Domaine jetable. Raccourci de features.disposable. |
alias | booléen | Adresse sous-adressée ([email protected]). Informatif, n'influence pas le verdict. |
finalDecision | accepted · rejected | Décision de votre politique de validation. Elle n'évalue que les règles de la politique : une adresse invalid qu'aucune règle ne vise reste accepted. |
policy | objet | decision, reasons (codes reject_*) et rejectedByClientConfig. Voir Politiques et listes. |
warnings | tableau | Signaux de risque relevés. Absent quand il n'y en a aucun. |
features : le détail de chaque contrôle
Chaque contrôle a la même forme :
{
result: 'valid' | 'invalid' | 'unknown'; // voir l'encadré ci-dessous
score: number; // 0–100
message: string; // explication lisible, en anglais
reasonCode?: string; // code machine stable, quand il existe
details?: object; // données propres au contrôle
}
features, invalid veut dire « signal détecté »Pour les contrôles de risque, result: "invalid" signifie que le signal est présent : features.disposable.result === "invalid" veut dire « adresse jetable », features.roleAccount.result === "invalid" veut dire « compte générique ». Ce n'est pas le verdict de l'adresse, qui reste dans result à la racine.
| Fonctionnalité | Présente si | invalid signifie | Détails utiles |
|---|---|---|---|
syntax | toujours | syntaxe fausse | normalizedEmail |
dns | toujours | domaine sans serveur de messagerie | mxRecords, primaryMx, hasARecord ; reasonCode : MX_FOUND, A_FALLBACK, NO_MX_NO_A, NULL_MX, DNS_ERROR |
smtp | SMTP activé sur la clé | boîte refusée | reasonCode : MAILBOX_EXISTS, MAILBOX_NOT_FOUND, ACCEPT_ALL_DOMAIN, GREYLISTED, TIMEOUT… ; details.smtpCode, details.providerDetected |
catchAll | domaine accept-all détecté | — (toujours unknown) | reasonCode: ACCEPT_ALL_DOMAIN |
disposable | contrôle actif | adresse jetable | provider |
maliciousDomains | contrôle actif | domaine malveillant | category (phishing, scam_fr, blacklist…), sources |
typoDomain | contrôle actif | faute de frappe probable | suggestedDomain, suggestedEmail, detectionMethod (list, typosquat, algorithm) |
typosquat | contrôle actif | domaine piège qui imite un fournisseur | impersonatedDomain (peut être null) |
typoCorrection | voir ci-dessous | — | correctedDomain, correctedEmail |
roleAccount | contrôle actif | compte générique | pattern, category |
randomDetection | contrôle actif | partie locale aléatoire | randomnessScore |
profanity | contrôle actif | terme injurieux | words, severity |
aliasing | contrôle actif | — (informatif) | isAlias, aliasType, baseEmail |
enrichment | contrôle actif | — | firstName, lastName, gender, presumedAge, presumedAgeRange, scores associés |
listCheck | listes actives | adresse en liste noire | isWhitelisted, isBlacklisted |
domainHealth | domaine non grand public | — | label (excellent → critical), contrôles MX, SPF, DMARC, âge du domaine |
network | contrôle actif et IP connue | — | voir ci-dessous |
Un contrôle désactivé sur la clé est absent de features. La syntaxe et le DNS sont toujours présents.
Faute de frappe, domaine piège et correction vérifiée
Trois signaux distincts, qui peuvent se cumuler :
typoDomain: l'utilisateur s'est probablement trompé (gmial.com→gmail.com).details.suggestedEmailpropose l'adresse corrigée. Aucune suggestion quand le domaine visé ne reçoit plus de courrier (details.suggestionWithheld: "dead_target").typosquat: le domaine saisi a été enregistré pour capter le courrier destiné à un fournisseur connu. Le message arrivera, mais pas à la personne voulue.typoCorrection: avec le SMTP activé, quand l'adresse saisie n'a pas de réponse SMTP fiable (accept-all, pas de serveur, domaine piège), YesWeCheck sonde aussi l'adresse corrigée, gratuitement. Le bloc n'est présent que si l'adresse corrigée est délivrable. Le verdict, le score et la facturation de l'adresse saisie ne changent pas.
Ordre de priorité pour proposer une correction : typoCorrection.correctedEmail (vérifiée), puis typoDomain.details.suggestedEmail. Si l'adresse saisie est valid, ne proposez rien : la faute n'est alors qu'une information.
network : l'IP qui appelle l'API
network analyse l'adresse IP qui a appelé l'API : pays, opérateur, Tor, VPN, hébergeur.
Quand votre backend appelle l'API, l'IP analysée est celle de votre serveur, pas celle de l'internaute. Vous verrez alors DATACENTER_IP dans warnings à chaque appel. Désactivez network sur les clés serveur, ou ignorez les codes réseau. Ce contrôle n'a de sens que pour le widget, où l'appel part du navigateur de l'internaute.
warnings : les signaux de risque
Un résumé lisible par machine de tout ce qui a été relevé. Il est descriptif : un signal présent n'implique pas un refus (voir finalDecision pour ça).
| Code | Sévérité | Signal |
|---|---|---|
DISPOSABLE_EMAIL | warning | Fournisseur d'adresses jetables |
TYPOSQUAT_DOMAIN | warning | Domaine qui imite un fournisseur connu ; data.impersonatedDomain |
TYPO_DETECTED | warning, ou info si l'adresse saisie est délivrable | Faute de frappe probable ; data.suggestedDomain |
TYPO_CORRECTION_VERIFIED | info | L'adresse corrigée a été vérifiée délivrable |
MALICIOUS_DOMAIN | error | Domaine signalé (hameçonnage, arnaque, liste noire) |
ROLE_ACCOUNT | info | Compte générique (contact@, info@…) |
CATCH_ALL_DOMAIN | info | Domaine accept-all |
RANDOM_LOCALPART | warning | Partie locale qui semble générée |
PROFANITY | info | Terme injurieux dans la partie locale |
TOR_EXIT_NODE | warning | Appel depuis un nœud de sortie Tor |
ANONYMOUS_NETWORK | warning | Appel depuis un réseau anonymisant (VPN, proxy) |
DATACENTER_IP | info | Appel depuis un hébergeur |
DUPLICATED_SUBMITTER | warning | Cette IP ou cet appareil a soumis un nombre inhabituel d'adresses différentes |
Chaque entrée a la forme { code, severity, message, data? }. Testez code, jamais message.
metadata
| Champ | Description |
|---|---|
requestId | Identifiant unique de l'appel. Communiquez-le au support en cas de question. |
timestamp | Date de la validation (ISO 8601, UTC). |
processingTime | Durée de traitement côté serveur, en millisecondes. |
credits.used | Crédits débités par cet appel : 0 ou 1. Toujours 0 sur le plan Pro. |
credits.remaining | Solde de l'organisation après l'appel. Renseigné seulement quand le SMTP a été exécuté ; vaut 0 sinon. |
credits.breakdown | Détail par contrôle ; seul smtp peut être non nul. |
apiVersion | "2.0". |