> For the complete documentation index, see [llms.txt](https://docs.premsoft.de/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.premsoft.de/plugins/produkt-konfigurator/store-api.md).

# Store API

> Diese Seite richtet sich an **Entwickler & Integratoren**. Sie beschreibt die HTTP-Schnittstellen für den Einsatz des Konfigurators in einem Headless-Frontend (PWA, App, Composable Commerce).

Die gesamte preiswirksame Logik ist über die **Store API** verfügbar. Ein Headless-Client benötigt drei Bausteine: Preis berechnen, in den Warenkorb legen und (optional) Konfigurationen speichern/laden.

Alle Store-API-Aufrufe benötigen den Header `sw-access-key` des Verkaufskanals. Der Kontext (Sprache, Währung, Kunde) wird wie üblich über `sw-context-token` geführt. Die Konfigurator-Routen sind **öffentlich** (`_loginNotRequired`), erfordern also keinen eingeloggten Kunden.

***

## Live-Preis berechnen

```http
POST /store-api/prems/configurator/price
```

Berechnet Stückpreis, Maße und Zwischenergebnisse für eine Konfiguration neu. Nicht gecacht.

**Request-Body:**

```json
{
  "productId": "0199b586c0f273aa8d2f4e1b2c3d4e5f",
  "fields": {
    "color": "gold",
    "width": "30",
    "height": "20",
    "extras": ["gift_wrap", "express"]
  }
}
```

* `productId` *(string, erforderlich)* – ID des Produkts.
* `fields` *(object, erforderlich)* – Map aus **technischem Bezeichner → Wert**. Werte sind Strings oder Arrays von Strings (Mehrfachauswahl).

**Response:**

```json
{
  "price": 149.0,
  "formattedPrice": "149,00 €",
  "priceChanged": true,
  "measurements": { "width": 30.0, "height": 20.0, "length": 0.0, "weight": 2.5 },
  "interimResults": { "area": "Fläche: 0,06 m²" }
}
```

* `price` *(float)* – neuer Stückpreis in der Kontextwährung.
* `formattedPrice` *(string)* – sprach-/währungsformatierter Preis.
* `priceChanged` *(bool)* – ob die Konfiguration den Preis verändert hat.
* `measurements` *(object)* – `width`, `height`, `length`, `weight` (neu berechnet oder Produktwerte).
* `interimResults` *(object)* – Map aus Feld-Bezeichner → berechnetem Anzeigetext.

Existiert kein (aktiver) Konfigurator für das Produkt, wird der Basispreis mit `priceChanged: false` zurückgegeben.

***

## In den Warenkorb legen

Es gibt **keine** eigene Warenkorb-Route. Verwende die Standard-Route und hänge das Objekt `premsConfigurator` auf **oberster Ebene** an den Request an:

```http
POST /store-api/checkout/cart/line-item
```

**Request-Body:**

```json
{
  "items": [
    {
      "type": "product",
      "referencedId": "0199b586c0f273aa8d2f4e1b2c3d4e5f",
      "quantity": 1
    }
  ],
  "premsConfigurator": {
    "productId": "0199b586c0f273aa8d2f4e1b2c3d4e5f",
    "fields": {
      "color": "gold",
      "width": "30",
      "height": "20"
    }
  }
}
```

Der Server validiert die Felder serverseitig (Pflichtfelder, E-Mail/Telefon, Min/Max, erlaubte Optionen). Bei Verstößen antwortet er mit einer **ConstraintViolation**. Bei Erfolg wird das Line-Item mit dem berechneten Preis, den Eingabewerten (für die Checkout-Anzeige) sowie ggf. berechneten Maßen und einer Artikelnummer angereichert. Positionen mit unterschiedlicher Konfiguration werden nicht zusammengeführt.

> Die Preisneuberechnung erfolgt bei jeder Warenkorb-Operation serverseitig – der Client muss den Preis nicht selbst setzen.

***

## Konfiguration speichern

```http
POST /store-api/prems/configurator/save
```

Erfordert, dass **Konfiguration speichern** im Verkaufskanal aktiviert ist (sonst Fehlerantwort).

**Request-Body:**

```json
{
  "productId": "0199b586c0f273aa8d2f4e1b2c3d4e5f",
  "fields": { "color": "gold", "width": "30", "height": "20" }
}
```

**Response:**

```json
{ "token": "8f14e45fceea167a5a36dedd4bea2543" }
```

* `token` *(string)* – öffentlicher Token der gespeicherten Konfiguration.

Mit dem Token lässt sich die Konfiguration später wiederherstellen. Im klassischen Storefront öffnet die Route `GET /prems/configurator/c/{token}` den Share-Link und leitet auf die Produktseite mit dem Query-Parameter `premsSavedConfig={token}` weiter; ein Headless-Frontend liest den Token selbst aus und ruft damit erneut die Preis-Route auf bzw. lädt die gespeicherten Werte.

***

## Storefront-Routen (klassisches Theme)

Diese Routen werden vom mitgelieferten Storefront genutzt und sind für Headless-Clients in der Regel nicht nötig:

| Route                               | Zweck                                                |
| ----------------------------------- | ---------------------------------------------------- |
| `POST /prems/configurator/price`    | Storefront-Wrapper der Preis-Route (XHR).            |
| `POST /prems/configurator/save`     | Speichern; liefert zusätzlich `shareUrl`.            |
| `POST /prems/configurator/change`   | „Konfiguration ändern" aus dem Warenkorb (Redirect). |
| `GET /prems/configurator/c/{token}` | Share-Link öffnen; Redirect auf die Produktseite.    |

***

## Admin-API: Formel prüfen

Nur im authentifizierten Admin-Kontext (für eigene Backend-Erweiterungen):

```http
POST /api/_action/prems-configurator/validate-formula
```

**Request (form-encoded):** `formula=<twig>` und optional `variables[]=<name>`.

**Response:**

```json
{ "valid": false, "message": "Unknown variable \"fields.foo\"", "line": 1 }
```

* `valid` *(bool)*, `message` *(string|null)*, `line` *(int|null)*.

***

## Integrations-Workflow (Headless)

1. Produktseite rendert das Konfigurator-Formular (Feldstruktur über deine eigene Datenquelle/Admin-API).
2. Bei jeder Eingabe-Änderung: `POST /store-api/prems/configurator/price` → Preis & Zwischenergebnisse aktualisieren.
3. „In den Warenkorb": `POST /store-api/checkout/cart/line-item` mit `premsConfigurator`. ConstraintViolations dem Nutzer anzeigen.
4. Optional „Speichern": `POST /store-api/prems/configurator/save` → Token teilen.
5. Beim Öffnen eines geteilten Links: Token auslesen, gespeicherte Werte laden und Schritt 2 erneut ausführen.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.premsoft.de/plugins/produkt-konfigurator/store-api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
