Markus Michalski FAQ

Newsletter Management: Shop API

Shop API des Newsletter-Plugins für Sylius - Anmeldung, Bestätigung, Abmeldung, Einstellungen und Kategorien headless nutzen, mit curl-Beispielen, Parametern und Fehlerformat

English Version

Zurück zur Übersicht

Newsletter Management: Shop API

Diese Dokumentation bezieht sich immer auf die aktuellste veröffentlichte Version.

Das Plugin läuft zweigleisig: Anmeldung, Bestätigung, Abmeldung und Verwalten des Abonnements funktionieren im Twig-Storefront und headless über die Shop API, und beide Wege laufen durch denselben Domain-Service (NewsletterSubscriptionManager). Es gibt keine zweite Geschäftslogik im API-Code.

graph LR
    A["Storefront Formular"] --> C["NewsletterSubscriptionManager"]
    B["Shop API Request"] --> C
    C --> D{"Newsletter im Channel aktiv?"}
    D -->|"Nein"| E["404"]
    D -->|"Ja"| F["PRE_SUBSCRIBE Event"]
    F -->|"abgelehnt"| G["422"]
    F -->|"akzeptiert"| H["Abonnement + Bestätigungs-Mail"]

Endpunkte

Alle Pfade liegen unter dem Shop-API-Präfix deines Sylius-Projekts (Standard: /api/v2), also zum Beispiel /api/v2/shop/newsletter-subscriptions. Anfragen mit Body (POST, PUT) senden Content-Type: application/json.

Method Path Beschreibung
POST /shop/newsletter-subscriptions Anmeldung. Antwortet mit 202 und ohne Body, egal ob die Adresse neu, noch unbestätigt oder schon bestätigt ist
POST /shop/newsletter-subscriptions/confirm Bestätigt per Token (Double Opt-in). 204 bei Erfolg, 404 bei unbekanntem oder bereits abgemeldetem Token
POST /shop/newsletter-subscriptions/unsubscribe Meldet per Token ab. 204 bei Erfolg (auch wenn schon abgemeldet), 404 bei unbekanntem Token
GET /shop/newsletter-preferences/{token} Liest Name, Kategorien und Tracking-Einwilligung eines bestätigten Abonnements
PUT /shop/newsletter-preferences/{token} Ändert Name, Kategorien und Tracking-Einwilligung. Die E-Mail-Adresse lässt sich nie ändern
GET /shop/newsletter-categories Liste der Kategorien, die der aktuelle Channel anbietet, nach Position sortiert
GET /shop/newsletter-categories/{id} Eine einzelne Kategorie (404, wenn deaktiviert oder für einen anderen Channel beschränkt)

Der Token in /confirm und /unsubscribe ist der 64 Zeichen lange Token aus dem Link der jeweiligen Mail. Bei /shop/newsletter-preferences/{token} ist es der Abmelde-Token, den jede Newsletter-Mail im Footer trägt. Ein Token anderer Länge im Body von /confirm und /unsubscribe ergibt 422, ein unbekannter Token in der URL von /shop/newsletter-preferences/{token} 404.

Channel

Die Endpunkte arbeiten immer für den Channel, den Sylius für die Anfrage ermittelt (in der Regel über den Hostnamen). Ist der Newsletter für diesen Channel nicht aktiviert, antwortet die Anmeldung mit 404, und die Kategorien-Liste ist unabhängig davon auf die Kategorien dieses Channels begrenzt. Die Einstellung findest du unter Konfiguration.

Anmeldung

Body

Feld Typ Pflicht Beschreibung
email string ja Gültige E-Mail-Adresse, maximal 255 Zeichen. Wird klein geschrieben gespeichert
consent boolean ja Muss true sein, sonst 422
firstName string nein Maximal 100 Zeichen
lastName string nein Maximal 100 Zeichen
categories string nein Kategorie-Codes. Leer bedeutet: der allgemeine Newsletter, also alles. Unbekannte, deaktivierte oder für den Channel nicht angebotene Codes werden verworfen
trackingConsent boolean nein Einwilligung in persönliches Tracking, Standard false. Zählt nur, wenn der Channel den Tracking-Modus Personenbezogen hat

Beispiel

curl -X POST https://shop.example.com/api/v2/shop/newsletter-subscriptions \
  -H "Content-Type: application/json" \
  -d '{
        "email": "anna.beispiel@example.com",
        "firstName": "Anna",
        "lastName": "Beispiel",
        "categories": ["neuheiten", "tutorials"],
        "consent": true
      }'

Antwort: 202 Accepted ohne Body. Bei aktiviertem Double Opt-in (Standard) bekommt die Adresse jetzt die Bestätigungs-Mail. Ist die Adresse schon bestätigt, ändert die Anfrage nichts am Abonnement, und die Adresse erhält stattdessen die Mail "bereits angemeldet". So lässt sich über die API nicht herausfinden, wer auf der Liste steht.

Mails, die ein öffentliches Formular auslöst, werden pro Adresse gedrosselt: Innerhalb von 10 Minuten geht höchstens eine solche Mail an dieselbe Adresse. Die Antwort bleibt trotzdem 202.

Bestätigen und Abmelden

Die Mail verlinkt auf die Storefront-Seite. Ein Headless-Shop liest den Token aus diesem Link (Pfad /newsletter/confirm/{token} beziehungsweise /newsletter/unsubscribe/{token}) und sendet ihn an die API:

curl -X POST https://shop.example.com/api/v2/shop/newsletter-subscriptions/confirm \
  -H "Content-Type: application/json" \
  -d '{"token": "3f9a1c0e5b7d42a8c6e1f0b9d8a7c6e5f4b3a29180716253443526170809a0b1"}'

Antwort: 204 No Content. Für die Abmeldung gilt derselbe Aufruf an /shop/newsletter-subscriptions/unsubscribe.

Einstellungen des Abonnenten

curl https://shop.example.com/api/v2/shop/newsletter-preferences/TOKEN \
  -H "Accept: application/json"

Die Antwort enthält email (nur lesbar), firstName, lastName, trackingConsent und categories (Liste der Codes). Der Token selbst steht nie in der Antwort. Für unbekannte Token und für noch unbestätigte Abonnements antwortet die API mit 404.

curl -X PUT https://shop.example.com/api/v2/shop/newsletter-preferences/TOKEN \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
        "firstName": "Anna",
        "lastName": "Beispiel",
        "categories": ["tutorials"],
        "trackingConsent": false
      }'

Die Antwort zeigt, was tatsächlich gespeichert wurde: unbekannte oder deaktivierte Kategorie-Codes fehlen dort. Ein mitgesendetes email-Feld wird ignoriert.

Feld Verhalten bei PUT
firstName, lastName Werden ersetzt (maximal 100 Zeichen). Fehlt ein Feld, wird der Name geleert
categories Ersetzt die bisherige Auswahl. Eine leere Liste bedeutet den allgemeinen Newsletter
trackingConsent Weggelassen (null) lässt die Einwilligung unverändert. false widerruft sie und löscht die persönlichen Tracking-Daten. true erteilt sie, aber nur wenn der Channel den Modus Personenbezogen hat

Kategorien

curl https://shop.example.com/api/v2/shop/newsletter-categories \
  -H "Accept: application/json"

Jede Kategorie enthält id, code, position, name und description; name und description kommen in der Sprache der Anfrage. Es erscheinen nur aktivierte Kategorien, die entweder für alle Channels oder für den aktuellen Channel angeboten werden.

Fehlerformat

Status Wann
202 Anmeldung angenommen (sagt nichts über den Zustand der Adresse aus)
204 Bestätigung oder Abmeldung erfolgreich
404 Newsletter für den Channel nicht aktiviert, unbekannter Token oder Kategorie nicht verfügbar
422 Validierungsfehler (ungültige E-Mail-Adresse, consent nicht true, Token nicht 64 Zeichen lang, Felder zu lang) oder Ablehnung durch ein PRE_SUBSCRIBE-Listener

Eine Ablehnung durch ein Spam-Schutz-Plugin liefert ebenfalls 422; als Meldung steht der Grund, den der Listener übergeben hat (ein Übersetzungsschlüssel oder der Standardtext "Signup rejected."). Wie du so einen Listener schreibst, steht unter Erweiterbarkeit.

Das ALTCHA-Plugin schützt die Anmeldung auch über die API. Der Proof gehört dann in den Header X-Altcha-Payload, siehe ALTCHA: Shop API.

Nicht über die API verfügbar

Die Shop API deckt nur das ab, was ein Kunde selbst tut. Folgendes gibt es ausschließlich im Admin (Twig):

Die Bestätigungs-Mail linkt auf die Storefront-Seite. Ein reiner Headless-Shop muss diesen Link in der Mail-Vorlage auf sein eigenes Frontend umschreiben und den Token von dort an die API senden.