Aller au contenu

Vérifier un email

Soumettez une adresse, interrogez le job, et lisez ses contrôles, son verdict honnête et son score de confiance : les contrôles sans réponse sont remboursés.

Soumettre un job

POST /api/verify réserve le coût, met le job en file et renvoie 202 Accepted avec un job_uuid. La réponse pose un en-tête Location avec l'URL d'interrogation et un Retry-After tant que le job tourne.

Requête
curl -X POST https://api.pricklymails.com/api/verify \
  -H "Authorization: Bearer pm_live_votre_cle" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: commande-1234" \
  -d '{ "email": "quelquun@example.com" }'

Passez un en-tête Idempotency-Key optionnel pour sécuriser les retries : pendant 24 heures, la même clé rejoue le job d'origine au lieu d'en facturer un nouveau (la réponse porte alors Idempotent-Replayed: true).

Interroger le résultat

GET /api/verify/{uuid} renvoie le job et ses résultats par contrôle, limités à votre compte. Il continue de poser Retry-After jusqu'à ce que le job atteigne un statut terminal (completed, failed ou canceled).

Une fois completed, verifications porte le résultat : le verdict (status), sa raison (reason), le score, la recommandation d'action et le résultat par contrôle. L'adresse elle-même n'est jamais stockée : le résultat ne l'identifie que par des empreintes à clé (hash). Un contrôle que votre clé n'active pas vaut { "status": "skipped" }. Ici, une adresse chez un fournisseur qui accepte tous les destinataires, où la sonde de boîte est sautée :

Réponse
{
    "job_uuid": "0192f3c4-8a6e-7b1d-9c2e-5f4a3b2c1d0e",
    "status": "completed",
    "verifications": [
        {
            "email_hash": "3b8f1c0d9e7a",
            "domain_hash": "a41e77c2d0b5",
            "status": "valid",
            "reason": "accept_all_provider",
            "score": 76,
            "recommendation": "send",
            "duration_ms": 412,
            "verified_at": "2026-10-01T09:12:45.120+00:00",
            "checks": {
                "syntax": true,
                "mx": { "valid": true, "records": ["gmail-smtp-in.l.google.com", "alt1.gmail-smtp-in.l.google.com"] },
                "disposable": false,
                "role": false,
                "free": true,
                "typo": { "detected": false },
                "smtp": { "status": "skipped" },
                "catchall": { "status": "skipped" }
            },
            "durations": {
                "syntax": 0,
                "mx": 38,
                "smtp": null,
                "disposable": 0,
                "role": 0,
                "free": 0,
                "catchall": null,
                "typo": 0
            }
        }
    ]
}

recommendation traduit le verdict honnête en action pour le nettoyage de liste : remove, send ou review (voir Batches).

Obtenir le résultat dans le même appel

Une requête qui peut attendre quelques secondes, comme un formulaire d'inscription, peut se passer de l'interrogation : envoyez Prefer: wait=N, le nombre de secondes qu'elle peut attendre, 12 au plus. Le job est mis en file et facturé exactement comme sans l'en-tête ; seule la réponse l'attend. S'il se termine à temps, la réponse est un 200 OK avec le résultat dans verification, sous la même forme qu'un résultat interrogé ; sinon, c'est le 202 Accepted habituel, et le job continue. Dans les deux cas, la réponse porte Preference-Applied: wait=N.

Requête
curl -X POST https://api.pricklymails.com/api/verify \
  -H "Authorization: Bearer pm_live_votre_cle" \
  -H "Content-Type: application/json" \
  -H "Prefer: wait=4" \
  -d '{ "email": "quelquun@example.com" }'
Réponse
{
    "job_uuid": "0fdfff58-5f5a-4c52-b66c-ee78705db27c",
    "status": "completed",
    "estimated_cost": 7,
    "idempotency_key": "14f4a9b6-9f45-4579-9bba-d4a282a08289",
    "replayed": false,
    "email": "quelquun@example.com",
    "verification": {
        "email_hash": "28ba1aff51a7",
        "domain_hash": "4ac0ea9fe911",
        "status": "invalid",
        "reason": "null_mx",
        "score": 0,
        "recommendation": "remove",
        "duration_ms": 277,
        "verified_at": "2026-10-21T20:35:30.938480+00:00",
        "checks": {
            "syntax": true,
            "mx": { "valid": false, "records": ["."] },
            "disposable": { "status": "skipped" },
            "role": { "status": "skipped" },
            "free": { "status": "skipped" },
            "typo": { "detected": false },
            "smtp": { "status": "skipped" },
            "catchall": { "status": "skipped" }
        },
        "durations": {
            "syntax": 0,
            "mx": 277,
            "smtp": null,
            "disposable": null,
            "role": null,
            "free": null,
            "catchall": null,
            "typo": 0
        }
    }
}

Un serveur de messagerie qui demande de réessayer plus tard retarde le résultat d'une minute ou plus. Là où rien ne peut attendre aussi longtemps, comme dans un hook d'inscription, prenez un 202 pour une réponse pas encore connue, et laissez l'étape continuer.

Les contrôles

Chaque adresse passe par les contrôles que votre clé active :

  • syntax : format RFC 5322.
  • mx : le domaine a des serveurs de mail utilisables (un MX absent, null, parké ou inactif échoue ici).
  • smtp : la boîte accepte le courrier (sonde de délivrabilité).
  • disposable : un fournisseur jetable connu, détecté sur le domaine de l'adresse ou son serveur de mail.
  • role : une adresse de rôle comme info@ ou support@.
  • free : un webmail gratuit.
  • catchall : le domaine accepte n'importe quelle adresse. Disponible à partir de l'offre Pro ; il envoie un destinataire aléatoire supplémentaire dans la même session que la sonde de boîte, et seulement quand il est demandé. Sans lui, checks.catchall vaut { "status": "skipped" } et aucun destinataire supplémentaire n'est jamais envoyé.

La détection de fautes de frappe s'exécute toujours, quels que soient les contrôles activés par votre clé : quand une faute probable est trouvée, la réponse renvoie une correction suggérée.

Pour lancer d'autres contrôles sur une requête, envoyez-les dans checks, par exemple { "email": "prenom@exemple.fr", "checks": ["mx", "smtp", "disposable"] }. Chacun doit être autorisé par votre offre, sinon la requête renvoie 403 ; un nom inconnu renvoie 400. Les dépendances sont ajoutées pour vous : smtp entraîne mx, catchall entraîne les deux, et le coût suit les contrôles lancés.

Verdict et score

Chaque résultat porte un verdict de délivrabilité dans son champ status (valid, invalid, risky, unknown) et un score de qualité de 0 à 100. Quand une faute est détectée, la réponse à la soumission renvoie une suggestion (par exemple quelquun@gmial.com suggère quelquun@gmail.com) ; le résultat interrogé ne porte que le domaine corrigé, dans checks.typo.suggested_domain, puisque l'adresse n'est jamais stockée.

Le score d'une boîte acceptée par le serveur plafonne à 88 quand le contrôle catch-all n'a pas tourné (Free et Starter), et monte à 96 quand il a tourné et écarté un domaine catch-all (Pro et supérieur) : les 8 points en plus récompensent la seule chose que ce contrôle peut établir.