Dispatch API v0.1

HTTP API zum Versand transaktionaler E-Mails via SMTP.

Authentifizierung

Alle Endpunkte außer POST /keys und GET /health erfordern einen Authorization-Header mit Bearer Token.

Authorization: Bearer dsp_...

Einen Key beantragen: POST /keys — nach Admin-Freigabe wird der Key per Mail zugestellt.

POST /keys — API Key beantragen

Stellt eine Anfrage für einen neuen API Key. Kein Auth erforderlich. Nach Eingang wird der Admin benachrichtigt und genehmigt den Key manuell. Der fertige Key wird per Mail zugestellt.

FeldTypPflichtBeschreibung
namestringjaName der anfragenden Person oder Organisation (max. 200 Zeichen)
emailstringjaE-Mail-Adresse, an die der Key zugestellt wird
curl -X POST https://dispatch.knerpi.de/keys \
  -H "Content-Type: application/json" \
  -d '{ "name": "Max Mustermann", "email": "max@example.com" }'
// Antwort (201 Created)
{
  "id": "4e564315-f1c8-4004-a489-9af1e50e4872",
  "status": "pending"
}

Fehlercodes

StatusnameUrsache
422missing_required_fieldname oder email fehlt
422invalid_emailUngültige E-Mail-Adresse

POST /emails — E-Mail senden

Sendet eine E-Mail. Entweder html, text oder react_template muss angegeben werden.

From-Domain: Ohne verifizierte Domains darf nur dispatch.knerpi.de als Absender-Domain verwendet werden. Mit verifizierten Domains muss eine davon genutzt werden — die Mail wird dann mit dem eigenen DKIM-Key signiert.

Das from-Feld unterstützt sowohl einfache Adressen (user@domain.com) als auch RFC-5322-Format ("Name" <user@domain.com>).

FeldTypPflichtBeschreibung
fromstringjaAbsender-Adresse
tostring | string[]jaEmpfänger (ein oder mehrere)
subjectstringjaBetreff
htmlstringja*HTML-Body (*mind. eines von html / text / react_template)
textstringneinPlaintext-Fallback
react_templatestringneinName eines Server-Templates (statt html)
react_propsobjectneinProps für das React-Template
reply_tostringneinReply-To-Adresse
ccstring | string[]neinCC-Empfänger
bccstring | string[]neinBCC-Empfänger
headersobjectneinZusätzliche Mail-Header als Key-Value-Objekt
curl -X POST https://dispatch.knerpi.de/emails \
  -H "Authorization: Bearer dsp_..." \
  -H "Content-Type: application/json" \
  -d '{
    "from":    "noreply@dispatch.knerpi.de",
    "to":      "empfaenger@example.com",
    "subject": "Hallo Welt",
    "html":    "<p>Das ist meine erste Mail.</p>",
    "text":    "Das ist meine erste Mail."
  }'
// Antwort (200 OK)
{ "id": "3c4a1b2e-...@dispatch.knerpi.de" }
// Mit React-Template
{
  "from":           "noreply@dispatch.knerpi.de",
  "to":             "empfaenger@example.com",
  "subject":        "Willkommen",
  "react_template": "welcome",
  "react_props":    { "name": "Arne" }
}

Fehlercodes

StatusnameUrsache
401missing_required_fieldKein Authorization-Header
401invalid_api_keyKey ungültig oder widerrufen
422missing_required_fieldfrom, to oder subject fehlt; kein Body angegeben
422invalid_emailUngültige Adresse in from, reply_to, cc oder bcc
403domain_not_allowedFrom-Domain nicht verifiziert oder nicht erlaubt
500internal_server_errorFehler beim Versand

GET /templates — Templates auflisten

Gibt alle auf dem Server verfügbaren React-Templates zurück.

curl https://dispatch.knerpi.de/templates \
  -H "Authorization: Bearer dsp_..."
// Antwort (200 OK)
{ "templates": ["welcome"] }

POST /templates — Template hochladen

Lädt ein React-Template (JSX oder TSX) auf den Server. Überschreibt ein bestehendes Template gleichen Namens. Das Template ist sofort nutzbar — kein Neustart erforderlich.

FeldTypPflichtBeschreibung
namestringjaTemplate-Name. Nur a–z A–Z 0–9 - _ erlaubt.
codestringjaQuellcode des Templates (JSX/TSX)
extstringneinjsx (Standard) oder tsx
curl -X POST https://dispatch.knerpi.de/templates \
  -H "Authorization: Bearer dsp_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "bestellung",
    "ext":  "jsx",
    "code": "import { Html, Text } from \"@react-email/components\";\nexport default function({ name }) {\n  return <Html><Text>Hallo {name}</Text></Html>;\n}"
  }'
// Antwort (200 OK)
{ "name": "bestellung", "path": "templates/bestellung.jsx" }

Fehlercodes

StatusnameUrsache
422missing_required_fieldname oder code fehlt
422invalid_template_nameName enthält unerlaubte Zeichen
422invalid_extensionext ist nicht jsx oder tsx

DELETE /templates/:name — Template löschen

Löscht ein Template vom Server. Der Name wird als URL-Parameter übergeben.

curl -X DELETE https://dispatch.knerpi.de/templates/bestellung \
  -H "Authorization: Bearer dsp_..."
// Antwort (200 OK)
{ "deleted": "bestellung" }

Fehlercodes

StatusnameUrsache
404not_foundTemplate existiert nicht
422invalid_template_nameName enthält unerlaubte Zeichen

Sending Domains

Eigene Domains registrieren, um mit benutzerdefiniertem DKIM zu versenden. Ohne verifizierte Domains kann nur die Shared Domain dispatch.knerpi.de als Absender genutzt werden.

Nach der Registrierung müssen SPF- und DKIM-DNS-Records innerhalb von 72 Stunden gesetzt werden. Ein automatischer Verifikations-Loop prüft alle 15 Minuten. Domains die nach Ablauf der Deadline nicht verifiziert sind, werden automatisch gelöscht.

POST /domains — Domain registrieren

Registriert eine neue Sending Domain. Generiert DKIM-Schlüsselpaar und gibt die erforderlichen DNS-Records zurück. Max. 10 Domains pro Account.

Admin: Muss ?account_id=... als Query-Parameter angeben, um die Domain einem Account zuzuordnen.

FeldTypPflichtBeschreibung
namestringjaDomain-Name (z.B. example.com). Keine Public-Domains (gmail.com etc.).
curl -X POST https://dispatch.knerpi.de/domains \
  -H "Authorization: Bearer dsp_..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "example.com" }'
// Antwort (201 Created)
{
  "id": "a1b2c3d4-...",
  "name": "example.com",
  "status": "pending",
  "verification_deadline": "2026-03-01T12:00:00.000Z",
  "dns_records": {
    "spf":   { "type": "TXT", "host": "example.com", "value": "v=spf1 ip4:168.119.233.28 -all" },
    "dkim":  { "type": "TXT", "host": "dispatch._domainkey.example.com", "value": "v=DKIM1; k=rsa; p=MIIBIjAN..." },
    "dmarc": { "type": "TXT", "host": "_dmarc.example.com", "value": "v=DMARC1; p=none; rua=mailto:dmarc@example.com;" }
  }
}

Fehlercodes

StatusnameUrsache
422missing_required_fieldname fehlt; Admin ohne account_id
422invalid_domainUngültiger Domain-Name
422public_domainPublic Email-Domains nicht erlaubt
422domain_limitMax. 10 Domains pro Account erreicht
409domain_existsDomain ist bereits registriert

GET /domains — Domains auflisten

Gibt alle Domains des Accounts zurück. Admin sieht alle Domains aller Accounts.

curl https://dispatch.knerpi.de/domains \
  -H "Authorization: Bearer dsp_..."
// Antwort (200 OK)
{
  "domains": [
    { "id": "a1b2c3d4-...", "name": "example.com", "status": "verified", "created_at": "2026-02-26T..." }
  ]
}

GET /domains/:id — Domain-Details

Gibt Details einer Domain zurück, inklusive der DNS-Records die gesetzt werden müssen.

curl https://dispatch.knerpi.de/domains/a1b2c3d4-... \
  -H "Authorization: Bearer dsp_..."
// Antwort (200 OK)
{
  "id": "a1b2c3d4-...",
  "name": "example.com",
  "status": "pending",
  "verification_deadline": "2026-03-01T12:00:00.000Z",
  "created_at": "2026-02-26T...",
  "dns_records": { /* ... */ }
}

Fehlercodes

StatusnameUrsache
404not_foundDomain nicht gefunden oder gehört anderem Account

DELETE /domains/:id — Domain löschen

Löscht eine registrierte Domain. Mails können danach nicht mehr über diese Domain versendet werden.

curl -X DELETE https://dispatch.knerpi.de/domains/a1b2c3d4-... \
  -H "Authorization: Bearer dsp_..."
// Antwort (200 OK)
{ "deleted": "example.com" }

POST /domains/:id/verify — Verifikation auslösen

Prüft sofort, ob die DNS-Records korrekt gesetzt sind (SPF + DKIM). Der automatische Check läuft alle 15 Minuten — dieser Endpunkt erlaubt eine sofortige Prüfung.

Wenn die Verifikations-Deadline abgelaufen ist, wird die Domain automatisch gelöscht und muss neu registriert werden.

curl -X POST https://dispatch.knerpi.de/domains/a1b2c3d4-.../verify \
  -H "Authorization: Bearer dsp_..."
// Antwort (200 OK)
{ "id": "a1b2c3d4-...", "name": "example.com", "status": "verified" }

Fehlercodes

StatusnameUrsache
404not_foundDomain nicht gefunden oder gehört anderem Account
410verification_expiredDeadline abgelaufen — Domain wurde gelöscht, erneut registrieren

GET /health — Status prüfen

Gibt den aktuellen Status des Servers zurück. Kein Auth erforderlich.

curl https://dispatch.knerpi.de/health
// Antwort (200 OK)
{ "status": "ok" }