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
- Beantrage in deinem Konto unter API den Zugang. Nach der Freigabe – meist innerhalb eines Werktags – erzeugst du dort einen Schlüssel.
- 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", …} - Schick deine Mail an diese Adresse – aus deiner Anwendung, deinem Newsletter-Tool oder deinem Mailserver.
- Frag das Ergebnis ab, bis
statusden Wertdonehat (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.
- Höchstens 60 Anfragen pro Minute und Schlüssel
- 20 (Pro: 200) Tests pro Tag (dasselbe Kontingent wie auf der Website)
- 5 (Pro: 50) Inbox-Tests pro Tag
Tests
| Aufruf | Zweck |
|---|---|
POST /api/v1/tests | Neuen Test anlegen. Antwort: code, address, status, report_url |
GET /api/v1/tests?limit=20 | Deine 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
| Aufruf | Zweck |
|---|---|
GET /api/v1/domains | Überwachte Domains mit Zustand und DMARC-Berichtsadresse |
POST /api/v1/domains | Domain überwachen. Body: {"domain": "beispiel.de"} |
GET /api/v1/domains/{domain}?days=30 | Letzte Prüfung, DMARC-Auswertung (Volumen, Bestehensquote, Absender, Werte pro Tag) und TLS-RPT-Auswertung |
Inbox-Test
| Aufruf | Zweck |
|---|---|
POST /api/v1/inbox-tests | Inbox-Test starten. Antwort: code (in Betreff oder Text schreiben) und addresses (Empfänger) |
POST /api/v1/inbox-tests/{code}/cancel | Laufenden 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…"}}
| Ereignis | Wann | Inhalt von data |
|---|---|---|
test.done | Ein Test ist ausgewertet | code, status, score, subject, from_domain, report_url |
domain.changed | Ein Ergebnis der täglichen Domain-Prüfung hat sich geändert | domain, status, changes (Prüfung, vorher, nachher, Details), url |
inbox_test.done | Ein Inbox-Test ist abgeschlossen | code, results (Anbieter und Ordner), url |
ping | Du 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"}.
| Status | Bedeutung |
|---|---|
401 | Schlüssel fehlt, ist falsch oder widerrufen |
403 | API-Zugang nicht (mehr) freigeschaltet, Anfrage von einer nicht freigegebenen Adresse oder Konto gesperrt |
404 | Test oder Domain gibt es nicht (oder gehört nicht zu deinem Konto) |
409 | Höchstzahl an Domains erreicht |
422 | Ungültige Eingabe |
429 | Limit erreicht – bei Minutenlimit steht im Header Retry-After, wann es weitergeht |