Email Spam Tester

Spamcheck-API voor e-mail,
inbox en domein

Stuur ons één echt bericht, of geef ons alleen een domein. Alles wordt beantwoord in JSON.

Geen sleutel, geen account.

Verzoek

# reserve a single-use address

$ curl -sX POST '.../api/v1/inbox?lang=en'

# send your message to that address, then

$ curl -s '.../api/v1/tests/k7m2x9qplw4tz8vn3b6c/status'

# read the report

$ curl -s '.../api/v1/tests/k7m2x9qplw4tz8vn3b6c'

Antwoord

200 OK

{
  "address": "test-k7m2x9qplw4tz8vn3b6c@t.email-spam-tester.com",
  "slug": "k7m2x9qplw4tz8vn3b6c",
  "expires_at": "2026-10-31T13:00:00Z"
}

200 OK

{
  "analysis_status": "checks_ready",
  "ai_status": "running",
  "checks_done": 42,
  "checks_total": 42
}

200 OK

{
  "score_ours": 86.4,
  "score_compat": 9.2,
  "subscores": {"auth": 100.0, "infra_spam": 78.1, "content": 92.0},
  "complete": true,
  "checks": [{"id": "auth.dmarc", "status": "warn"}],
  "fixes": [{"id": "dmarc-enforce", "gain_ours": 4.0}]
}

Verzoek

# create a test

$ curl -sX POST '.../api/v1/placement' \ -d '{"public_results_accepted":true}'

# put the marker in the subject, send once to all, then

$ curl -s '.../api/v1/placement/wR3kP9xLq2vT8mZc'

Antwoord

201 Created

{
  "marker": "est-3f9a1c7e2b4d6a80c5e1f2d3",
  "status": "waiting",
  "results": [{"provider": "gmail", "placement": "pending"}],
  "fleet": {"status": "observing", "results": [
    {"provider": "yahoo", "placement": "pending"},
    {"provider": "outlook", "placement": "pending"}
  ]}
}

200 OK

{
  "status": "complete",
  "results": [{"provider": "gmail", "placement": "primary"}],
  "fleet": {"status": "finished", "results": [
    {"provider": "yahoo", "placement": "inbox"},
    {"provider": "outlook", "placement": "spam"}
  ]}
}

Verzoek

# no email needed, one GET

$ curl -s '.../api/v1/infra/check?domain=example.com'

# compare with your last run

$ curl -s '.../api/v1/infra/check?domain=example.com&diff=true' \ | jq '.diff'

Antwoord

200 OK

{
  "domain": "example.com",
  "ok": false,
  "status": "fail",
  "score": 78,
  "coverage": {"answered": 7, "total": 8},
  "sections": {"ptr": {"status": "fail", "core": true}}
}

200 OK

{
  "changed": true,
  "worsened": true,
  "status_from": "pass",
  "score_from": 100,
  "changes": [{"path": "dkim.key.mail.sha256", "kind": "removed",
               "severity": "critical", "effect": "worsened"}]
}
Op deze pagina

E-mailtest

We lezen één echt bericht volledig uit: inhoud, handtekening, headers en de server die het heeft verstuurd. Je krijgt een score, een lijst met oplossingen en elke onderliggende controle.

Snel aan de slag

Drie aanroepen. Geen sleutel, geen account, geen registratie. Twee verzoeken en één e-mail. De derde aanroep is alleen nodig omdat de analyse enkele seconden duurt.

  1. Reserveer een adres

    Stuur een POST-verzoek naar het inbox-endpoint. Je krijgt een adres terug dat precies één bericht accepteert en na een uur verloopt, plus de slug waaraan al het andere is gekoppeld.

    Verzoek

    # 1. reserve a single-use address
    curl -sX POST 'https://email-spam-tester.com/api/v1/inbox?lang=en'

    Antwoord

    {
      "address": "test-<slug>@t.email-spam-tester.com",
      "slug": "<slug>",
      "expires_at": "2026-01-01T12:00:00Z"
    }
  2. Stuur het echte bericht ernaartoe

    Via SMTP, vanaf het platform dat de campagne zal verzenden. De helft van de controles leest headers die je verzendplatform toevoegt, dus een handmatig opgesteld bericht meet het verkeerde.

    Verzoek

    # 2. send your message to that address, from your own platform
    To: test-<slug>@t.email-spam-tester.com
  3. Poll de status en lees daarna het rapport

    Het status-endpoint is enkele honderden bytes groot en vertelt je of het volledige rapport al kan worden opgehaald. Het rapport zelf beslaat enkele duizenden regels.

    Verzoek

    # 3. poll
    curl -s 'https://email-spam-tester.com/api/v1/tests/<slug>/status'

    Antwoord

    {
      "slug": "<slug>",
      "analysis_status": "checks_ready",
      "ai_status": "running",
      "checks_done": 42,
      "checks_total": 42
    }

    Verzoek

    # 4. read the report once analysis_status is checks_ready
    curl -s 'https://email-spam-tester.com/api/v1/tests/<slug>'

    Antwoord

    {
      "report_url": "https://email-spam-tester.com/t/<slug>",
      "score_ours": 86.4,
      "score_compat": 9.2,
      "subscores": {"auth": 100.0, "infra_spam": 78.1, "content": 92.0, "compliance": 75.0},
      "complete": true,
      "checks": [
        {
          "id": "auth.dmarc",
          "status": "warn",
          "title": "DMARC result",
          "summary": "DMARC passes, but the policy is p=none.",
          "weight_ours": -4.0,
          "evidence": {"policy": "none", "aligned": "dkim"},
          "citations": {"standards": [{"title": "RFC 9989 §4.7", "quote": "..."}]}
        }
      ],
      "fixes": [
        {"id": "dmarc-enforce", "gain_ours": 4.0, "gain_compat": 0.0,
         "fix": {"title": "Move DMARC to quarantine", "severity": "medium"}}
      ]
    }

Reserveer een adres, stuur het bericht dat je naar je lijst wilde verzenden en lees het rapport. Alles wat de pagina toont, staat in de JSON, inclusief de score, alle 42 controles met het bijbehorende bewijs en de sectie van de standaard waarop elke bevinding berust.

De eerste 100.000 rapporten zijn gratis, zonder sleutel en zonder account. Als je een agent in plaats van een script integreert, is de MCP-server geschikter dan polling.

Endpoints

Basisadres https://email-spam-tester.com. Alles retourneert JSON.

POST/api/v1/inbox

Reserveert een adres voor eenmalig gebruik. Beide parameters zijn optioneel.

langTaal waarin het verbeterplan en de bevindingen per controle worden geschreven, als ISO-code. Wordt nu bepaald omdat het bericht minuten later via SMTP binnenkomt en geen aanwijzing bevat over wie erop wacht. Bij een onbekende code wordt teruggevallen op Engels.
utm_source, utm_medium, utm_campaignWorden doorgegeven aan onze analytics. Nuttig als je je eigen integratie meet.

GET/api/v1/tests/{slug}/status

Goedkoop om te pollen. Retourneert de twee statusvelden en hoe ver de controles zijn gevorderd, en verder niets.

Poll dit in plaats van het rapport. analysis_status bereikt eerst checks_ready, en het AI-plan verschijnt ongeveer een minuut later onder ai_status, zodat een aanroeper die alleen de deterministische controles wil, niet op het plan hoeft te wachten.

GET/api/v1/tests/{slug}

Het volledige rapport. Retourneert 202 zolang het adres is gereserveerd en er nog niets is binnengekomen, en 200 zodra dat wel het geval is.

GET/api/v1/tests/{slug}/message

Het bericht precies zoals het is afgeleverd: elke header in transmissievolgorde, beide berichtteksten, de lijst met bijlagen en de onbewerkte bron. Wordt afzonderlijk opgehaald omdat het rapport wordt gepolld en dit tot een megabyte groot kan zijn.

Het onbewerkte bericht wordt volgens een eigen tijdschema verwijderd, eerder dan het rapport. Daarna antwoordt dit endpoint met de reden in plaats van de bron.

PUT/api/v1/tests/{slug}/locale

Wijzigt de taal van een reservering die nog niet is gebruikt. Voor een agent die pas ontdekt welke taal zijn gebruiker leest nadat deze al om het adres heeft gevraagd. Wordt geweigerd zodra het bericht is aangekomen, omdat de analyse dan al wordt uitgevoerd.

InboxplaatsingBèta

Stuur één bericht naar een lijst met testinboxen en bekijk waar het bij Gmail, Outlook, Yahoo en andere providers terechtkwam: Inbox, Reclame of Spam.

Snel aan de slag

  1. Maak een test

    Stuur een POST naar het plaatsingseindpunt. Je krijgt een markering en de testinboxen terug.

    Verzoek

    # 1. create a test
    curl -sX POST 'https://email-spam-tester.com/api/v1/placement' \
      -H 'Content-Type: application/json' \
      -d '{"public_results_accepted":true}'

    Antwoord

    {
      "slug": "<slug>",
      "marker": "est-3f9a1c7e2b4d6a80c5e1f2d3",
      "status": "waiting",
      "deadline": "2026-10-31T12:30:00Z",
      "poll_after_seconds": 60,
      "results": [
        {"address": "<seed>", "provider": "gmail", "kind": "Gmail",
         "placement": "pending", "observed_at": null}
      ],
      "fleet": {
        "status": "observing",
        "results": [
          {"address": "<mailbox>", "provider": "yahoo", "available": true,
           "placement": "pending", "coverage": "pending"}
        ]
      }
    }
  2. Stuur één bericht naar elke inbox

    Zet de markering in het onderwerp en stuur het vanaf je normale platform in één keer naar alle adressen.

    Verzoek

    # 2. one message to every address, with the marker in the subject
    Subject: October invoice est-3f9a1c7e2b4d6a80c5e1f2d3
    To: <seed>, <mailbox>, ...
  3. Vraag de mappen op

    Bij elk adres worden de provider en map ingevuld. Blijf opvragen totdat de status niet meer waiting is.

    Verzoek

    # 3. poll for the folders
    curl -s 'https://email-spam-tester.com/api/v1/placement/<slug>'

    Antwoord

    {
      "status": "complete",
      "received": 2,
      "total": 2,
      "results": [
        {"address": "<seed>", "provider": "gmail", "kind": "Gmail",
         "placement": "primary", "observed_at": "2026-10-31T12:04:11Z"},
        {"address": "<seed>", "provider": "gmail", "kind": "Google Workspace",
         "placement": "promotions", "observed_at": "2026-10-31T12:04:11Z"}
      ],
      "fleet": {
        "status": "finished",
        "results": [
          {"address": "<mailbox>", "provider": "yahoo", "available": true,
           "placement": "inbox", "coverage": "ok"},
          {"address": "<mailbox>", "provider": "outlook", "available": true,
           "placement": "spam", "coverage": "ok"}
        ]
      }
    }

Endpoints

An optional test using public GMass seed inboxes and available project test mailboxes, alone or alongside the email score. Explain to the sender that GMass receives their email and publishes its subject, sender name and placement before creating a test. Use all test mailboxes for non-confidential test messages only.

GET /api/v1/placement/availability

Returns providers: the provider identifiers of currently healthy, admitted project mailboxes. No addresses or credentials are exposed. This read does not create a test or contact GMass. Actual recipients are allocated at creation and may differ as availability or capacity changes.

POST /api/v1/placement

Send JSON {"public_results_accepted":true}. Returns HTTP 201 with slug, marker, results (the seed addresses), deadline and expires_at. Limit: 20 tests per IP per UTC day.

For one-send combined testing, first reserve an email score address and include its score_slug in the placement creation JSON. Repeated creation for that score returns the same placement test. Send the marked email to the score address, every returned seed and every available fleet.results address; keep the main /t/<score_slug> report link. Creating a link after the score address was used or expired returns HTTP 409.

GET /api/v1/placement/by-score/{score_slug}

Read and refresh the placement run attached to the main email test. The response has the same format and polling limits as the standalone endpoint below. HTTP 404 means placement was not included or its stored results have been removed.

GET /api/v1/placement/{slug}

Use poll_after_seconds (normally 60 seconds) while the page is open. Upstream errors trigger a shared cooldown. Add the marker to the subject and send through the sender's normal platform to every seed. Observations are saved for 30 days. Collection ends after 30 minutes or when all seeds have results.

status: waiting, complete or timed_out. Each result has an address, provider, kind, placement and observed_at. Placement is primary, promotions, inbox, updates, social, forums, spam, unknown, pending or not_observed. Missing results do not mean Spam; Promotions is an inbox category. provider_error indicates an upstream outage without discarding saved observations. HTTP 404 means unknown, 410 expired, 429 quota exhausted, and 503 no test inboxes available at creation.

The optional fleet object contains independently collected project mailbox results, with status observing, settling or finished. Refresh every 30 seconds until it finishes, even when Gmail has completed. Each fleet result includes address, provider, available, placement, category and coverage. Exclude unavailable addresses from new sends; retain their saved observations. Category data may be unavailable even when the physical folder is known.

If GMass is unavailable at creation but project mailboxes can be allocated, provider is fleet and the top-level seed results are empty. Use fleet.results; do not interpret an empty Gmail list as successful delivery. Existing runs never gain new recipient addresses silently.

Infrastructuurcontrole

Eén GET-verzoek controleert de e-mailconfiguratie van een domein zonder iets te verzenden, bewaart het resultaat en vertelt je wat er sinds je vorige uitvoering is veranderd. Geen sleutel nodig. In cron eindigt de onderstaande regel met een niet-nulstatus wanneer het domein defect is of de configuratie ervan op een relevante manier is gewijzigd.

Snel aan de slag

  1. Doe één GET

    Geef het domein door. ip voegt je verzendadressen toe, en selector noemt de DKIM-selectors die moeten worden gelezen.

    Verzoek

    curl -s 'https://email-spam-tester.com/api/v1/infra/check?domain=example.com&selector=mail&diff=true'
  2. Lees het oordeel

    ok is het antwoord voor een script, en sections laat zien welk onderdeel is mislukt.

    Antwoord

    {
      "id": "ir_01JB8Y4T2M6K9QZ7H3V5N1XWDA",
      "domain": "example.com",
      "checked_at": "2026-10-31T12:00:00Z",
      "ok": false,
      "status": "fail",
      "score": 78,
      "coverage": {"answered": 7, "total": 8},
      "ips": [{"ip": "203.0.113.5", "sources": ["mx", "spf"], "managed": false}],
      "sections": {
        "dkim": {"status": "pass", "core": true, "findings": [], "data": {}},
        "ptr": {"status": "fail", "core": true, "findings": [], "data": {}}
      },
      "not_checked": [
        {"check": "dkim_signature", "reason": "needs_a_message"},
        {"check": "alignment", "reason": "needs_a_message"}
      ],
      "diff": {
        "baseline": {"id": "ir_01JB2...", "checked_at": "2026-10-24T12:00:00Z"},
        "first_run": false,
        "changed": true,
        "worsened": true,
        "status_from": "pass",
        "score_from": 100,
        "changes": [
          {"path": "dkim.key.mail.sha256", "section": "dkim", "kind": "removed",
           "severity": "critical", "effect": "worsened", "from": "9f2c...", "to": null}
        ],
        "not_compared": [
          {"path": "blocklist_ip.203.0.113.5.bl.spamcop.net.listed", "reason": "lookup_failed"}
        ]
      }
    }
  3. Zet het in cron

    Met diff=true wordt elke uitvoering vergeleken met je vorige, en jq zet het antwoord om in een afsluitcode.

    Verzoek

    # exits non-zero if the domain is broken or its setup changed
    curl -s 'https://email-spam-tester.com/api/v1/infra/check?domain=example.com&selector=mail&diff=true' \
      | jq -e '.ok and (.diff.changed | not)'
domainVereist. Accepteert wat de tools accepteren: een domein, een URL, een e-mailadres.
ipJe verzendadres. Herhaal dit voor meer adressen, tot maximaal 6.
selectorEen DKIM-selector. Herhaal dit voor meer selectors, tot maximaal 10. Elke selector die je doorgeeft moet bestaan, anders mislukt de DKIM-sectie.
heloDe naam die je server opgeeft in HELO, vergeleken met zijn PTR.
accountVoor wie het verzoek is. Vereist bij een sleutel die voor veel mensen wordt gebruikt.
checksUit te voeren secties, door komma's gescheiden. Standaard allemaal.
difftrue vergelijkt deze uitvoering met je laatste uitvoering van het domein.
since7d, 12h of een ISO 8601-datum. Vergelijkt met je uitvoering die binnen 12 uur het dichtst bij dat moment ligt, anders met de laatste uitvoering ervoor. Schakelt diff in.
baselineDe id van een van je uitvoeringen om mee te vergelijken. Schakelt diff in.
freshtrue slaat de cache van 60 seconden over.

Het antwoord lezen

Een voltooide controle antwoordt met 200 en het oordeel staat in de body. status is de slechtste van de vereiste secties: spf, dkim, dmarc, ptr, blocklist_ip, blocklist_domain, mx en smtp. unknown in een vereiste sectie telt als warn. ok is true wanneer de status pass of warn is. score loopt van 0 tot 100 over de vereiste secties die een antwoord gaven en is null wanneer er door errors en unknowns minder dan de helft van het toepasselijke gewicht overblijft. mta_sts, tls_rpt, bimi, dnssec, dane, ns en registration worden gerapporteerd en vergeleken, maar hebben geen invloed op ok of score.

Een sectie kan pass, warn, fail, error (we konden de controle niet uitvoeren), unknown (te weinig informatie) of skipped (niet van toepassing) zijn. skipped heeft geen invloed op het resultaat en de reden staat in not_checked. dkim_signature en alignment zijn er altijd, omdat ze een echt bericht nodig hebben.

Wat ip en selector veranderen

PTR en blocklists gaan over adressen, dus een run heeft er enkele nodig. De run gebruikt de ip-waarden die je doorgeeft. Zonder waarden neemt de run er maximaal vier van je MX-hosts en uit ip4:- en ip6:-termen met één adres in het SPF-record op het hoofddomein. Adressen van een bekende mailprovider worden als managed vermeld en niet gecontroleerd, en als er niets overblijft, antwoorden ptr en blocklist_ip met skipped. Een selector kan niet uit DNS worden afgeleid, dus een run probeert die van jou, de selectors die tijdens je eerdere runs zijn gevonden en een lijst met gangbare namen. Niets vinden bewijst niets en dkim antwoordt met unknown. Als je vanaf je eigen server verstuurt, geef je beide door.

Wat is veranderd

Elke vermelding in diff.changes heeft een path, een kind (added, removed, changed), een severity (critical, warning, info) en een effect (worsened, improved, neutral). Alleen critical en warning stellen diff.changed in, zodat een geroteerde DKIM-sleutel met dezelfde lengte, een nieuw MX-adres of een vernieuwd certificaat de cronregel niet laat mislukken. diff.worsened volgt het effect van elke wijziging. Bij een eerste uitvoering is er niets om mee te vergelijken, en diff.first_run geeft dat aan.

Een baseline is altijd een run van jezelf, dus als iemand anders het domein tussen twee van je runs controleert, blijft er niets verborgen. Alles wat we deze keer niet konden uitlezen, gaat naar diff.not_compared, waarbij de laatst bekende waarde behouden blijft. Dit betekent dat een wijziging die tijdens een storing is aangebracht zichtbaar wordt zodra de lookup weer werkt. Een run met een andere ip of selector blijft in dezelfde reeks en wat die run niet opvroeg, wordt ook niet vergeleken.

Waarom een geplande controle een sleutel moet gebruiken

Zonder sleutel hoort je geschiedenis bij een hash met sleutel van je IP-adres, dus eindigt die wanneer het adres verandert en delen mensen achter hetzelfde adres die geschiedenis: de run van een collega verplaatst je baseline. Met een persoonlijke API-sleutel in Authorization: Bearer volgt de geschiedenis de sleutel. Runs met een sleutel worden 365 dagen bewaard en zijn alleen met die sleutel toegankelijk. Runs zonder sleutel worden 30 dagen bewaard en zijn toegankelijk voor iedereen die de id ervan heeft.

6 requests per minuut en 50 per dag per IP, of 30 en 500 per sleutel. Daarboven is het antwoord 429 met Retry-After. Een identiek request binnen 60 seconden komt uit een cache, wordt gemarkeerd met cached: true, maakt geen run aan en telt niet mee. Het lezen van opgeslagen runs staat 120 requests per minuut per client toe. 503 met Retry-After betekent dat er te veel controles worden uitgevoerd of, bij het lezen van opgeslagen runs, dat de opslag niet beschikbaar is. 401 betekent een onjuiste sleutel. 422 bevat detail.code: invalid_domain, invalid_ip, invalid_selector, invalid_check, invalid_since, unknown_baseline of account_required.

Endpoints

GET/api/v1/infra/check

Voert de controle uit. De parameters staan in de tabel hierboven.

GET/api/v1/infra/runs/{public_id}

Eén opgeslagen uitvoering, volledig. 404 als deze niet bestaat of bij een andere sleutel hoort.

GET/api/v1/infra/domains/{domain}/runs

Jouw uitvoeringen voor een domein, nieuwste eerst: id, tijd, status, score en aantal wijzigingen. Accepteert limit (1 tot 100, standaard 30) en before, een uitvoerings-id.

GET/api/v1/infra/diff

Dezelfde vergelijking tussen twee opgeslagen uitvoeringen, ?from=<id>&to=<id>. Je hebt toegang tot beide nodig.

GET/api/v1/infra/checks

Elke sectie met het gewicht, de scoreversie en de limieten.

Afzonderlijke controles

Elke aanroep beantwoordt één vraag en bewaart geen geschiedenis. Een tool voert zelfstandig één deel van de infrastructuurcontrole uit, behalve de headertool, die een bericht leest dat je al hebt ontvangen.

Snel aan de slag

  1. Kies een controle

    Kies de tool uit de onderstaande lijst en geef het domein, het adres of het IP door waarnaar wordt gevraagd.

    Verzoek

    curl -s 'https://email-spam-tester.com/api/v1/tools/spf?domain=example.com'
  2. Lees de status en bevindingen

    Elke tool antwoordt met een status en de bijbehorende bevindingen. De velden daarna zijn afhankelijk van de tool.

    Antwoord

    {
      "tool": "spf",
      "query": {"domain": "example.com"},
      "checked_at": "2026-10-31T12:00:00Z",
      "duration_ms": 412,
      "status": "fail",
      "findings": [
        {"code": "spf.too_many_lookups", "level": "fail",
         "params": {"limit": 10, "count": 12},
         "message": "RFC 7208 §4.6.4 allows at most 10 DNS lookups, and this record needs 12, so receivers return permerror."}
      ],
      "record": "v=spf1 include:_spf.example.net ~all",
      "lookups": {"count": 12, "limit": 10, "void": 0}
    }

Endpoints

Ze antwoorden allemaal met 200, een status en een lijst met bevindingen, elk met een code en de bijbehorende parameters. De status is pass, warn, fail of error, en een tool die ook voor de infrastructuurcontrole wordt gebruikt, kan ook antwoorden met unknown of skipped. Een lookup met een time-out of een lijst die de query weigerde, telt nooit als pass. 30 verzoeken per minuut en 300 per dag per IP voor alle tools samen; daarboven is het antwoord 429 met Retry-After.

GET/api/v1/tools/spf

Het SPF-record van een domein: de syntaxis, elke gevolgde include en redirect, en hoeveel DNS-lookups de volledige boom gebruikt van de limiet van tien. Geef ?domain=example.com door.

GET/api/v1/tools/dmarc

Het DMARC-record van een domein, of van het organisatiedomein als het zelf geen record heeft: de tags, het beleid en of elk extern rapportadres ermee heeft ingestemd rapporten te ontvangen. Geef ?domain=example.com door.

GET/api/v1/tools/dkim

De DKIM-sleutel die voor een selector is gepubliceerd: of deze bestaat en kan worden gedecodeerd, het type en de grootte, en de vlaggen voor intrekking en testen. Geef ?domain=example.com&selector=s1 door.

GET/api/v1/tools/blocklist

Een IPv4-adres, een IPv6-adres of een domein dat wordt gecontroleerd aan de hand van de DNS-blocklists die het rapport gebruikt, met het antwoord van elke lijst. Geef ?target=203.0.113.5 door.

GET/api/v1/tools/mx

De MX-records van een domein in de volgorde waarin afzenders ze proberen, met de IPv4- en IPv6-adressen van elke host. Null MX, een domein zonder MX, hosts die IP-adressen of CNAMEs zijn en hosts die niet kunnen worden omgezet, worden gerapporteerd, net als de MTA-STS- en TLS-RPT-records. Geef ?domain=example.com door.

GET/api/v1/tools/bimi

De BIMI-configuratie van een domein in vier stappen: het DMARC-beleid dat BIMI vereist, het record op default._bimi, het SVG-logo dat wordt gecontroleerd aan de hand van het Tiny PS-profiel, en het merkcertificaat met het type, de domeinen en de vervaldatum. Geef ?domain=example.com door, en &selector= voor een andere selector dan default.

GET/api/v1/tools/ptr

De PTR-records van een adres en of een van die namen weer naar dat adres verwijst. Een mislukte lookup geeft de status error; een ontbrekend record geeft de status fail. Geef ?ip=8.8.8.8 door.

GET/api/v1/tools/mta-sts

Het MTA-STS-record van een domein en het beleidsbestand waarnaar het verwijst: de modus, de vermelde hosts en elke MX-host die niet onder het beleid valt. Geef ?domain=example.com mee.

GET/api/v1/tools/tls-rpt

Het TLS-RPT-record van een domein en de adressen die de rapporten ontvangen. Geef ?domain=example.com mee.

GET/api/v1/tools/dnssec

Of de zone van een domein ondertekend, niet ondertekend of defect is, op basis van de DNSKEY- en DS-records. Een ongeldige handtekening wordt onderscheiden van een storing van de resolver. Geef ?domain=example.com mee.

GET/api/v1/tools/dane

De TLSA-records van de MX-hosts, vergeleken met het certificaat dat een host presenteert wanneer dat certificaat kon worden gelezen. Geef ?domain=example.com mee.

GET/api/v1/tools/smtp

STARTTLS en het certificaat op de eerste twee MX-hosts: TLS-versie, uitgever, vervaldatum en of de keten en de naam geldig zijn. We maken alleen verbinding met hosts onder het domein waarnaar je hebt gevraagd en slaan e-mailproviders over, en per adres wordt één resultaat 6 uur lang gedeeld. Er wordt geen e-mail verzonden. Geef ?domain=example.com mee.

GET/api/v1/tools/ns

De naamservers van een domein en of de zone een SOA-record heeft. Eén naamserver is een waarschuwing. Geef ?domain=example.com mee.

GET/api/v1/tools/registration

Wanneer de registratie van een domein verloopt, volgens RDAP. Minder dan 30 resterende dagen is een waarschuwing. Een zone zonder RDAP-service antwoordt met skipped. Geef ?domain=example.com mee.

POST/api/v1/tools/header

De headers van een ontvangen bericht, verzonden als JSON {"headers": "..."} of als text/plain: de route van hop tot hop met vertragingen, TLS en klokafwijking, de eigen Authentication-Results van de ontvanger, de overeenstemming tussen de domeinen van From, DKIM d= en Return-Path, en de headers voor DKIM, ARC, afmelden en spamfilters. Alles na de eerste lege regel wordt ongelezen verwijderd. De headers worden in het geheugen verwerkt en niet opgeslagen, gecachet of gelogd.

Controleer het domein elke nacht.
Test de e-mail voordat die wordt verzonden.

Gedeeld door elk product

Toegang, sleutels, de rapportindeling, statussen, fouten, plus OpenAPI en llms.txt voor machines.

Authenticatie

Die is er niet. Geen sleutel om aan te vragen, geen header om in te stellen, geen account om aan te maken. De slug die je terugkrijgt is de toegang: wie deze bezit, kan dat rapport lezen, en niemand anders kan deze raden.

Dat betekent ook dat je een slug als een wachtwoord moet behandelen. Een rapport toont de onderwerpregel, de afzender, het retouradres en de volledige bron van het bericht aan iedereen die de link bezit.

Persoonlijke API-sleutels

Everything above works without a key. A key is for automation platforms such as Zapier, where every user's calls come from the platform's servers and per-IP limits would be shared by all of them. With a key, limits count per key (50 tests a day, 3 with placement, 5 permanent mailboxes), the key's tests form a history, and the key can keep permanent mailboxes whose reports only it can read. Send the key as Authorization: Bearer est_live_… on any call on this page. The routes below also take account, a short name of your choosing ([A-Za-z0-9_-], up to 64 characters) that keeps separate lists under one key. GET /api/v1/installations/tests requires it; pass the same one on POST /api/v1/inbox so the test shows up there. The Zapier integration uses zapier.

POST /api/v1/keys

Send JSON {"email":"you@example.com"}. Returns HTTP 201 with key and email. The key is shown once; only its hash is kept. Asking again gives a new key and leaves the earlier ones working. Limit: 5 keys per IP per UTC day. The form on /zapier/ calls this.

GET /api/v1/keys/me

Returns email, key_prefix and created_at of the key in the header, or HTTP 401. Use it to check a key.

GET /api/v1/installations/tests

The key's tests, newest first: ?account=…&limit=50 (up to 100), and before=<slug> for the next page. Each item has slug, created_at, analysis_status (waiting or expired before an email arrived), score_ours, score_compat, placement and changes, the checks that moved since the previous test of the same sending domain. Read the full report at /api/v1/tests/{slug}.

POST /api/v1/installations/mailboxes

Send JSON {"domain":"example.com","account":"…"}. Returns the permanent mailbox of that sending domain: id, address, domain, state, daily_cap and created. HTTP 201 when it is new, 200 when it already existed, 409 when the key keeps as many mailboxes as it may. Subscribe the address to a newsletter or a sequence and every email that arrives is checked. GET on the same path with ?account=… lists them, and DELETE /api/v1/installations/mailboxes/{mailbox_id} stops one.

GET /api/v1/installations/mailboxes/{mailbox_id}/letters

The emails that arrived, oldest first, paged with after_id and next_after_id. settled=true ends the page before the first email still being checked, so paging never skips one. newest=true turns the order round, for a quick look at the latest; settled does nothing with it. Each has test_id, slug, received_at, analysis_status, score_ours, score_compat, subject, from_addr and kind.

GET /api/v1/installations/letters/{slug}

The report of one email in a permanent mailbox, the same JSON as /api/v1/tests/{slug} with report_url null: there is no public page for it. HTTP 410 once the report has expired.

Het rapport lezen

De velden die het antwoord bevatten, in de volgorde waarin je ze waarschijnlijk wilt lezen.

score_ours0 tot 100. Ons model. Authenticatie en infrastructuur wegen het zwaarst, omdat zij de bezorging bepalen voordat een filter ook maar één woord van de tekst leest.
score_compat0 tot 10. Reproduceert het SpamAssassin-achtige getal dat mensen al gebruiken om te vergelijken, zodat het rapport vergelijkbaar is met wat iemand elders heeft gezien.
subscoresDezelfde schaal van 0 tot 100 per sectie: auth, infra_spam, content, compliance.
checks[]Alle 42, elk met een status, een bevinding van één regel, het bewijs waarop de beslissing is gebaseerd en hoeveel punten dit in beide scores kostte.
checks[].citationsWaar de bevinding vandaan komt: de sectie van de RFC, letterlijk geciteerd, en de pagina waarop Google zijn eigen vereiste vermeldt. Handmatig samengesteld in plaats van gegenereerd, zodat erop kan worden vertrouwd.
oplossingen[]Wat moet worden gewijzigd, in de juiste volgorde, met het aantal punten dat elke wijziging waard is. De winst wordt berekend door het rapport opnieuw te scoren, niet geschat.
volledigOnwaar wanneer een controle niet kon worden uitgevoerd. Een niet-gecontroleerd item geldt nooit als geslaagd, dus beschouw de score als optimistisch totdat dit waar is.
rapport_urlDe voor mensen leesbare pagina. Geef die aan een persoon in plaats van een muur van JSON.

Statussen

Een controle is een van vijf dingen, en het verschil tussen twee ervan is belangrijker dan het lijkt.

geslaagdDe controle is uitgevoerd en heeft niets verkeerds gevonden.
waarschuwingDe moeite waard om op te lossen. Kost punten.
misluktKost je bezorging. Kost meer punten.
overslaanNiet van toepassing. Geen bijlagen om te scannen, geen HTML-gedeelte om te wegen. Niet geslaagd.
foutWe konden dit niet vaststellen. Uitgesloten van de score en gemarkeerd, in plaats van als geslaagd meegeteld.

analysis_status doorloopt received, analyzing, checks_ready, failed. ai_status doorloopt pending, running, ready, fallback, error. Het deterministische rapport is definitief bij checks_ready; ai_status voegt alleen het plan toe.

Wat kan worden teruggegeven

202Het adres is gereserveerd en er is geen bericht aangekomen. De hoofdtekst bevat het adres, de vervaldatum en de taal, zodat een aanroeper die de reservering niet heeft aangemaakt deze toch kan weergeven.
404Deze slug bestaat niet. Deze heeft nooit bestaan of de reservering is vergeten.
410Het adres is verlopen voordat er een bericht aankwam.
409Je hebt geprobeerd de taal te wijzigen nadat het bericht al was aangekomen.
429De limiet voor gratis tests voor je adres. Er geldt momenteel geen limiet per persoon voor deze service; als die ooit wordt ingesteld, vermeldt de hoofdtekst wanneer deze opnieuw wordt ingesteld.

Vier dingen om te weten

Eén bericht per adres

Het tweede wordt geweigerd. Je eerdere rapport blijft intact, wat precies de bedoeling is.

Een uur om het te gebruiken

Het adres verloopt; het rapport niet. Rapportlinks zijn permanent, dus een link die in een ticket is geplakt, blijft werken.

Verzenden vanaf het platform

Als je een campagne vanuit een persoonlijk account test, meet je dat account. Bijna alles in het gedeelte over authenticatie gaat over de verzendinfrastructuur, niet over de tekst.

Opnieuw testen na herstel

De verwachte verbeteringen worden per oplossing berekend en kunnen niet worden gecombineerd. Het tweede rapport geeft het eerlijke getal.

Voor machines

GET/api/health

Liveness. Geen authenticatie, geen bijwerkingen.

Probeer er eerst één handmatig

Het duurt ongeveer een minuut en laat je precies zien wat de JSON beschrijft.

Vraag een testadres aan

Sandbox.

Elk endpoint, met een knop die het uitvoert op de live service. Hiervoor is geen sleutel nodig, dus een verzoek dat je vanaf deze pagina verstuurt is echt: het reserveert een echt adres en telt mee.

Probeer het in de sandbox