LeoVerifier API
Verify whether an email address is real, deliverable, and safe to send to. One JSON request, one structured JSON response.
Overview
LeoVerifier is a single full-stack service: the dashboard, the docs, and the API all live on the same host. The API is a standard HTTPS REST service — all requests and responses are JSON.
https://verify.leomail.xyzBuilding with AI? Point your coding agent at /llms.txt — a compact, plain-text reference of every public endpoint for fast, accurate AI development.
- The public verification endpoints require an API key (see Authentication).
- Send
Content-Type: application/jsonon every request. - Requests are rate-limited per second and counted against your monthly quota.
Authentication
Authenticate with your API key using a Bearer token. Keys are created by your administrator and shown only once — store them securely and never expose them in client-side code.
Authorization: Bearer lv_live_xxxxxxxxxxxxxxxxxxxxxxxx
You may also send the key in an x-api-key header. Live keys start with lv_live_; test keys start with lv_test_. Need access? Contact support@leomail.xyz.
Verify an email
Validate a single address. Returns a status, a confidence score, and per-check details.
Verify a single email address
{
"email": "jane@example.com"
}{
"email": "jane@example.com",
"status": "valid",
"score": 98,
"result": "deliverable",
"deliverable": true,
"domain": "example.com",
"provider": "business",
"mxHost": "aspmx.l.example.com",
"smtpCode": 250,
"checks": {
"syntax": true,
"domain": true,
"mx": true,
"disposable": false,
"role": false,
"catch_all": false
},
"reasons": [],
"cached": false,
"checkedAt": "2026-01-01T12:00:00.000Z",
"runId": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
}Example request:
curl -X POST https://verify.leomail.xyz/api/v1/verify \
-H "Authorization: Bearer lv_live_..." \
-H "Content-Type: application/json" \
-d '{"email": "jane@example.com"}'Verify in bulk
Validate up to 1,000 addresses in a single call. Each address in the batch counts as one verification against your monthly quota. The response contains a results array of the same objects returned by the single endpoint.
Verify multiple email addresses
{
"emails": [
"jane@example.com",
"no-reply@company.com"
]
}{
"job": "batch",
"jobId": "job1700000000abc",
"runId": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"count": 2,
"results": [
{
"email": "jane@example.com",
"status": "valid",
"score": 98,
"result": "deliverable",
"deliverable": true
},
{
"email": "no-reply@company.com",
"status": "risky",
"score": 55,
"result": "risky",
"deliverable": false,
"reasons": [
"role_based"
]
}
]
}curl -X POST https://verify.leomail.xyz/api/v1/verify/bulk \
-H "Authorization: Bearer lv_live_..." \
-H "Content-Type: application/json" \
-d '{"emails": ["jane@example.com", "no-reply@company.com"]}'Account & usage
Return the full license picture for the authenticated key: account, plan, quota, current usage, and lifetime totals.
Get account, plan, key and usage for the current key
{
"account": {
"id": "acc_1a2b3c",
"name": "Acme Inc",
"status": "active"
},
"plan": {
"id": "scale",
"name": "Scale",
"monthly_quota": 1000000,
"rate_per_sec": 200
},
"key": {
"prefix": "lv_live_ab12",
"environment": "live",
"status": "active",
"expiry_date": null,
"last_used_at": "2026-01-01T12:00:00.000Z"
},
"usage": {
"used_this_month": 5230,
"quota": 1000000,
"remaining": 994770,
"period_start": "2026-01-01"
},
"totals": {
"runs": 128,
"verifications": 5230
}
}curl https://verify.leomail.xyz/api/v1/me \ -H "Authorization: Bearer lv_live_..."
List runs
List your verification runs, most recent first (up to 200). Every single or bulk verify call creates one run with aggregate stats.
List verification runs
{
"runs": [
{
"id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"mode": "bulk",
"job_id": "job1700000000abc",
"total": 500,
"deliverable": 430,
"undeliverable": 45,
"risky": 20,
"unknown": 5,
"avg_score": 82,
"source": "api",
"created_at": "2026-01-01T12:00:00.000Z"
}
]
}curl https://verify.leomail.xyz/api/v1/runs \ -H "Authorization: Bearer lv_live_..."
Run results
Fetch one run by its id, including the per-email results for that run. Use the runId returned by the verify endpoints, or an id from /api/v1/runs. Returns 404 not_found if the run isn’t part of your account.
Get a run and its individual email results
{
"run": {
"id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"mode": "bulk",
"total": 2,
"deliverable": 1,
"undeliverable": 1,
"risky": 0,
"unknown": 0,
"avg_score": 74,
"source": "api",
"created_at": "2026-01-01T12:00:00.000Z"
},
"results": [
{
"email": "jane@example.com",
"status": "valid",
"score": 98,
"domain": "example.com",
"from_cache": false,
"deliverable": true
},
{
"email": "no-reply@company.com",
"status": "invalid",
"score": 20,
"domain": "company.com",
"from_cache": false,
"deliverable": false
}
]
}curl https://verify.leomail.xyz/api/v1/runs/RUN_ID \ -H "Authorization: Bearer lv_live_..."
Result schema
Each verified address returns the following fields.
| Field | Type | Description |
|---|---|---|
email | string | The address that was checked (normalized to lowercase). |
status | string | valid, risky, invalid, disposable, or unknown. |
score | number | Confidence from 0–100. |
result | string | Outcome label: deliverable, undeliverable, risky, disposable, or unknown. |
deliverable | boolean | Shortcut for status === 'valid'. |
domain | string | The domain part of the address. |
provider | string | free (e.g. Gmail) or business. |
mxHost | string | null | The primary MX host used for the SMTP probe. |
smtpCode | number | null | SMTP reply code from the RCPT probe (null if not probed). |
checks | object | Per-check booleans: syntax, domain, mx, disposable, role, catch_all. |
reasons | string[] | Machine-readable reason codes, e.g. role_based, catch_all, greylisted. |
cached | boolean | Whether the result came from a recent cached check (7-day cache). |
checkedAt | string | ISO-8601 timestamp of the check. |
Status & scores
| Status | Typical score | Meaning |
|---|---|---|
| valid | 85–100 | Mailbox exists and accepts mail. Safe to send. |
| risky | 55–79 | Accepts mail but is a role address, catch-all, or a provider that blocks verification. |
| disposable | varies | A known throwaway / temporary email domain. |
| unknown | ~50 | The mailbox could not be confirmed (greylisting or blocked probe). Retry later. |
| invalid | 0–39 | Undeliverable — bad syntax, no MX, or the mailbox was rejected. |
Quotas & rate limits
Each plan sets a monthly verification quota and a per-second request rate. Limits are enforced on the backend and can be inspected in the dashboard:
| Plan | Monthly quota | Rate / sec | Max keys |
|---|---|---|---|
| Free | 1,000 | 5 | 2 |
| Pro | 100,000 | 50 | 10 |
| Scale | 1,000,000 | 200 | 50 |
Exceeding the per-second rate returns 429 rate_limited; exhausting the monthly quota returns 429 quota_exceeded. Cached results still count as one verification.
Error codes
Errors return the matching HTTP status and a JSON body of the form { "error": "..." }.
| HTTP | error | Meaning |
|---|---|---|
| 400 | invalid_email | The email failed basic validation. |
| 400 | no_valid_emails | Bulk request contained no valid addresses. |
| 400 | batch_too_large | Bulk request exceeded 1,000 addresses. |
| 401 | missing_key / invalid_key | No key, or the key is unknown. |
| 401 | key_revoked / key_expired | The key is no longer usable. |
| 402 | account_suspended | The account is not active. |
| 403 | origin_not_allowed | Request origin is not in the key’s allowed-origins list. |
| 429 | rate_limited | Too many requests — slow down. |
| 429 | quota_exceeded | Monthly quota reached. |
| 502 | verification_unavailable | Temporary upstream issue — retry shortly. |