Watch-IP

API-Referenz zur E-Mail-Prüfung

POST/v1/email/validate

Prüft eine E-Mail-Adresse: Syntax, bekannte Wegwerf-/Temporär-Domains, den Mailserver (MX) der Domain, wahrscheinliche Tippfehler und Funktionsadressen, und liefert ein Urteil accept/review/reject samt Gründen. Senden Sie einen JSON-Body { "email": "user@example.com" }. Gedacht für den Aufruf aus dem JavaScript eines Registrierungsformulars, mit demselben Modell aus veröffentlichbarem, Origin-gebundenem Schlüssel wie GET /v1/geo. Für viele Adressen oder eine serverseitige Registrierungsentscheidung nutzen Sie die weiter unten beschriebenen Endpoints für Batch, Listenjobs und Registrierungsprüfung. Alle Prüfungen erfolgen auf Domain- und Adressebene: Kein Postfach wird kontaktiert, daher belegt kein Ergebnis, dass ein Postfach existiert, wem es gehört oder dass E-Mails dort ankommen.

Authentifizierung

POST /v1/email/validate akzeptiert einen veröffentlichbaren, Origin-gebundenen Schlüssel im Header X-Api-Key – derselbe Schlüsseltyp und dasselbe Modell erlaubter Origins wie bei GET /v1/geo. Alle anderen Endpoints auf dieser Seite (Batch, Listenjobs, Registrierungsprüfung) akzeptieren viele Adressen oder eine beliebige IP, erfordern daher Ihren geheimen Schlüssel über Authorization: Bearer und dürfen nur aus Ihrem Backend aufgerufen werden; ein veröffentlichbarer Schlüssel erhält dort eine 403.

Antwortfelder

email
Die gesendete Adresse, exakt so zurückgegeben, wie sie übermittelt wurde.
domain
Die Domain in Kleinbuchstaben (internationalisierte Domains in Punycode) oder null, wenn syntaxValid false ist.
syntaxValid
Ob die Adresse syntaktisch gültig ist. Keine Prüfung auf Existenz des Postfachs oder Zustellbarkeit.
isDisposable
Ob die Domain einem bekannten Wegwerf-/Temporär-E-Mail-Anbieter entspricht – direkt, über eine übergeordnete Domain oder über einen Mailserver, der bekanntermaßen Wegwerf-Domains bedient. Immer false, wenn syntaxValid false ist.
normalizedEmail
Bereinigte Adresse in Kleinbuchstaben mit der Domain in Punycode oder null, wenn syntaxValid false ist.
canonicalEmail
normalizedEmail ohne +Tag (bei Gmail zusätzlich ohne Punkte und mit googlemail.com auf gmail.com abgebildet) – speichern Sie den Wert, um dieselbe Person bei einer zweiten Registrierung zu erkennen. Null, wenn syntaxValid false ist.
disposableSource
Warum isDisposable true ist: list (die Domain selbst steht auf der Liste), parent_domain (eine übergeordnete Domain steht auf der Liste, z. B. a.b.mailinator.com) oder mx_host (der Mailserver der Domain bedient bekannte Wegwerf-Domains). Null, wenn isDisposable false ist.
isFreeProvider
Ob die Domain ein Postfachanbieter für Endkunden wie gmail.com oder outlook.com ist. Nur zur Information – ändert nie das Urteil.
isRoleAccount
Ob der lokale Teil eine Funktionsadresse wie admin@, info@ oder noreply@ ist.
didYouMean
Eine wahrscheinliche Tippfehlerkorrektur der gesamten Adresse (john@gmial.com → john@gmail.com) oder null. Eine Domain mit eigenem funktionierendem Mailserver wird nur „korrigiert“, wenn sie eine Änderung von einem gängigen Anbieter entfernt ist.
mx.status
found (MX-Einträge vorhanden), implicit (kein MX, aber ein A/AAAA-Eintrag), none (keines von beiden), null_mx (die Domain erklärt, keine E-Mails anzunehmen), no_domain (die Domain existiert nicht) oder unknown (die Abfrage ist fehlgeschlagen oder hat das Zeitlimit überschritten). Das gesamte mx-Objekt ist null, wenn syntaxValid false ist.
mx.host
Der MX-Host mit der niedrigsten Präferenz, wenn status found ist, sonst null. Sagt nichts darüber aus, ob das einzelne Postfach existiert.
verdict
accept, review oder reject – die schwerwiegendste der Bedingungen in reasons. Eine Empfehlung für Ihre eigene Richtlinie, keine endgültige Entscheidung.
reasons
Jede zutreffende Bedingung, die schwerwiegendste zuerst; leer, wenn verdict accept ist. Siehe „Urteile und Grundcodes“ weiter unten.

Fehler

400
Fehlerhafter Anfrage-Body. Batch: empty_batch oder batch_too_large (mehr als 100 Adressen). Registrierungsprüfung: invalid_ip. Listenjobs: invalid_body, empty_job oder job_too_large (mehr als 100.000 Adressen). Eine ungültige E-Mail-Adresse ist nie eine 400 – sie ist ein Ergebnis mit dem Urteil reject und dem Grund invalid_syntax.
401
Fehlender oder ungültiger API-Schlüssel.
403
POST /v1/email/validate: Origin/Referer der Anfrage steht nicht auf der Liste erlaubter Origins des Schlüssels (es wird kein CORS-Header gesetzt, daher blockiert der Browser die Antwort unabhängig vom JSON-Body). Endpoints mit geheimem Schlüssel: Es wurde ein veröffentlichbarer Schlüssel verwendet.
404
job_not_found – kein Listenjob mit dieser ID in Ihrem Konto.
409
job_not_completed – der Job ist noch in der Warteschlange oder in Bearbeitung oder ist fehlgeschlagen; Ergebnisse können erst nach Abschluss heruntergeladen werden.
410
job_expired – die hochgeladenen Adressen und Ergebnisse des Jobs wurden gelöscht (7 Tage nach der Erstellung).
413
body_too_large – ein CSV-Upload für einen Job, der größer als 10 MB ist.
415
Ein Listenjob-Body, der weder JSON noch text/csv ist.
429
Die Ratenbegrenzung pro Minute oder monthly_limit_exceeded, wenn das monatliche Anfragekontingent des Tarifs überschritten würde – siehe Fehler und Ratenbegrenzungen, um beides zu unterscheiden. Ein Batch oder Listenjob, der das Kontingent überschreiten würde, wird vollständig abgelehnt, bevor irgendetwas verarbeitet wird.
503
job_storage_unavailable – ein Listenjob konnte nicht gespeichert werden. Es wurde nichts berechnet; versuchen Sie es erneut.

Beispiel

Anfrage

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"}'

Antwort

{
  "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"
  ]
}

Urteile und Grundcodes

Jede Bedingung setzt ein Mindesturteil; die schwerwiegendste gewinnt, und reasons listet alle auf, die schwerwiegendste zuerst. Ob eine Adresse eines Freemail-Anbieters akzeptabel ist, entscheiden Sie – das Urteil ändert sich dadurch nie.

invalid_syntax
Reject. Die Adresse ist syntaktisch ungültig (Längengrenzen, erlaubte Zeichen, Position der Punkte, eine echte Domain statt eines IP-Literals). Auch lokale Teile in Anführungszeichen werden abgelehnt – zulässig, aber bei Registrierungen praktisch nie verwendet.
domain_not_found
Reject. Die Domain existiert nicht im DNS.
no_mail_server
Reject. Die Domain erklärt, keine E-Mails anzunehmen (ein „Null-MX“), oder hat weder MX- noch A/AAAA-Einträge.
disposable_domain
Reject. Die Domain, eine übergeordnete Domain oder der Mailserver der Domain entspricht bekannten Wegwerf-/Temporär-E-Mail-Anbietern – siehe disposableSource.
typo_suspected
Review. didYouMean enthält eine wahrscheinliche Korrektur, etwa gmial.com → gmail.com.
role_account
Review. Der lokale Teil ist eine Funktionsadresse wie admin@, info@, support@ oder noreply@, die meist gemeinsam statt persönlich genutzt wird.
implicit_mx
Review. Die Domain hat keinen MX-Eintrag; E-Mails würden auf ihre A/AAAA-Adresse zurückfallen, was bei echten Mail-Domains selten ist.
dns_unavailable
Review. Die DNS-Abfrage ist fehlgeschlagen oder hat das Zeitlimit überschritten, daher ist die Mail-Konfiguration der Domain unbekannt (mx.status: unknown). Kein Indiz gegen die Adresse.

Batch-Prüfung

POST/v1/email/batch

Prüft 1–100 Adressen in einer Anfrage mit denselben Prüfungen und derselben Ergebnisform wie POST /v1/email/validate, ein Ergebnis pro Adresse in Eingabereihenfolge. Senden Sie { "emails": [...] }. Adressen derselben Domain teilen sich eine DNS-Abfrage. Zählt eine Anfrage pro Adresse gegen Ihr monatliches Tarifkontingent; ein Batch, der das Kontingent überschreiten würde, wird vollständig mit 429 monthly_limit_exceeded abgelehnt. Für die Ratenbegrenzung pro Minute zählt der gesamte Aufruf als eine Anfrage. Nur mit geheimem Schlüssel.

Anfrage

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"]}'

Antwort

{
  "results": [
    { "email": "user@gmail.com", "verdict": "accept", "reasons": [], ... },
    { "email": "someone@mailinator.com", "isDisposable": true, "disposableSource": "list", "verdict": "reject", "reasons": ["disposable_domain"], ... }
  ]
}

E-Mail-Listenjobs

POST/v1/email/jobs

Prüft bis zu 100.000 Adressen im Hintergrund. Senden Sie JSON { "emails": [...], "filename": "..." } oder einen text/csv-Body von höchstens 10 MB: Verwendet wird die Spalte mit der Überschrift email (auch e-mail, email address, email_address oder mail, ohne Beachtung der Groß-/Kleinschreibung) oder die erste Spalte, wenn keine Überschrift eine solche benennt; Komma, Semikolon und Tabulator als Trennzeichen werden erkannt. Der Job wird bei der Erstellung berechnet – eine Anfrage pro eindeutiger Adresse (exakte Übereinstimmung), Duplikate werden also geprüft, aber nur einmal berechnet – und eine Liste, die Ihr Monatskontingent überschreiten würde, wird vollständig abgelehnt. Kann ein Teil eines Jobs auch nach Wiederholungen nicht verarbeitet werden, wird der Job als failed markiert und die Credits für den nicht verarbeiteten Teil werden erstattet. Antwortet mit 202 und dem Job-Objekt. Nur mit geheimem Schlüssel; dieselben Jobs lassen sich auch auf der Dashboard-Seite Email lists hoch- und herunterladen.

Anfrage

curl https://api.watch-ip.com/v1/email/jobs \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -H "Content-Type: text/csv" \
  --data-binary @newsletter.csv

Antwort

{
  "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"
}

Job-Status

GET/v1/email/jobs/{id}

Gibt dasselbe Job-Objekt zurück. Fragen Sie es ab, bis status completed ist; Abfragen werden nicht berechnet.

status
queued → processing → completed. failed: Ein Teil der Liste konnte auch nach Wiederholungen nicht verarbeitet werden; es sind keine Ergebnisse verfügbar und die Credits für den nicht verarbeiteten Teil wurden erstattet. expired: Die hochgeladenen Adressen und Ergebnisse wurden 7 Tage nach der Erstellung gelöscht.
total
Übermittelte Zeilen, einschließlich Duplikaten.
credits
Berechnete Anfragen: eine pro eindeutiger Adresse.
processed
Bisher geprüfte Zeilen.
summary
Nach Abschluss: Zeilenanzahl pro Urteil (accept/review/reject) und pro aufgetretenem Grundcode. Vorher null.
expiresAt
Zeitpunkt, zu dem die hochgeladenen Adressen und Ergebnisse gelöscht werden.

Job-Ergebnisse

GET/v1/email/jobs/{id}/results

Lädt eine CSV-Datei mit einer Zeile pro übermittelter Zeile herunter, in Übermittlungsreihenfolge – einschließlich Duplikaten. Spalten: 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 ist durch Semikolons getrennt, leere Zellen bedeuten null, und mx_status ist bei syntaktisch ungültigen Adressen leer (es wurde nichts abgefragt). Einer ungültigen Adresse, die mit =, +, - oder @ beginnt, wird ein Apostroph vorangestellt, damit Tabellenkalkulationen sie nicht als Formel ausführen. 409, bis der Job abgeschlossen ist, 410, sobald er abgelaufen ist. Der Download wird nicht berechnet.

Anfrage

curl https://api.watch-ip.com/v1/email/jobs/5b0d6f5e-8a51-4f7e-9d0e-2c1f3f7f8a11/results \
  -H "Authorization: Bearer YOUR_SECRET_KEY" -o results.csv

Registrierungsprüfung

POST/v1/signup/check

Bewertet eine Registrierung anhand von E-Mail-Adresse und IP in einem Aufruf, aus Ihrem Backend beim Absenden des Registrierungsformulars (ein im Browser berechnetes Urteil kann gefälscht werden). Senden Sie { "email": "...", "ip": "...", "userAgent": "..." } – userAgent ist optional. Die Antwort enthält das vollständige Ergebnis der E-Mail-Prüfung (email), Land und ASN der IP sowie – in Tarifen mit Sicherheitsdaten – ihre VPN-/Tor-/Rechenzentrums-/Bedrohungsindikatoren (ip), das Alter der E-Mail-Domain in Tagen laut öffentlichen Registrierungsdaten (RDAP) (emailDomainAgeDays, null wenn unbekannt und bei bekannten Endkunden-Anbietern), einen Score von 0–100 (die Summe der unten aufgeführten Gewichte der Gründe, begrenzt auf 100) und ein Urteil: reject ab 60, review ab 25, sonst accept. In einem Tarif ohne Sicherheitsdaten ist ip.security null, der Score nutzt nur die E-Mail-Signale und reasons enthält ip_security_unavailable. Zählt als eine Anfrage. Nur mit geheimem Schlüssel.

invalid_syntax
70
domain_not_found · no_mail_server · disposable_domain
je 60
ip_tor · ip_threat
je 40
ip_vpn
25
new_domain
25 – die E-Mail-Domain wurde vor weniger als 30 Tagen registriert
ip_datacenter
20 – nur wenn die IP nicht bereits ein VPN- oder Tor-Exit ist
automated_user_agent
20 – der übergebene userAgent sieht nach einem Bot oder Skript aus
typo_suspected
15
role_account · implicit_mx
je 10
dns_unavailable
5
ip_security_unavailable
0 – zur Information: Dieser Tarif enthält keine Sicherheitsdaten

Anfrage

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"}'

Antwort

{
  "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"]
}

Limits

Jede geprüfte Adresse zählt als eine Anfrage gegen das gemeinsame Monatskontingent Ihres Tarifs – eine Einzelprüfung, jede Adresse in einem Batch, jede eindeutige Adresse in einem Listenjob – und eine Registrierungsprüfung ist eine Anfrage. Batches und Listenjobs werden vollständig angenommen oder abgelehnt, nie teilweise ausgeführt. Die Ratenbegrenzung pro Minute zählt HTTP-Aufrufe, nicht Einträge: Ein Batch mit bis zu 100 IPs oder E-Mail-Adressen zählt als eine Anfrage, während jeder Eintrag weiterhin einzeln auf das monatliche Anfragekontingent angerechnet wird. Uploads und Ergebnisse von Listenjobs werden 7 Tage nach Erstellung des Jobs gelöscht. DNS-Abfragen haben ein kurzes Zeitbudget: Schlägt eine fehl oder überschreitet sie das Zeitlimit, fällt das Ergebnis auf mx.status unknown und den Grund dns_unavailable zurück statt auf einen Fehler. Die Daten zu Wegwerf-Domains werden aus drei von der Community gepflegten Open-Source-Listen zusammengeführt, alle paar Stunden aktualisiert und um Mailserver ergänzt, die nachweislich gelistete Domains bedienen – siehe Datenquellen. Ein sehr neuer Wegwerf-Anbieter wird möglicherweise noch nicht erkannt. Alle Prüfungen erfolgen auf Domain- und Adressebene: Kein Postfach wird kontaktiert, daher belegt kein Ergebnis, dass ein Postfach existiert, wem es gehört oder dass E-Mails dort ankommen.

Verwandte Seiten