Documentation de l'API
Une requête par adresse, ou des lots jusqu'à un million. Même moteur et mêmes crédits que le tableau de bord. Les clés viennent de votre compte.
Authentification
Créez une clé dans Tableau de bord → Clés API et envoyez-la dans l'en-tête X-API-Key (ou sous la forme Authorization: Bearer mk_live_…). Les clés commencent par mk_live_, ne sont affichées qu'une fois et peuvent être révoquées à tout moment. URL de base : https://api.mailok.io.
Vérifier une adresse
POST /v1/verify avec { "email" }, ou GET /v1/verify?email=. Réponse en quelques secondes ; une vraie conversation SMTP peut prendre jusqu'à 60 s sur les serveurs lents.
curl https://api.mailok.io/v1/verify \
-H "X-API-Key: mk_live_…" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'{
"email": "[email protected]",
"status": "valid",
"catch_all": false,
"disposable": false,
"role": false,
"mailbox_full": false,
"mx_found": true,
"mx_record": "mx1.northwindtraders.com",
"domain": "northwindtraders.com",
"account": "sarah",
"credits_remaining": 9999
}Statuts
Indicateurs sur chaque résultat : catch_all, disposable, role, mailbox_full, mx_found, mx_record. credits_remaining est votre solde après l'appel.
Lots
Envoyez une liste, interrogez jusqu'à ready, parcourez les résultats page par page. Les doublons au sein d'une liste sont marqués et gratuits. Les listes apparaissent aussi dans votre tableau de bord.
POST /v1/batches
{ "emails": ["[email protected]", "[email protected]"], "name": "October import" }
→ { "uid": "k3d9x1qzpa", "name": "October import", "status": "pending", "total": 2, "completed": 0,
"stats": { "valid": 0, "invalid": 0, "risky": 0, "unknown": 0, "duplicate": 0 }, "created_at": "…" }GET /v1/batches/k3d9x1qzpa → same shape plus "percent", "eta_seconds", "credits_used"; "status": "ready" when done
GET /v1/batches/k3d9x1qzpa/results?page_size=1000&status=valid,risky
→ { "items": [ { "id": 4102, "email": "[email protected]", "status": "valid", "checked_at": "…" } ], "total": 1, "next_after": 4102, … }
GET /v1/batches/k3d9x1qzpa/results?page_size=1000&after=4102 → the next page, in file order
GET /v1/batches/k3d9x1qzpa/download?format=xlsx&statuses=valid → the file (your columns + MailStatus, or email,MailStatus)POST /v1/batches/upload multipart: file (CSV or .xlsx), name, callback_url, auto_start (default true)
PUT /v1/batches/k3d9x1qzpa/start { "sample": 100 } optional: verify the first 100 first, then start again for the rest
PUT /v1/batches/k3d9x1qzpa/cancel stops it; verified addresses stay, nothing else is charged
DELETE /v1/batches/k3d9x1qzpa removes the batch, its results and its filesStatuts : pending (lecture) → parsed (seulement avec auto_start: false, en attente de start) → processing → completed → ready ; sampled après un échantillon ; paused quand le compte n'a plus de crédits (reprend seul dès que des crédits arrivent) ; cancelled ; failed avec un message error. Les adresses inconnues sont revérifiées une fois gratuitement avant ready. GET /v1/batches liste vos lots.
Compte
GET /v1/account renvoie credits, subscription_credits, credits_remaining, plan et votre rate_limit_per_minute. Pratique pour des alertes avant une campagne.
Webhooks
Passez une callback_url (hôte public https ou http) à la création d'un lot et nous envoyons en POST un événement batch.ready quand il est terminé. Répondez par un 2xx sous 10 s ; sinon nous réessayons après 1, 5 et 30 minutes, puis abandonnons. Chaque tentative est listée dans Tableau de bord → Clés API, où se trouve aussi le secret de signature.
POST <your callback_url>
X-MailOK-Event: batch.ready
X-MailOK-Timestamp: 1760000000
X-MailOK-Signature: sha256=…
X-MailOK-Delivery: 42
{ "event": "batch.ready", "created_at": "…",
"data": { "uid": "k3d9x1qzpa", "name": "October import", "status": "ready", "total": 2, "completed": 2,
"stats": { "valid": 1, "invalid": 1, "risky": 0, "unknown": 0, "duplicate": 0 },
"created_at": "…", "completed_at": "…", "error": null } }Vérifiez la signature avant de faire confiance au contenu : HMAC-SHA256 de "{timestamp}.{raw body}" avec votre secret, comparé en temps constant. Rejetez les horodatages vieux de plus de quelques minutes pour bloquer les rejeux.
import crypto from 'node:crypto'
// signature = "sha256=" + HMAC_SHA256(secret, timestamp + "." + rawBody)
export function verify(rawBody, headers, secret) {
const expected = 'sha256=' + crypto.createHmac('sha256', secret)
.update(headers['x-mailok-timestamp'] + '.' + rawBody).digest('hex')
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(headers['x-mailok-signature'] ?? ''))
}Erreurs et limites
Chaque erreur a la même forme et un code stable :
{ "error": { "code": "insufficient_credits", "message": "No credits left. Buy credits or choose a plan in the dashboard." } }Limite : 60 requêtes par minute et par clé par défaut (en-tête X-RateLimit-Limit sur chaque réponse) ; les abonnements peuvent avoir une limite plus élevée. Besoin de plus ? Écrivez-nous.
