Referência da API de verificação de e-mail
POST/v1/email/validate
Verifica um endereço de e-mail: sintaxe, domínios descartáveis/temporários conhecidos, o servidor de correio (MX) do domínio, gralhas prováveis e endereços funcionais, e devolve um veredicto accept/review/reject com os respetivos motivos. Envie um corpo JSON { "email": "user@example.com" }. Concebido para ser chamado a partir do JavaScript do próprio formulário de registo, com o mesmo modelo de chave publicável restrita por origem que GET /v1/geo. Para muitos endereços ou uma decisão de registo do lado do servidor, utilize os endpoints de lote, de tarefas de lista e de verificação de registo descritos mais abaixo. Todas as verificações são ao nível do domínio e do endereço: nenhuma caixa de correio é contactada, pelo que nenhum resultado estabelece que uma caixa de correio existe, quem é o titular ou que o correio lá chegará.
Autenticação
POST /v1/email/validate aceita uma chave publicável restrita por origem através do cabeçalho X-Api-Key — o mesmo tipo de chave e o mesmo modelo de origens permitidas que GET /v1/geo. Todos os outros endpoints desta página (lote, tarefas de lista, verificação de registo) aceitam muitos endereços ou um IP arbitrário, pelo que exigem a sua chave secreta através de Authorization: Bearer e só devem ser chamados a partir do seu back-end; uma chave publicável recebe um 403 nesses endpoints.
Campos de resposta
- O endereço que enviou, devolvido exatamente como foi submetido.
- domain
- O domínio em minúsculas (domínios internacionalizados em punycode), ou null quando syntaxValid é false.
- syntaxValid
- Se o endereço é sintaticamente válido. Não é uma verificação da existência da caixa de correio nem da capacidade de entrega.
- isDisposable
- Se o domínio corresponde a um fornecedor de e-mail descartável/temporário conhecido — diretamente, através de um domínio pai ou através de um servidor de correio conhecido por servir domínios descartáveis. Sempre false quando syntaxValid é false.
- normalizedEmail
- Endereço sem espaços e em minúsculas, com o domínio em punycode, ou null quando syntaxValid é false.
- canonicalEmail
- normalizedEmail sem qualquer +tag (e, no Gmail, sem pontos e com googlemail.com convertido em gmail.com) — guarde-o para detetar a mesma pessoa a registar-se duas vezes. Null quando syntaxValid é false.
- disposableSource
- Porque é que isDisposable é true: list (o próprio domínio está na lista), parent_domain (um domínio pai está na lista, p. ex. a.b.mailinator.com) ou mx_host (o servidor de correio do domínio serve domínios descartáveis conhecidos). Null quando isDisposable é false.
- isFreeProvider
- Se o domínio é um fornecedor de correio para consumidores, como gmail.com ou outlook.com. Apenas informativo — nunca altera o veredicto.
- isRoleAccount
- Se a parte local é um endereço funcional como admin@, info@ ou noreply@.
- didYouMean
- Uma correção provável de gralha no endereço completo (john@gmial.com → john@gmail.com), ou null. Um domínio com o seu próprio servidor de correio funcional não é «corrigido», a menos que esteja a uma edição de distância de um fornecedor comum.
- mx.status
- found (existem registos MX), implicit (sem MX, mas com um registo A/AAAA), none (nenhum dos dois), null_mx (o domínio declara que não aceita correio), no_domain (o domínio não existe) ou unknown (a consulta falhou ou excedeu o tempo limite). O objeto mx inteiro é null quando syntaxValid é false.
- mx.host
- O anfitrião MX de menor preferência quando status é found; caso contrário, null. Nada indica sobre a existência da caixa de correio individual.
- verdict
- accept, review ou reject — a mais grave das condições em reasons. Uma recomendação para a sua própria política, não uma decisão final.
- reasons
- Todas as condições verificadas, da mais grave para a menos grave; vazio quando verdict é accept. Consulte «Veredictos e códigos de motivo» abaixo.
Erros
- 400
- Corpo do pedido mal formado. Lote: empty_batch ou batch_too_large (mais de 100 endereços). Verificação de registo: invalid_ip. Tarefas de lista: invalid_body, empty_job ou job_too_large (mais de 100 000 endereços). Um endereço de e-mail inválido nunca dá um 400 — é um resultado com veredicto reject e motivo invalid_syntax.
- 401
- Chave de API em falta ou inválida.
- 403
- POST /v1/email/validate: o Origin/Referer do pedido não consta da lista de origens permitidas da chave (não é definido nenhum cabeçalho CORS, pelo que o navegador bloqueia a resposta independentemente do corpo JSON). Endpoints com chave secreta: foi utilizada uma chave publicável.
- 404
- job_not_found — não existe nenhuma tarefa de lista com este id na sua conta.
- 409
- job_not_completed — a tarefa ainda está em fila ou em processamento, ou falhou; os resultados só podem ser transferidos depois de concluída.
- 410
- job_expired — os endereços carregados e os resultados da tarefa foram eliminados (7 dias após a criação).
- 413
- body_too_large — um carregamento CSV de tarefa com mais de 10 MB.
- 415
- Um corpo de tarefa de lista que não é JSON nem text/csv.
- 429
- O limite de taxa por minuto, ou monthly_limit_exceeded quando o limite mensal de pedidos do plano seria excedido — consulte erros e limites de taxa para saber qual. Um lote ou tarefa de lista que excederia o limite é rejeitado na totalidade, antes de qualquer processamento.
- 503
- job_storage_unavailable — não foi possível armazenar uma tarefa de lista. Nada foi cobrado; tente novamente.
Exemplo
Pedido
curl https://api.watch-ip.com/v1/email/validate \
-H "X-Api-Key: YOUR_PUBLISHABLE_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "John.Doe+news@Gmial.com"}'Resposta
{
"email": "John.Doe+news@Gmial.com",
"domain": "gmial.com",
"syntaxValid": true,
"isDisposable": false,
"normalizedEmail": "john.doe+news@gmial.com",
"canonicalEmail": "john.doe@gmial.com",
"disposableSource": null,
"isFreeProvider": false,
"isRoleAccount": false,
"didYouMean": "john.doe+news@gmail.com",
"mx": {
"status": "none",
"host": null
},
"verdict": "reject",
"reasons": [
"no_mail_server",
"typo_suspected"
]
}Veredictos e códigos de motivo
Cada condição define um veredicto mínimo; prevalece a mais grave, e reasons enumera todas, da mais grave para a menos grave. Se um endereço de um fornecedor gratuito é aceitável fica ao seu critério — nunca altera o veredicto.
- invalid_syntax
- Reject. O endereço não é sintaticamente válido (limites de comprimento, caracteres permitidos, posição dos pontos, um domínio real em vez de um IP literal). As partes locais entre aspas também são rejeitadas — são legais, mas na prática nunca são usadas num registo.
- domain_not_found
- Reject. O domínio não existe no DNS.
- no_mail_server
- Reject. O domínio declara que não aceita correio (um «null MX»), ou não tem registos MX nem A/AAAA.
- disposable_domain
- Reject. O domínio, um domínio pai ou o servidor de correio do domínio corresponde a fornecedores de e-mail descartável/temporário conhecidos — consulte disposableSource.
- typo_suspected
- Review. didYouMean contém uma correção provável, como gmial.com → gmail.com.
- role_account
- Review. A parte local é um endereço funcional como admin@, info@, support@ ou noreply@, normalmente partilhado e não pessoal.
- implicit_mx
- Review. O domínio não tem registo MX; o correio recorreria ao seu endereço A/AAAA, o que é raro em domínios de correio reais.
- dns_unavailable
- Review. A consulta DNS falhou ou excedeu o tempo limite, pelo que a configuração de correio do domínio é desconhecida (mx.status: unknown). Não é um indício contra o endereço.
Verificação em lote
POST/v1/email/batch
Verifica 1 a 100 endereços num único pedido, com as mesmas verificações e a mesma forma de resultado que POST /v1/email/validate, um resultado por endereço pela ordem de entrada. Envie { "emails": [...] }. Os endereços do mesmo domínio partilham uma única consulta DNS. Conta um pedido por endereço no limite mensal do seu plano; um lote que excederia o limite é rejeitado na totalidade com 429 monthly_limit_exceeded. Para o limite de taxa por minuto, a chamada inteira conta como um único pedido. Apenas com chave secreta.
Pedido
curl https://api.watch-ip.com/v1/email/batch \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"emails": ["user@gmail.com", "someone@mailinator.com"]}'Resposta
{
"results": [
{ "email": "user@gmail.com", "verdict": "accept", "reasons": [], ... },
{ "email": "someone@mailinator.com", "isDisposable": true, "disposableSource": "list", "verdict": "reject", "reasons": ["disposable_domain"], ... }
]
}Tarefas de lista de e-mails
POST/v1/email/jobs
Verifica até 100 000 endereços em segundo plano. Envie JSON { "emails": [...], "filename": "..." } ou um corpo text/csv de 10 MB no máximo: é utilizada a coluna com o cabeçalho email (também e-mail, email address, email_address ou mail, sem distinção entre maiúsculas e minúsculas), ou a primeira coluna se nenhum cabeçalho a indicar; os separadores vírgula, ponto e vírgula e tabulação são detetados. A tarefa é cobrada no momento da criação — um pedido por endereço distinto (correspondência exata), pelo que os duplicados são verificados mas cobrados uma vez — e uma lista que excederia o seu limite mensal é rejeitada na totalidade. Se parte de uma tarefa não puder ser processada após novas tentativas, a tarefa é marcada como failed e os créditos da parte não processada são devolvidos. Responde 202 com o objeto da tarefa. Apenas com chave secreta; as mesmas tarefas também podem ser carregadas e transferidas a partir da página Email lists do painel.
Pedido
curl https://api.watch-ip.com/v1/email/jobs \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-H "Content-Type: text/csv" \
--data-binary @newsletter.csvResposta
{
"id": "5b0d6f5e-8a51-4f7e-9d0e-2c1f3f7f8a11",
"status": "queued",
"source": "api",
"filename": null,
"total": 12840,
"credits": 12512,
"processed": 0,
"summary": null,
"createdAt": "2026-09-28T10:00:00.000Z",
"completedAt": null,
"expiresAt": "2026-10-05T10:00:00.000Z"
}Estado da tarefa
GET/v1/email/jobs/{id}
Devolve o mesmo objeto da tarefa. Consulte-o periodicamente até status ser completed; as consultas não são cobradas.
- status
- queued → processing → completed. failed: parte da lista não pôde ser processada após novas tentativas; não há resultados disponíveis e os créditos da parte não processada foram devolvidos. expired: os endereços carregados e os resultados foram eliminados 7 dias após a criação.
- total
- Linhas submetidas, incluindo duplicados.
- credits
- Pedidos cobrados: um por endereço distinto.
- processed
- Linhas verificadas até ao momento.
- summary
- Após a conclusão: número de linhas por veredicto (accept/review/reject) e por cada código de motivo ocorrido. Null até lá.
- expiresAt
- Quando os endereços carregados e os resultados são eliminados.
Resultados da tarefa
GET/v1/email/jobs/{id}/results
Transfere um CSV com uma linha por cada linha submetida, pela ordem de submissão — incluindo duplicados. Colunas: email, normalized_email, verdict, reasons, syntax_valid, is_disposable, disposable_source, is_free_provider, is_role_account, did_you_mean, mx_status, mx_host. reasons é separado por ponto e vírgula, as células vazias significam null e mx_status fica vazio para endereços sintaticamente inválidos (nada foi consultado). Um endereço inválido que comece por =, +, - ou @ é precedido de um apóstrofo para que as folhas de cálculo não o executem como fórmula. 409 até a tarefa estar concluída, 410 depois de expirar. A transferência não é cobrada.
Pedido
curl https://api.watch-ip.com/v1/email/jobs/5b0d6f5e-8a51-4f7e-9d0e-2c1f3f7f8a11/results \
-H "Authorization: Bearer YOUR_SECRET_KEY" -o results.csvVerificação de registo
POST/v1/signup/check
Pontua um registo a partir do endereço de e-mail e do IP numa única chamada, a partir do seu back-end quando o formulário de registo é submetido (um veredicto calculado no navegador pode ser falsificado). Envie { "email": "...", "ip": "...", "userAgent": "..." } — userAgent é opcional. A resposta contém o resultado completo da verificação de e-mail (email), o país e o ASN do IP e — nos planos que incluem dados de segurança — os seus indicadores de VPN/Tor/centro de dados/ameaça (ip), a idade do domínio do e-mail em dias segundo os dados públicos de registo (RDAP) (emailDomainAgeDays, null quando desconhecida e para os grandes fornecedores de consumo), uma pontuação de 0 a 100 (a soma dos pesos dos motivos abaixo, com máximo de 100) e um veredicto: reject a partir de 60, review a partir de 25, caso contrário accept. Num plano sem dados de segurança, ip.security é null, a pontuação usa apenas os sinais do e-mail e reasons inclui ip_security_unavailable. Conta como um pedido. Apenas com chave secreta.
- invalid_syntax
- 70
- domain_not_found · no_mail_server · disposable_domain
- 60 cada
- ip_tor · ip_threat
- 40 cada
- ip_vpn
- 25
- new_domain
- 25 — o domínio do e-mail foi registado há menos de 30 dias
- ip_datacenter
- 20 — apenas quando o IP não é já uma saída de VPN ou Tor
- automated_user_agent
- 20 — o userAgent fornecido parece um bot ou script
- typo_suspected
- 15
- role_account · implicit_mx
- 10 cada
- dns_unavailable
- 5
- ip_security_unavailable
- 0 — informativo: este plano não inclui dados de segurança
Pedido
curl https://api.watch-ip.com/v1/signup/check \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "jane@new-startup.io", "ip": "203.0.113.1"}'Resposta
{
"email": { "email": "jane@new-startup.io", "verdict": "accept", "reasons": [], ... },
"ip": {
"ip": "203.0.113.1",
"country": "US",
"asn": 64500,
"asOrganization": "Example Hosting",
"security": { "isTor": false, "isVpn": false, "isDatacenter": true, "isThreat": false, "isSanctionedNetwork": false }
},
"emailDomainAgeDays": 12,
"score": 45,
"verdict": "review",
"reasons": ["new_domain", "ip_datacenter"]
}Limites
Cada endereço verificado conta como um pedido no limite mensal partilhado do seu plano — uma verificação individual, cada endereço de um lote, cada endereço distinto de uma tarefa de lista — e uma verificação de registo é um pedido. Os lotes e as tarefas de lista são admitidos ou rejeitados na totalidade, nunca executados parcialmente. O limite de taxa por minuto conta chamadas HTTP, não itens: um lote de até 100 IP ou endereços de e-mail conta como um único pedido, enquanto cada item continua a contar separadamente para o limite mensal de pedidos. Os carregamentos e resultados das tarefas de lista são eliminados 7 dias após a criação da tarefa. As consultas DNS têm um orçamento de tempo curto: quando uma falha ou excede o tempo limite, o resultado degrada-se para mx.status unknown e motivo dns_unavailable em vez de um erro. Os dados de domínios descartáveis resultam da fusão de três listas de código aberto mantidas pela comunidade, atualizadas de poucas em poucas horas e complementadas com os servidores de correio observados a servir domínios listados — consulte fontes de dados. Um fornecedor descartável muito recente pode ainda não ser assinalado. Todas as verificações são ao nível do domínio e do endereço: nenhuma caixa de correio é contactada, pelo que nenhum resultado estabelece que uma caixa de correio existe, quem é o titular ou que o correio lá chegará.
Páginas relacionadas
- AutenticaçãoChaves publicáveis vs. secretas, bloqueio por origem, e limites de taxa.
- Referência de GET /v1/geoReferência completa de campos para o endpoint de geolocalização de visitante.
- Deteção de e-mail descartávelAssinale e-mails de registo descartáveis, mal escritos ou sem servidor de correio, um a um ou em lote.
- Prevenção de abuso de registoCombine sinais do e-mail e do IP numa decisão de registo: aceitar, rever ou rejeitar.
- Fontes de dadosQue fonte sustenta cada campo de resposta, e as suas lacunas conhecidas.