API-Referenz
Über die Shopware Admin API können Integrationen Landingpages und Generierungsregeln verwalten, Generierungsläufe starten und Laufberichte auslesen. Dieses Kapitel beschreibt die Schnittstellen des Plugins für Shopware 6.7.
Zugang und Konventionen
Legen Sie in Shopware unter Einstellungen → System → Integrationen einen Zugang mit den benötigten Berechtigungen an. Mit Zugangs-ID und Sicherheitsschlüssel erhalten Sie ein OAuth-Token:
POST /api/oauth/token
Content-Type: application/json
Accept: application/json
{
"grant_type": "client_credentials",
"client_id": "<zugangs-id>",
"client_secret": "<sicherheitsschluessel>"
}Verwenden Sie access_token aus der Antwort als Bearer-Token und beachten Sie seine Gültigkeit in expires_in. Details erläutert die Shopware-Dokumentation zur Authentifizierung.
Für alle folgenden Admin-Requests gelten diese Header; sw-language-id ist optional und wählt die Sprache für übersetzte Felder:
Authorization: Bearer <access-token>
Content-Type: application/json
Accept: application/json
sw-language-id: <sprach-id>- Alle Pfade sind relativ zur Shop-Basis-URL, beispielsweise
https://shop.example.com. - Ersetzen Sie Platzhalter in spitzen Klammern und Pfadparameter wie
{id}. Entity-IDs sind UUIDs als 32 Hex-Zeichen ohne Bindestriche. - Die Beispiele verwenden
Accept: application/json. Entity-Suchen liefern einedata-Liste, Einzelabfragen ein Objekt unterdata. Mitapplication/vnd.api+jsonverwendet Shopware eine andere Darstellung mitattributesundrelationships. - Plugin-Aktionen liefern eigene JSON-Objekte, etwa
{"run": {...}}oder{"success": true}. - Bei Schreibzugriffen auf übersetzte Felder muss die Systemsprache versorgt sein. Weitere Sprachen können Sie über
translationsmit der Sprach-ID als Schlüssel schreiben.
Berechtigungen und Erweiterungen
Entity-Zugriffe benötigen die passenden Rechte im Format entity:read, entity:create, entity:update oder entity:delete. Die technischen Entity-Namen enthalten Unterstriche, die URL-Pfade Bindestriche. Beim Lesen und Schreiben von Associations werden zusätzlich die Rechte der beteiligten Entities benötigt, etwa für Übersetzungen, Kategorie, Eigenschaften und Verkaufskanäle.
Die Landingpage-Rollen Betrachter, Bearbeiter, Ersteller und Löscher bündeln diese Rechte in der Administration. Für die Plugin-Aktionen gelten folgende zusätzlich am Endpunkt hinterlegte ACL-Rechte:
| Aktion | ACL-Recht |
|---|---|
| Generierungsläufe starten, alle starten, abbrechen | repertus_landingpage_generation_rule:update |
| Worker-Konfiguration lesen | repertus_landingpage_generation_run:read |
| Verfügbare Facettenwerte lesen | repertus_seo_filter_landingpage.viewer |
Aufruf-URLs neu generieren (generate, generateAll) | api_action_cache_index |
IAP-Status, Konvertierung, Navigationswarnungen und Kategorie-Filter haben aktuell kein zusätzliches _acl-Recht an der Route. Sie erfordern weiterhin eine Admin-API-Authentifizierung. Die nachfolgenden IAP- und Datenprüfungen gelten unabhängig davon.
Die Erweiterung Landingpage-Generator ist für das Anlegen und Bearbeiten von Generierungsregeln samt Unterobjekten sowie für neue Läufe erforderlich. Lesen, Abbrechen, Abkoppeln und Löschen bleiben ohne diese Erweiterung möglich. Für die Konvertierung zu per_sales_channel und das Bearbeiten solcher Landingpages ist die separate Erweiterung Pro-Sales-Channel-Konfiguration erforderlich. Die Rückkehr zu shared bleibt möglich. Siehe Generator und Konfiguration pro Sales-Channel.
Entity-Endpunkte
Das Plugin verwendet Shopwares generische Entity-Endpunkte:
| Daten | Technischer Entity-Name | Pfad unter /api/ |
|---|---|---|
| Landingpages einschließlich Sales-Channel-Variants | repertus_seo_filter_landingpage | repertus-seo-filter-landingpage |
| Parameter einer Landingpage | repertus_seo_filter_landingpage_parameter | repertus-seo-filter-landingpage-parameter |
| Generierungsregeln | repertus_landingpage_generation_rule | repertus-landingpage-generation-rule |
| Facetten | repertus_landingpage_generation_rule_facet | repertus-landingpage-generation-rule-facet |
| Kombinationsmuster | repertus_landingpage_generation_rule_pattern | repertus-landingpage-generation-rule-pattern |
| Preisspannen | repertus_landingpage_generation_rule_price_range | repertus-landingpage-generation-rule-price-range |
| Generierungsläufe, nur lesbar | repertus_landingpage_generation_run | repertus-landingpage-generation-run |
| Methode und Pfad | Verwendung |
|---|---|
POST /api/search/{entity-pfad} | Suchen mit Filtern, Sortierung, Seitennavigation und Associations |
GET /api/{entity-pfad}/{id} | Einzelnen Datensatz lesen |
POST /api/{entity-pfad} | Datensatz anlegen |
PATCH /api/{entity-pfad}/{id} | Nur die zu ändernden Felder schreiben |
DELETE /api/{entity-pfad}/{id} | Datensatz löschen |
Erfolgreiche Schreibzugriffe liefern standardmäßig 204 No Content. Bei POST und PATCH können Sie mit ?_response=detail den gespeicherten Datensatz anfordern. Grundlagen und Association-Verhalten beschreibt Shopware unter „Writing entities“.
Die vollständigen Felddefinitionen des installierten Plugins erhalten Sie mit einem authentifizierten GET /api/_info/entity-schema.json. Die obige Tabelle enthält die wichtigsten Entities; Übersetzungs- und Zuordnungstabellen sind ebenfalls im Schema enthalten. Die generierte Shopware-Referenz ergänzt den allgemeinen API-Vertrag.
Landingpages lesen und schreiben
Master-Landingpages suchen
Der Filter auf parentId: null liefert nur Master-Landingpages. Ohne diesen Filter können auch Sales-Channel-Variants als eigene Treffer erscheinen. Für ausschließlich manuelle oder abgekoppelte Seiten ergänzen Sie einen Equals-Filter auf generationRuleId: null.
POST /api/search/repertus-seo-filter-landingpage
{
"page": 1,
"limit": 25,
"total-count-mode": 1,
"filter": [{ "type": "equals", "field": "parentId", "value": null }],
"sort": [{ "field": "createdAt", "order": "DESC" }],
"associations": {
"translations": {},
"salesChannels": {},
"properties": {},
"manufacturers": {},
"parameters": {},
"children": {
"associations": {
"salesChannel": {},
"properties": {},
"manufacturers": {},
"parameters": {}
}
}
}
}Manuelle Landingpage anlegen
Dieses Beispiel legt eine aktive Master-Landingpage im Konfigurations-Modus shared an. Verwenden Sie existierende IDs für Kategorie, Property-Option und Verkaufskanal sowie eine neue ID für die Landingpage. Schreiben Sie das Beispiel in der Systemsprache; für weitere Sprachen verwenden Sie translations.
POST /api/repertus-seo-filter-landingpage
{
"id": "<neue-landingpage-id>",
"name": "Tischdeko in Creme",
"configurationMode": "shared",
"enabled": true,
"robotType": "follow, index",
"title": "Tischdeko in Creme",
"metaTitle": "Tischdeko in Creme kaufen",
"categoryId": "<kategorie-id>",
"canonicalForeignKey": "<neue-landingpage-id>",
"salesChannels": [{ "id": "<sales-channel-id>" }],
"properties": [{ "id": "<property-option-id>" }],
"parameters": [{ "type": "min-price", "value": "10" }]
}| Feld | Bedeutung |
|---|---|
name, robotType, title, metaTitle | Pflichtangaben beim Anlegen einer Master-Landingpage; title und metaTitle sind übersetzbar. |
categoryId, properties, manufacturers, parameters | Kategorie und vollständige FilterCombination. properties referenziert Property-Optionen; manufacturers referenziert Produkthersteller. Parameter bestehen aus type und einem String in value, etwa max-price / 30 oder shipping-free / 1. |
salesChannels | Sales-Channel-Sichtbarkeit im Modus shared. |
parentId, salesChannelId, children | Parent-Child-Zuordnung im Modus per_sales_channel; die Sichtbarkeit ergibt sich dort aus den Sales-Channel-Variants. |
enabled | Aktivierung am Master, gilt auch für seine Sales-Channel-Variants. |
cmsPageId, slotConfig | Erlebniswelten-Layout und übersetzbare Slot-Konfiguration. |
metaDescription, keywords, description, breadcrumb, ogTitle, ogDescription | Weitere übersetzbare Inhalte. |
openGraphMediaId, sitemapPrio, changeFreq, sitemapExclude, useScNav | Open-Graph-Bild, Sitemap- und Navigationseinstellungen. |
canonicalForeignKey | ID des Canonical-Ziels (seo_url.foreign_key), keine URL und keine seo_url.id. Für Selbstbezug die ID der identitätstragenden Landingpage verwenden. |
generationRuleId, generationKey | Zuordnung einer generierten Landingpage. Die Zuordnung setzt der Generator. |
Bei Updates werden Associations ergänzt bzw. ihre enthaltenen Datensätze aktualisiert. Ein leeres properties, salesChannels oder parameters entfernt vorhandene Zuordnungen nicht. Löschen Sie entfernte Zuordnungen bzw. Parameter gezielt über die entsprechenden Entity-/Association-Endpunkte. Beim Ändern eines Parameters dessen vorhandene id mitsenden, um ihn zu aktualisieren.
Sales-Channel-Variants tragen ihre vollständige Kategorie und FilterCombination selbst. categoryId ist erforderlich, useScNav: true ist dort unzulässig. Die Admin API liest standardmäßig Rohwerte ohne aufgelöste Vererbung; leere Variant-Felder bedeuten deshalb nicht automatisch leere Storefront-Inhalte. Verwenden Sie für einen bestehenden Master die unten beschriebenen Konvertierungsaktionen.
Generierte Landingpage abkoppeln
Solange generationRuleId gesetzt ist, sind Inhaltsänderungen über den Landingpage-Entity-Endpunkt gesperrt. Das Abkoppeln ist ein eigener Schreibzugriff mit ausschließlich diesem Feld:
PATCH /api/repertus-seo-filter-landingpage/{id}
{ "generationRuleId": null }Danach können Sie Inhalte in einem weiteren Request ändern. URL, Inhalt und generationKey bleiben beim Abkoppeln erhalten; der Generator überspringt die weiterhin belegte FilterCombination. Ein DELETE entfernt die Seite, verhindert aber keine spätere Neuanlage durch ihre Regel.
Generierungsregeln
Regeln werden über repertus-landingpage-generation-rule angelegt und geändert. Die wichtigsten Felder und Associations sind:
| Feld | Inhalt |
|---|---|
name, active | Name und Aktivierung; inaktive Regeln lassen sich nicht starten. |
minProductCount, maxLandingpageCount | Mindestproduktzahl und Obergrenze, jeweils mindestens 1; Standard 1 und 1000. |
salesChannels, languages, categories | Je eine Liste aus {"id": "…"}. Kategorien werden explizit zugewiesen, Unterkategorien nicht automatisch aufgenommen. |
facets | type: manufacturer, property_group oder price_range; dazu variableName und valueMode (all oder explicit). Property-Facetten verwenden propertyGroupId und ggf. options, Herstellerfacetten ggf. manufacturers, Preisfacetten priceRanges. |
priceRanges an einer Facette | Je min, max und übersetzbarer name. Mindestens eine Grenze ist erforderlich; Grenzen sind nicht negativ und bei zwei Grenzen gilt min < max. |
patterns | Mindestens eine Referenz unter facets; übersetzbare Pflichtfelder titleTemplate und metaTitleTemplate, optional metaDescriptionTemplate, breadcrumbTemplate und urlTemplate. |
| Seiteneinstellungen | An Regel und Muster u. a. cmsPageId, robotType, sitemapPrio, changeFreq, sitemapExclude, useScNav, openGraphMediaId und übersetzbare Inhalte samt slotConfig. Die Vererbung erläutert der Generator. |
lastRunId, lastRun, runs | Letzter Lauf und Historie; nur lesbar. lastRun ist eine Association und muss beim Lesen angefordert werden. |
Variablennamen müssen innerhalb einer Regel eindeutig sein. Ein Muster darf nur Facetten derselben Regel referenzieren; zwei Muster dürfen nicht dieselbe Facettenmenge verwenden. Die fachliche Einrichtung und die Twig-Vorlagen beschreibt die Generator-Anleitung.
POST /api/search/repertus-landingpage-generation-rule
{
"ids": ["<regel-id>"],
"associations": {
"salesChannels": {},
"languages": {},
"categories": {},
"facets": {
"associations": {
"options": {},
"manufacturers": {},
"priceRanges": { "associations": { "translations": {} } }
}
},
"patterns": { "associations": { "facets": {}, "translations": {} } },
"lastRun": {}
}
}DELETE /api/repertus-landingpage-generation-rule/{id} löscht die Regel und koppelt ihre Landingpages ab. Soll auch der Seitenbestand gelöscht werden, löschen Sie die über generationRuleId gefundenen Landingpages vor der Regel. Beenden Sie zuvor offene Läufe. Die Laufhistorie bleibt bis zur Aufbewahrungsbereinigung ohne Regelbezug erhalten.
Verfügbare Facettenwerte
POST /api/_action/repertus/landingpage-generation-rule/facet-values
{
"categoryIds": ["<kategorie-id>"],
"salesChannelIds": ["<sales-channel-id>"]
}Die Antwort enthält die Vereinigung der in den Listings vorkommenden Werte über die angefragten Kategorien und Verkaufskanäle. Namen stehen in der Request-Sprache und sind je Liste nach Namen sortiert:
{
"manufacturers": [{ "id": "<hersteller-id>", "name": "Beispielhersteller" }],
"propertyGroups": {
"<property-gruppen-id>": [{ "id": "<property-option-id>", "name": "Creme" }]
}
}Ohne passende Werte sind die Listen leer; propertyGroups wird im leeren Fall als [] serialisiert. Die beiden Eingabelisten enthalten UUIDs; doppelte IDs werden entfernt. Ungültige UUIDs liefern 400 mit TONUR_SEO_FILTER_LANDINGPAGE__INVALID_ID_LIST.
Generierungsläufe
Starten und abbrechen
| Methode und Pfad | Body | Erfolg |
|---|---|---|
POST /api/_action/repertus/landingpage-generation-rule/{id}/start | {} oder {"onConflict":"reject"}, {"onConflict":"queue"}, {"onConflict":"restart"} | 202, Objekt run |
POST /api/_action/repertus/landingpage-generation-rule/start-all | {} | 202, Listen created und skipped |
POST /api/_action/repertus/landingpage-generation-run/{id}/cancel | {} | 200, Objekt run |
GET /api/_action/repertus/landingpage-generation-run/worker-config | keiner | 200, {"enableAdminWorker":true} bzw. false |
Ein Start bestätigt die Einreihung, nicht den Abschluss. Global läuft höchstens ein Generierungslauf; weitere warten in Anlagereihenfolge. Zur Verarbeitung sind Worker erforderlich.
Ist für dieselbe Regel bereits ein Lauf pending oder running, liefert der Standard reject einen Konflikt. Beispiel, auf die entscheidenden Felder gekürzt:
{
"errors": [{ "code": "TONUR_GENERATION_RUN_CONFLICT", "detail": "…" }],
"run": { "id": "<vorhandene-lauf-id>", "status": "running" }
}Die Antwort hat Status 409. queue reiht einen weiteren Lauf ein; restart fordert den Abbruch aller offenen Läufe dieser Regel an und reiht einen Ersatz ein. Bei start-all enthält created neue Laufobjekte; skipped enthält je generationRuleId und den vorhandenen run. Regeln mit offenem Lauf werden dabei übersprungen.
Beim Abbrechen wird ein wartender Lauf sofort cancelled. Ein laufender Auftrag darf die aktuelle Kategorie abschließen und verarbeitet anschließend den Abbruch. Bereits geschriebene Seiten bleiben; die abschließende Bereinigung entfällt. Wiederholtes Abbrechen eines beendeten Laufs verändert sein Ergebnis nicht.
Status und Historie lesen
POST /api/search/repertus-landingpage-generation-run
{
"page": 1,
"limit": 25,
"total-count-mode": 1,
"filter": [{ "type": "equals", "field": "generationRuleId", "value": "<regel-id>" }],
"sort": [{ "field": "createdAt", "order": "DESC" }]
}Einen Lauf lesen Sie mit GET /api/repertus-landingpage-generation-run/{id}. Fragen Sie ihn beispielsweise alle fünf Sekunden erneut ab, solange sein Status pending oder running ist.
| Feld | Bedeutung |
|---|---|
id, generationRuleId | Lauf-ID und Regelbezug; der Regelbezug kann nach Löschung null sein. |
trigger, userId | manual für Admin-API, cli für Konsole, scheduled für den täglichen Task. Bei Integrationen, CLI und geplanten Läufen ist userId leer; Admin-Benutzer werden bei ihrem manuellen Start zugeordnet. |
status | pending, running, completed, limit_reached, failed oder cancelled. Die letzten vier sind Endstatus. |
createdAt, startedAt, finishedAt | Einreihung, Start und Ende; Start und Ende können noch null sein. createdAt steht im Entity-Leseergebnis, nicht im Laufobjekt der Aktionen. |
categoriesProcessed, categoriesTotal, categoriesOpen | Kategorienfortschritt; er wird nach bestätigten Kategorien aktualisiert. |
minProductCount | Mindestproduktzahl des Laufs. |
created, updated, deactivated, deleted, skipped | Fünf Zähler direkt am Lauf, ohne verschachteltes counters. Reaktivierungen zählen als updated. |
reasons, reasonsDropped, error | Höchstens 500 Gründe, Zahl weiterer Gründe und Fehler- bzw. Abbruchmeldung. |
cancelRequested | Nur in den Laufobjekten der Start-/Abbruchaktionen und der Konfliktantwort; kein Feld des Entity-Endpunkts. |
reasons unterscheidet unter anderem collision, url_collision, no_products, below_threshold und pattern_skipped. Auch ein completed-Lauf kann übersprungene Kombinationen enthalten. executionState ist interner Fortsetzungszustand und kein stabiles Integrationsformat.
Generierungsläufe sind schreibgeschützt: Anlegen, Ändern, Löschen und Klonen über die Admin API sind gesperrt, ebenso Schreibzugriffe über die Sync API. Eine geklonte Regel beginnt ohne Laufhistorie. Beendete Läufe werden gemäß Aufbewahrung des Generator-Logs bereinigt; offene Läufe und der neueste Lauf jeder bestehenden Regel bleiben erhalten.
Weitere Landingpage-Aktionen
Alle folgenden Pfade beginnen mit /api/_action/repertus/seo-filter-landingpage:
| Methode und Pfad nach dem Präfix | Eingabe | Antwort bei Erfolg |
|---|---|---|
GET /iap/status | keine | 200, boolesche Felder perSalesChannelEnabled, generatorEnabled, devOverrideActive |
POST /{id}/convert-to-per-sales-channel | Master-ID; Body {} | 200, {"success":true}; bei bereits konvertiertem Master zusätzlich alreadyConverted: true |
POST /{id}/convert-to-shared | Master-ID; {"chosenVariantId":"<variant-id>"} | 200, {"success":true} |
GET /{id}/nav-tree-warnings | Master-ID | 200, {"warnings":[...]} |
POST /generate | {"landingpageId":"<landingpage-id>"} | 200, {"success":true} |
POST /generateAll | {} | 204, leerer Body |
Konvertierung und Navigationswarnungen
convert-to-per-sales-channel kopiert die Identität in eine Sales-Channel-Variant je zugewiesenem Kanal und übergibt die Aufruf-URLs. convert-to-shared übernimmt die Identität der gewählten Variant und entfernt alle Variants; die bisher über Variants sichtbaren Kanäle werden als salesChannels übernommen. Verwenden Sie diese Aktionen, damit auch URLs und Canonical-Bezüge umgestellt werden. Ein alleiniger Feldwechsel von configurationMode führt diese Schritte nicht aus.
chosenVariantId muss zum angegebenen Master gehören. Bei einer Wiederholung der Rückkonvertierung existiert die gewählte Variant nicht mehr; die Aktion liefert dann 422. Die Rückkonvertierung benötigt keine aktive Pro-Sales-Channel-Erweiterung.
Navigationswarnungen sind unverbindliche Hinweise zu Kategorien außerhalb des Navigationsbaums eines Verkaufskanals. Jeder Eintrag enthält variantId, salesChannelId, salesChannelName, categoryId, categoryPath und suggestion. Ohne Hinweise ist warnings leer.
Aufruf-URLs und Kategorie-Filter
generate stößt die SEO-URL-Indexierung einer bestehenden Landingpage an. generateAll reiht eine Indexierungsnachricht für alle Landingpages ein. Diese Aktionen erzeugen keine neuen Landingpages aus Generierungsregeln; dafür verwenden Sie die Startaktionen des Generators.
Fehler behandeln
Fehler stehen üblicherweise in einer errors-Liste mit code und detail; Shopware kann zusätzlich status, title und source.pointer für ein fehlerhaftes Feld liefern.
| HTTP-Status | Typische Ursache |
|---|---|
400 | Ungültige UUID, fehlender chosenVariantId, ungültiges onConflict, inaktive Regel oder ungültige Felder/Facetten/Vorlagen. |
401 | Admin-Token fehlt, ist ungültig oder abgelaufen. |
403 | Fehlende Rechte, erforderliche IAP inaktiv oder generierte Landingpage schreibgeschützt. |
404 | Landingpage/Master, Generierungsregel oder Generierungslauf nicht gefunden. |
409 | Bereits offener Generierungslauf; bei der Startaktion den enthaltenen run auswerten. |
422 | Ungültige Sales-Channel-Variant oder gewählte Variant gehört nicht zum Master. |
