API-Dokumentation

Mit der Postwacht-API prüfst du deine Mails automatisch – zum Beispiel nach jedem Deployment oder vor jedem Newsletter. Die API ist kostenlos und wird auf Antrag freigeschaltet.

Schnellstart

  1. Beantrage in deinem Konto unter API den Zugang. Nach der Freigabe – meist innerhalb eines Werktags – erzeugst du dort einen Schlüssel.
  2. Lege einen Test an. Du bekommst eine Einweg-Adresse zurück:
    curl -X POST https://postwacht.de/api/v1/tests \
      -H "Authorization: Bearer pwk_…"
    
    {"code": "k7m2x9…", "address": "k7m2x9…@in.postwacht.de", "status": "waiting", …}
  3. Schick deine Mail an diese Adresse – aus deiner Anwendung, deinem Newsletter-Tool oder deinem Mailserver.
  4. Frag das Ergebnis ab, bis status den Wert done hat (meist nach 10 bis 30 Sekunden):
    curl https://postwacht.de/api/v1/tests/k7m2x9… \
      -H "Authorization: Bearer pwk_…"

Anmeldung und Limits

Jede Anfrage braucht den Header Authorization: Bearer <Schlüssel>. Ein Schlüssel hat dieselben Rechte wie dein Konto. Du kannst ihn jederzeit im Konto widerrufen.

Im Antrag gibst du an, von welchen Servern deine Anwendung die API aufruft (Hostname, IP-Adresse oder kleines Netz). Anfragen von anderen Adressen werden abgewiesen – auch mit gültigem Schlüssel.

Tests

AufrufZweck
POST /api/v1/testsNeuen Test anlegen. Antwort: code, address, status, report_url
GET /api/v1/tests?limit=20Deine letzten Tests
GET /api/v1/tests/{code}Ergebnis eines Tests mit Punktzahl, allen Prüfungen und Maßnahmenplan

status ist waiting (Mail noch nicht da), received, analyzing, done oder failed. Bei done enthält die Antwort score (0 bis 10), results mit jeder einzelnen Prüfung und fix_plan mit den empfohlenen Maßnahmen.

Beispiel für eine Prüfung in einer CI-Pipeline:

SCORE=$(curl -s https://postwacht.de/api/v1/tests/$CODE \
  -H "Authorization: Bearer $POSTWACHT_KEY" | jq .score)
[ "$(echo "$SCORE >= 9" | bc)" = 1 ] || exit 1

Titel und Befunde in den Antworten sind auf Deutsch. Mit dem Header Accept-Language: en bekommst du sie auf Englisch.

Domains und DMARC

AufrufZweck
GET /api/v1/domainsÜberwachte Domains mit Zustand und DMARC-Berichtsadresse
POST /api/v1/domainsDomain überwachen. Body: {"domain": "beispiel.de"}
GET /api/v1/domains/{domain}?days=30Letzte Prüfung, DMARC-Auswertung (Volumen, Bestehensquote, Absender, Werte pro Tag) und TLS-RPT-Auswertung

Inbox-Test

AufrufZweck
POST /api/v1/inbox-testsInbox-Test starten. Antwort: code (in Betreff oder Text schreiben) und addresses (Empfänger)
POST /api/v1/inbox-tests/{code}/cancelLaufenden Inbox-Test abbrechen. Hatte noch kein Postfach die Mail gefunden, zählt er nicht gegen das Tageslimit.
GET /api/v1/inbox-tests/{code}Ordner je Anbieter: inbox, promotions, spam, missing, cancelled oder null (wird noch geprüft)

Webhooks

Statt regelmäßig nachzufragen, kannst du dir Ereignisse schicken lassen. Lege dazu unter Konto → API eine HTTPS-Adresse an. Postwacht sendet dann einen POST mit JSON:

{"event": "test.done",
 "created_at": "2026-10-11T09:03:56+00:00",
 "data": {"code": "k7m2x9…", "status": "done", "score": 9.4,
          "from_domain": "beispiel.de", "report_url": "https://postwacht.de/t/k7m2x9…"}}
EreignisWannInhalt von data
test.doneEin Test ist ausgewertetcode, status, score, subject, from_domain, report_url
domain.changedEin Ergebnis der täglichen Domain-Prüfung hat sich geändertdomain, status, changes (Prüfung, vorher, nachher, Details), url
inbox_test.doneEin Inbox-Test ist abgeschlossencode, results (Anbieter und Ordner), url
pingDu klickst auf „Test senden“message

Signatur prüfen

Jeder Aufruf trägt die Kopfzeilen X-Postwacht-Event, X-Postwacht-Timestamp und X-Postwacht-Signature. Die Signatur ist ein HMAC-SHA256 über <Timestamp>.<Body> mit deinem Geheimnis. Prüfe sie und verwirf Aufrufe, deren Zeitstempel älter als fünf Minuten ist:

import hashlib, hmac, time

def echt(secret: str, timestamp: str, body: bytes, signature: str) -> bool:
    if abs(time.time() - int(timestamp)) > 300:
        return False
    mac = hmac.new(secret.encode(), timestamp.encode() + b"." + body, hashlib.sha256)
    return hmac.compare_digest("sha256=" + mac.hexdigest(), signature)

Antworte mit einem Status von 200 bis 299. Bei anderen Antworten oder wenn deine Adresse nicht erreichbar ist, versucht Postwacht es nach 1, 5 und 30 Minuten erneut. Nach 20 Fehlschlägen in Folge wird der Webhook abgeschaltet; mit „Test senden“ schaltest du ihn wieder ein. Weiterleitungen werden nicht verfolgt, und es werden nur öffentliche Adressen aufgerufen.

Fehler

Fehler kommen als JSON mit passendem HTTP-Status, z. B. {"error": "Tageslimit von 20 Tests erreicht"}.

StatusBedeutung
401Schlüssel fehlt, ist falsch oder widerrufen
403API-Zugang nicht (mehr) freigeschaltet, Anfrage von einer nicht freigegebenen Adresse oder Konto gesperrt
404Test oder Domain gibt es nicht (oder gehört nicht zu deinem Konto)
409Höchstzahl an Domains erreicht
422Ungültige Eingabe
429Limit erreicht – bei Minutenlimit steht im Header Retry-After, wann es weitergeht