Watch-IP

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

email
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.csv

Resposta

{
  "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.csv

Verificaçã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