Endpunkt- & Antwort-Referenz
POST/api/shop/sessionerstellen mit Bearer-Secret
DELETE/api/shop/session/:tokenwiderrufen mit Bearer-Secret
Beide Aufrufe kommen von deinem Backend: Es authentifiziert sich mit dem Mint-Secret deines Clients (erzeugt in der ADITUS-Admin-Konsole) als Bearer-Token. Eine Session pro Login ist das normale Muster; der Browser sieht nur den entstandenen Token. Websites ohne Backend nutzen diese Endpunkte nicht: Das Element erstellt seine Browser-Session selbst über den domain-beschränkten POST /api/shop/embed-session (public-key mit cart-scope="tab").
Diesen exakten Ablauf kannst du mit deinen eigenen Zugangsdaten im Integrations-Tester ausprobieren. Erstelle eine Session, mounte den Shop und durchlaufe die Journey.
Session erstellen: Request
HeaderWertBedeutung
AuthorizationBearer <mint-secret>Das Mint-Secret deines Clients, erzeugt in der ADITUS-Admin-Konsole. Nur server-seitig. Es darf nie in einen Browser oder ein App-Bundle gelangen.
Content-Typeapplication/jsonDer Body ist ein JSON-Objekt.
Idempotency-Keystring · 8–200 visible ASCII chars · required with redeemVoucherOnMintPflicht bei redeemVoucherOnMint: true: 8–200 sichtbare ASCII-Zeichen. Ein stabiler Schlüssel für einen logischen Einlöseversuch; auf deinem Backend speichern und bei Wiederholungen mit exakt demselben Request verwenden. Ein anderer Request mit demselben Schlüssel liefert 409 idempotency_conflict. Weder Mint-Secret noch diesen Schlüssel im Browser senden.
Body-FeldTypBedeutung
sharedCartKeystring · optionalIdentifizierte, server-zu-server erstellte Sessions teilen normalerweise über die vertrauenswürdige Identität. Für anonyme gemeinsame Warenkörbe MUSS dein Backend die Session mit sharedCartKey erstellen: einer opaken, stabilen Besucherreferenz aus deiner eigenen vertrauenswürdigen Besucher-Session, keiner E-Mail. Das ist ein reines Server-Session-Feld, keine Browser-Config und kein HTML-Attribut. Akzeptiere niemals beliebige E-Mail, Identität oder sharedCartKey aus dem Browser. Eine im Browser erstellte Session allein kann keine sichere Freigabe herstellen; shared ohne vertrauenswürdige Identität liefert einen expliziten Nicht-unterstützt-Fehler, auch beim Weglassen des Scopes. Explizite 'tab'-Isolation benötigt keinen sharedCartKey; es gibt keinen stillen Fallback.
publicKeystring · PflichtDer Publishable Key, für den die Session erstellt wird. Es muss derselbe Key sein, mit dem das Micro-Frontend mountet. Jeder spätere Shop-Call wird dagegen geprüft (403 bei Abweichung). Das Bearer-Secret muss zum Client dieses Keys gehören.
emailstring · optionalDer Shop-User, als der die Session agiert. Nimm sie aus deiner authentifizierten Server-Session (Login-/SSO-Cookie oder JWT), nie aus dem Browser-Request, sonst könnte ein Besucher eine fremde Session erhalten. Fehlt das Feld, entsteht eine anonyme Session: Der Besucher kann browsen und den Warenkorb füllen, aber das Micro-Frontend blockiert den Schritt aus dem Warenkorb, bis dein onUserRequired-Callback eine nutzergebundene Session liefert (siehe Optional-User-Flow). Eine mitgeschickte, aber ungültige E-Mail bleibt ein 400.
externalUserIdstring · optionalDeine stabile Nutzerreferenz aus deiner authentifizierten Server-Session. Wird an der Session gespeichert und, wenn vorhanden, für den Identitäts-Scope genutzt; ändere sie beim Token-Refresh nicht und akzeptiere sie nicht aus beliebiger Browser-Eingabe. Sie ist selbst keine Authentifizierung.
ttlSecondsnumber · optionalLebensdauer der Session in Sekunden. Default 20 Minuten, Obergrenze 24 Stunden. Nach Ablauf liefern Shop-Calls 401 session_expired. Stelle dann einen frischen Token aus; mit refreshSession in der Config fordert das Micro-Frontend ihn automatisch an.
eventSlugstring · optionalLegt den Einstiegspunkt der Journey serverseitig fest: gesetzt startet das Micro-Frontend direkt in der Artikelauswahl dieser Veranstaltung; weggelassen mit der Veranstaltungsübersicht. Da er Teil der erstellten Session ist, kann der Browser ihn nicht manipulieren. Ungültige Zeichen liefern 400 invalid_event_slug; bei einem Slug ohne passendes Live-Event (404 event_not_found) oder einem geschlossenen bzw. nicht verkaufbaren Event (409 event_not_sellable) schlägt die Session-Erstellung bewusst fehl. Es wird keine Session erstellt und es gibt keinen Rückfall auf die Veranstaltungsübersicht.
startMode "home" Einstiegsansicht der Journey. "articles" (Standard) öffnet die Artikelauswahl; "home" öffnet die Startseite der Veranstaltung mit ihren Einstiegen (Tickets, Gutschein, freigegebene Sortimente); "voucher" öffnet zuerst die Gutschein-/Ticketcode-Maske. Die Gutschein-Maske verhält sich wie unter „Gutschein einlösen / Ticket registrieren“ beschrieben. Ohne eventSlug kommt zuerst die Veranstaltungsauswahl, danach gilt der Modus für das gewählte Event.
assortmentstring · optionalBeschränkt den Artikelstart auf ein Sortiment der festgelegten Veranstaltung (braucht eventSlug; bei startMode "voucher" ohne Wirkung). Angegeben wird die Sortiments-Id oder der exakte Name (Groß-/Kleinschreibung egal); versteckte Sortimente sind erlaubt. Ein Wert ohne Treffer zeigt im Micro-Frontend eine sichtbare Fehlermeldung statt still auf die volle Liste zurückzufallen. Max. 200 Zeichen, sonst 400 invalid_assortment.
voucherCodestring · optionalGutschein-/Ticketcode, den dein Server mit der Session übergibt (beide Startmodi). Standardmäßig löst das Embed ihn bei einer frischen Journey ein, ohne festgelegtes Event erst nach der Eventauswahl; eine Ablehnung erscheint in der Maske bzw. am ersten Warenkorb. Mit redeemVoucherOnMint: true wird er stattdessen vor einer erfolgreichen Session-Antwort serverseitig reserviert – nur für ein festgelegtes Event und einen identifizierten Nutzer. Format: 1–100 Zeichen ohne Leerzeichen oder URL-Trennzeichen, sonst 400 invalid_voucher_code.
redeemVoucherOnMintboolean · optional (default false)Nur bei serverseitiger Session-Erstellung mit voucherCode, festgelegtem eventSlug, identifizierter email und Idempotency-Key auf true setzen. Die Session-Erstellung legt einen nutzergebundenen Warenkorb an und reserviert den Gutschein tatsächlich, bevor er die Session ausgibt. Das Embed übernimmt den Warenkorb ohne zweite Anlage oder Einlösung; beide Startmodi funktionieren. Nur Gutschein-/Ticketcodes, keine PromotionCodes. Ohne die Option gilt die normale voucherCode-Übergabe. Registrierung und Abschluss folgen weiterhin.
Session erstellen: Antwort (200)
FeldTypBedeutung
sessionTokenstringOpaker Token (sess_…). An den Browser weiterreichen und bei mount() als sessionToken setzen; das Micro-Frontend sendet ihn bei jedem Shop-Call als X-Aditus-Session. Er enthält keine Nutzerdaten und ist nicht dekodierbar.
expiresAtnumberAblauf als Unix-Timestamp in Millisekunden. Rein informativ für deine eigene Planung. Das Micro-Frontend reagiert selbst auf das 401.
voucherRedeemedboolean · only with redeemVoucherOnMinttrue, wenn die optionale Session-Erstellung mit vorbereitetem Gutschein erfolgreich ist. Der zurückgegebene Session-Token besitzt bereits einen Warenkorb mit Gutscheinreservierung; das Embed übernimmt ihn. Dies ist keine abgeschlossene Ticketregistrierung.
Session widerrufen
DELETE /api/shop/session/:token mit demselben Bearer-Secret. Es muss zum Client gehören, für den die Session erstellt wurde. Beim Logout oder Kiosk-Reset aufrufen, damit der Token zusammen mit deiner eigenen Session stirbt. Bei anonymen (token-gebundenen) Sessions löscht der Aufruf zusätzlich die Warenkörbe der Session in der Shop-API. Von diesen Warenkörben gehaltene Gutschein-Reservierungen werden sofort frei, nicht erst mit dem Ablauf des Warenkorbs. Antwort: { "revoked": true, "carts": { "scope": "token", "deleted": 1, "failed": 0 } } (revoked false, wenn die Session schon abgelaufen war; scope "identity" bei nutzergebundenen Sessions, deren Warenkörbe einen einzelnen Token überdauern und unangetastet bleiben). Der Widerruf ist idempotent und kann fire-and-forget gesendet werden.
Server-zu-Server-Reads
Ein Backend, das das Micro-Frontend steuert (eine Kiosk-Shell, ein Onsite-Shop) braucht meist Mandantenfakten, bevor es eine Session erstellt: welche Events es gibt und im Verkauf sind, welche Sprachen der Shop spricht, welche Lookup-Listen und welches Branding gelten. Vier Lese-Endpunkte beantworten das mit denselben Zugangsdaten wie die Session-Erstellung (Bearer Mint-Secret + Header X-Aditus-Public-Key, gleiches Rate-Limit, Cache-Control: no-store). Sie sind Whitelist-Projektionen der Shop-API, nie eine Rohweiterleitung; ?language= (oder Accept-Language, Standard de) wählt die Sprache der Namen. Fehler: 400 invalid_public_key, 401 unauthorized, 503 shop_api_not_configured, 502 upstream_error.
EndpunktLiefert
GET /api/shop/events?language=deAlle Events des Mandanten: id, slug, name, year, start/end, location, saleState (open · registration_only · closed), die Rohflags, showInOverview, languages, Icon-/Logo-URLs. Den Slug für die Session nimmst du von hier.
GET /api/shop/configurationMandantendaten: mandator, die Namen der Lookup-Listen (Anreden, Länder, Titel, Cookie-Consent) und websiteMetricTracking. Login-Provider-Zugangsdaten des Mandanten sind bewusst nie enthalten.
GET /api/shop/languagessystemLanguage plus die Liste der Shop-Sprachen ({ code, name }). Dies sind die Werte, die das culture-Attribut des Micro-Frontends akzeptiert.
GET /api/shop/branding?images=ONSITE_SHOP_LOGO,…Das Shop-Theme des Mandanten: styles als flache key → value-Map, die Theme-Bilder mit URLs und (für bis zu 40 von dir genannte Bild-Keys (A–Z, 0–9, _ , -)) ob der Key existiert, seine öffentliche URL und der Content-Type. Bild-URLs brauchen keine Auth und lassen sich direkt in deiner Shell verwenden. Mit &eventSlug=<slug> oder &event=<GUID> beziehst du Theme und Keys auf ein Event (Event-Overrides, nur dort vorhandene Keys wie ONSITE_SHOP_HEADER / ONSITE_SHOP_ATTRACT_*); die Antwort nennt dann das aufgelöste Event. Unbekannter Slug → 404 event_not_found, kein GUID → 400 invalid_event, Shop-API nicht erreichbar → 503 event_unavailable.
Fehler sind explizit
StatusCodeBedeutung
503session_not_configuredMinting ist für diesen Client deaktiviert: Im Admin wurde noch kein Mint-Secret erzeugt.
401unauthorizeddas Mint-Secret ist falsch oder fehlt. Prüfe, ob das Secret zum Client genau dieses Public Keys gehört (ein rotiertes Secret macht das alte sofort ungültig).
400invalid_public_keyder Public Key ist fehlerhaft oder nicht registriert. Er muss die Form pk_… haben und zu einem eingerichteten Client gehören.
400invalid_emaildie E-Mail des Shop-Users fehlt oder ist keine gültige Adresse.
400invalid_tokender Session-Token im Revoke-Aufruf ist fehlerhaft. Übergib genau den sessionToken aus der Mint-Antwort.
429rate_limitedzu viele Mint-/Revoke-Aufrufe von deiner IP. Warte eine Minute und versuch es erneut.
403public_key_invalidder Header X-Aditus-Public-Key ist fehlerhaft. Er muss die Form pk_… haben, genau wie beim Onboarding ausgegeben.
403public_key_unknownder X-Aditus-Public-Key ist wohlgeformt, aber nicht registriert (oder deaktiviert). Prüfe auf Tippfehler und ob der Client des Keys aktiv ist.
403public_key_origin_unresolveddie Anfrage trug einen publicKey, aber keinen verwertbaren Origin-/Referer-Header, daher kann die Domain-Whitelist nicht geprüft werden. Browser senden Origin automatisch; Server-zu-Server-Aufrufe dürfen den publicKey-Header nicht nutzen.
403public_key_domain_not_alloweddie Herkunftsdomain der Anfrage steht nicht auf der Whitelist dieses publicKey. Lass die Domain beim Onboarding (oder im Admin) freischalten, bevor du dort live gehst.
401invalid_sessionder Shop-Call trug einen fehlerhaften X-Aditus-Session-Token. Es gibt keinen Rückfall auf einen anderen Nutzer. Übergib genau den sessionToken (sess_…) aus der Mint-Antwort.
401session_expiredder X-Aditus-Session-Token ist unbekannt, widerrufen oder abgelaufen. Es gibt keinen Rückfall auf einen anderen Nutzer. Minte server-zu-server eine frische Session.
403session_requires_public_keyeine Session wurde ohne den Header X-Aditus-Public-Key gesendet (Origin-Pinning ist Pflicht, sobald eine Session im Spiel ist).
403session_key_mismatchder X-Aditus-Public-Key passt nicht zu dem Key, für den die Session gemintet wurde.
403anonymous_sessiondie Session wurde OHNE E-Mail gemintet (anonym) und erlaubt nur Browsen und Warenkorb. Registrierung, Zahlung und Checkout brauchen eine nutzergebundene Session. Erstelle sie über onUserRequired.