> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# API-Referenz Produkte

> Produkte, Varianten und Lagerbestände über die Admin Interface API anlegen, abrufen, aktualisieren, löschen sowie Bulk-Operationen ausführen.

Der Endpunkt `/products` stellt Ihnen eine Schnittstelle bereit, mit der Sie Produktdaten und Lagerbestände in unserem Shop-System verwalten können. Darüber können Sie Produkte erstellen, bearbeiten, filtern, abrufen und löschen sowie Lagerbestandsinformationen zu Produkten abrufen, aktualisieren und löschen.

***

## Unterstützte Methoden

| **Befehl/Info**                | **Endpunkte**           | **GET**               | **POST**              | **PUT**               | **DELETE**            |
| ------------------------------ | ----------------------- | --------------------- | --------------------- | --------------------- | --------------------- |
| **Allgemeines Produkt**        | products/               | <Icon icon="check" /> | <Icon icon="check" /> | <Icon icon="check" /> | <Icon icon="check" /> |
| **Allgemeines Produkt (Bulk)** | bulk/products           | <Icon icon="ban" />   | <Icon icon="ban" />   | <Icon icon="ban" />   |                       |
| **Variantenattribute**         | products/variants       | <Icon icon="check" /> | <Icon icon="check" /> | <Icon icon="check" /> | <Icon icon="check" /> |
| **Varianten**                  | <Icon icon="check" />   | <Icon icon="check" /> | <Icon icon="check" /> | <Icon icon="check" /> |                       |
| **Varianten (Bulk)**           | bulk/products/variants  | <Icon icon="ban" />   | <Icon icon="check" /> | <Icon icon="ban" />   | <Icon icon="ban" />   |
| **Lagerbestand Allgemein**     | products/inventory      | <Icon icon="check" /> | <Icon icon="check" /> | <Icon icon="check" /> | <Icon icon="check" /> |
| **Lagerbestand für Produkte**  | <Icon icon="check" />   | <Icon icon="ban" />   | <Icon icon="check" /> | <Icon icon="ban" />   |                       |
| **Lagerbestand für Varianten** | <Icon icon="check" />   | <Icon icon="ban" />   | <Icon icon="check" /> | <Icon icon="ban" />   |                       |
| **Lagerbestand (Bulk)**        | bulk/products/inventory | <Icon icon="ban" />   | <Icon icon="check" /> | <Icon icon="ban" />   | <Icon icon="ban" />   |
| **Set-Produkte**               | <Icon icon="check" />   | <Icon icon="check" /> | <Icon icon="check" /> | <Icon icon="check" /> |                       |

## Datenfelder

Felder werden in der Konfiguration verwaltet und als ein JSON-Objekt in der Tabelle gespeichert.

Es wird unterschieden zwischen Standardproduktdatenfeldern und benutzerdefinierten Produktdatenfeldern. Benutzerdefinierte Produktdatenfelder können beliebig angelegt werden, während Standardproduktdatenfelder vom Shop vorgegeben werden und immer definiert sind. Alle benutzerdefinierte Produktdatenfelder sind im Abschnitt custom zu finden. Alle anderen Einträge stellen Standardproduktdatenfelder dar.

| **Name**                               | **Typ** | **Bedeutung**                                                               |
| -------------------------------------- | ------- | --------------------------------------------------------------------------- |
| **active**                             | String  | Aktivitätsstatus des Produkts (z. B. „always“, „never“)                     |
| **custom**                             | Objekt  | Benutzerdefinierte Felder                                                   |
| **custom.liste**                       | Array   | Beispielhafte Liste                                                         |
| **custom.map**                         | Objekt  | Beispielhafte Schlüssel-Wert-Zuordnungen                                    |
| **custom.robotsNoFollow**              | Boolean | True = Link zu diesem Produkt sollte von Suchmaschinen nicht gefolgt werden |
| **custom.robotsNoIndex**               | Boolean | True = Produktseite sollte nicht in Suchmaschinen indiziert werden          |
| **custom.weight**                      | Float   | Gewicht des Produkts in Kilogramm (zur Priorisierung oder Sortierung)       |
| **descr**                              | String  | Produktbeschreibung                                                         |
| **hasVariants**                        | Boolean | Gibt an, ob das Produkt Varianten besitzt (z. B. Größe, Farbe)              |
| **id**                                 | String  | Technische ID des Produkts                                                  |
| **itemNumber**                         | String  | Artikelnummer (kann identisch mit `id` sein)                                |
| **name**                               | String  | Klartext-Name des Produkts                                                  |
| **price**                              | String  | Standardpreis des Produkts (z. B. "89.900000")                              |
| **ratingApprovalConfig.maximumRating** | Integer | Maximal zulässige Bewertung (z. B. 5)                                       |
| **ratingApprovalConfig.minimumRating** | Integer | Minimal zulässige Bewertung (z. B. 0)                                       |
| **setPrice**                           | String  | Setpreis (bei Produktbündeln)                                               |
| **statistics.averageRating**           | Float   | Durchschnittliche Bewertung des Produkts                                    |
| **statistics.ratingCount**             | Integer | Anzahl der abgegebenen Bewertungen                                          |
| **statisticsPerPoint**                 | Array   | Bewertungshistogramm: für jeden möglichen Wert Anzahl Bewertungen           |
| **taxRateId**                          | String  | ID des angewendeten Steuersatzes                                            |
| **timestampCreatedAt**                 | String  | Zeitpunkt der Erstellung (ISO 8601-Format, UTC)                             |
| **timestampUpdatedAt**                 | String  | Zeitpunkt der letzten Produktänderung (ISO 8601-Format, UTC)                |

#### Beispielhafter Datensatz

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": "always",
    "custom": {
        "liste": [
            "123",
            "234",
            "456"
        ],
        "map": {
            "a": "b",
            "c": "d",
            "e": "f"
        },
        "robotsNoFollow": false,
        "robotsNoIndex": false,
        "weight": 0.33
    },
    "descr": "Lässiges Barbour-Shirt aus Baumwoll-Piqué mit Langarm.<span class='passform'> Gearbeitet in gerader, normaler Passform (Regular Fit)</span> mit Kontrastbesatz im 'Barbour-Tartan' an der Knopfleiste und im Kragen. Mit klassischem Polokragen, Ärmelbündchen und gesticktem Barbour-Logo. Ein Mode-Klassiker für die Freizeit, in dem sich jeder Mann wohlfühlt.<span class='mass'> Länge ca. 75 cm.</span><span class='katalogfarbe'>Farbe: Navy.</span><span class='herkunft'> Original Barbour. </span>  <span class='groessen'> Größen: M (48), L (50), XL (52/54), XXL (56/58), XXXL (58/60) </span>  <span class='material'> Reine Baumwolle.</span>",
    "hasVariants": true,
    "id": "11-1701",
    "itemNumber": "11-1701",
    "name": "Tartan-Langarm-Polo in Navy",
    "price": "89.900000",
    "ratingApprovalConfig": {
        "maximumRating": 5,
        "minimumRating": 0
    },
    "setPrice": "0.000000",
    "statistics": {
        "averageRating": 0,
        "ratingCount": 0
    },
    "taxRateId": "1",
    "statisticsPerPoint": [
        [
            0,
            0
        ],
        [
            1,
            0
        ],
        [
            2,
            0
        ],
        [
            3,
            0
        ],
        [
            4,
            0
        ],
        [
            5,
            0
        ]
    ],
    "timestampCreatedAt": "2024-11-14T10:41:25.000Z",
    "timestampUpdatedAt": "2025-01-24T09:28:06.000Z"
}
```

## Methoden für Produkte

Die hier dokumentierten Endpunkte ermöglichen den Lese-, Schreib-, Änderungs- und Löschzugriff auf Produktdaten im Shopsystem. Sie können zur Verwaltung des Produktkatalogs genutzt werden – sowohl zur Initialbefüllung als auch zur laufenden Aktualisierung von Inhalten.

Zusätzlich stehen Endpunkte zur Verfügung, um Produktsuchen auf Basis definierter Regeln durchzuführen.

Da jeder Subshop eine eigene Produktmenge hat, sollen URLs den Parameter `subshopId` enthalten.

Für alle Endpunkte ist eine gültige Authentifizierung erforderlich. Die jeweiligen Berechtigungen zum Lesen, Schreiben, Erstellen oder Löschen von Produkten müssen vorhanden sein.

### GET products

Mit diesem Endpunkt können Sie eine Liste aller Produkte im System abrufen.

Optional kann die Ergebnismenge mithilfe von Filterparametern eingeschränkt werden, z. B. auf Produkte, die einer bestimmten Kategorie zugeordnet sind (`inCategory`) oder aus einer bestimmten Kategorie ausgeschlossen werden sollen (`notInCategory`). Beide Parameter dürfen nicht gleichzeitig verwendet werden.

Wenn der Parameter `inCategory` verwendet wird, erfolgt die Ausgabe der Produkte nicht in der im Shop gepflegten Reihenfolge innerhalb der Kategorie. Um die Produkte in der korrekten Reihenfolge zu erhalten, verwenden Sie bitte den Endpunkt `GET categories/{categoryId}/products`.

Damit der Endpunkt verwendet werden kann, müssen die entsprechenden Berechtigungen zum Lesen von Produkten vorhanden sein.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products?subshopId=deutsch
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "endReached": false,
    "items": [
        {
            "active": "always",
            "custom": {
                ...
            },
            "descr": "Lässiges Barbour-Shirt aus Baumwoll-Piqué mit Langarm.<span class='passform'> Gearbeitet in gerader, normaler Passform (Regular Fit)</span> mit Kontrastbesatz im 'Barbour-Tartan' an der Knopfleiste und im Kragen. Mit klassischem Polokragen, Ärmelbündchen und gesticktem Barbour-Logo. Ein Mode-Klassiker für die Freizeit, in dem sich jeder Mann wohlfühlt.<span class='mass'> Länge ca. 75 cm.</span><span class='katalogfarbe'>Farbe: Navy.</span><span class='herkunft'> Original Barbour. </span>  <span class='groessen'> Größen: M (48), L (50), XL (52/54), XXL (56/58), XXXL (58/60) </span>  <span class='material'> Reine Baumwolle.</span>",
            "hasVariants": false,
            "id": "11-1701",
            "itemNumber": "11-1701",
            "name": "Tartan-Langarm-Polo in Navy",
            "price": "89.900000",
            "setPrice": "0.000000",
            "taxRateId": "1",
            "timestampCreatedAt": "2024-11-14T10:41:25.000Z",
            "timestampUpdatedAt": "2025-01-24T09:28:06.000Z"
        }
    ],
    "nextPageToken": "WzAuMCwiMTEtMjgxNV9kZXV0c2NoXzMiXQ",
    "totalCount": 1296
}
```

#### Filterfelder

Alle Produktdatenfelder, `inCategory`, `notInCategory`, `inSetProduct`, `notInSetProduct`

#### Sortierfelder

Alle Produktdatenfelder

#### Sonstige Parameter

`from`

#### Fehlercodes

| **Fehler**              | **Typ**              | **Grund**                                                                                                                                                                                                                                     |
| ----------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized        |                      | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                                                                                                                 |
| 403 Forbidden           |                      | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Produkten.                                                                                                                                                                    |
| 400 Bad Request         |                      | Request body konnte nicht geladen werden.                                                                                                                                                                                                     |
| 400 Bad Request         | "invalidValue"       | "stage" ist ungültig <br />`size` ∉ \[1;300] <br />`pageToken` ist keine Zahl oder kleiner als 0. <br />`from` ist größer als 9999.<br />Es wird versucht, Produkte nach einem Feld vom Typ `Liste`, `Map`, `Bild` oder `Video` zu sortieren. |
| 400 Bad Request         | "unknownDataField"   | Ein Filter- oder Sortierfeld ist ungültig.                                                                                                                                                                                                    |
| 400 Bad Request         | "illegalOperation"   | Ein Filtertyp ist ungültig.                                                                                                                                                                                                                   |
| 400 Bad Request         | "invalidCharacters"  | Ein Filterwert ist ungültig.<br />`size` ist keine Ganzzahl.                                                                                                                                                                                  |
| 400 Bad Request         | "invalidCombination" | Die Filter `inCategory` und `notInCategory` oder `inSetProduct` und `notInSetProduct` sind gleichzeitig gesetzt.                                                                                                                              |
| 503 Service Unavailable | "serviceUnavailable" | Das Lesen von Daten ist fehlgeschlagen.                                                                                                                                                                                                       |

### GET products/\{productId}

Mit diesem Endpunkt können Sie die vollständigen Daten eines einzelnen Produkts abrufen. Geben Sie dazu die Produkt-ID als Pfadparameter an. Neben den Basisdaten werden auch benutzerdefinierte Felder zurückgegeben.

Damit der Endpunkt verwendet werden kann, müssen die entsprechenden Berechtigungen zum Lesen von Produkten vorhanden sein.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-1701?subshopId=deutsch
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": "always",
    "custom": {
        "liste": [
            "123",
            "234",
            "456"
        ],
        "map": {
            "a": "b",
            "c": "d",
            "e": "f"
        },
        "robotsNoFollow": false,
        "robotsNoIndex": false,
        "weight": 0.33
    },
    "descr": "Lässiges Barbour-Shirt aus Baumwoll-Piqué mit Langarm.<span class='passform'> Gearbeitet in gerader, normaler Passform (Regular Fit)</span> mit Kontrastbesatz im 'Barbour-Tartan' an der Knopfleiste und im Kragen. Mit klassischem Polokragen, Ärmelbündchen und gesticktem Barbour-Logo. Ein Mode-Klassiker für die Freizeit, in dem sich jeder Mann wohlfühlt.<span class='mass'> Länge ca. 75 cm.</span><span class='katalogfarbe'>Farbe: Navy.</span><span class='herkunft'> Original Barbour. </span>  <span class='groessen'> Größen: M (48), L (50), XL (52/54), XXL (56/58), XXXL (58/60) </span>  <span class='material'> Reine Baumwolle.</span>",
    "hasVariants": false,
    "id": "11-1701",
    "itemNumber": "11-1701",
    "name": "Tartan-Langarm-Polo in Navy",
    "price": "89.900000",
    "ratingApprovalConfig": {
        "maximumRating": 5.0,
        "minimumRating": 1.0
    },
    "setPrice": "0.000000",
    "statistics": {
        "averageRating": 4.5,
        "ratingCount": 12
    },
    "statisticsPerPoint": {
        "1": 0,
        "2": 1,
        "3": 2,
        "4": 3,
        "5": 6
    },
    "taxRateId": "1",
    "timestampCreatedAt": "2024-11-14T10:41:25.000Z",
    "timestampUpdatedAt": "2025-01-24T09:28:06.000Z"
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                  |
| ---------------- | -------------- | -------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                              |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Produkten. |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.                                   |
| 404 Not Found    |                | Produkt mit `id`=`{id}` wurde nicht gefunden.                              |

### GET products/\{productId}/url

Mit diesem Endpunkt können Sie die vollständige URL eines Produkts abrufen.

Für die Nutzung dieses Endpunkts sind Leseberechtigungen für Produkt-Daten erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/143-68071/url?subshopId=deutsch
```

#### Antwort

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/SEOURL/
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                  |
| ---------------- | -------------- | -------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                              |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Produkten. |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.                                   |

### GET products/testRule

Mit diesem Endpunkt können Sie gezielt Produkte abrufen, die einer oder mehreren angegebenen Regeln entsprechen. Die Regeln werden als JSON-formatiertes Array in der Query-URL übergeben und ermöglichen eine flexible Filterung nach Produktfeldern wie z. B. Aktivitätsstatus, Artikelnummern oder Preisangaben. Die Regeln dürfen nur gültige Felder und zulässige Operatoren enthalten.

Damit dieser Endpunkt verwendet werden kann, müssen die entsprechenden Berechtigungen zum Lesen von Produktdaten vorhanden sein.

#### Beispiel

Die Regeln werden in der URL als JSON-Array kodiert und über den Parameter `rules` übergeben. Um korrekt interpretiert zu werden, muss dieser Parameter URL-dekodiert werden.

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/testRule?size=100&rules=%5B%7B%22field%22%3A%22&active%22%2C%22mode%22%3A%22eq%22%2C%22value%22%3A%22always%22%7D%2C%7B%22field%22%3A%22itemNumber%22%2C%22mode%22%3A%22contains%22%2C%22value%22%3A%225%22%7D%5D&&
```

Die URL ruft Produkte ab, die zwei Bedingungen erfüllen:

1. Das Feld `active`muss den Wert`always`haben.\
   Es werden nur Produkte berücksichtigt, die dauerhaft aktiv sind.
2. Die Artikelnummer (`itemNumber`) muss die Ziffer „5“ enthalten.\
   Es werden nur Produkte ausgewählt, deren Artikelnummer irgendwo die „5“ enthält (z. B. `11-2518`).

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "items": [
        {
            "active": "always",
            "custom": {
                "brand": "",
                "commission": 0,
                "commissionTaxRate": "",
                "crossSelling": [],
                "customNumber": "",
                "ean": "",
                "filterField": "",
                "image": [],
                "isbn": "",
                "mainCategory": "",
                "metaDescription": "",
                "metaDescriptionSetManually": false,
                "metaTitle": "",
                "metaTitleSetManually": false,
                "multiProducts": "",
                "oneTimeFee": 0,
                "oneTimeFeeTaxRate": "",
                "productDiscount": 0,
                "productDiscountAbsolute": false,
                "productType": "",
                "robotsNoFollow": false,
                "robotsNoIndex": false,
                "setOrgPrice": "0.000000",
                "validForDiscount": false,
                "video": "",
                "voucherProductActive": false,
                "voucherProductHtmlTemplate": "",
                "voucherProductPrice": false,
                "voucherProductTemplate": "",
                "weight": 0
            },
            "descr": "Dieses weiße Poloshirt ist alles andere als gewöhnlich, sondern ...",
            "hasVariants": true,
            "id": "11-2451",
            "itemNumber": "11-2451",
            "name": "Samtweiches Polo aus Luxusjersey",
            "price": "89.900000",
            "setPrice": "0.000000",
            "taxRateId": "1",
            "timestampCreatedAt": "2025-02-14T10:50:38.000Z",
            "timestampUpdatedAt": "2025-04-28T10:24:24.000Z"
        },
        {
            "active": "always",
            "custom": {
                "brand": "",
                "commission": 0,
                "commissionTaxRate": "",
                "crossSelling": [],
                "customNumber": "",
                "ean": "",
                "filterField": "",
                "image": [],
                "isbn": "",
                "mainCategory": "",
                "metaDescription": "",
                "metaDescriptionSetManually": false,
                "metaTitle": "",
                "metaTitleSetManually": false,
                "multiProducts": "",
                "oneTimeFee": 0,
                "oneTimeFeeTaxRate": "",
                "productDiscount": 0,
                "productDiscountAbsolute": false,
                "productType": "",
                "robotsNoFollow": false,
                "robotsNoIndex": false,
                "setOrgPrice": "0.000000",
                "validForDiscount": false,
                "video": "",
                "voucherProductActive": false,
                "voucherProductHtmlTemplate": "",
                "voucherProductPrice": false,
                "voucherProductTemplate": "",
                "weight": 0
            },
            "descr": "Einmal angezogen, wollen Sie aus diesem kuschelig weichen Flane...",
            "hasVariants": true,
            "id": "11-2518",
            "itemNumber": "11-2518",
            "name": "Lieblingshemd aus Fischgrat-Gewebe",
            "price": "79.900000",
            "setPrice": "0.000000",
            "taxRateId": "1",
            "timestampCreatedAt": "2025-02-14T10:50:45.000Z",
            "timestampUpdatedAt": "2025-04-28T10:24:24.000Z"
        },
        ...
    ],
    "nextPageToken": "WzAuMCwiMTQzLTY4MDcxX2RldXRzY2hfMyJd",
    "totalCount": 64,
    "warnings": {
        "invalidValue": [],
        "unknownFilters": [],
        "wrongOperators": []
    }
}
```

#### Mögliche Werte für `mode`

`gt` (größer), `gte` (größer oder gleich), `lt` (kleiner), `lte` (kleiner oder gleich), `eq` (gleich), `neq` (ungleich), `contains` (enthält), `notcontains` (nicht enthält)

#### Fehlercodes

| **Fehler**       | **Typ**            | **Grund**                                                                      |
| ---------------- | ------------------ | ------------------------------------------------------------------------------ |
| 401 Unauthorized |                    | Nicht autorisiert: Sie sind nicht angemeldet.                                  |
| 403 Forbidden    |                    | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Produkt-Daten. |
| 400 Bad Request  |                    | Regeln konnten nicht geparst werden.                                           |
| 400 Bad Request  | "syntaxError"      | `sort` enthält mehr als einen oder keinen ":".                                 |
| 400 Bad Request  | "unknownDataField" | Ein Sortierfeld ist ungültig.                                                  |
| 400 Bad Request  | "invalidValue"     |                                                                                |

### POST products

Mit dem Endpunkt `/products` können neue Produkte im Shop-System angelegt werden. Alle für die Erstellung erforderlichen Produktinformationen müssen im Request Body übergeben werden. Die Antwort enthält die vollständigen Produktdaten des neu erstellten Produkts im JSON-Format.

Zum Erstellen eines Produkts sind entsprechende Berechtigungen erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products
```

#### Request Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "custom": {
        "liste": [],
        "map": {}
    },
    "active": "always",
    "descr": "This is a new Produkt",
    "itemNumber": "new",
    "name": "NewProdukt",
    "price": "1",
    "taxRateId": "19"
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": "always",
    "custom": {
        "brand": "",
        "commission": {
            "source": "0.0",
            "parsedValue": 0
        },
        "commissionTaxRate": "",
        "crossSelling": [],
        "customNumber": "",
        "ean": "",
        "filterField": "",
        "image": [],
        "isbn": "",
        "liste": [],
        "map": {},
        ...
        "weight": {
            "source": "0.0",
            "parsedValue": 0
        }
    },
    "descr": "This is a new Produkt",
    "hasVariants": false,
    "id": "144-46864",
    "itemNumber": "new",
    "name": "NewProdukt",
    "price": "1.000000",
    "setPrice": "0.000000",
    "taxRateId": "19",
    "timestampCreatedAt": "2025-05-09T14:57:36.000Z",
    "timestampUpdatedAt": "2025-05-09T14:57:36.000Z"
}
```

#### Fehlercodes

| **Fehler**       | **Typ**             | **Grund**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ---------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized |                     | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| 403 Forbidden    |                     | Sie verfügen nicht über die erforderlichen Rechte zum Erstellen von Produkten.                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| 400 Bad Request  |                     | Der Request-Body konnte nicht geladen werden.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| 400 Bad Request  | "invalidValue"      | Es wurde eine ungültige Stage oder ein ungültiger Subshop angegeben.<br />Ein Feld enthält den Wert `null`.<br />Ein Wert hat den Typ, der mit dem Typ aus der Konfiguration nicht übereinstimmt.<br />Ein Preis-Wert kann nicht geparst werden.<br />Ein Feld vom Typ `Map` hat einen Schlüssel, der kein String ist.<br />Ein Feld vom Typ `List` ist kein Array von Strings.<br />Ein Zeitwert ist nicht in ISO 8601 Format.<br />Bild-Daten von einem Bild sind kein Array von Objekten.<br />`id` des Formats oder `path` sind keine Strings. |
| 400 Bad Request  | "invalidFormat"     | `custom` ist kein Objekt.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| 400 Bad Request  | "unknownDataField"  | Ein nicht existierendes Produktdatenfeld wurde im Request-Body angegeben.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| 400 Bad Request  | "notManualEditable" | Ein nicht bearbeitbares Produktdatenfeld wurde im Request-Body angegeben.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |

### PUT products/\{productId}

Mit dem Endpunkt `products/{productId}` können Produktdaten aktualisiert werden. Wird ein Produkt mit der angegebenen ID nicht gefunden, kann bei gesetztem Parameter `createMissing=yes` automatisch ein neues Produkt angelegt werden.

Die vollständigen Produktdaten müssen im Request-Body übergeben werden.

Das optionale Feld `set` kann benutzt werden, um andere Produkte zusammen mit dem Aktuellen einem Set zuzuweisen. Alternativ können [die Endpunkte für Set-Produkte](#9-methoden-für-set-produkte) genutzt werden.

Zum Bearbeiten oder Anlegen eines Produkts sind entsprechende Berechtigungen erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-1966
```

#### Request-Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "custom": {
        "brand": "",
        "commission": 0,
        "commissionTaxRate": "",
        "crossSelling": [],
        "customNumber": "",
        "ean": "",
        "filterField": "",
        "image": [],
        "isbn": "",
        "mainCategory": "",
        "metaDescription": "",
        "metaDescriptionSetManually": false,
        "metaTitle": "",
        "metaTitleSetManually": false,
        "multiProducts": "",
        "oneTimeFee": 0,
        "oneTimeFeeTaxRate": "",
        "productDiscount": 0,
        "productDiscountAbsolute": false,
        "productType": "",
        "robotsNoFollow": false,
        "robotsNoIndex": false,
        "setOrgPrice": "0.000000",
        "validForDiscount": false,
        "video": "",
        "voucherProductActive": false,
        "voucherProductHtmlTemplate": "",
        "voucherProductPrice": false,
        "voucherProductTemplate": "",
        "weight": 0
    },
    "active": "always",
    "descr": "Jedes Stück, das von dem Strickunternehmen Kero Design kommt, ist ein echtes Unikat! Genau wie dieser Cardigan: Hier mischen sich zarte und kräftige Blautöne und ergeben ein effektvolles Strickkunstwerk. Diese handgestrickte Optik mit ihren schönen Farbverläufen erhält der Cardigan vor allem durch seine aufwendig von Hand gefärbten Garne. Reine Baumwolle macht die Strickjacke schön leicht und weich. Ein echter Blickfang und sehr besonders! Mit langen Ärmeln, Rundhals und Perlmutt-Knöpfen.<br /><span class='passform'> Gerade Form (Regular Fit).</span><span class='mass'> Länge ca. 60 cm.</span><span class='katalogfarbe'>Farbe: Multicolor Blue.</span><span class='herkunft'> Original Kero Design.</span>  <span class='material'>65 % Baumwolle (Bio-Baumwolle), 35 % Baumwolle.</span>",
    "itemNumber": "12-2144",
    "name": "Cardigan 'Amelia'",
    "price": "139.00",
    "setPrice": "0.00",
    "taxRateId": "1",
    "set": [
        {
            "id": "11-2497",
            "quantityFactor": 1,
            "usePrice": true,
            "fixQuantity": false,
            "hidden": false
        },
        {
            "id": "11-2492",
            "quantityFactor": 1,
            "usePrice": true,
            "fixQuantity": false,
            "hidden": false
        }
    ]
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": "always",
    "custom": {
        "brand": "",
        "commission": 0,
        "commissionTaxRate": "",
        "crossSelling": [],
        "customNumber": "",
        "ean": "",
        "filterField": "",
        "image": [],
        "isbn": "",
        "mainCategory": "",
        "metaDescription": "",
        "metaDescriptionSetManually": false,
        "metaTitle": "",
        "metaTitleSetManually": false,
        "multiProducts": "",
        "oneTimeFee": 0,
        "oneTimeFeeTaxRate": "",
        "productDiscount": 0,
        "productDiscountAbsolute": false,
        "productType": "",
        "robotsNoFollow": false,
        "robotsNoIndex": false,
        "setOrgPrice": "0.000000",
        "validForDiscount": false,
        "video": "",
        "voucherProductActive": false,
        "voucherProductHtmlTemplate": "",
        "voucherProductPrice": false,
        "voucherProductTemplate": "",
        "weight": 0
    },
    "descr": "Jedes Stück, das von dem Strickunternehmen Kero Design kommt, ist ein echtes Unikat! Genau wie dieser Cardigan: Hier mischen sich zarte und kräftige Blautöne und ergeben ein effektvolles Strickkunstwerk. Diese handgestrickte Optik mit ihren schönen Farbverläufen erhält der Cardigan vor allem durch seine aufwendig von Hand gefärbten Garne. Reine Baumwolle macht die Strickjacke schön leicht und weich. Ein echter Blickfang und sehr besonders! Mit langen Ärmeln, Rundhals und Perlmutt-Knöpfen.<br /><span class='passform'> Gerade Form (Regular Fit).</span><span class='mass'> Länge ca. 60 cm.</span><span class='katalogfarbe'>Farbe: Multicolor Blue.</span><span class='herkunft'> Original Kero Design.</span>  <span class='material'>65 % Baumwolle (Bio-Baumwolle), 35 % Baumwolle.</span>",
    "hasVariants": true,
    "id": "12-2144",
    "itemNumber": "12-2144",
    "name": "Cardigan 'Amelia'",
    "price": "139.000000",
    "setPrice": "259.700000",
    "taxRateId": "1",
    "timestampCreatedAt": "2025-02-14T10:54:45.000Z",
    "timestampUpdatedAt": "2025-05-10T16:19:36.000Z"
}
```

#### Fehlercodes

| **Fehler**              | **Typ**                    | **Grund**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ----------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized        |                            | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| 403 Forbidden           |                            | Sie verfügen nicht über die erforderlichen Rechte zum Schreiben von Produkten.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| 400 Bad Request         |                            | Der Request-Body konnte nicht geladen werden.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| 400 Bad Request         | "invalidValue"             | Die `productId` im Pfad ist ungültig.<br />Es wurde eine ungültige Stage oder ein ungültiger Subshop angegeben.<br />Ein Feld enthält den Wert `null`.<br />Ein Wert hat den Typ, der mit dem Typ aus der Konfiguration nicht übereinstimmt.<br />Ein Preis-Wert kann nicht geparst werden.<br />Ein Feld vom Typ `Map` hat einen Schlüssel, der kein String ist.<br />Ein Feld vom Typ `List` ist kein Array von Strings.<br />Ein Zeitwert ist nicht in ISO 8601 Format.<br />Bild-Daten von einem Bild sind kein Array von Objekten.<br />`id` des Formats oder `path` sind keine Strings. |
| 400 Bad Request         | "invalidFormat"            | `custom` ist kein Objekt.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| 400 Bad Request         | "unknownDataField"         | Ein nicht existierendes Produktdatenfeld wurde im Request-Body angegeben.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| 400 Bad Request         | "notManualEditable"        | Ein nicht bearbeitbares Produktdatenfeld wurde im Request-Body angegeben.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| 400 Bad Request         | "protectedFieldWriteError" | Ein geschütztes Produktdatenfeld wurde im Request-Body angegeben und der Benutzer hat keine Berechtigung, dieses Feld zu ändern.                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| 503 Service Unavailable | "internalError"            | Das Produkt konnte nach mehreren Versuchen aufgrund von Versionskonflikten nicht gespeichert werden.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| 404 Not Found           |                            | Das Produkt mit `id={id}` wurde nicht gefunden und der Parameter `createMissing` ist nicht auf `yes` gesetzt.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |

### DELETE products/\{productId}

Mit dem Endpunkt `products/{productId}` kann ein Produkt mit der angegebenen ID dauerhaft gelöscht werden.

Dieser Vorgang entfernt das Produkt vollständig aus dem System.

Zum Löschen eines Produkts sind entsprechende Berechtigungen erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/123456
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "success": true
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                    |
| ---------------- | -------------- | ---------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Löschen von Produkten. |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.                                     |
| 404 Not Found    |                | Das Produkt mit `id={id}` existiert nicht.                                   |

## Bulk-Methoden für Produkte

In diesem Abschnitt werden die Bulk-Endpunkte beschrieben, mit denen mehrere Datensätze in einem einzigen Request abgefragt oder verarbeitet werden können.

### POST bulk/products

Ermöglicht das massenhafte Erstellen und Aktualisieren von Produktdaten in einem einzigen Request. Der Request-Body ist ein JSON-Array, in dem jedes Element ein Produkt mit ID beschreibt. Erstell- und Schreibrechte für Produkte sind erforderlich.

Standardmäßig werden nur Produkte aktualisiert. Wird der Parameter createMissing=yes gesetzt, dann werden Produkte in der Anfrage die noch nicht existieren automatisch neues angelegt.

In einem Request können maximal 1000 Einträge verarbeitet werden.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/bulk/products
```

#### Request Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
[
    {
        "custom": {
            "liste": [],
            "map": {}
        },
        "id": "144-46864",
        "active": "always",
        "descr": "This is a new Produkt",
        "itemNumber": "new",
        "name": "NewProdukt",
        "price": "1",
        "taxRateId": "19"
    },
    {
        "custom": {
            "liste": [],
            "map": {}
        },
        "id": "145-26318",
        "active": "always",
        "descr": "This is an existing Produkt",
        "itemNumber": "existing",
        "name": "existingProduct",
        "price": "1",
        "taxRateId": "19"
    }
]
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "items": ["145-26318"],
    "skippedLines": [{
        "lineNumber": 0,
        "productId": "144-46864",
        "errorType": "notFound",
        "fieldErrors": {}
    }]
}
```

#### Fehlercodes

| **Fehler**       | **Typ**             | **Grund**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ---------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized |                     | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| 403 Forbidden    |                     | Sie verfügen nicht über die erforderlichen Rechte zum Erstellen oder aktualisieren von Produkten.                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| 400 Bad Request  |                     | Der Request-Body konnte nicht geladen werden. <br /> Es wurden mehr als 1000 Einträge angegeben.                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| 400 Bad Request  | "invalidValue"      | Es wurde eine ungültige Stage oder ein ungültiger Subshop angegeben.<br />Ein Feld enthält den Wert `null`.<br />Ein Wert hat den Typ, der mit dem Typ aus der Konfiguration nicht übereinstimmt.<br />Ein Preis-Wert kann nicht geparst werden.<br />Ein Feld vom Typ `Map` hat einen Schlüssel, der kein String ist.<br />Ein Feld vom Typ `List` ist kein Array von Strings.<br />Ein Zeitwert ist nicht in ISO 8601 Format.<br />Bild-Daten von einem Bild sind kein Array von Objekten.<br />`id` des Formats oder `path` sind keine Strings. |
| 400 Bad Request  | "invalidFormat"     | `custom` ist kein Objekt.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| 400 Bad Request  | "unknownDataField"  | Ein nicht existierendes Produktdatenfeld wurde im Request-Body angegeben.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| 400 Bad Request  | "notManualEditable" | Ein nicht bearbeitbares Produktdatenfeld wurde im Request-Body angegeben.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |

## Methoden für Variantenattribute

Mit den Endpunkten im Bereich `products/variants/` lassen sich die Variantenattribute und zugehörige Optionen verwalten, die zur Bildung von Produktvarianten im Shop verwendet werden. Sie können neue Attribut-Optionen hinzufügen, bestehende anpassen oder Attribute löschen. Ebenso können Sie die Anzeige-Reihenfolge von Optionen ändern oder gezielt einzelne Optionen abfragen.

Für alle hier dokumentierten Endpunkte ist eine gültige Authentifizierung erforderlich. Zusätzlich benötigen Sie die Berechtigungen zum Lesen, Erstellen oder Bearbeiten von Produktdaten.

### GET products/variants

Mit diesem Endpunkt kann eine Liste aller im Shop-System definierten Varianten-Attribute und deren verfügbaren Optionen abgerufen werden. Die Antwort gibt Aufschluss darüber, welche Attributnamen (z. B. „Größe“, „Farbe“) verwendet werden und welche Ausprägungen pro Attribut zur Verfügung stehen. Dies ist besonders hilfreich für das Anlegen oder Bearbeiten von Produktvarianten.

Für diesen Endpunkt ist eine gültige Authentifizierung erforderlich. Sie müssen über die Berechtigung zum Lesen von Produkten verfügen.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/variants
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
[
    {
        "name": "Größe",
        "options": [
            {
                "id": 1,
                "option": "L"
            },
            {
                "id": 2,
                "option": "XL"
            }
        ]
    },
    {
        "name": "Farbe",
        "options": [
            {
                "id": 4,
                "option": "Rot"
            },
            {
                "id": 3,
                "option": "Grün"
            }
        ]
    }
]
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                         |
| ---------------- | -------------- | --------------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                     |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Produktvarianten. |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.                                          |

### GET products/variants/\{id}

Mit diesem Endpunkt kann entweder ein Varianten-Attribut mit seinen zugehörigen Optionen oder eine einzelne Variante-Option abgerufen werden.

Wird in der URL ein Attributname (z. B. „Farbe“) übergeben, liefert die Antwort alle Optionen zu diesem Attribut. Wird hingegen eine Options-ID übergeben, muss zusätzlich der Parameter `singleOption=yes` gesetzt werden, um die Daten zu einer konkreten Variante-Option abzurufen. Die Suche nach dem Attributnamen erfolgt unabhängig von der Groß-/Kleinschreibung.

Für die Nutzung dieses Endpunkts ist eine gültige Authentifizierung notwendig. Sie benötigen die Berechtigung zum Lesen von Produkten.

#### Beispiel (Attribut)

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/variants/Farbe
```

#### Antwort (Attribut)

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "name": "Farbe",
    "options": [
        {
            "id": 4,
            "option": "Rot"
        },
        {
            "id": 3,
            "option": "Grün"
        }
    ]
}
```

#### Beispiel (Option)

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/variants/4?singleOption=yes
```

#### Antwort (Option)

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "id": 4,
    "attribute": "Farbe",
    "option": "Rot"
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                                                               |
| ---------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                                                           |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Produktvarianten.                                       |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.<br />Die übergebene `id` ist keine positive Ganzzahl (bei `singleOption=yes`). |
| 404 Not Found    |                | Die Option oder das Attribute wurde nicht gefunden.                                                                     |

### POST products/variants

Mit diesem Endpunkt wird ein neues Varianten-Attribut mit beliebigen Optionswerten erstellt. Sollte das Attribut bereits existieren (Groß-/Kleinschreibung wird nicht berücksichtigt), wird es um die neuen, bislang nicht vorhandenen Optionen ergänzt. Ist eine der angegebenen Optionen für das Attribut bereits vorhanden, wird der Vorgang mit einem Konfliktfehler (409) abgebrochen.

Für die Nutzung dieses Endpunkts ist eine gültige Authentifizierung erforderlich. Sie benötigen die Berechtigung zum Erstellen von Produkten.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/variants
```

#### Request-Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "attribute": "color",
    "options": [
        "red",
        "blue",
        "white"
    ]
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "attribute": "color",
    "options": [
        {
            "id": 23,
            "option": "red"
        },
        {
            "id": 24,
            "option": "blue"
        },
        {
            "id": 25,
            "option": "white"
        }
    ]
}
```

#### Fehlercodes

| **Fehler**       | **Typ**                | **Grund**                                                                                                                                                                                |
| ---------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized |                        | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                                                            |
| 403 Forbidden    |                        | Sie verfügen nicht über die erforderlichen Rechte zum Erstellen von Produktvarianten.                                                                                                    |
| 400 Bad Request  |                        | Der Request-Body konnte nicht geladen werden.                                                                                                                                            |
| 400 Bad Request  | "invalidValue"         | Es wurde eine ungültige Stage angegeben.<br />`attribute` oder `options` sind leer.<br />Die Länge von `attribute` oder von einzelnen Optionen ist gleich 0 oder größer als 128 Zeichen. |
| 400 Bad Request  | "missing"              | Parameter `attribute` oder `options` fehlen.                                                                                                                                             |
| 400 Bad Request  | "invalidFormat"        | `attribute` ist kein String.<br />`options` ist kein Array.                                                                                                                              |
| 400 Bad Request  | "unknownDataField"     | Ein unbekanntes Feld wurde im Request-Body angegeben.                                                                                                                                    |
| 409 Conflict     | "variantAlreadyExists" | Ein Attribut mit der angegebenen Option existiert bereits.                                                                                                                               |

### PUT products/variants/\{attributeId}

Mit diesem Endpunkt wird ein bestehendes Varianten-Attribut aktualisiert. Die Suche nach dem Attributnamen erfolgt unabhängig von der Groß-/Kleinschreibung.

Es können neue Optionen hinzugefügt, bestehende bearbeitet und die Reihenfolge der Optionen geändert werden. Das Umbenennen des Attributs ist über den optionalen Parameter `newAttributeName` möglich. Bereits existierende Optionen, die im Request-Body nicht enthalten sind, bleiben unverändert bestehen.

Für die Nutzung dieses Endpunkts ist eine gültige Authentifizierung erforderlich. Sie benötigen die Berechtigung zum Schreiben von Produkten.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/variants/color
```

#### Request-Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "options": [
        {
            "option": "blueUpd",
            "id": 24
        },
        {
            "id": 23,
            "option": "red"
        },
        {
            "id": 25,
            "option": "white"
        },
        {
            "option": "newColor"
        }
    ],
    "newAttributeName": "colorUpd"
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "attribute": "colorUpd"
}
```

#### Fehlercodes

| **Fehler**         | **Typ**         | **Grund**                                                                                                                                                                           |
| ------------------ | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized   |                 | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                                                       |
| 403 Forbidden      |                 | Sie verfügen nicht über die erforderlichen Rechte zum Bearbeiten von Produktvarianten.                                                                                              |
| 400 Bad Request    |                 | Der Request-Body konnte nicht geladen werden.                                                                                                                                       |
| 400 Bad Request    | "invalidValue"  | Es wurde eine ungültige Stage angegeben.<br />`options` ist kein Array.<br />Die Länge von `newAttributeName` oder von einzelnen Optionen ist gleich 0 oder größer als 128 Zeichen. |
| 400 Bad Request    | "missing"       | `attributeId` fehlt.                                                                                                                                                                |
| 404 Not Found      |                 | Das Attribut wurde nicht gefunden.                                                                                                                                                  |
| 503 Internal Error | "internalError" | Das Aktualisieren ist fehlgeschlagen.                                                                                                                                               |

### DELETE products/variants/\{id}

Mit diesem Endpunkt können Sie entweder ein Varianten-Attribut samt aller zugehörigen Optionen oder eine einzelne Option löschen. Wird das Attribut derzeit noch von einem Produkt verwendet, wird der Vorgang mit einem Konfliktfehler abgebrochen.

Für die Nutzung dieses Endpunkts ist eine gültige Authentifizierung erforderlich. Sie benötigen die Berechtigung zum Löschen von Produktdaten.

Wird in der URL ein Attributname übergeben, werden das Attribut und alle zugehörigen Optionen gelöscht. Die Suche nach dem Attributnamen erfolgt unabhängig von der Groß-/Kleinschreibung. Wird hingegen eine Options-ID übergeben, muss zusätzlich der Parameter `singleOption=yes` gesetzt werden, um nur diese einzelne Option zu löschen.

#### Beispiel (Attribut)

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/variants/color
```

#### Antwort (Attribut)

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "success": true
}
```

#### Beispiel (Option)

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/variants/4?singleOption=yes
```

#### Antwort (Option)

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "id": 4,
    "attribute": "Farbe",
    "option": "Rot"
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                                                               |
| ---------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                                                           |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Löschen von Produktvarianten.                                     |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.<br />Die übergebene `id` ist keine positive Ganzzahl (bei `singleOption=yes`). |
| 404 Not Found    |                | Die Option oder das Attribut wurden nicht gefunden.                                                                     |
| 409 Conflict     | "variantInUse" | Dieses Varianten-Attribut wird von einer Produktvariante verwendet.                                                     |

## Methoden für Produktvarianten

Die folgenden Endpunkte ermöglichen das Verwalten von Produktvarianten innerhalb eines bestehenden Produkts. Varianten stellen spezifische Ausprägungen eines Produkts dar (z. B. Größen oder Farben) und basieren auf den zuvor definierten Variantenattributen. Die API erlaubt es, Varianten einzeln abzurufen, zu erstellen, zu aktualisieren oder zu löschen sowie komplette Variantenkombinationen automatisch zu erzeugen.

Für alle Endpunkte in diesem Abschnitt ist sicherzustellen, dass die entsprechenden Lese-, Schreib- oder Löschberechtigungen für Produktvarianten vorliegen.

### GET products/\{productId}/variants

Mit diesem Endpunkt kann eine Liste aller Varianten für das angegebene Produkt geladen werden.

Varianten sind Produktversionen, die sich durch unterschiedliche Attributkombinationen (wie z. B. Größe oder Farbe) vom Hauptprodukt unterscheiden. Die Antwort enthält grundlegende Produktdaten sowie die zugehörigen Attributwerte unter `selection`.

Um diesen Endpunkt nutzen zu können, sind entsprechende Berechtigungen zum Lesen von Produktvarianten erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-1701/variants
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "endReached": true,
    "items": [
        {
            "active": "always",
            "custom": {
                "weight": 0.33
            },
            "descr": null,
            "id": "8310",
            "itemNumber": "11-1701-M",
            "name": null,
            "price": "89.900000",
            "selection": {
                "Größe": "M"
            },
            "taxRateId": null
        },
        ...
    ],
    "nextPageToken": "MTAw",
    "totalCount": 6
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                         |
| ---------------- | -------------- | --------------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                     |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Produktvarianten. |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.                                          |
| 404 Not Found    |                | Das Produkt mit `id={productId}` wurde nicht gefunden.                            |

### GET products/\{productId}/variants/\{variantId}

Mit diesem Endpunkt kann eine bestimmte Produktvariante anhand ihrer ID innerhalb eines Produkts geladen werden. Die Produkt-ID wird als Teil der URL übergeben, ebenso die Varianten-ID.

Die Antwort enthält die zugehörigen Variantendaten inklusive Preis, Artikelnummer, Auswahlattribute (`selection`) und weiterer Detailinformationen.

Für die Nutzung dieses Endpunkts sind entsprechende Berechtigungen zum Lesen von Produktvarianten erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-1701/variants/8310
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": "always",
    "custom": {
        "weight": 0.33
    },
    "descr": null,
    "id": "8310",
    "itemNumber": "11-1701-M",
    "name": null,
    "price": "89.900000",
    "selection": {
        "Größe": "M"
    },
    "taxRateId": null
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                                                       |
| ---------------- | -------------- | --------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                                                   |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Produktvarianten.                               |
| 400 Bad Request  | "invalidValue" | `id` ist ungültig. Es wurde eine ungültige Stage angegeben.                                                     |
| 404 Not Found    |                | Produkt mit `id`=`{productId}` wurde nicht gefunden. Produktvariante mit `id={variantId}` wurde nicht gefunden. |

### PUT products/\{productId}/variants/\{variantId}

Mit diesem Endpunkt können die Daten einer bestimmten Produktvariante anhand ihrer Produkt-ID und Varianten-ID aktualisiert werden. Die Variante wird anhand der angegebenen ID identifiziert und mit den im Request-Body übermittelten Werten überschrieben.

Für die Nutzung dieses Endpunkts sind Schreibrechte für Produktvarianten erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-1701/variants/8310
```

#### Request-Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": "always",
    "custom": {
        "weight": 0.33
    },
    "descr": null,
    "id": "8310",
    "itemNumber": "11-1701-M",
    "name": null,
    "price": "89.900000",
    "selection": {
        "Größe": "M"
    },
    "set": [],
    "setPrice": null,
    "taxRateId": null
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": "always",
    "custom": {
        "weight": 0.33
    },
    "descr": null,
    "id": "8310",
    "itemNumber": "11-1701-M",
    "name": null,
    "price": "89.900000",
    "selection": {
        "Größe": "M"
    },
    "setPrice": null,
    "taxRateId": null
}
```

#### Fehlercodes

| **Fehler**              | **Typ**            | **Grund**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| ----------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized        |                    | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| 403 Forbidden           |                    | Sie verfügen nicht über die erforderlichen Rechte zum Schreiben von Produktvarianten.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| 400 Bad Request         |                    | Der Request-Body konnte nicht geladen werden                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| 400 Bad Request         | "invalidValue"     | Es wurde eine ungültige Stage angegeben oder ein ungültiger Subshop angegeben.<br />`custom` ist kein Objekt.<br />Ein Feld enthält den Wert `null`.<br />Ein Wert hat den Typ, der mit dem Typ aus der Konfiguration nicht übereinstimmt.<br />Ein Preis-Wert kann nicht geparst werden.<br />Ein Feld vom Typ `Map` hat einen Schlüssel, der kein String ist.<br />Ein Feld vom Typ `List` ist kein Array von Strings.<br />Ein Zeitwert ist nicht in ISO 8601 Format.<br />Bild-Daten von einem Bild sind kein Array von Objekten.<br />`id` des Formats oder `path` sind keine Strings. |
| 400 Bad Request         | "unknownDataField" | Ein nicht existierendes Produktdatenfeld wurde im Request-Body angegeben.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| 404 Not Found           |                    | Produkt mit `id`=`{productId}` wurde nicht gefunden <br /> Produktvariante mit `id={variantId}` wurde nicht gefunden.                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| 400 Bad Request         | "invalidFormat"    | `custom` ist kein Objekt.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| 503 Service Unavailable | "internalError"    | Das Produkt konnte nach mehreren Versuchen aufgrund von Versionskonflikten nicht gespeichert werden.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |

### POST products/\{productId}/variantAttributes

Mit diesem Endpunkt können für ein bestimmtes Produkt Varianten automatisch aus den übergebenen Attributen erzeugt werden. Dabei wird jede mögliche Kombination der Attribut-Optionen als eigene Produktvariante angelegt.

Wenn dem Produkt bisher nicht zugewiesene Attribute ergänzt oder vorhandene Attribute entfernt werden, wird der Vorgang standardmäßig abgebrochen und es wird ein 400-Fehler mit dem Fehlertyp `conflict` zurückgegeben. Um diesen Abbruch zu umgehen, kann der optionale Parameter `force=yes` verwendet werden – in diesem Fall werden alle bisherigen Kombinationen gelöscht und durch die neuen ersetzt.

Für die Nutzung dieses Endpunkts sind Schreibrechte für Produktvarianten erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-1701/variantAttributes
```

#### Request-Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "attributes": [ "größe", "farbe" ]
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "success": true
}
```

#### Fehlercodes

| **Fehler**              | **Typ**            | **Grund**                                                                                                                                                        |
| ----------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized        |                    | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                                    |
| 403 Forbidden           |                    | Sie verfügen nicht über die erforderlichen Rechte zum Erstellen von Produktvarianten.                                                                            |
| 400 Bad Request         |                    | Der Request-Body konnte nicht geladen werden.                                                                                                                    |
| 400 Bad Request         | "invalidValue"     | Es wurde eine ungültige Stage angegeben. <br /> Ein angegebenes Attribut existiert nicht.                                                                        |
| 400 Bad Request         | "missing"          | `attributes` fehlt im Request-Body.                                                                                                                              |
| 400 Bad Request         | "invalidFormat"    | `attributes` ist kein Array. <br /> Ein Element in `attributes` ist kein String.                                                                                 |
| 400 Bad Request         | "unknownDataField" | Ein unbekanntes Feld wurde im Request-Body angegeben.                                                                                                            |
| 400 Bad Request         | "conflict"         | Die Variantenattribute des Produkts haben sich geändert. Bestehende Varianten würden gelöscht. Verwenden Sie `force=yes`, um den Vorgang trotzdem durchzuführen. |
| 404 Not Found           |                    | Das Produkt mit `id`=`{productId}` wurde nicht gefunden.                                                                                                         |
| 503 Service Unavailable | "internalError"    | Das Produkt konnte nicht aktualisiert werden.                                                                                                                    |

### POST products/\{productId}/variants/manage

Dieser Endpunkt ermöglicht es, gezielt bestimmte Varianten-Kombinationen für ein bestehendes Produkt anzulegen.

Anders als beim Endpunkt `POST products/{productId}/variantAttributes`, der automatisch alle möglichen Kombinationen aus den angegebenen Attributen generiert, werden hier nur die explizit übermittelten Kombinationen erzeugt. Bereits existierende Kombinationen werden ignoriert; bei Kollisionen wird ein entsprechender Fehlercode zurückgegeben. Optional können auch IDs übergeben.

Der Endpunkt eignet sich besonders, wenn nicht alle theoretisch möglichen Kombinationen eines Produkts benötigt werden, sondern nur eine gezielte Auswahl.

Für die Nutzung sind Schreibrechte für Produktvarianten erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-1701/variants/manage
```

#### Request-Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "selections": [
        {
            "größe": "M",
            "farbe": "rot"
        },
        {
            "id": "443",
            "größe": "L",
            "farbe": "blau"
        },
        ...
    ]
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "items": [
        {
            "id": "42",
            "selection": {
                "größe": "M",
                "farbe": "rot"
            }
        },
        {
            "id": "443",
            "selection": {
                "größe": "L",
                "farbe": "blau"
            }
        },
        ...
    ]
}
```

#### Fehlercodes

| **Fehler**       | **Typ**            | **Grund**                                                                                                                      |
| ---------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| 401 Unauthorized |                    | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                  |
| 403 Forbidden    |                    | Sie verfügen nicht über die erforderlichen Rechte zum Erstellen von Produktvarianten.                                          |
| 400 Bad Request  |                    | Der Request-Body konnte nicht geladen werden                                                                                   |
| 400 Bad Request  | "invalidValue"     | Es wurde eine ungültige Stage angegeben.<br />`selections` beinhaltet ungültige Attribut oder Attributwerte.                   |
| 400 Bad Request  | "duplicateEntry"   | Eine übergebene Attributkombination existiert bereits als Produktvariante.                                                     |
| 400 Bad Request  | "missing"          | `selections` fehlt im Request-Body.                                                                                            |
| 400 Bad Request  | "invalidFormat"    | `selections` ist kein Array. <br /> Ein Element in `selections` ist kein JSON-Objekt. <br /> Ein Attributwert ist kein String. |
| 400 Bad Request  | "unknownDataField" | Ein unbekanntes Feld wurde im Request-Body angegeben.                                                                          |
| 404 Not Found    |                    | Produkt mit `id`=`{productId}` wurde nicht gefunden                                                                            |
| 409 Conflict     | "versionConflict"  | Das Produkt wurde während des Generierens der Varianten verändert.                                                             |

### DELETE products/\{productId}/variants/\{variantId}

Mit diesem Endpunkt kann eine bestehende Produktvariante anhand von Produkt-ID und Varianten-ID gelöscht werden. Dies ist etwa dann sinnvoll, wenn bestimmte Kombinationen von Varianten (z. B. Größe/Farbe) nicht mehr angeboten werden sollen.

Sowohl das übergeordnete Produkt als auch die Variante müssen existieren – andernfalls wird ein entsprechender Fehler zurückgegeben.

Für die Nutzung sind Löschberechtigungen für Produktvarianten erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-1701/variants/1
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "success": true
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                                                       |
| ---------------- | -------------- | --------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                                                   |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Löschen von Produktvarianten.                             |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.                                                                        |
| 404 Not Found    |                | Produkt mit `id`=`{productId}` wurde nicht gefunden   Produktvariante mit `id={variantId}` wurde nicht gefunden |

## Bulk-Methoden für Varianten

In diesem Abschnitt werden die Bulk-Endpunkte beschrieben, mit denen mehrere Datensätze in einem einzigen Request abgefragt oder verarbeitet werden können.

### POST bulk/products/variants

Ermöglicht das massenhafte Erstellen und Aktualisieren von Produktdaten in einem einzigen Request. Der Request-Body ist ein JSON-Array, in dem jedes Element ein Produkt beschreibt. Erstell- und Schreibrechte für Produktvarianten sind erforderlich.

Für jeden Eintrag wird die jeweilige Produktvariante über die Felder `productId`, `variantId` und `selection` identifiziert. Zum Aktualisieren einer Variante genügt `productId` in Kombination mit `selection` oder `variantId`. Beim Anlegen einer neuen Variante ist `selection` verpflichtend; wird zusätzlich `variantId` mitgegeben, wird die neue Variante mit dieser ID erstellt.

Standardmäßig werden nur Produktvarianten aktualisiert. Wird der Parameter createMissing=yes gesetzt, dann werden Produktvarianten in der Anfrage die noch nicht existieren automatisch neues angelegt.

In einem Request können maximal 1000 Einträge verarbeitet werden.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/bulk/products/variants
```

#### Request Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
[
    {
        "custom": {
            "liste": [],
            "map": {}
        },
        "productId": "144-46864",
        "selection": {
            "größe": "M",
            "farbe": "rot"
        }
        "id": "",
        "active": "always",
        "descr": "This is a new Variant",
        "name": "NewVariant",
    },
    {
        "custom": {
            "liste": [],
            "map": {}
        },
        "productId": "144-46864",
        "selection": {
            "größe": "L",
            "farbe": "blau"
        }
        "active": "always",
        "descr": "This is an existing Variant",
        "name": "existingVariant",
    }
]
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "items": [{"lineNumber": 1, "productId": "144-46864", "variantId": "43"}],
    "skippedLines": [{
        "lineNumber": 0,
        "productId": "144-46864",
        "errorType": "notFound",
        "fieldErrors": {}
    }]
}
```

#### Fehlercodes

| **Fehler**       | **Typ**              | **Grund**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ---------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized |                      | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| 403 Forbidden    |                      | Sie verfügen nicht über die erforderlichen Rechte zum Erstellen oder aktualisieren von Produkten.                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| 400 Bad Request  |                      | Der Request-Body konnte nicht geladen werden. <br /> Es wurden mehr als 1000 Einträge angegeben.                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| 400 Bad Request  | "invalidValue"       | Es wurde eine ungültige Stage oder ein ungültiger Subshop angegeben.<br />Ein Feld enthält den Wert `null`.<br />Ein Wert hat den Typ, der mit dem Typ aus der Konfiguration nicht übereinstimmt.<br />Ein Preis-Wert kann nicht geparst werden.<br />Ein Feld vom Typ `Map` hat einen Schlüssel, der kein String ist.<br />Ein Feld vom Typ `List` ist kein Array von Strings.<br />Ein Zeitwert ist nicht in ISO 8601 Format.<br />Bild-Daten von einem Bild sind kein Array von Objekten.<br />`id` des Formats oder `path` sind keine Strings. |
| 400 Bad Request  | "invalidCombination" | Es wurden `variantId` und `selection` angegeben, jedoch passt die `variantId` nicht zur über `selection` identifizierten Variante.                                                                                                                                                                                                                                                                                                                                                                                                                 |
| 400 Bad Request  | "invalidFormat"      | `custom` ist kein Objekt.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| 400 Bad Request  | "unknownDataField"   | Ein nicht existierendes Produktdatenfeld wurde im Request-Body angegeben.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| 400 Bad Request  | "notManualEditable"  | Ein nicht bearbeitbares Produktdatenfeld wurde im Request-Body angegeben.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |

## Methoden für Lagerbestand Allgemein

Die folgenden Endpunkte ermöglichen das Abrufen, Erstellen, Aktualisieren und Löschen von Lagerbeständen im System. Jeder Lagerbestand wird durch eine eindeutige `inventoryId` identifiziert, die üblicherweise mit einer Produkt- oder Varianten-ID übereinstimmt.

Abhängig vom Endpunkt können Lagerbestände direkt gesetzt oder relativ verändert werden (z. B. beim Buchen von Zu- oder Abgängen).

Für alle hier dokumentierten Endpunkte ist eine entsprechende Berechtigung für den Zugriff auf Lagerbestände erforderlich.

Alle Endpunkte in diesem Abschnitt unterstützen den optionalen URL-Parameter `storageId`, mit dem die Lager-ID explizit angegeben werden kann. Wird dieser Parameter nicht gesetzt, wird automatisch die Lager-ID des aktiven Subshops verwendet.

### GET products/inventory/\{inventoryId}

Mit diesem Endpunkt kann der Lagerbestand eines Produkts oder einer Produktvariante anhand der Lagerbestands-ID (`inventoryId`) abgerufen werden. Die Antwort enthält Informationen über den aktuellen Bestand, offene Bestellungen sowie den Zeitpunkt der letzten Aktualisierung.

Damit der Endpunkt genutzt werden kann, müssen die entsprechenden Berechtigungen zum Lesen von Lagerbeständen vorhanden sein.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/inventory/11-1701%20M
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "amount": 10.0,
    "id": "100-21456",
    "openOrder": 0.0,
    "setAt": "2024-08-19T08:03:26.000Z",
    "updatedAt": "2024-08-19T08:03:26.000Z"
}
```

#### Fehlercodes

| **Fehler**       | **Typ** | **Grund**                                                                        |
| ---------------- | ------- | -------------------------------------------------------------------------------- |
| 401 Unauthorized |         | Nicht autorisiert: Sie sind nicht angemeldet.                                    |
| 403 Forbidden    |         | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Lagerbeständen.  |
| 404 Not Found    |         | Es wurde kein Lagerbestand mit `id={inventoryId}` im aktuellen Subshop gefunden. |

### POST products/inventory

Mit diesem Endpunkt wird ein neuer Lagerbestand für ein Produkt oder eine Produktvariante angelegt. Dabei wird eine eindeutige Lagerbestands-ID (`id`) sowie die verfügbaren und offenen Mengen angegeben.

Damit dieser Endpunkt verwendet werden kann, müssen die entsprechenden Berechtigungen zum Erstellen von Lagerbeständen vorhanden sein.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/inventory
```

#### Request-Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "id": "11-1701 M",
    "amount": 10.0,
    "openOrder": 0.0
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "amount": 10.0,
    "id": "11-1701 M",
    "openOrder": 0.0,
    "setAt": "2025-05-01T10:12:00.000Z",
    "updatedAt": "2025-05-01T10:12:00.000Z"
}
```

#### Fehlercodes

| **Fehler**       | **Typ**            | **Grund**                                                                           |
| ---------------- | ------------------ | ----------------------------------------------------------------------------------- |
| 401 Unauthorized |                    | Nicht autorisiert: Sie sind nicht angemeldet.                                       |
| 403 Forbidden    |                    | Sie verfügen nicht über die erforderlichen Rechte zum Erstellen von Lagerbeständen. |
| 400 Bad Request  |                    | Der Request-Body konnte nicht geladen werden                                        |
| 400 Bad Request  | "missing"          | Das Pflichtfeld `id` fehlt im Request-Body                                          |
| 400 Bad Request  | "invalidValue"     | Das Feld `id` darf nicht leer sein                                                  |
| 400 Bad Request  | "invalidFormat"    | Ein Feldwert hat einen falschen Datentyp (z. B. Number statt String für `id`)       |
| 400 Bad Request  | "unknownDataField" | Der Request-Body enthält ein unbekanntes Feld                                       |
| 400 Bad Request  | "duplicateEntry"   | Ein Lagerbestand mit der angegebenen `id` existiert bereits                         |

### PUT products/inventory/\{inventoryId}

Mit diesem Endpunkt aktualisieren Sie den Lagerbestand eines bestimmten Produkts anhand der übergebenen Parameter. Dabei können Sie sowohl den Bestand (`amount`) als auch die Anzahl der offenen Bestellungen (`openOrder`) anpassen – entweder absolut oder relativ:

* Ist `amountType` auf `relative` gesetzt, wird der aktuelle Lagerbestand um den angegebenen `amount` erhöht oder – falls der Wert negativ ist – verringert. Andernfalls wird der Lagerbestand auf den Wert von `amount` gesetzt.
* Entsprechend funktioniert `openOrderType`: Ist dieser auf `relative` gesetzt, wird die Anzahl der offenen Bestellungen um `openOrder` erhöht oder verringert (bei negativem Wert). Ohne `relative` wird `openOrder` direkt gesetzt.

Existiert noch kein Lagerbestand für die angegebene `{inventoryId}`, kann über den optionalen URL-Parameter `createMissing=yes` automatisch ein neuer Eintrag angelegt werden.

Um diesen Endpunkt verwenden zu können, benötigen Sie die Berechtigung zum Schreiben von Lagerbeständen.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/inventory/1
```

#### Request-Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "amount": 10.0,
    "amountType": "absolute",
    "openOrder": -1.0,
    "openOrderType": "relative"
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "amount": 15.0,
    "id": "11-1701 M",
    "openOrder": 4.0,
    "setAt": "2025-05-01T14:22:30.000Z",
    "updatedAt": "2025-05-01T14:22:30.000Z"
}
```

#### Fehlercodes

| **Fehler**       | **Typ**         | **Grund**                                                                                                           |
| ---------------- | --------------- | ------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized |                 | Nicht autorisiert: Sie sind nicht angemeldet.                                                                       |
| 403 Forbidden    |                 | Sie verfügen nicht über die erforderlichen Rechte zum Schreiben von Lagerbeständen.                                 |
| 400 Bad Request  |                 | Der Request-Body konnte nicht geladen werden                                                                        |
| 400 Bad Request  | "invalidFormat" | `amount` oder `openOrder` ist kein gültiger Number-Typ                                                              |
| 404 Not Found    |                 | Es wurde kein Lagerbestand mit `id={inventoryId}` im aktuellen Subshop gefunden und `createMissing` ist nicht `yes` |

### DELETE products/inventory/\{inventoryId}

Mit diesem Endpunkt löschen Sie den Lagerbestand eines Produkts für die angegebene `{inventoryId}` im aktuellen Subshop. Wenn kein entsprechender Eintrag existiert, wird ein Fehler zurückgegeben.

Um diesen Endpunkt verwenden zu können, benötigen Sie die Berechtigung zum Löschen von Lagerbeständen.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/inventory/1
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "success": true
}
```

#### Fehlercodes

| **Fehler**       | **Typ** | **Grund**                                                                         |
| ---------------- | ------- | --------------------------------------------------------------------------------- |
| 401 Unauthorized |         | Nicht autorisiert: Sie sind nicht angemeldet.                                     |
| 403 Forbidden    |         | Sie verfügen nicht über die erforderlichen Rechte zum Löschen von Lagerbeständen. |
| 404 Not Found    |         | Es wurde kein Lagerbestand mit `id={inventoryId}` im aktuellen Subshop gefunden   |

### PUT bulk/products/inventory

Mit diesem Endpunkt können Sie mehrere Lagerbestände gleichzeitig aktualisieren. Die zu aktualisierenden Einträge werden als Array im Request-Body übergeben. Jeder Eintrag muss eine `id` (Lagerbestands-ID) enthalten. Für jeden Eintrag können sowohl der Bestand (`amount`) als auch die Anzahl der offenen Bestellungen (`openOrder`) angepasst werden – entweder absolut oder relativ:

* Ist `amountType` auf `relative` gesetzt, wird der aktuelle Lagerbestand um den angegebenen `amount` erhöht oder – falls der Wert negativ ist – verringert. Andernfalls wird der Lagerbestand auf den Wert von `amount` gesetzt.
* Entsprechend funktioniert `openOrderType`: Ist dieser auf `relative` gesetzt, wird die Anzahl der offenen Bestellungen um `openOrder` erhöht oder verringert (bei negativem Wert). Ohne `relative` wird `openOrder` direkt gesetzt.
* Existiert noch kein Lagerbestand für eine angegebene `id`, kann über den optionalen URL-Parameter `createMissing=yes` automatisch ein neuer Eintrag angelegt werden. Einträge mit ungültigen Daten (z. B. `amount` ist kein Number-Typ) werden übersprungen.

Um diesen Endpunkt verwenden zu können, benötigen Sie die Berechtigung zum Schreiben von Lagerbeständen.

In einem Request können maximal 1000 Einträge verarbeitet werden.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/bulk/products/inventory?createMissing=yes
```

#### Request-Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
[
    {
        "id": "11-1701 M",
        "amount": 10.0,
        "amountType": "absolute",
        "openOrder": -1.0,
        "openOrderType": "relative"
    },
    {
        "id": "11-1702 L",
        "amount": 5.0
    }
]
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "items": ["11-1701 M", "11-1702 L"],
    "skippedLines": []
}
```

#### Fehlercodes

| **Fehler**       | **Typ**         | **Grund**                                                                                        |
| ---------------- | --------------- | ------------------------------------------------------------------------------------------------ |
| 401 Unauthorized |                 | Nicht autorisiert: Sie sind nicht angemeldet.                                                    |
| 403 Forbidden    |                 | Sie verfügen nicht über die erforderlichen Rechte zum Schreiben von Lagerbeständen.              |
| 400 Bad Request  |                 | Der Request-Body konnte nicht geladen werden. <br /> Es wurden mehr als 1000 Einträge angegeben. |
| 400 Bad Request  | "invalidFormat" | Der URL-Parameter `stageId` ist ungültig.                                                        |

## Methoden für Produkte Lagerbestand

Über die folgenden Endpunkte lassen sich lagerbezogene Einstellungen für einzelne Produkte verwalten. Dazu zählen sowohl die Zuordnung zu einem Lagerbestandseintrag als auch die Konfiguration der Darstellung im Shop, wie z. B. farbliche Ampellogik, individuelle Lagermeldungen und Reservierungszeiten. Die Einstellungen greifen dabei direkt auf die allgemeinen Lagerbestände zu, die über die Endpunkte aus Kapitel 6 gepflegt werden.

Für den Zugriff auf diese Endpunkte sind Lese- oder Schreibrechte für Produktdaten erforderlich, je nach gewählter Operation.

### GET products/\{productId}/inventory

Mit diesem Endpunkt können Sie die Lagerbestandskonfiguration eines bestimmten Produkts abrufen. Diese Konfiguration umfasst unter anderem Schwellwerte für Ampelfarben, individuelle Lagermeldungen und die Reservierungsdauer. Die Angabe `storeId` verweist auf einen allgemeinen Lagerbestandseintrag, wie er über die Lagerbestands-Endpunkte verwaltet wird.

Für die Verwendung dieses Endpunkts sind Lese-Berechtigungen für Produktdaten erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-703/inventory
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": true,
    "greenYellowBorder": 0,
    "messageLimit": 5,
    "messageMail": "m.mustermann@websale.de",
    "messageMode": "inactive",
    "redOrder": true,
    "reservationTime": 10,
    "state": "dynamic",
    "storeId": "11-1701%20M",
    "textGreen": "auf Lager",
    "textRed": "Wieder vorrätig in 1 Woche(n)",
    "textYellow": "Geringe Stückzahl",
    "useGlobalBorders": false,
    "useGlobalReservationTime": true,
    "useGlobalTexts": true,
    "yellowRedBorder": 0
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                                                                   |
| ---------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                                                               |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Produktdaten.                                               |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.                                                                                    |
| 404 Not Found    |                | Das Produkt mit `id={productId}` wurde nicht gefunden   Kein Lagerbestand ist dem Produkt mit `id`=`{productId}` zugewiesen |

### PUT products/\{productId}/inventory

Dieser Endpunkt dient dazu, die Lagerbestandseinstellungen eines Produkts zu aktualisieren. Dabei lassen sich z. B. die Darstellung im Shop (Ampel-Logik), Lagermeldungen oder die Reservierungszeit anpassen. Die Einstellung `storeId` bleibt hierbei unverändert und muss nicht übergeben werden.

Für die Verwendung dieses Endpunkts sind Schreib-Berechtigungen für Produktdaten erforderlich.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-703/inventory
```

#### Request-Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": true,
    "greenYellowBorder": 0,
    "messageLimit": 5,
    "messageMail": "m.mustermann@websale.de",
    "messageMode": "inactive",
    "redOrder": true,
    "reservationTime": 10,
    "state": "dynamic",
    "textGreen": "auf Lager",
    "textRed": "Wieder vorrätig in 1 Woche(n)",
    "textYellow": "Geringe Stückzahl",
    "useGlobalBorders": false,
    "useGlobalReservationTime": true,
    "useGlobalTexts": true,
    "yellowRedBorder": 0
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": true,
    "greenYellowBorder": 0,
    "messageLimit": 5,
    "messageMail": "m.mustermann@websale.de",
    "messageMode": "inactive",
    "redOrder": true,
    "reservationTime": 10,
    "state": "dynamic",
    "storeId": "11-1701%20M",
    "textGreen": "auf Lager",
    "textRed": "Wieder vorrätig in 1 Woche(n)",
    "textYellow": "Geringe Stückzahl",
    "useGlobalBorders": false,
    "useGlobalReservationTime": true,
    "useGlobalTexts": true,
    "yellowRedBorder": 0
}
```

#### Fehlercodes

| **Fehler**              | **Typ**         | **Grund**                                                                                                                                                  |
| ----------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized        |                 | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                              |
| 403 Forbidden           |                 | Sie verfügen nicht über die erforderlichen Rechte zum Schreiben von Produktdaten.                                                                          |
| 400 Bad Request         | "invalidValue"  | Es wurde eine ungültige Stage angegeben   `state` ∉ `{“dynamic”, “green”, “yellow”, “redhard”, “redsoft”}messageMode` ∉ `{“inactive”, “active”, “global”}` |
| 400 Bad Request         | "invalidFormat" | Ein Feldwert hat einen falschen Datentyp (z. B. String statt Boolean oder Number)                                                                          |
| 400 Bad Request         |                 | Der Request-Body konnte nicht geladen werden                                                                                                               |
| 404 Not Found           |                 | Das Produkt mit `id={productId}` wurde nicht gefunden   Kein Lagerbestand ist dem Produkt mit `id`=`{productId}` zugewiesen                                |
| 503 Service Unavailable |                 | Versionskonflikte: Die Aktualisierung konnte nach mehreren Versuchen nicht durchgeführt werden.                                                            |

## Methoden für Varianten Lagerbestand

Dieses Kapitel beschreibt die Endpunkte zur Verwaltung von lagerbezogenen Einstellungen einzelner Produktvarianten. Wie bei Produkten lassen sich auch für Varianten spezifische Lagerbestandsanzeigen, Ampelgrenzen, individuelle Texte und Reservierungszeiten festlegen. Die Zuordnung erfolgt ebenfalls über einen `storeId`, der auf einen zentral gepflegten Lagerbestand verweist.

Für den Zugriff sind entsprechende Lese- oder Schreibrechte auf Produktdaten erforderlich.

### GET products/\{productId}/variants/\{variantId}/inventory

Ruft die Lagerbestandseinstellungen der Produktvariante mit der angegebenen `variantId` ab.

Die Einstellungen beinhalten unter anderem Ampelgrenzen, Verfügbarkeitsanzeige, E-Mail-Benachrichtigungen sowie den Verweis (`storeId`) auf den zugehörigen zentralen Lagerbestand.

Für diese Abfrage werden Lese-Rechte auf Produktvarianten benötigt.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-703/variants/1/inventory
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": true,
    "greenYellowBorder": 0,
    "messageLimit": 5,
    "messageMail": "m.mustermann@websale.de",
    "messageMode": "inactive",
    "redOrder": true,
    "reservationTime": 10,
    "state": "dynamic",
    "storeId": "GUT",
    "textGreen": "auf Lager",
    "textRed": "Wieder vorrätig in 1 Woche(n)",
    "textYellow": "Geringe Stückzahl",
    "useGlobalBorders": false,
    "useGlobalReservationTime": true,
    "useGlobalTexts": true,
    "yellowRedBorder": 0
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                                                                                                                                   |
| ---------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                                                               |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Produktvarianten.                                                                                                           |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.                                                                                                                                                    |
| 404 Not Found    |                | Das Produkt mit `id={productId}` wurde nicht gefunden   Die Produktvariante mit `id={variantId}` wurde nicht gefunden   Kein Lagerbestand ist dem Produkt mit `id`=`{productId}` zugewiesen |

### PUT products/\{productId}/variants/\{variantId}/inventory

Aktualisiert die Lagerbestandseinstellungen der Produktvariante mit der angegebenen `variantId`.

Die Konfigurationen wirken sich direkt auf die Darstellung im Shop aus und steuern z. B. die Verfügbarkeitsanzeige. Die Verknüpfung zum zentralen Lager erfolgt über das Feld `storeId`.

Für diese Operation werden Schreibrechte auf Produktvarianten benötigt.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-703/variants/1/inventory
```

#### Request-Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": true,
    "greenYellowBorder": 0,
    "messageLimit": 5,
    "messageMail": "m.mustermann@websale.de",
    "messageMode": "inactive",
    "redOrder": true,
    "reservationTime": 10,
    "state": "dynamic",
    "textGreen": "auf Lager",
    "textRed": "Wieder bestellbar in 1 Woche(n)",
    "textYellow": "Geringe Menge",
    "useGlobalBorders": false,
    "useGlobalReservationTime": true,
    "useGlobalTexts": true,
    "yellowRedBorder": 0
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "active": true,
    "greenYellowBorder": 0,
    "messageLimit": 5,
    "messageMail": "m.mustermann@websale.de",
    "messageMode": "inactive",
    "redOrder": true,
    "reservationTime": 10,
    "state": "dynamic",
    "textGreen": "auf Lager",
    "textRed": "Wieder bestellbar in 1 Woche(n)",
    "textYellow": "Geringe Menge",
    "useGlobalBorders": false,
    "useGlobalReservationTime": true,
    "useGlobalTexts": true,
    "yellowRedBorder": 0
}
```

#### Fehlercodes

| **Fehler**              | **Typ**         | **Grund**                                                                                                                                                                                   |
| ----------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401 Unauthorized        |                 | Nicht autorisiert: Sie sind nicht angemeldet.                                                                                                                                               |
| 403 Forbidden           |                 | Sie verfügen nicht über die erforderlichen Rechte zum Schreiben von Produktvarianten.                                                                                                       |
| 400 Bad Request         | "invalidValue"  | Es wurde eine ungültige Stage angegeben   `state` ∉ `{“dynamic”, “green”, “yellow”, “redhard”, “redsoft”}messageMode` ∉ `{“inactive”, “active”, “global”}`                                  |
| 400 Bad Request         | "invalidFormat" | Ein Feldwert hat einen falschen Datentyp (z. B. String statt Boolean oder Number)                                                                                                           |
| 400 Bad Request         |                 | Der Request-Body konnte nicht geladen werden                                                                                                                                                |
| 404 Not Found           |                 | Das Produkt mit `id={productId}` wurde nicht gefunden   Die Produktvariante mit `id={variantId}` wurde nicht gefunden   Kein Lagerbestand ist dem Produkt mit `id`=`{productId}` zugewiesen |
| 503 Service Unavailable |                 | Versionskonflikte: Die Aktualisierung konnte nach mehreren Versuchen nicht durchgeführt werden.                                                                                             |

## Methoden für Set-Produkte

Dieses Kapitel beschreibt die Endpunkte zur Verwaltung von Set-Produkten (Produktbündeln)

Für den Zugriff sind entsprechende Lese- oder Schreibrechte auf Produktdaten erforderlich.

### products/\{parentProductId}/setproducts

Gibt eine Liste mit Unterprodukten zurück, wenn das Produkt mit `id=parentProductId` einen Set besitzt. Optional kann `setParentProductList` IDs der Produkte enthalten, zu deren Sets das aktuelle Produkt gehört.

Für diese Abfrage werden Lese-Rechte auf Produktdaten benötigt.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/12-2325/setproducts?subshopId=deutsch&from=0&size=100
```

#### Antwort (Hauptprodukt)

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "endReached": true,
    "isChildProduct": false,
    "items": [
        {
            "active": "always",
            "custom": {
                "brand": "",
                "commission": 0,
                "commissionTaxRate": "",
                "crossSelling": [],
                "customNumber": "",
                "ean": "",
                "filterField": "",
                "image": [],
                "isbn": "",
                "mainCategory": "",
                "metaDescription": "",
                "metaDescriptionSetManually": false,
                "metaTitle": "",
                "metaTitleSetManually": false,
                "multiProducts": "",
                "oneTimeFee": 0,
                "oneTimeFeeTaxRate": "",
                "productDiscount": 0,
                "productDiscountAbsolute": false,
                "productType": "",
                "robotsNoFollow": false,
                "robotsNoIndex": false,
                "setOrgPrice": "0.000000",
                "validForDiscount": false,
                "video": "",
                "voucherProductActive": false,
                "voucherProductHtmlTemplate": "",
                "voucherProductPrice": false,
                "voucherProductTemplate": "",
                "weight": 0
            },
            "descr": "Beautiful! Mit unserer neuen, weißen Bluse mit femininen Volants an Kragen und Knopfleiste kreieren Sie im Nu lässig verspielte Looks. Das sportliche Feinoxford-Gewebe trägt sich sehr komfortabel und schmeichelt der Haut. Ein absolutes Must-have und Lieblingsteil für die neue Saison. Geschneidert <span class='passform'>in leicht taillierter Form (Regular Fit)</span> mit verdeckter Knopfleiste und gerundeter Saumlinie. <span class='mass'>Länge ca. 68 cm.</span><span class='katalogfarbe'>Farbe: Weiß.</span><span class='herkunft'>Original Herringbone.</span>  <span class='material'>Reine Baumwolle.</span>",
            "hasVariants": true,
            "id": "11-2492",
            "itemNumber": "11-2492",
            "name": "Rüschenbluse 'Florence'",
            "price": "69.900000",
            "setPrice": "0.000000",
            "taxRateId": "1",
            "timestampCreatedAt": "2025-02-14T10:50:41.000Z",
            "timestampUpdatedAt": "2025-04-28T10:24:24.000Z"
        },
        {
            "active": "always",
            "custom": {
                "brand": "",
                "commission": 0,
                "commissionTaxRate": "",
                "crossSelling": [],
                "customNumber": "",
                "ean": "",
                "filterField": "",
                "image": [],
                "isbn": "",
                "mainCategory": "",
                "metaDescription": "",
                "metaDescriptionSetManually": false,
                "metaTitle": "",
                "metaTitleSetManually": false,
                "multiProducts": "",
                "oneTimeFee": 0,
                "oneTimeFeeTaxRate": "",
                "productDiscount": 0,
                "productDiscountAbsolute": false,
                "productType": "",
                "robotsNoFollow": false,
                "robotsNoIndex": false,
                "setOrgPrice": "0.000000",
                "validForDiscount": false,
                "video": "",
                "voucherProductActive": false,
                "voucherProductHtmlTemplate": "",
                "voucherProductPrice": false,
                "voucherProductTemplate": "",
                "weight": 0
            },
            "descr": "Schlichter Unterziehrolli? Von wegen! Dieses Basicteil werden Sie lieben, sobald Sie es das erste Mal getragen haben. Es ist aus besonders edlem Swiss Cotton Jersey gefertigt, einem sehr feinen, samtweichen und luxuriösen Jersey mit zartem Glanz. Auf der Haut fühlt er sich wahnsinnig gut an und durch seine Elastizität ist er unendlich bequem. Der etwas weiter geschnittene Rollkragen, wird locker drapiert und engt daher überhaupt nicht ein. Tragen Sie dieses Rollkragenshirt unter Blazern, Westen, Hemdjacken oder Blusen und Sie werden nicht nur top aussehen, sondern sich auch so fühlen! <span class='passform'>Normale Form (Regular Fit).</span><span class='mass'>Länge ca. 66 cm.</span><span class='katalogfarbe'>Farbe: Ecru.</span><span class='herkunft'>Original Herringbone.</span>  <span class='material'>Reine Baumwolle.</span>",
            "hasVariants": true,
            "id": "11-2497",
            "itemNumber": "11-2497",
            "name": "Edles Rollkragenshirt",
            "price": "89.900000",
            "setPrice": "0.000000",
            "taxRateId": "1",
            "timestampCreatedAt": "2025-02-14T10:50:43.000Z",
            "timestampUpdatedAt": "2025-04-28T10:24:24.000Z"
        }
    ],
    "setData": {
        "items": [
            {
                "fixQuantity": false,
                "hidden": false,
                "id": "11-2497",
                "quantityFactor": 1,
                "usePrice": true
            },
            {
                "fixQuantity": false,
                "hidden": false,
                "id": "11-2492",
                "quantityFactor": 1,
                "usePrice": true
            }
        ]
    },
    "setParentProductList": [],
    "totalCount": 2
}
```

#### Antwort (Set-Unterprodukt)

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "endReached": true,
    "isChildProduct": true,
    "items": [],
    "setData": {},
    "setParentProductList": [
        "12-2325"
    ],
    "totalCount": 0
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                     |
| ---------------- | -------------- | ----------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                 |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Lesen von Produktdaten. |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.                                      |

### POST products/\{parentProductId}/setproducts/assign

Produkte aus dem Request Body werden dem Set vom Produkt mit `id=parentProductId` zugewiesen. Das Feld `prodId` kann entweder ein einzelner String oder ein Array von Strings sein.

Für diese Abfrage werden Schreib-Rechte auf Produktdaten benötigt.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-2803/setproducts/assign?subshopId=deutsch
```

#### Request Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
	"prodId": [
		"105-59442"
	]
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "success": true
}
```

#### Fehlercodes

| **Fehler**       | **Typ**            | **Grund**                                                                         |
| ---------------- | ------------------ | --------------------------------------------------------------------------------- |
| 401 Unauthorized |                    | Nicht autorisiert: Sie sind nicht angemeldet.                                     |
| 403 Forbidden    |                    | Sie verfügen nicht über die erforderlichen Rechte zum Schreiben von Produktdaten. |
| 400 Bad Request  |                    | Request body konnte nicht geladen werden.                                         |
| 400 Bad Request  | "invalidValue"     | Es wurde eine ungültige Stage angegeben.                                          |
| 400 Bad Request  | "missing"          | `prodId` fehlt oder ist leer.                                                     |
| 400 Bad Request  | "invalidFormat"    | `prodId` ist kein Array von Strings.                                              |
| 400 Bad Request  | "unknownDataField" | Der Request Body enthält unbekannte Felder.                                       |
| 404 Not Found    |                    | `parentProductId` fehlt.                                                          |

### POST products/\{parentProductId}/setproducts/update/\{childProductId}

Daten vom Produkt mit `id=childProductId` im Set vom Produkt mit `id=parentProductId` werden aktualisiert.

Für diese Abfrage werden Schreib-Rechte auf Produktdaten benötigt.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/12-2325/setproducts/update/11-2492?subshopId=deutsch
```

#### Request Body

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "setData": {
        "id": "11-2492",
        "quantityFactor": 1,
        "usePrice": true,
        "fixQuantity": false,
        "hidden": false
    }
}
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "parentProductId": "12-2325",
    "childProductId": "11-2492",
    "setData": {
        "id": "11-2492",
        "quantityFactor": 1,
        "usePrice": true,
        "fixQuantity": false,
        "hidden": false
    }
}
```

#### Fehlercodes

| **Fehler**       | **Typ**            | **Grund**                                                                         |
| ---------------- | ------------------ | --------------------------------------------------------------------------------- |
| 401 Unauthorized |                    | Nicht autorisiert: Sie sind nicht angemeldet.                                     |
| 403 Forbidden    |                    | Sie verfügen nicht über die erforderlichen Rechte zum Schreiben von Produktdaten. |
| 400 Bad Request  |                    | Request body konnte nicht geladen werden.                                         |
| 400 Bad Request  | "invalidValue"     | Es wurde eine ungültige Stage angegeben.                                          |
| 400 Bad Request  | "missing"          | `setData` fehlt im Request Body.                                                  |
| 400 Bad Request  | "invalidFormat"    | `setData` ist kein Objekt.                                                        |
| 400 Bad Request  | "unknownDataField" | Der Request Body enthält unbekannte Felder.                                       |
| 404 Not Found    |                    | `parentProductId` oder `childProductId` fehlen.                                   |

### PUT products/\{childProductId}/setproducts/recalculate

Die Preise von Produkten, die zum Set des Produkts mit `id=childProductId` gehören, sowie von Produkten, zu deren Sets das Produkt mit `id=childProductId` gehört, werden neu berechnet. Varianten werden berücksichtigt.

Für diese Abfrage werden Schreib-Rechte auf Produktdaten benötigt.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-2803/setproducts/recalculate
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "success": true
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                         |
| ---------------- | -------------- | --------------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                     |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Schreiben von Produktdaten. |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.                                          |
| 404 Not Found    |                | `childProductId` fehlt.                                                           |

### DELETE products/\{parentProductId}/setproducts/\{childProductId}

Das Produkt mit `id=childProductId` wird aus dem Set vom Produkt mit `id=parentProductId` entfernt. Gilt `childProductId=all`, werden alle Produkte aus dem Set entfernt. Gilt `parentProductId=all`, wird das Produkt mit `id=childProductId` aus allen Sets entfernt, in denen es enthalten ist.

Für diese Abfrage werden Löschberechtigungen für Produktdaten benötigt.

#### Beispiel

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/api/v1/products/11-2527/setproducts/11-703
```

#### Antwort

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "success": true
}
```

#### Fehlercodes

| **Fehler**       | **Typ**        | **Grund**                                                                       |
| ---------------- | -------------- | ------------------------------------------------------------------------------- |
| 401 Unauthorized |                | Nicht autorisiert: Sie sind nicht angemeldet.                                   |
| 403 Forbidden    |                | Sie verfügen nicht über die erforderlichen Rechte zum Löschen von Produktdaten. |
| 400 Bad Request  | "invalidValue" | Es wurde eine ungültige Stage angegeben.                                        |
| 404 Not Found    |                | `parentProductId` oder `childProductId` fehlen.                                 |

## Ergänzende Referenzen

* [API-Referenz Bildkonverter](/schnittstellen/admin-interface-api/api-referenz-bildkonverter)
* [API-Referenz Kategorien](/schnittstellen/admin-interface-api/api-referenz-kategorien)
* [API-Referenz Konfiguration](/schnittstellen/admin-interface-api/api-referenz-konfiguration)
* [API-Referenz Meta-Daten](/schnittstellen/admin-interface-api/api-referenz-meta-daten)
* [API-Referenz SEO-URLs](/schnittstellen/admin-interface-api/api-referenz-seo-urls)
* [content - Katalog (Kategorien & Produkte)](/konfiguration/content-katalog-kategorien-produkte)

## Hinweis zu Produktdatenfeldern

Neue Produktdatenfelder (zusätzliche Eigenschaften, Attribute oder technische Felder) können nicht direkt über die Produkt-API erstellt werden. Die API dient ausschließlich dem Auslesen und Pflegen vorhandener Felder.

Um neue Felder zu definieren, muss die Konfiguration im Knoten `content.customProductField` verwendet werden. → [content - Katalog (Kategorien & Produkte)](/konfiguration/content-katalog-kategorien-produkte)

Dort lassen sich individuelle Felder mit Typ, Suchrelevanz, Pflichtstatus und Varianteneigenschaften anlegen. Sobald ein Feld dort konfiguriert wurde, steht es anschließend automatisch in der Produkt-API zur Verfügung (z. B. in `GET products` oder `POST products`).

## Support

Bei technischen Fragen und Hilfestellungen ist unser Support-Team für Sie erreichbar: [Zum Kundenportal](https://websale.atlassian.net/servicedesk/customer/portal/6)

Bitte senden Sie uns eine möglichst detaillierte Beschreibung sowie Screenshots, Requests/Antworten, damit wir Ihre Anfrage zeitnah und zielführend beantworten können.
