API und MCP

Alles, was Sie im Dashboard tun, geht auch über die REST-API oder einen KI-Agenten — mit einer Ausnahme: Senden entscheidet immer ein Mensch. Die Endpunkte auf dieser Seite sind aus dem Code erzeugt, in dem zugestellt sie ausführt.

Überblick

Jede Funktion von zugestellt ist eine Aktion mit Namen, Eingabe und Rechten. Dieselbe Aktion läuft im Dashboard, als REST-Endpunkt und als MCP-Werkzeug mit identischen Feldern und Prüfungen.

REST-API
https://zugestellt.ch/api/v1
MCP-Server
https://zugestellt.ch/mcp
Anmeldeformular
https://zugestellt.ch/api/anmelden

Über API und MCP stehen 24 Aktionen bereit. 12 weitere — darunter senden, Versand fortsetzen, Importe und API-Schlüssel — gibt es nur im Dashboard. Ein Aufruf über die API beantwortet zugestellt dort mit 403 nur_mensch.

Authentifizierung

Einen API-Schlüssel erstellen Admins im Dashboard unter «API und KI-Agenten». Er beginnt mit zst_ und wird genau einmal angezeigt; zugestellt speichert nur einen Fingerabdruck. Ältere Schlüssel mit nsy_ gelten weiter.

Senden Sie den Schlüssel bei jeder Anfrage im Header:

Authorization: Bearer zst_…

Jeder Schlüssel gehört zu einem Konto und hat eine von zwei Stufen:

  • Entwürfe, Leser, Berichte (voll): alle Aktionen, die nicht dem Dashboard vorbehalten sind.
  • Nur Anmeldungen (anmeldungen): nur kontakt_hinzufuegen. Richtig für ein CRM oder ein eigenes Formular.

Widerrufene Schlüssel gelten sofort nicht mehr. Jede schreibende Aktion wird mit dem Präfix des Schlüssels protokolliert.

Anfragen und Antworten

  • GET: Felder als Query-Parameter, zum Beispiel ?publikation_id=…&status=aktiv. limit und offset werden als Zahl gelesen, alles andere als Text.
  • POST und PATCH: Felder als JSON im Körper, mit Content-Type: application/json.
  • Die Antwort ist JSON: bei Erfolg direkt das Ergebnis, bei einem Fehler ein Objekt mit fehler und code.
  • IDs sind UUIDs. Zeitpunkte schreiben Sie nach ISO 8601 mit Zeitzone, zum Beispiel 2026-11-12T08:00:00+01:00.
  • Unbekannte Felder werden ignoriert.

Fehler

Jeder Fehler hat einen HTTP-Status, einen festen code für Ihr Programm und eine Meldung auf Deutsch für Menschen:

{
  "fehler": "publikation_id: Invalid UUID",
  "code": "eingabe",
  "details": [ { "path": ["publikation_id"], "message": "Invalid UUID", … } ]
}
400 eingabe
Der Körper einer POST- oder PATCH-Anfrage ist kein JSON.
401 nicht_angemeldet
Schlüssel fehlt, ist widerrufen oder hat das falsche Format.
403 nur_mensch
Die Aktion ist nur im Dashboard möglich, zum Beispiel senden. Fordern Sie stattdessen eine Freigabe an.
403 keine_rechte
Der Schlüssel hat die Stufe «Nur Anmeldungen» und darf diese Aktion nicht.
404 unbekannt
Diesen Pfad gibt es mit dieser Methode nicht.
404 nicht_gefunden
Die ID gibt es in Ihrem Konto nicht.
409 konflikt
Der Zustand lässt die Aktion nicht zu, etwa wenn eine Ausgabe kein Entwurf mehr ist. Die Meldung nennt den Grund.
422 eingabe
Ein Feld fehlt oder ist ungültig. «details» enthält jede Abweichung mit Pfad.
422 adresse_…
Die E-Mail-Adresse wurde abgelehnt: adresse_ungueltig, adresse_wegwerf oder adresse_tippfehler (mit Vorschlag in der Meldung). Mit «tippfehler_ok»: true übernehmen Sie die Adresse trotzdem.
423 konto_gesperrt
Das Konto ist gesperrt. Lesen und Anhalten bleiben möglich.
500 fehler
Unerwarteter Fehler. Er ist bei uns protokolliert.
503 ses_fehlt
Der Mailversand ist für diese Umgebung noch nicht eingerichtet.

Einzelne Aktionen haben eigene Codes, etwa vorpruefung oder domain_nicht_bereit; die Meldung sagt dann, was fehlt. Wiederholen Sie Anfragen mit 4xx nicht unverändert. Bei 5xx lohnt ein späterer neuer Versuch.

Beispiele

Newsletter des Kontos auflisten
curl https://zugestellt.ch/api/v1/publikationen \
  -H "Authorization: Bearer zst_…"
Einen Leser eintragen (er bestätigt per Mail)
curl -X POST https://zugestellt.ch/api/v1/kontakte \
  -H "Authorization: Bearer zst_…" \
  -H "Content-Type: application/json" \
  -d '{
    "publikation_id": "…",
    "email": "anna@beispiel.ch",
    "vorname": "Anna",
    "tags": ["kunde", "zug"],
    "einwilligung": "Anmeldung am Messestand, 12.11.2026"
  }'
Einen Entwurf anlegen
curl -X POST https://zugestellt.ch/api/v1/ausgaben \
  -H "Authorization: Bearer zst_…" \
  -H "Content-Type: application/json" \
  -d '{
    "publikation_id": "…",
    "titel": "November",
    "betreff": "Neue Öffnungszeiten ab Dezember",
    "vorschautext": "Und ein Gutschein für Stammkunden.",
    "inhalt": [
      { "typ": "ueberschrift", "text": "Neue Öffnungszeiten" },
      { "typ": "absatz", "text": "{{vorname|Guten Tag}}, ab 1. Dezember sind wir **samstags bis 16 Uhr** für Sie da." },
      { "typ": "knopf", "text": "Termin buchen", "url": "https://www.ihre-firma.ch/termin" }
    ]
  }'
Prüfen und zur Freigabe vorlegen
curl -X POST https://zugestellt.ch/api/v1/ausgaben/vorpruefen \
  -H "Authorization: Bearer zst_…" -H "Content-Type: application/json" \
  -d '{ "ausgabe_id": "…" }'

curl -X POST https://zugestellt.ch/api/v1/ausgaben/freigabe-anfordern \
  -H "Authorization: Bearer zst_…" -H "Content-Type: application/json" \
  -d '{ "ausgabe_id": "…", "geplant_fuer": "2026-11-12T08:00:00+01:00" }'

Danach sieht ein Mensch die Ausgabe im Dashboard als «zur Freigabe» und entscheidet, ob und wann sie gesendet wird. Ändert Ihr Programm die Ausgabe danach, wird die Freigabe zurückgesetzt.

Kennzahlen der letzten 30 Tage
curl "https://zugestellt.ch/api/v1/uebersicht" \
  -H "Authorization: Bearer zst_…"

Inhalt einer Ausgabe

Der Inhalt ist eine Liste von Blöcken, höchstens 300. Rohes HTML gibt es nicht; daraus entstehen Mail, Klartext und Webseite. Im Text gelten **fett**, *kursiv*, [Text](https://…) und {{vorname|Ersatz}}.

ueberschrift
text, stufe (1–3, Standard 2)
absatz
text
liste
punkte (Liste von Texten), nummeriert (Standard false)
bild
url, alt, optional link und bildunterschrift
knopf
text, url
zitat
text, optional quelle
trenner
keine Felder

Links sind nur mit https://, http:// oder mailto: erlaubt. Die gerenderte Mail darf höchstens 100 KB gross sein.

Alle Endpunkte

Pfade relativ zu https://zugestellt.ch/api/v1. Der Name des MCP-Werkzeugs ist jeweils der Name der Aktion.

Newsletter

GET/api/v1/publikationen

Alle Publikationen (Newsletter) des Kontos mit Anzahl aktiver Leser.

MCP-Werkzeug publikationen_liste · liest nur · auch bei gesperrtem Konto

Keine Felder.

POST/api/v1/publikationen

Neue Publikation mit Absender und Postadresse anlegen.

MCP-Werkzeug publikation_erstellen

namePflicht
string1–120 Zeichen
kuerzelPflicht
string
absender_namePflicht
string1–120 Zeichen
absender_adressePflicht
string (E-Mail)
antwort_an
string (E-Mail)
postadressePflicht
string5–300 Zeichen
double_opt_in
booleanStandard true

GET/api/v1/publikationen/lesen

Alle Einstellungen eines Newsletters (Absender, Design, Willkommensmail, Formular).

MCP-Werkzeug publikation_lesen · liest nur · auch bei gesperrtem Konto

publikation_idPflicht
string (uuid)

Nur im Dashboard

  • publikation_aendern — Einstellungen eines Newsletters ändern: Name, Absender, Postadresse, Design, Willkommensmail, erlaubte Websites fürs Formular.

Leser und Tags

GET/api/v1/kontakte

Leser einer Publikation, optional nach Status oder Adresse gefiltert.

MCP-Werkzeug kontakte_liste · liest nur · auch bei gesperrtem Konto

publikation_idPflicht
string (uuid)
status
"unbestaetigt" | "aktiv" | "abgemeldet" | "unzustellbar" | "beschwerde" | "ruhend"
suche
stringhöchstens 100 Zeichen
tag
stringhöchstens 50 Zeichen
limit
integer1 bis 500 · Standard 50
offset
integerab 0 · Standard 0

POST/api/v1/kontakte

Leser hinzufügen. Über API und MCP gilt immer Double-Opt-in: der Leser bestätigt per Mail. Bounces und Beschwerden bleiben gesperrt.

MCP-Werkzeug kontakt_hinzufuegen · auch mit Schlüssel «Nur Anmeldungen»

publikation_idPflicht
string (uuid)
emailPflicht
stringhöchstens 254 Zeichen
vorname
stringhöchstens 100 Zeichen
nachname
stringhöchstens 100 Zeichen
tags
string[]höchstens 20 Einträge
einwilligung
stringhöchstens 500 Zeichen
direkt_aktiv
boolean
tippfehler_ok
boolean

POST/api/v1/kontakte/abmelden

Einen Leser von seiner Publikation abmelden.

MCP-Werkzeug kontakt_abmelden · auch bei gesperrtem Konto

kontakt_idPflicht
string (uuid)

GET/api/v1/tags

Alle Tags einer Publikation mit der Zahl aktiver und aller Leser.

MCP-Werkzeug tags_liste · liest nur · auch bei gesperrtem Konto

publikation_idPflicht
string (uuid)

POST/api/v1/kontakte/tags

Tags bei bis zu 1000 Lesern setzen oder entfernen. Tags gelten ohne Gross/Klein.

MCP-Werkzeug kontakte_taggen

publikation_idPflicht
string (uuid)
kontakt_idsPflicht
string (uuid)[]1 bis 1000 Einträge
hinzufuegen
string[]höchstens 20 Einträge
entfernen
string[]höchstens 20 Einträge

Nur im Dashboard

  • kontakt_loeschen — Leser endgültig löschen (z. B. auf Wunsch nach nDSG). Abgemeldete, Bounces und Beschwerden bleiben als Adresse gesperrt.
  • kontakte_export — Alle Leser einer Publikation (optional nach Status oder Tag) als Zeilen für eine CSV.

Ausgaben

GET/api/v1/ausgaben

Ausgaben (Beiträge) einer Publikation, neueste zuerst.

MCP-Werkzeug ausgaben_liste · liest nur · auch bei gesperrtem Konto

publikation_idPflicht
string (uuid)
status
"entwurf" | "freigabe_offen" | "geplant" | "sendet" | "pausiert" | "gesendet" | "abgebrochen"

GET/api/v1/ausgaben/lesen

Eine Ausgabe mit Inhalt und den Zahlen ihrer Versände.

MCP-Werkzeug ausgabe_lesen · liest nur · auch bei gesperrtem Konto

ausgabe_idPflicht
string (uuid)

POST/api/v1/ausgaben

Neuen Entwurf anlegen. Inhalt als Blöcke (ueberschrift, absatz mit **fett**/*kursiv*/[Link](url), liste, bild, knopf, zitat, trenner). Versendet nichts.

MCP-Werkzeug ausgabe_erstellen

publikation_idPflicht
string (uuid)
titel
stringhöchstens 200 Zeichen
betreff
stringhöchstens 200 Zeichen
vorschautext
stringhöchstens 300 Zeichen
inhalt
Block[]höchstens 300 Einträge
slug
string

PATCH/api/v1/ausgaben

Entwurf ändern. Eine offene Freigabe wird dabei zurückgesetzt — sie galt für den alten Inhalt.

MCP-Werkzeug ausgabe_aendern

ausgabe_idPflicht
string (uuid)
titel
stringhöchstens 200 Zeichen
betreff
stringhöchstens 200 Zeichen
vorschautext
stringhöchstens 300 Zeichen
inhalt
Block[]höchstens 300 Einträge
slug
string
zielgruppe
{ mit, ohne }

POST/api/v1/ausgaben/vorpruefen

Prüft eine Ausgabe vor dem Versand: was blockiert, was nur eine Warnung ist, wie gross die Mail ist.

MCP-Werkzeug ausgabe_vorpruefen · liest nur · auch bei gesperrtem Konto

ausgabe_idPflicht
string (uuid)

POST/api/v1/ausgaben/freigabe-anfordern

Bittet einen Menschen, die Ausgabe freizugeben (optional mit Wunschzeit). Senden kann nur ein Mensch im Dashboard.

MCP-Werkzeug freigabe_anfordern

ausgabe_idPflicht
string (uuid)
geplant_fuer
string (ISO 8601 mit Zeitzone)

POST/api/v1/ausgaben/planung-aufheben

Einen geplanten Versand aufheben. Die Ausgabe wird wieder Entwurf und braucht eine neue Freigabe.

MCP-Werkzeug planung_aufheben · auch bei gesperrtem Konto

ausgabe_idPflicht
string (uuid)

PATCH/api/v1/ausgaben/absender

Für diese Ausgabe einen anderen Absendernamen, eine andere Antwortadresse oder einen eigenen UTM-Kampagnennamen setzen (leer = wie der Newsletter).

MCP-Werkzeug ausgabe_absender

ausgabe_idPflicht
string (uuid)
absender_name
stringhöchstens 120 Zeichen
antwort_an
string (E-Mail) | ""leer = wie beim Newsletter
utm_kampagne
string | ""leer = wie beim Newsletter

Nur im Dashboard

  • freigeben — Freigabe durch einen Menschen: sendet sofort oder plant den Versand. Senden lässt sich nicht rückgängig machen.
  • testmail_senden — Die Ausgabe als Testmail an bis zu drei Adressen senden (Betreff mit [Test]). Nur im Dashboard.

Versand

POST/api/v1/versaende/pausieren

Laufenden Versand anhalten. Bereits gesendete Mails bleiben gesendet.

MCP-Werkzeug versand_pausieren · auch bei gesperrtem Konto

versand_idPflicht
string (uuid)

Nur im Dashboard

  • versand_fortsetzen — Pausierten Versand fortsetzen (nur Mensch). Nach einer Pause wegen Bounces stoppt danach nur noch die Sperr-Schwelle.

Übersicht und Berichte

GET/api/v1/uebersicht

Kennzahlen eines Zeitraums (Standard: letzte 30 Tage) im Vergleich zum gleich langen Zeitraum davor, optional für einen Newsletter.

MCP-Werkzeug uebersicht · liest nur · auch bei gesperrtem Konto

von
string (ISO 8601 mit Zeitzone)
bis
string (ISO 8601 mit Zeitzone)
publikation_id
string (uuid)

GET/api/v1/berichte

Alle Versände eines Newsletters mit Zustellung, Öffnungen, Klicks, Bounces und Abmeldungen.

MCP-Werkzeug berichte_liste · liest nur · auch bei gesperrtem Konto

publikation_idPflicht
string (uuid)

GET/api/v1/berichte/versand

Bericht eines Versands: Kennzahlen, geklickte Links (Leser pro Link), Öffnungen nach Stunden, Mail-Anbieter.

MCP-Werkzeug bericht · liest nur · auch bei gesperrtem Konto

versand_idPflicht
string (uuid)

Importe

GET/api/v1/importe

Die letzten Importe eines Newsletters mit Ergebnis.

MCP-Werkzeug importe_liste · liest nur · auch bei gesperrtem Konto

publikation_idPflicht
string (uuid)

Nur im Dashboard

  • import_starten — Einen Kontakt-Import beginnen. Pflicht: wie die Leser eingewilligt haben. Danach Zeilen mit import_teil senden und mit import_abschliessen beenden.
  • import_teil — Bis zu 1000 Zeilen eines Imports. Status pro Zeile: aktiv, abgemeldet, unzustellbar oder beschwerde. Niemand wird über den Import wieder angemeldet; Abmeldungen und Bounces werden übernommen.
  • import_abschliessen — Import beenden und das Ergebnis erhalten (neu, aktualisiert, abgemeldet, gesperrt, übersprungen).

Absender-Domains

GET/api/v1/domains

Absender-Domains des Kontos mit Stand von DKIM, MAIL FROM und DMARC.

MCP-Werkzeug domains_liste · liest nur · auch bei gesperrtem Konto

Keine Felder.

POST/api/v1/domains

Absender-Domain hinzufügen. Gibt die DNS-Einträge zurück, die beim Domain-Anbieter zu setzen sind.

MCP-Werkzeug domain_hinzufuegen

domainPflicht
stringhöchstens 253 Zeichen

POST/api/v1/domains/pruefen

DNS-Einträge einer Domain erneut prüfen und den Stand speichern.

MCP-Werkzeug domain_pruefen · auch bei gesperrtem Konto

domainPflicht
string

API-Schlüssel

Nur im Dashboard

  • schluessel_liste — Aktive API-Schlüssel des Kontos (ohne den Schlüssel selbst).
  • schluessel_erstellen — Neuen API-Schlüssel erzeugen. Er wird genau einmal angezeigt.
  • schluessel_widerrufen — API-Schlüssel sofort ungültig machen.

MCP-Server

Der MCP-Server spricht Streamable HTTP (Protokoll 2025-06-18), zustandslos und nur mit JSON-Antworten. Er nimmt POST-Anfragen unter https://zugestellt.ch/mcp entgegen, auch als Batch. Die Werkzeuge sind die 24 Aktionen oben, mit denselben Feldern; Hinweise wie «liest nur» gehen als Annotationen mit.

Angemeldet wird mit demselben API-Schlüssel als Bearer-Token.

Claude Code
claude mcp add --transport http zugestellt https://zugestellt.ch/mcp \
  --header "Authorization: Bearer zst_…"
.mcp.json (Claude Code im Projekt) oder Cursor
{
  "mcpServers": {
    "zugestellt": {
      "type": "http",
      "url": "https://zugestellt.ch/mcp",
      "headers": {
        "Authorization": "Bearer zst_…"
      }
    }
  }
}

Connectors in claude.ai und ChatGPT melden sich über OAuth an. Das unterstützt zugestellt noch nicht; bis dahin verbinden Sie Claude Code, Cursor oder einen eigenen Agenten mit dem Schlüssel.

Ohne Client: Werkzeuge abfragen
curl -X POST https://zugestellt.ch/mcp \
  -H "Authorization: Bearer zst_…" \
  -H "Content-Type: application/json" \
  -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }'

Ohne gültigen Schlüssel antwortet der Server mit HTTP 401 und dem JSON-RPC-Fehler -32001. Schlägt eine Aktion fehl, enthält das Ergebnis isError: true und Code und Meldung wie bei der REST-API.

Anmeldeformular

POST https://zugestellt.ch/api/anmelden nimmt Anmeldungen von Ihrer Website an. Es braucht keinen Schlüssel; der Newsletter wird über sein Kürzel bestimmt. Die Anleitung für Website-Betreiber steht im Hilfe-Artikel.

newsletter
Kürzel des Newsletters (Pflicht)
email
E-Mail-Adresse (Pflicht)
vorname
optional, höchstens 100 Zeichen
website
unsichtbares Feld gegen Roboter, muss leer bleiben

Als Formular (application/x-www-form-urlencoded) leitet zugestellt mit 303 auf die Archivseite/p/<kürzel>?anmeldung=… weiter. Mit Content-Type: application/json oder Accept: application/json kommt JSON zurück. CORS ist für alle Herkünfte offen.

JSON
curl -X POST https://zugestellt.ch/api/anmelden \
  -H "Content-Type: application/json" \
  -d '{ "newsletter": "ihr-kuerzel", "email": "anna@beispiel.ch", "vorname": "Anna" }'

{ "ok": true, "ergebnis": "bestaetigen" }
200 bestaetigen
Bestätigungsmail ist unterwegs (Double-Opt-in).
200 angemeldet
Ohne Double-Opt-in direkt angemeldet.
422 fehler_adresse
Adresse ungültig, Wegwerf-Adresse oder Tippfehler.
429 fehler_zu_viele
Mehr als 5 Versuche pro IP in 10 Minuten oder Flut auf den Newsletter.
403 fehler_seite
Die Website steht nicht in der Liste der erlaubten Websites.
404 fehler_unbekannt
Kürzel unbekannt.

Ob eine Adresse neu, schon angemeldet oder gesperrt ist, verrät die Antwort absichtlich nicht. Die erlaubten Websites prüft zugestellt am Origin-Header; Anfragen von einem Server ohne diesen Header werden bei gefüllter Liste abgelehnt. Von einem Server aus nehmen Sie darum besser kontakt_hinzufuegen mit einem Schlüssel der Stufe «Nur Anmeldungen».