- Início
- API
API v1
API de validação de e-mail
REST e JSON. Valide um endereço em tempo real, lotes de até 100 ou arquivos inteiros. Base: https://api.mailchecker.dev
Visão geral
Todas as rotas ficam em https://api.mailchecker.dev/v1, respondem JSON em UTF-8 (exceto o download de resultados, em CSV) e exigem uma chave de API. Crie e revogue chaves no portal, em API keys; a chave completa aparece uma única vez.
A especificação OpenAPI 3.1 fica em https://api.mailchecker.dev/v1/openapi.json.
Autenticação
Envie a chave (mc_live_…) no cabeçalho Authorization: Bearer ou, para compatibilidade com o ZeroBounce, no parâmetro api_key da query. Prefira o cabeçalho: URLs costumam parar em logs.
# Cabeçalho (recomendado)
curl "https://api.mailchecker.dev/v1/credits" \
-H "Authorization: Bearer mc_live_…"
# Ou na query, como no ZeroBounce
curl "https://api.mailchecker.dev/v1/credits?api_key=mc_live_…"
Endpoints
| Rota | Para quê |
|---|---|
GET /v1/validate | Um endereço, síncrono |
POST /v1/validate/batch | Até 100 endereços, síncrono |
POST /v1/files | Envia uma lista (CSV/XLSX) |
GET /v1/files/{id} | Progresso e totais da lista |
GET /v1/files/{id}/download | Resultado da lista em CSV |
GET /v1/credits | Saldo de créditos |
GET /v1/usage | Uso por dia e status |
GET /v1/openapi.json | Especificação OpenAPI 3.1 |
/v1/validate?email=
Verifica um endereço e devolve um Verdict. Parâmetro: email (obrigatório).
curl "https://api.mailchecker.dev/v1/validate?email=joao.silva@gmail.com" \
-H "Authorization: Bearer mc_live_…"
{
"address": "joao.silva@gmail.com",
"status": "valid",
"sub_status": "",
"account": "joao.silva",
"domain": "gmail.com",
"did_you_mean": null,
"free_email": true,
"role_based": false,
"disposable": false,
"mx_found": true,
"mx_record": "gmail-smtp-in.l.google.com",
"smtp_provider": "google",
"domain_age_days": 11318,
"processed_at": "2026-11-07T12:34:56Z",
"domain_score": 100,
"domain_reasons": ["dmarc_none", "free_email"]
}
/v1/validate/batch
Corpo {"emails": [...]} com até 100 endereços. Devolve um Verdict por endereço e o custo total do lote; repetidos no mesmo lote não são cobrados.
curl -X POST "https://api.mailchecker.dev/v1/validate/batch" \
-H "Authorization: Bearer mc_live_…" \
-H "Content-Type: application/json" \
-d '{"emails": ["ana@empresa.com.br", "joao@gmial.com"]}'
{
"results": [ /* um Verdict por endereço */ ],
"cost": 2
}
/v1/files
Multipart com file (CSV ou XLSX, até 1 milhão de linhas), column (opcional: a coluna do e-mail) e name. Responde 201 com a lista no estado queued.
curl -X POST "https://api.mailchecker.dev/v1/files" \
-H "Authorization: Bearer mc_live_…" \
-F "file=@clientes.csv" -F "column=2" -F "name=Clientes novembro"
/v1/files/{id}
O estado da lista: uploaded, queued, running, done, failed ou cancelled, com os totais por status. Consulte de tempos em tempos até done.
{
"id": "0193f1c2-…",
"name": "Clientes novembro",
"original_filename": "clientes.csv",
"state": "running",
"total": 12480, "unique_count": 12011, "duplicates": 469,
"processed": 8300,
"counts": { "valid": 6904, "invalid": 811, "catch-all": 402, "unknown": 183 },
"cost": 8117,
"error": null,
"created_at": "2026-11-07T12:00:00Z", "started_at": "2026-11-07T12:00:02Z", "finished_at": null
}
/v1/files/{id}/download?filter=
O resultado em CSV. filter=all (padrão) traz tudo, valid só os válidos, no_invalid tudo menos os inválidos.
/v1/credits
Saldo do time: {"balance": 1840}.
/v1/usage?from=&to=
Uso diário por status, com datas AAAA-MM-DD: {"days": [{"day", "status", "count", "cost"}]}.
O resultado (Verdict)
Cada endereço verificado vira um objeto com estes campos:
| Campo | Tipo | Descrição |
|---|---|---|
address | string | Endereço normalizado (sem espaços, domínio em minúsculas). |
status | string | valid, invalid, catch-all, unknown, spamtrap, abuse ou do_not_mail. |
sub_status | string | Detalhe do status (lista abaixo); "" quando não há. |
account | string | Parte antes do @. |
domain | string | Parte depois do @. |
did_you_mean | string | null | Correção sugerida para erro de digitação no domínio (gmial.com → gmail.com). |
free_email | boolean | Provedor gratuito (Gmail, Outlook, Yahoo, UOL, BOL…). |
role_based | boolean | Endereço de função: contato@, vendas@, suporte@… |
disposable | boolean | Serviço de e-mail descartável/temporário. |
mx_found | boolean | O domínio tem servidor de e-mail. |
mx_record | string | null | MX de maior prioridade. |
smtp_provider | string | null | google, microsoft, yahoo, proofpoint, mimecast, zoho, other… |
domain_age_days | integer | null | Idade do domínio em dias (RDAP). |
processed_at | string | Data e hora da verificação, ISO 8601 (UTC). |
domain_score | integer | null | Reputação do domínio, 0–100 (maior = mais seguro), só de consultas DNS e de registro (RDAP), sem contato com o servidor de e-mail. Não altera o status. null quando não calculada. |
domain_reasons | string[] | Motivos da pontuação, códigos estáveis em ordem fixa (lista abaixo). |
Motivos da reputação do domínio
Cada motivo tira pontos de 100; os marcados "sem penalidade" são só informativos. Domínios de e-mail grátis (Gmail, Outlook…) só perdem pontos por blocklist.
| Código | Significado |
|---|---|
disposable_domain | domínio descartável |
blocklist_spamhaus_dbl | listado na Spamhaus DBL |
blocklist_surbl | listado na SURBL |
blocklist_uribl | listado na URIBL |
blocklist_spamhaus_zen | MX listado na Spamhaus ZEN |
blocklist_barracuda | MX listado na Barracuda |
blocklist_unknown | blocklist sem resposta (sem penalidade) |
parked_domain | domínio estacionado ou à venda |
null_mx | declara que não recebe e-mail (MX nulo) |
no_mx | sem registro MX |
mx_ip_literal | MX é um IP, não um nome |
mx_private_ip | MX aponta para IP privado ou reservado |
mx_no_address | servidor MX sem endereço IP |
domain_age_lt_30d | domínio registrado há menos de 30 dias |
domain_age_lt_1y | domínio registrado há menos de 1 ano |
domain_age_unknown | idade do domínio desconhecida (sem penalidade) |
no_spf | sem SPF |
spf_invalid | SPF inválido (mais de um registro) |
spf_plus_all | SPF permite qualquer remetente (+all) |
no_dmarc | sem DMARC |
dmarc_none | DMARC só monitora (p=none) |
free_email | provedor de e-mail grátis (sem penalidade) |
role_based | endereço de função (sem penalidade) |
Status e sub-status
O mesmo vocabulário do ZeroBounce.
| Status | Significado | Sub-status possíveis |
|---|---|---|
| valid | A caixa existe e o servidor aceitou o destinatário. Pode enviar. | — |
| invalid | O endereço não recebe: caixa inexistente, domínio sem servidor de e-mail, erro de digitação ou sintaxe errada. Remova da lista: é o que gera bounce. | mailbox_not_found, no_dns_entries, failed_syntax_check, possible_typo, unroutable_ip_address, does_not_accept_mail, mailbox_quota_exceeded, leading_period_removed |
| catch-all | O domínio aceita qualquer endereço, então não dá para confirmar a caixa. Envie com cautela, de preferência em lotes menores. | — |
| unknown | O servidor não respondeu de forma conclusiva (greylisting, antispam, timeout). Não cobramos: tente de novo mais tarde. | greylisted, antispam_system, mail_server_temporary_error, mail_server_did_not_respond, timeout_exceeded, failed_smtp_connection, forcible_disconnect, exception_occurred |
| do_not_mail | O endereço existe, mas enviar é arriscado: e-mail descartável, de função (contato@, vendas@), tóxico ou em lista de supressão. | role_based, disposable, toxic, global_suppression, role_based_catch_all, alias_address, mx_forward |
| spamtrap | Provável armadilha de spam: um envio pode colocar seu domínio em blocklist. | possible_trap |
| abuse | Endereço conhecido por marcar mensagens como spam e denunciar remetentes. | — |
Erros
Todo erro vem no mesmo formato: um código estável em error, uma mensagem legível em message e, nos erros de validação, os campos com problema em fields.
{
"error": "validation",
"message": "O campo email é obrigatório.",
"fields": { "email": ["obrigatório"] }
}
| HTTP | error | Quando |
|---|---|---|
| 401 | unauthorized | Chave ausente, inválida ou revogada. |
| 402 | no_credit | Saldo insuficiente. Numa lista, o processamento para com state=failed e error=no_credit. |
| 422 | validation | Parâmetro faltando ou inválido; veja fields. |
| 429 | rate_limited | Limite de requisições da chave excedido; aguarde e tente de novo. |
Limites
- Requisições: limite por chave, em balde de fichas (token bucket); o padrão é 10 requisições por segundo. Precisa de mais? Fale com a gente.
- Lote síncrono: até 100 endereços por
POST /v1/validate/batch. - Arquivos: CSV ou XLSX com até 1 milhão de linhas.
- Retenção: resultados ficam disponíveis por 30 dias e depois são apagados (LGPD).
Cobrança
O débito acontece junto com a gravação do resultado: 1 crédito por endereço, inclusive catch-all. unknown custa 0 e endereços repetidos na mesma lista ou lote também. Consulte o saldo em GET /v1/credits e veja os preços.
Migrando do ZeroBounce
Desenhamos a API para que a migração seja curta:
- Mesmos status e sub-status, com os mesmos nomes.
- Mesmos nomes nos campos principais do resultado (
address,status,sub_status,account,domain,did_you_mean,free_email,mx_found,mx_record,smtp_provider,domain_age_days,processed_at). - Chave aceita em
?api_key=. - Mesmas regras de cobrança:
unknowne duplicatas não cobram.
# ZeroBounce
GET https://api.zerobounce.net/v2/validate?api_key=SUA_CHAVE&email=ana@empresa.com.br
# mailchecker: troque a base e a chave
GET https://api.mailchecker.dev/v1/validate?api_key=mc_live_…&email=ana@empresa.com.br
O que muda: a URL base e o caminho (/v1/...), a chave, e os campos de nome, gênero e localização, que não existem nesta versão. Adicionamos role_based e disposable como booleanos. Confira os tipos dos campos no seu parser antes de trocar em produção.
Veja também a comparação completa.