Skip to content

Artikelverwaltung – Vollständige API-Referenz ​

Fach-API für den Artikelstamm: anlegen, lesen, ändern, Preise, Varianten, Stücklisten, Attribute, Einheiten, Bilder und Bestand. Basis ist https://core-backend.reybex.com/api (Staging: https://io-staging-partner.reybex.com/api). Authentifizierung wie im API: --header "authorization: Basic $TOKEN".

Pfade mit /connector gehören nicht zu dieser Referenz.

1. Grundlagen ​

1.2 Endpunkt-Übersicht aller Material-Schnittstellen ​

BereichBasisZweck
Artikel/api/materialStamm, Suche, Kopie, Massenänderung, GTIN, Bestandssicht
Varianten/api/materialVariantVarianten lesen, erzeugen, ändern, löschen
Stückliste/api/materialBomSet-Komponenten
Attribute/api/materialAttribute, /api/materialAttributeValueZuordnung und Werte
Preise/api/materialPricesStaffeln, Aktionen, Kundengruppen
Einheiten/api/materialUnitsUmrechnungen, EAN
Übersetzungen/api/materialTranslationSprachtexte
Bilder/api/materialPicturesReihenfolge, Marktplatz, Attribute
Kategorien/api/materialCategoryShop-Kategorien
Bestand/api/materialStockLagerzeilen, Pickplatz, Wareneingang
Marktplatz/api/materialMarketplaceKanalzuordnung, Amazon ASIN
Prüftabellen/api/checkTables, /api/domains/{domain}Artikelgruppe, Status, Einheit, Steuer, Währung
Kunden und Lieferanten/api/customerKunde, Lieferant, Adresse, Bank
CRM/api/crmAction, /api/crmOpportunityAktivität, Verkaufschance, Angebot aus der Chance
Auftragsverwaltung/api/salesHeadVerkaufsbelege mit diesen Artikeln
Kassenverwaltung/api/cashRegisterKasse, Schicht, Bon
Einkauf-Verwaltung/api/purHeadEinkaufsbelege mit diesen Artikeln
Lager und Inventur/api/stock, /api/stockHeadBestand, Buchung, Wareneingang, Inventur

1.3 Antwortformat (Erfolg, Listen, Fehler) ​

Einzelnes Speichern der Fach-API liefert die Id:

json
{ "id": 10482 }

Lesen eines Artikels über GET /api/material/{id} kapselt den Datensatz:

json
{
  "data": {
    "id": 10482,
    "matCode": "ART-100",
    "sku": "ART-100",
    "name": "Lagerartikel",
    "isStocked": true,
    "isDelete": false
  },
  "meta": {
    "domain": "Material",
    "total": 1
  }
}

meta kann zusätzlich requiredFields, readOnlyFields, hiddenFields und invisibleFields enthalten. Leere Listen und Fehler der generischen Domain-API stehen in den jeweiligen Abschnitten.

1.4 Fehlerformat (HTTP 500 vs. 400 vs. 422) ​

SituationHTTPKörper
Fach-API POST /api/material/ – Validierung, fehlende Artikelnummer, unbekanntes Ziel500{ "data": { "error": "…" }, "meta": {} }
Bestandsübernahme POST /api/material/materialStocks – fachlicher AbbruchStatus aus der Ausnahme, oft 404{ "error": "…" }
Bestandsübernahme – sonstiger Abbruch500{ "error": "…" }
Generische Domain-API – ungültiger Filter oder unbekannte Domain400{ "error": "…" }
Fehlende Anmeldung401—

HTTP 422 wird von diesen Schnittstellen nicht verwendet. Fachliche Meldungen der Artikel-API kommen als Text im Feld error (HTTP 500), nicht als 422.

1.5 Verweise auf Stammdaten (ID vs. Suchschlüssel) ​

Im Request eine bekannte id oder einen Suchschlüssel senden, nicht beides erfinden.

ZielSuchschlüssel
ArtikelmatCode, sonst sku
Artikelgruppe, Status, Art, Steuer, Einheit, Währung, Markecode, sonst type, sonst name
Lagercode, sonst name
LagerplatzstockplaceCode oder name, immer mit warehouse
json
{
  "matGroup": { "code": "HAUPT" },
  "vatKey": { "code": "19" },
  "warehouseUnit": { "code": "ST" }
}

In Responses liefert die API die gespeicherte id und die Felder des Datensatzes.

2. Stammdaten nachschlagen ​

Generische Abfrage. Filter als Query: feld=wert oder Ausdrücke eq, neq, gt, gte, lt, lte, like, between, isNull, isNotNull, isEmpty, isNotEmpty. Steuerung: sort, sort=desc(name), take (höchstens 100), skip. responseFormat=api liefert die Domäne roh.

Anlegen, Ändern, Deaktivieren, Sortieren, Übersetzen und Tabellenimport sind ausführlich unter Prüftabellen-Verwaltung beschrieben.

2.1 Verfügbare Domains anzeigen (GET /api/domains/showDomains) ​

Request

bash
curl --header "authorization: Basic $TOKEN" \
  "https://core-backend.reybex.com/api/domains/showDomains"

Response (Auszug)

json
{
  "matGroup": { "id": "Long", "code": "String", "name": "String" },
  "unit": { "id": "Long", "code": "String", "name": "String" }
}

Schlüssel ist der Domain-Name für GET /api/domains/{domain}.

2.2 Artikelgruppen lesen (GET /api/domains/matGroup) ​

Request: GET /api/domains/matGroup?take=100&sort=code

Response

json
[{ "id": 12, "code": "HAUPT", "name": "Hauptgruppe" }]

2.3 Artikelstatus lesen (GET /api/domains/matStatus) ​

Request: GET /api/domains/matStatus?take=100

Response: [{ "id": 1, "code": "AKTIV", "name": "Aktiv" }]

2.4 Artikelarten lesen (GET /api/domains/materialType) ​

Request: GET /api/domains/materialType?take=100

Response: [{ "id": 3, "code": "WARE", "name": "Ware" }]

Die Artikelart kann einen Nummernkreis tragen. Fehlt matCode beim Anlegen, wird zuerst der Nummernkreis der Marke, sonst der der Artikelart verwendet. Liefert keiner einen Wert, bricht das Speichern mit material.save.matCode.error ab (HTTP 500).

2.5 Steuerschlüssel lesen (GET /api/domains/vatKey) ​

Request: GET /api/domains/vatKey?take=100

Response: [{ "id": 2, "code": "19", "rate": 19 }]

rate steuert die Umrechnung Brutto/Netto beim Speichern des Artikels.

2.6 Einheiten lesen (GET /api/domains/unit) ​

Request: GET /api/domains/unit?code=ST

Response: [{ "id": 5, "code": "ST", "name": "Stück" }]

2.7 Marken lesen (GET /api/domains/brand) ​

Request: GET /api/domains/brand?take=50

Response: [{ "id": 8, "code": "EIGEN", "name": "Eigenmarke" }]

2.8 Währungen lesen (GET /api/domains/currency) ​

Request: GET /api/domains/currency?code=EUR

Response: [{ "id": 1, "code": "EUR", "name": "Euro" }]

2.9 Attribute und Optionen lesen (GET /api/domains/attribute, attributeOption) ​

Request: GET /api/domains/attribute?take=100 und GET /api/domains/attributeOption?take=100

Response

json
[{ "id": 21, "code": "FARBE", "name": "Farbe" }]
json
[{ "id": 210, "code": "ROT", "name": "Rot" }]

variableType 5 oder 6 speichert den Optionswert als Zahl (numberValue), sonst als Option.

2.10 Anzahl der Treffer (GET /api/domains/{domain}/count) ​

Request: GET /api/domains/matGroup/count?code=HAUPT

Response: 1

2.11 Filter, Sortierung und Pagination der generischen API ​

Request

bash
curl --header "authorization: Basic $TOKEN" \
  "https://core-backend.reybex.com/api/domains/material?sku=like(ART%)&sort=desc(name)&take=20&skip=0"

Response: JSON-Liste der Artikel. Ungültige Felder oder Ausdrücke: HTTP 400, { "error": "…" }. take über 100 wird abgelehnt.

Gelöschte Artikel (isDelete) sind in der Standardabfrage ausgeblendet. Sichtbar mit isDelete=true oder ignoreSoftDelete.

3. Artikel anlegen – nach Artikeltyp ​

POST /api/material/ legt an, wenn der Body keine id enthält. Leere Objekte {} werden vor dem Speichern zu null. Antwort ist immer { "id": … }.

3.1 Pflichtfelder und Standardwerte ​

Ohne die folgenden Felder bricht POST /api/material/ mit Validierungsfehler ab (HTTP 500, Text im Feld error). Die API setzt keinen Mandanten-Standard.

FeldPflichtVerhalten
namejaBezeichnung, Länge 1–300
vatKeyjaSteuerschlüssel, Suchschlüssel code. rate steuert Brutto/Netto
warehouseUnitjaLagereinheit, Suchschlüssel code
matGroupjaArtikelgruppe, Suchschlüssel code
matStatusjaArtikelstatus, Suchschlüssel code
materialTypejaArtikelart, Suchschlüssel code. Kann den Nummernkreis tragen
matCodeneinSonst Nummernkreis der Marke, dann der Artikelart. Sonst material.save.matCode.error. Länge 1–100
skuneinSonst matCode, danach notfalls gtin
salUnitneinVerkaufseinheit
currencyneinWährung des Artikels
isStockedneinStandard true
isSerialManagementneinStandard false. Wird true, sobald isSerialNumberRequired gesetzt ist
isSerialNumberRequiredneinStandard false
isLotEnabledneinCharge. Standard false
isShelfLifeneinMHD. Standard false
isSetneinSet/Bundle. Standard false
isTemplateneinnull wird zu false. true macht den Artikel zur Vorlage, siehe 3.10
salesPriceGrossneinWenn > 0, wird salesPrice aus Brutto und vatKey.rate mit 4 Nachkommastellen berechnet
salesPriceneinNur wenn Brutto nicht > 0 ist, wird daraus der Bruttobetrag berechnet
asinneinLänge genau 10, sonst Validierungsfehler (HTTP 500)

GET /api/material/{id} und GET /api/material?isNew=true liefern in meta.requiredFields zusätzliche Pflichtfelder der Feldrechte dieses Benutzers. Die sechs Pflichtfelder oben bleiben beim Speichern Pflicht.

shortDescription überschreibt detailDescription, wenn beide gesendet werden.

Auflösung, wenn ein Pflichtfeld fehlt ​

Die API setzt Pflicht-Referenzen nicht von selbst. Fehlt ein Feld, in dieser Reihenfolge füllen. Der erste Treffer gilt.

  1. Angabe – Wert aus dem Auftrag für dieses Feld.
  2. Vorlage – dasselbe Feld aus GET /api/material/{id} der Vorlage. id, matCode und sku nicht übernehmen; bei units die id entfernen und isTemplate auf false setzen. Ist eine Vorlage genannt, diese lesen. Ist keine genannt und 4.11 enthält genau eine Vorlage, diese verwenden. Mehrere ohne Nennung: keine raten, mit Schritt 3 weiter.
  3. Standard – Wert aus der Tabelle. Einen Code per Suchschlüssel laden (code). Existiert er nicht, Schritt 4.
  4. Domäne – GET /api/domains/{domain}?take=1&sort=code. Diese Domänen haben kein isDefault. Den Treffer als { "code": "…" } in den Request setzen.
  5. Stopp – die Domäne ist leer. Artikel nicht anlegen. Den fehlenden Stammdatensatz nennen (vatKey, unit, matGroup, matStatus oder materialType).
FeldPflichtVorlageStandardDomäne
namejaname——
vatKeyjavatKeyGET /api/company/ → configuration.defaultVatKey, sonst code 19vatKey
warehouseUnitjawarehouseUnitcode ST (Stück)unit
matGroupjamatGroup—matGroup
matStatusjamatStatus—matStatus
materialTypejamaterialType—materialType
salUnitneinsalUnitcode STunit
currencyneincurrencyGET /api/company/ → homeCurrency, sonst code EURcurrency
matCodeneinnicht übernehmenNummernkreis Marke, dann Artikelart—
skuneinnicht übernehmenwird matCode—

isStocked ohne Angabe ist true. Die Schalter isSerialManagement, isSerialNumberRequired, isLotEnabled, isShelfLife, isSet und isTemplate ohne Angabe sind false. Preise ohne Angabe sind 0. Diese Felder nicht aus der Domäne füllen.

Beispiel: Auftrag nennt nur name „Lagerartikel“ und matCode „ART-100“. Eine Vorlage existiert nicht. Dann GET /api/company/ für configuration.defaultVatKey und homeCurrency, warehouseUnit mit code ST, und für matGroup, matStatus, materialType jeweils den ersten Eintrag der Domäne. Danach POST /api/material/ mit diesen Werten.

3.2 Normaler Lagerartikel (POST /api/material/) ​

Request

json
{
  "name": "Lagerartikel",
  "matCode": "ART-100",
  "sku": "ART-100",
  "isStocked": true,
  "matGroup": { "code": "HAUPT" },
  "matStatus": { "code": "AKTIV" },
  "materialType": { "code": "WARE" },
  "vatKey": { "code": "19" },
  "warehouseUnit": { "code": "ST" },
  "salUnit": { "code": "ST" },
  "salesPrice": 10.0
}

Response: { "id": 10482 }

3.3 Artikel ohne Bestand / Dienstleistung (POST /api/material/) ​

Request: wie 3.2, zusätzlich "isStocked": false, "isService": true. matCode z. B. DL-10.

Response: { "id": 10490 }

isStocked=false verhindert Lagerbuchungen. Dienstleistungsartikel erscheinen in GET /api/material/getServiceMaterials.

3.4 Chargengeführter Artikel (POST /api/material/) ​

Request: wie 3.2, zusätzlich "isLotEnabled": true.

Response: { "id": 10501 }

3.5 Artikel mit MHD (POST /api/material/) ​

Request: wie 3.2, zusätzlich "isShelfLife": true. Charge und MHD sind getrennte Schalter und können zusammen gesetzt werden.

Response: { "id": 10502 }

3.6 Seriennummernpflichtiger Artikel (POST /api/material/) ​

Request

json
{
  "name": "Gerät mit Serie",
  "matCode": "SER-1",
  "isSerialNumberRequired": true,
  "vatKey": { "code": "19" },
  "warehouseUnit": { "code": "ST" }
}

Response: { "id": 10510 }

isSerialNumberRequired setzt isSerialManagement automatisch auf true. isSoftSerialManagement bleibt unabhängig und standardmäßig false.

3.7 Set / Bundle anlegen (POST /api/material/ + POST /api/materialBom/) ​

Zuerst den Kopf mit "isSet": true anlegen (Response { "id": 10600 }). Danach die Komponente:

Request POST /api/materialBom/

json
{
  "materialBom": {
    "material": { "matCode": "SET-1" },
    "component": { "matCode": "ART-100" },
    "amount": 2,
    "unit": { "code": "ST" }
  }
}

Response: { "id": 8801 }

Ohne unit bricht das Speichern ab: material.must.have.to.material.unit. Positionen ohne Komponente oder ohne Menge werden verworfen.

3.8 Variantenartikel anlegen (POST /api/material/ + POST /api/materialVariant/) ​

Kopf anlegen, dann:

Request POST /api/materialVariant/

json
{
  "materialId": 10620,
  "sku": "ART-100.1",
  "attributes": [{ "id": 21, "options": [210] }]
}

Response: { "id": 3301 }

Hat der Artikel offenen Bestand (total, reserved oder avail) und noch keine Varianten, wird die Anlage abgelehnt: material.has.stock.

3.9 Artikel mit Attributen (POST /api/materialAttributeValue/ + POST /api/materialAttribute/) ​

Request POST /api/materialAttribute/

json
{
  "material": { "matCode": "ART-100" },
  "attribute": { "code": "FARBE" }
}

Response: { "id": 701 }

Request POST /api/materialAttributeValue/

json
{
  "materialId": 10482,
  "attributeOptions": [
    { "attributeId": 21, "attributeOptionId": [210], "isConstant": false }
  ]
}

Response: leer (der Aufruf bestätigt mit HTTP 200, ohne Id). Bestehende Werte des Artikels werden vorher auf isDelete=true gesetzt und durch die neue Liste ersetzt.

3.10 Artikel aus einer Vorlage (POST /api/material/) ​

Eine Vorlage ist ein Artikel mit "isTemplate": true. Die Anlegemaske liest sie und übernimmt die Detailfelder in den neuen Artikel. Dieselbe Übernahme steht in 3.1 als Schritt 2.

  1. Vorlagen laden: 4.10 oder 4.11.
  2. GET /api/material/{id} der Vorlage.
  3. id, matCode und sku entfernen, isTemplate auf false setzen, bei jedem Eintrag in units die id entfernen.
  4. Felder, die der Auftrag nennt, überschreiben die Vorlage. Fehlende Pflichtfelder danach mit Schritt 3 und 4 aus 3.1 füllen.
  5. POST /api/material/.

Übernommen werden unter anderem vatKey, Einheiten, Preise, Texte, Gewichte, Maße und Lieferzeit. templateMaterialId kopiert nur Attribute und Attributwerte und ersetzt diesen Ablauf nicht.

Request Artikel, nachdem die Vorlage gelesen wurde. Auftrag nennt Name und Artikelnummer, den Rest liefert die Vorlage.

json
{
  "name": "Lagerartikel aus Vorlage",
  "matCode": "ART-200",
  "sku": "ART-200",
  "isTemplate": false,
  "isStocked": true,
  "matGroup": { "code": "HAUPT" },
  "matStatus": { "code": "AKTIV" },
  "materialType": { "code": "WARE" },
  "vatKey": { "code": "19" },
  "warehouseUnit": { "code": "ST" },
  "salUnit": { "code": "ST" },
  "currency": { "code": "EUR" },
  "salesPrice": 12.5,
  "purPrice": 6.0,
  "netWeight": 0.4,
  "deliveryDays": 3,
  "description": "Kurztext der Vorlage",
  "templateMaterialId": 10700
}

Response: { "id": 10710 }

templateMaterialId 10700 ist die Id der gelesenen Vorlage. Eine mitkopierte gtin vor dem Speichern entfernen, wenn der neue Artikel eine eigene Nummer bekommen soll.

4. Artikel auflisten und suchen ​

4.1 Einzelnen Artikel lesen (GET /api/material/{id}) ​

Request: GET /api/material/10482

Response: Umschlag aus 1.3. Unbekannte Id: resource.not.found.

GET /api/material?isNew=true liefert eine leere Vorlage (name, matCode, sku, Preise 0, isTemplate false) im selben Umschlag.

4.2 Artikelliste mit Filtern, Sortierung, Pagination (GET /api/material) ​

Request: GET /api/material?take=50&skip=0&sort=matCode

Response

json
{
  "data": [{ "id": 10482, "matCode": "ART-100", "name": "Lagerartikel" }],
  "meta": { "total": 1 }
}

meta wird um die Tabellenkonfiguration materialList ergänzt.

4.3 Artikel per Barcode/SKU suchen (GET /api/material?barcode=…) ​

Request: GET /api/material?barcode=4006381333931

Response: ein Artikel im Umschlag aus 1.3.

Kein Treffer: resource.not.found. Mehrere Treffer: there.is.more.than.one.record.

4.4 Mehrere Artikel per ID-Liste (POST /api/material/list) ​

Request: { "ids": [10482, 10490] }

Response: Liste der gefundenen Artikel.

4.5 Artikelsuche für Dialoge (GET /api/material/materialsForZoomDialog) ​

Request: GET /api/material/materialsForZoomDialog?searchedText=ART

Response: reduzierte Trefferliste für Auswahldialoge (id, matCode, name).

4.6 Artikelsuche für Mobile (GET /api/material/mobile) ​

Request: GET /api/material/mobile?searchedText=ART

Response: dieselbe Suchliste in der mobilen Feldauswahl.

4.7 Suchliste aufbauen/ergänzen (POST /api/material/appendMissingMaterials2Search) ​

Request: POST ohne Body.

Response: { "success": true }

Der Aufruf ergänzt fehlende Artikel im Suchindex. Es wird kein Artikelstamm geändert.

4.8 Artikelsuche für Schnellsuche (GET /api/material/getMaterialSearchList) ​

Request: GET /api/material/getMaterialSearchList?searchedText=ART

Response: [{ "id": 10482, "matCode": "ART-100", "name": "Lagerartikel" }]

4.9 Dienstleistungsartikel auflisten (GET /api/material/getServiceMaterials) ​

Request: GET /api/material/getServiceMaterials

Response

json
[{
  "materialId": 10490,
  "matCode": "DL-10",
  "materialName": "Montage",
  "unitName": "Stück",
  "vatRate": 19
}]

4.10 Artikelvorlagen nach Artikelart (GET /api/material/templatesByMaterialType) ​

Request: GET /api/material/templatesByMaterialType?materialTypeId=3

Response: Vorlagen (isTemplate=true) dieser Art.

4.11 Artikelvorlagenliste (GET /api/material/materialTemplateList) ​

Request: GET /api/material/materialTemplateList

Response: alle Vorlagen des Mandanten (id, translatedName).

Die Übernahme der Detailfelder steht in 3.1 und 3.10. templateMaterialId kopiert nur Attribute und Attributwerte.

4.12 Artikelstatistiken (GET /api/material/materialStatistics) ​

Request: GET /api/material/materialStatistics?materialId=10482

Response: Mengen und Umsätze des aktuellen und des Vorjahres. Unbekannte Id: resource.not.found.

4.13 Bestandsinformation (GET /api/material/materialStockInfo) ​

Request: GET /api/material/materialStockInfo?materialId=10482

Response: verfügbare Menge, reservierte Menge und Lagerübersicht des Artikels.

4.14 Hauptbild-URL ermitteln (GET /api/material/getMainPictureUrl) ​

Request: GET /api/material/getMainPictureUrl?materialId=10482&variantId=3301

variantId ist optional.

Response: { "mainPictureUrl": "https://…" }

5. Artikel ändern ​

5.1 Artikel ändern (POST /api/material/ mit id) ​

Request

json
{
  "id": 10482,
  "name": "Lagerartikel neu",
  "vatKey": { "code": "19" }
}

Response: { "id": 10482 }

Unbekannte id: material.not.found.

5.2 Verkaufspreis korrekt ändern (Preisregel Brutto/Netto) ​

salesPriceGross > 0 gewinnt: der Nettopreis wird neu gerechnet, ein mitgesendeter salesPrice wird überschrieben. Nur wenn der Bruttobetrag nicht größer als 0 ist und salesPrice > 0, wird der Bruttobetrag aus dem Netto berechnet. Steuersatz ist vatKey.rate, Rundung auf 4 Stellen.

Ändert sich salesPrice bei einem bestehenden Artikel, werden die zugehörigen Preisstaffeln nachgezogen.

Request

json
{ "id": 10482, "salesPriceGross": 11.9, "vatKey": { "code": "19" } }

Response: { "id": 10482 }

5.3 Verhalten beim Ändern (Kategorien, Rohstoffe, Einheiten) ​

  • Kategorien des Artikels werden vor dem Schreiben geleert und aus dem Request neu gesetzt. Ein Update ohne Kategorien entfernt die bisherigen Zuordnungen.
  • Rohstoffe (rawMaterials) werden gelöscht und durch die gesendete Liste ersetzt. Die Liste erwartet Einträge mit id.
  • Einheiten ohne exchangeRatio fallen weg, sobald units mitgeschickt wird oder der Artikel neu ist. warehouseExchangeRatio wird auf 1 gesetzt, wenn es leer ist, und danach auf baseExchangeRatio.
  • Stücklistenpositionen ohne Komponente oder Menge fallen weg, sobald materialBoms gesendet wird.
  • Übersetzungen ohne name fallen weg.
  • Marktplatz-Kategorien werden geleert, wenn Marktplatzdaten im Request stehen.
  • Leere Maps werden zu null. salesUnitCode aus dem Request wird verworfen und aus den Einheiten neu berechnet.

5.4 Artikel kopieren (POST /api/material/copy) ​

Request

json
{
  "materialId": 10482,
  "matCode": "ART-100-K",
  "sku": "ART-100-K",
  "title": "Kopie",
  "articleVariants": true,
  "articlePictures": true
}

Response: { "id": 10900 }

Die Kopie übernimmt die Stammdaten ohne gtin. Einkaufs- und Durchschnittspreise starten bei 0. Ohne matCode gilt der Nummernkreis, ohne sku wird matCode verwendet. title setzt name. Varianten-SKUs werden mit dem konfigurierten Trenner und einer laufenden Nummer gebildet (Standard .). Unbekannte Quelle: resource.not.found.

5.5 Artikel-Massenänderung – Parameter lesen (GET /api/material/massUpdate) ​

Request: GET /api/material/massUpdate

Response

json
{
  "properties": [{ "name": "Bezeichnung", "code": "material.name" }],
  "numericProperties": [{ "name": "Verkaufspreis", "code": "material.salesPrice" }]
}

Ausgeschlossen sind unter anderem matCode, id, tenantId, warehouseUnit, Datumfelder und der Bestand.

5.6 Artikel-Massenänderung – ausführen (POST /api/material/massUpdate) ​

Request

json
{
  "updatingMaterialIds": [10482, 10490],
  "values": [{ "property": "material.name", "operator": "set", "value": "Neu", "calculationProperty": null }]
}

Response: { "id": null } bei Erfolg. Sammelfehler der Laufes stehen in error (HTTP 500).

5.7 Varianten-Massenänderung – Parameter lesen (GET /api/material/variantMassUpdate) ​

Request: GET /api/material/variantMassUpdate

Response: dieselbe Form wie 5.5, Codes beginnen mit materialVariant.. variantCode und isDelete sind ausgeschlossen.

5.8 Varianten-Massenänderung – ausführen (POST /api/material/variantMassUpdate) ​

Request: wie 5.6, property mit Präfix materialVariant..

Response: Erfolg ohne Fehlerliste, sonst HTTP 500 mit zusammengefassten Meldungen.

5.9 Rechnung-Anhang umschalten (POST /api/material/toggleIsInvoiceAttachment/{id}) ​

id ist die Id des Anhangs, nicht die Artikel-Id. Der Schalter isInvoiceAttachment wird invertiert.

Request: POST /api/material/toggleIsInvoiceAttachment/4401 ohne Body.

Response: { "success": true }

Unbekannter Anhang: resource.not.found.

5.10 Einkauf-Anhang umschalten (POST /api/material/toggleIsPurchaseAttachment/{id}) ​

Wie 5.9 für isPurchaseAttachment.

Request: POST /api/material/toggleIsPurchaseAttachment/4401

Response: { "success": true }

5.11 GTIN/EAN generieren (POST /api/material/generateGtinCode) ​

Request: { "ids": [10482] }

Response

json
{
  "materialGtins": [{ "materialId": 10482, "materialMatCode": "ART-100", "gtin": "4006381333931" }],
  "errors": []
}

Unbekannter Artikel in errors: material.not.found. Nummernkreis erschöpft: message.max.gtin.reached.error. Bereits vergebene GTIN: message.gtin.already.created.error.

5.12 Text übersetzen (POST /api/material/translate) ​

Pflichtfelder: text, sourceLang, targetLang.

Request

json
{ "text": "Lagerartikel", "sourceLang": "de", "targetLang": "en" }

Response: der übersetzte Text.

Der Aufruf schreibt die Artikelübersetzung nicht selbst; dafür dient Abschnitt 13.

6. Alle bestehenden Artikel übertragen (Massenübernahme) ​

6.1 Massenimport (POST /api/material/connector) ​

Dieser Pfad ist für Konnektoren vorgesehen und gehört nicht zu den normalen Aufrufen. Für die Übernahme einzelner Artikel 6.2 verwenden, für Bestand, Einkaufspreise und Entsorgungsgebühren die folgenden Abschnitte.

6.2 Alternative: Einzelübertragung (POST /api/material/) ​

Jeden Artikel wie in Abschnitt 3 senden. Mit id wird aktualisiert, ohne id angelegt. Pro Aufruf eine Response { "id": … }.

6.3 Bestände übernehmen (POST /api/material/materialStocks) ​

Request

json
{
  "materials": [{
    "matCode": "ART-100",
    "quantity": 25,
    "warehouse": { "code": "HAUPT" },
    "stockplace": { "stockplaceCode": "*", "warehouse": { "code": "HAUPT" } }
  }]
}

Response

json
{ "errors": [] }

Fehlerzeilen tragen sku, matCode und message. material.isStocked.book.error, wenn der Artikel nicht bestandsgeführt ist. Variante wird über variantSku oder variantGtin aufgelöst. resetStockData: true löscht vorher die Bestände der genannten matCode (offene Reservierungen bleiben). Buchung läuft als Wareneingang oder Warenausgang, Quelle API. Fachlicher Abbruch: { "error": "…" } mit dem Status der Ausnahme.

6.4 Einkaufspreise in Masse (POST /api/material/materialPrices) ​

Request

json
{
  "materials": [{
    "matCode": "ART-100",
    "purPrice": 4.5,
    "currency": { "code": "EUR" }
  }]
}

Response: { "response": [] }

Jede Ausnahme landet in response mit sku, matCode und message. Der HTTP-Status bleibt 200, solange der Aufruf selbst nicht abbricht. Ein Abbruch des gesamten Aufrufs ist HTTP 500, { "data": { "error": "…" }, "meta": {} }.

6.5 Entsorgungsgebühren importieren (POST /api/material/materialDisposalFee) ​

Request

json
{
  "materials": [{
    "sku": "ART-100",
    "vendorMatCode": "ART-100",
    "fee": 0.15
  }]
}

Response: { "response": [] }

Nicht gefundener Artikel: { "sku": "ART-100", "matCode": "ART-100", "message": "material.not.found" } innerhalb von response.

7. Artikel löschen – Soft Delete ​

7.1 Einzelnen Artikel löschen (DELETE /api/material/) ​

Request: { "id": 10482 }

Response: { "id": 10482 }

Es wird isDelete=true gesetzt. Liegt Bestand (Menge > 0), bricht der Aufruf ab: material.delete.error.caused.by.stock. Varianten des Artikels werden mitgelöscht, Variantenbilder vorher geleert.

7.2 Mehrere Artikel löschen (POST /api/material/deleteMaterials) ​

Request: { "ids": [10482, 10490] }

Response: { "ids": [10482, 10490] }

Dieselbe Bestandsprüfung je Id. Nach jeweils 10 Artikeln wird der Persistenzkontext geleert.

7.3 Gelöschte Artikel finden ​

Request: GET /api/domains/material?isDelete=true&take=50

Response: Liste mit "isDelete": true. Ohne diesen Filter sind gelöschte Artikel unsichtbar.

7.4 Gelöschten Artikel wiederherstellen ​

Request POST /api/material/

json
{ "id": 10482, "isDelete": false }

Response: { "id": 10482 }

Die Fach-API setzt das Kennzeichen über das normale Speichern. Ein Artikel mit Bestand ließ sich vorher nicht löschen; die Wiederherstellung prüft den Bestand nicht erneut.

7.5 Unterschied: DELETE /api/material/ vs. DELETE /api/domains/material ​

Fach-APIDomain-API
AufrufDELETE /api/material/ Body { "id": 10482 }DELETE /api/domains/material?id=10482
Wirkung beim ArtikelSoft Delete, Bestand sperrtDomänen löschen je nach Modell physikalisch oder per Kennzeichen
Response{ "id": 10482 }{ "id": 10482 }
FehlerBestand: material.delete.error.caused.by.stockUngültige Id: HTTP 400

Für den Artikelstamm die Fach-API verwenden.

8. Varianten verwalten (/api/materialVariant) ​

8.1 Varianten eines Artikels lesen (GET /api/materialVariant/{id}) ​

Request: GET /api/materialVariant?materialId=10482 oder GET /api/materialVariant/3301

Response: Liste nicht gelöschter Varianten (isDelete=false). Unbekannter Artikel: resource.not.found.

8.2 Varianten erzeugen (POST /api/materialVariant/) ​

Request und Response wie 3.8. Offener Bestand ohne bestehende Varianten: material.has.stock.

8.3 Einzelne Variante ändern (POST /api/materialVariant/{id}) ​

Request POST /api/materialVariant/3301

json
{ "id": 3301, "sku": "ART-100.1", "eanCode": "4006381333931" }

Response: { "id": 3301 }

eanCode, das bereits einem anderen Artikel gehört: sku.defined.for.different.material.

8.4 Variante löschen (DELETE /api/materialVariant/) ​

Request: { "id": 3301 }

Response: { "id": 3301 }

Soft Delete der Variante.

Alternativ ist auch der Generic-Domain-Weg möglich: DELETE /api/domains/materialVariant.

8.5 Variantenliste lesen (POST /api/material/getVariantList) ​

Request: { "materialId": 10482 }

Response: [{ "id": 3301, "sku": "ART-100.1" }]

9. Stückliste / BOM verwalten (/api/materialBom) ​

9.1 Stückliste lesen (GET /api/materialBom/{id}) ​

Request: GET /api/materialBom?materialId=10600

Response

json
[{
  "id": 8801,
  "amount": 2,
  "component": { "id": 10482, "matCode": "ART-100" }
}]

Unbekannte Id oder unbekannter Artikel: resource.not.found.

9.2 Stücklistenposition anlegen (POST /api/materialBom/) ​

Request und Response wie 3.7. Pflicht: unit.

9.3 Stücklistenposition löschen (DELETE /api/materialBom/) ​

Request: { "id": 8801 }

Response: { "id": 8801 }

10. Attribute und Attributwerte ​

10.1 Attribute eines Artikels lesen (GET /api/materialAttribute/{id}) ​

Request: GET /api/materialAttribute?materialId=10482

Response

json
{
  "data": [{ "id": 701, "attribute": { "id": 21, "code": "FARBE" } }],
  "meta": { "domain": "MaterialAttribute" }
}

10.2 Attribut mit Optionen und Aufpreis zuordnen (POST /api/materialAttribute/) ​

Request

json
{
  "material": { "matCode": "ART-100" },
  "attribute": { "code": "FARBE" },
  "surcharge": 1.5
}

Response: { "id": 701 }

10.3 Attributzuordnung löschen (DELETE /api/materialAttribute/) ​

Request: { "id": 701 }

Response: { "id": 701 }

10.4 Lesbaren Attributcode lesen (GET /api/materialAttribute/readableCode) ​

Request: GET /api/materialAttribute/readableCode?materialId=10482

Response: { "code": "FARBE-ROT" }

10.5 Gewicht aus Attribut lesen (GET /api/materialAttribute/weight) ​

Request: GET /api/materialAttribute/weight?materialId=10482

Response: { "weight": 0.4 }

10.6 Attributwerte eines Artikels lesen (GET /api/materialAttributeValue/{id}) ​

Request: GET /api/materialAttributeValue?materialId=10482

Response: Liste der Werte. Unbekannter Artikel: material.not.found.error.

10.7 Attributwerte setzen (POST /api/materialAttributeValue/) ​

Request wie 3.9. Response: HTTP 200 ohne Körper. Vorherige Werte werden als gelöscht markiert.

11. Preise anlegen und pflegen (/api/materialPrices) ​

Preiszeilen hängen an material. Lesen ohne materialId und ohne id: material.not.found.error. Gleiche Gültigkeit, Währung, Menge und Variantenkombination werden als eine Staffel gelesen.

11.1 Preise eines Artikels lesen (GET /api/materialPrices?materialId=…) ​

Request: GET /api/materialPrices?materialId=10482

Response

json
[{
  "id": 501,
  "price": 9.5,
  "quantity": 1,
  "isDelete": false
}]

Nur isDelete=false. Sortierung: Marktplatz, Kundengruppe, Variante, Menge.

11.2 Einzelnen Preis lesen (GET /api/materialPrices/{id}) ​

Request: GET /api/materialPrices/501

Response: die Staffelzeilen derselben Gültigkeit, Währung, Einheitsmenge und Variantenkombination. Nichts gefunden: resource.not.found.

11.3 Preise anlegen (POST /api/materialPrices/) ​

Request

json
{
  "material": { "id": 10482 },
  "materialPrices": [{
    "price": 9.5,
    "quantity": 10,
    "currency": { "code": "EUR" },
    "unit": { "code": "ST" },
    "validFrom": "2026-10-01",
    "validUntil": "2026-12-31"
  }]
}

Response: { "id": 10482 }

price: null wird entfernt und nicht überschrieben. Für Variantenpreise die Variante in variants mitgeben. Aktionspreis über das Gültigkeitsfenster validFrom/validUntil. Rabatt als eigener Preis mit geringerer price in der Staffel.

11.4 Preis ändern (POST /api/materialPrices/ mit id) ​

Request: dasselbe Objekt, in der Zeile "id": 501 und neuer price.

Response: { "id": 10482 }

11.5 Einzelnen Preis löschen (DELETE /api/materialPrices/{id}) ​

Request: DELETE /api/materialPrices/501

Response: { "id": 501 }

11.6 Alle Preise lesen (GET /api/materialPrices/all) ​

Request: GET /api/materialPrices/all?materialId=10482

Response: alle Preiszeilen des Artikels, einschließlich der Staffeln.

11.7 Preise in Masse ändern (POST /api/materialPrices/all) ​

Request

json
{
  "material": { "id": 10482 },
  "materialPrices": [{ "id": 501, "price": 8.9 }]
}

Response: { "id": 10482 }

11.8 Preise in Masse löschen (DELETE /api/materialPrices/all) ​

Request: { "materialId": 10482, "ids": [501, 502] }

Response: { "ids": [501, 502] }

11.9 Preis berechnen (POST /api/materialPrices/calculateMaterialPrice) ​

Request

json
{ "materialId": 10482, "quantity": 10, "currency": { "code": "EUR" } }

Response: { "price": 9.5, "quantity": 10 }

11.10 Rabattpreis berechnen (POST /api/materialPrices/calculateDiscountedPrice) ​

Request: { "price": 10, "discountPercent": 10 }

Response: { "price": 9 }

11.11 Preise für Kundengruppe – Parameter (GET /api/materialPrices/createPricesForCustomerGroup) ​

Request: GET /api/materialPrices/createPricesForCustomerGroup

Response: { "customerGroups": [{ "id": 4, "code": "HAENDLER" }] }

11.12 Preise für Kundengruppe erzeugen (POST /api/materialPrices/createPricesForCustomerGroup) ​

Request

json
{
  "materialId": 10482,
  "customerGroup": { "code": "HAENDLER" },
  "discountPercent": 10
}

Response: { "id": 510 }

12. Einheiten und Umrechnungen (/api/materialUnits) ​

12.1 Einheiten eines Artikels lesen (GET /api/materialUnits/{id}) ​

Request: GET /api/materialUnits?materialId=10482

Response: [{ "id": 90, "exchangeRatio": 1, "isDelete": false }]

12.2 Einheitenliste mit Grid-Konfiguration (GET /api/materialUnits/listWithGridConfig) ​

Request: GET /api/materialUnits/listWithGridConfig?materialId=10482

Response: { "data": [], "meta": { "columns": [] } }

12.3 Einheit speichern (POST /api/materialUnits/) ​

Request

json
{
  "material": { "matCode": "ART-100" },
  "unit": { "code": "KT" },
  "exchangeRatio": 6,
  "baseExchangeRatio": 6
}

Response: { "id": 91 }

12.4 Einheit mit verwandten Einheiten speichern (POST /api/materialUnits/saveWithRelatedUnits) ​

Request: wie 12.3, plus "relatedUnits": [{ "unit": { "code": "ST" }, "exchangeRatio": 1 }].

Response: { "id": 91 }

12.5 Einheit löschen (DELETE /api/materialUnits/) ​

Request: { "id": 91 }

Response: { "id": 91 }

12.6 Einheit mit verwandten löschen (DELETE /api/materialUnits/deleteWithRelatedUnits/{id}) ​

Request: DELETE /api/materialUnits/deleteWithRelatedUnits/91

Response: { "id": 91 }

12.7 EAN-Code für Einheit generieren (GET /api/materialUnits/generateEanCode) ​

Request: GET /api/materialUnits/generateEanCode?materialId=10482

Response: { "eanCode": "4006381333931" }

12.8 Artikeleinheiten lesen (GET /api/material/getMaterialUnits) ​

Request: GET /api/material/getMaterialUnits?materialId=10482

Response: [{ "code": "ST", "exchangeRatio": 1 }]

12.9 Alle Einheiten mit Umrechnungsfaktor (GET /api/material/getAllUnitsWithExchangeRatio) ​

Request: GET /api/material/getAllUnitsWithExchangeRatio?materialId=10482

Response: [{ "code": "KT", "exchangeRatio": 6 }]

13. Übersetzungen (/api/materialTranslation) ​

13.1 Übersetzungen eines Artikels lesen (GET /api/materialTranslation/{id}) ​

Request: GET /api/materialTranslation?materialId=10482

Response: [{ "id": 15, "language": "en", "name": "Stock item" }]

13.2 Übersetzung speichern (POST /api/materialTranslation/) ​

Request

json
{
  "material": { "matCode": "ART-100" },
  "language": { "code": "en" },
  "name": "Stock item"
}

Response: { "id": 15 }

Übersetzungen ohne name werden beim Artikel-Speichern entfernt.

13.3 Übersetzung löschen (DELETE /api/materialTranslation/{id}) ​

Request: DELETE /api/materialTranslation/15

Response: { "id": 15 }

13.4 Übersetzungen nach Sprachen (GET /api/materialTranslation/materialTranslationsByLanguages) ​

Request: GET /api/materialTranslation/materialTranslationsByLanguages?materialId=10482

Response: { "en": { "name": "Stock item" }, "de": { "name": "Lagerartikel" } }

13.5 Übersetzungen in Masse aktualisieren (POST /api/materialTranslation/batchUpdate) ​

Request

json
{
  "items": [
    { "material": { "matCode": "ART-100" }, "language": { "code": "en" }, "name": "Stock item" }
  ]
}

Response: { "ids": [15] }

14. Bilder (/api/materialPictures, /api/materialVariantPictures) ​

14.1 Bilder eines Artikels lesen (GET /api/materialPictures/{id}) ​

Request: GET /api/materialPictures?materialId=10482

Response: [{ "id": 40, "sortOrder": 1, "isMain": true }]

Variantenbilder: GET /api/materialVariantPictures?materialVariantId=3301.

14.2 Bildreihenfolge ändern (POST /api/materialPictures/sortPictures) ​

Request: { "itemOrder": "41,40" }

Response: { "success": "success" }

itemOrder ist die neue Reihenfolge der Bild-Ids, kommagetrennt.

14.3 Marktplatz-Konfiguration für Bilder (POST /api/materialPictures/saveMarketPlaceConfig) ​

Request

json
{
  "selectedImageIds": [40],
  "selectedMarketplaces": [{ "id": 3 }]
}

Response: { "id": { "id": 40 } }

id in der Antwort ist das erste geänderte Bild. Ohne selectedImageIds: resource.not.found. Bestehende Marktplatz-Zuordnungen dieser Bilder werden vorher geleert.

14.4 Attribut-Optionen für Bilder (POST /api/materialPictures/attributeOptions) ​

Request

json
{
  "selectedImageIds": [40],
  "selectedAttributeOptions": [{ "id": 210 }]
}

Response: { "id": 40 }

Bestehende Attribut-Optionen der Bilder werden vorher geleert.

14.5 Bild bearbeiten (POST /api/material/editMaterialPicture) ​

Request: { "id": 40, "sortOrder": 1 }

Response: { "id": 40 }

14.6 Hauptbild-URL ermitteln (GET /api/material/getMainPictureUrl) ​

Request und Response wie 4.14.

15. Kategorien (/api/materialCategory) ​

15.1 Kategorien eines Artikels lesen (GET /api/materialCategory/{id}) ​

Request: GET /api/materialCategory?materialId=10482

Response: [{ "id": 7, "code": "SHOP", "name": "Shop" }]

15.2 Kategorienbaum lesen (GET /api/materialCategory/getCategoriesAsTree) ​

Request: GET /api/materialCategory/getCategoriesAsTree

Response: [{ "id": 7, "name": "Shop", "items": [] }]

15.3 Kategorien per IDs lesen (POST /api/materialCategory/listCategoriesByIds) ​

Request: { "ids": [7, 8] }

Response: [{ "id": 7, "name": "Shop" }]

15.4 Kategoriezuordnung löschen (DELETE /api/materialCategory/) ​

Request: { "id": 7, "materialId": 10482 }

Response: { "id": 7 }

Ein späteres POST /api/material/ ohne Kategorien leert die Zuordnungen ebenfalls, siehe 5.3.

16. Bestand (/api/materialStock) ​

16.1 Bestand eines Artikels lesen (GET /api/materialStock/{id}) ​

Request: GET /api/materialStock?materialId=10482

Response

json
[{
  "id": 600,
  "avail": 25,
  "warehouse": { "code": "HAUPT" }
}]

16.2 Bestand speichern (POST /api/materialStock/) ​

Request

json
{
  "material": { "matCode": "ART-100" },
  "warehouse": { "code": "HAUPT" },
  "stockplace": { "stockplaceCode": "*", "warehouse": { "code": "HAUPT" } },
  "quantity": 25
}

Response: { "id": 600 }

Das ist die Pflege der Bestandszeile. Eine buchende Übernahme ist 6.3. Für Generic-Domain-Abläufe sind zusätzlich GET /api/domains/materialStock und DELETE /api/domains/materialStock verfügbar.

16.3 Bestand löschen (DELETE /api/materialStock/{id}) ​

Request: DELETE /api/materialStock/600

Response: { "id": 600 }

16.4 Pickplatz-Liste lesen (GET /api/materialStock/getPickplaceList) ​

Request: GET /api/materialStock/getPickplaceList?materialId=10482

Response: [{ "stockplaceCode": "A-01", "warehouse": { "code": "HAUPT" } }]

16.5 Pickplatz aktualisieren (POST /api/materialStock/pickplace) ​

Request

json
{
  "material": { "matCode": "ART-100" },
  "warehouse": { "code": "HAUPT" },
  "stockplace": { "stockplaceCode": "A-01", "warehouse": { "code": "HAUPT" } }
}

Response: { "id": 600 }

16.6 Wareneingänge lesen (GET /api/materialStock/getMaterialIncomeDetail) ​

Request: GET /api/materialStock/getMaterialIncomeDetail?materialId=10482

Response: [{ "docDate": "2026-10-06", "quantity": 25 }]

16.7 Bestand nach Lager und Lagerplatz (GET /api/material/availStockGroupByWarehouseAndStockplace) ​

Request: GET /api/material/availStockGroupByWarehouseAndStockplace?materialId=10482

Response: [{ "warehouseCode": "HAUPT", "stockplaceCode": "*", "avail": 25 }]

16.8 Bestandsübernahme (POST /api/material/materialStocks) ​

Request und Response wie 6.3.

16.9 Bestände lesen (GET /api/material/materialStocks) ​

Request: GET /api/material/materialStocks?materialId=10482

Response: [{ "warehouseCode": "HAUPT", "quantity": 25 }]

16.10 Letzte Einkaufspreise (GET /api/material/lastPurPriceList) ​

Request: GET /api/material/lastPurPriceList?materialId=10482

Response: [{ "purPrice": 4.5, "currency": "EUR" }]

17. Marktplatz (/api/materialMarketplace) ​

17.1 Marktplatz-Zuordnung lesen (GET /api/materialMarketplace/{id}) ​

Request: GET /api/materialMarketplace?materialId=10482

Response: [{ "id": 12, "isActive": true }]

17.2 Marktplatz-Zuordnung speichern (POST /api/materialMarketplace/) ​

Request

json
{
  "material": { "matCode": "ART-100" },
  "marktplace": { "code": "AMAZON" },
  "isActive": true
}

Response: { "id": 12 }

17.3 Amazon ASIN-SKU-Mapping lesen (GET /api/material/getAmazonAsinSkuMapping/{id}) ​

Request: GET /api/material/getAmazonAsinSkuMapping/10482

Response: [{ "asin": "B00EXAMPLE", "sku": "ART-100" }]

17.4 Amazon ASIN-SKU-Mapping anlegen (POST /api/material/createAmazonAsinSkuMapping) ​

Request: { "materialId": 10482, "asin": "B00EXAMPLE", "sku": "ART-100" }

Response: { "id": 77 }

SKU bereits anderem Artikel zugeordnet: sku.defined.for.different.material. asin am Artikel selbst muss genau 10 Zeichen haben.

17.5 Amazon ASIN-SKU-Mapping löschen (DELETE /api/material/deleteAmazonAsinSkuMapping/{id}) ​

Request: DELETE /api/material/deleteAmazonAsinSkuMapping/77

Response: { "id": 77 }

Nicht gefunden: amazon.asin.sku.mapping.not.found.

18. Mandantenübergreifend ​

18.1 Artikel an andere Mandanten übertragen (POST /api/material/transferMaterialsToCrossTenants) ​

Request: { "ids": [10482], "tenantIds": [2] }

Response: { "ids": [10482] }

Zusätzlich legt das Speichern eines Artikels automatisch einen Übertrag an, wenn die Mandantenkonfiguration die Artikelkopie aktiv hat. Schlägt nur dieser automatische Eintrag fehl, bleibt der Artikel im Quellmandanten gespeichert.

19. Sonstiges ​

19.1 Operatoren und Werte für Filter (GET /api/material/operatorsAndValues) ​

Liefert die Operatoren der Massenänderung für ein Feld, nicht die Filter der Domain-API. Query-Parameter classAndProperty, zum Beispiel material.name oder material.salesPrice.

Request: GET /api/material/operatorsAndValues?classAndProperty=material.salesPrice

Response

json
{
  "type": "decimal",
  "operators": [
    { "name": "Setzen", "code": "set" },
    { "name": "Plus", "code": "plus" },
    { "name": "Minus", "code": "minus" }
  ],
  "values": []
}

Texte haben set, prepend, append, remove. Kategorien haben set, plus, remove. Der Code aus operators ist der operator in 5.6. Die Filterausdrücke eq, like, between gehören zu 2.11.

19.2 Paketanzahl berechnen (POST /api/material/calculateNumberOfPacks) ​

Request

json
{
  "materialIdsToQuantities": [
    { "materialId": 10482, "quantity": 13 }
  ]
}

Response: { "numberOfPacks": 3 }

Mehrere Artikel stehen als weitere Einträge in materialIdsToQuantities. Die Rechnung nutzt die Umrechnung der Artikeleinheit (Abschnitt 12).

20. Artikelgruppen anlegen und pflegen ​

Über die generische Domain-API. Suchschlüssel im Request: code.

20.1 Artikelgruppe anlegen (POST /api/domains/matGroup) ​

Request

json
{ "code": "HAUPT", "name": "Hauptgruppe" }

Response: { "id": 12 }

Ungültiges JSON: HTTP 400.

20.2 Artikelgruppen lesen (GET /api/domains/matGroup) ​

Request und Response wie 2.2.

20.3 Artikelgruppe ändern (POST /api/domains/matGroup mit id) ​

Request: { "id": 12, "name": "Hauptgruppe neu" }

Response: { "id": 12 }

20.4 Artikelgruppe deaktivieren statt löschen ​

Request: { "id": 12, "isDisabled": true }

Response: { "id": 12 }

Bestehende Artikel behalten die Gruppe. Ein Hard Delete ist nur sinnvoll, wenn keine Artikel mehr darauf zeigen.

20.5 Artikelgruppe endgültig löschen (DELETE /api/domains/matGroup?id=…) ​

Request: DELETE /api/domains/matGroup?id=12

Response: { "id": 12 }

Noch zugeordnete Artikel verhindern das Löschen (HTTP 400, { "error": "…" }).

21. Attributstamm, Import, Export, Kalkulation ​

Abschnitt Attribute ordnet ein vorhandenes Attribut einem Artikel zu. Der Stamm selbst, der Import, der Export und die Preiskalkulation liegen auf eigenen Controllern. POST ohne weiteren Pfad speichert den Datensatz. Die Zahlen 9201 und 9301 sind Beispiel-Ids.

POST /api/attribute/attributeJson setzt die Beschreibung, Feld domain. POST /api/attribute/getMaterialAttributes liest die Werte eines Artikels. materialId ist die Artikel-Id. Fehlt der Artikel: material.not.found. Optional filtert attributeCode.

CSV-Import anstoßen: POST /api/materialImport/doMaterialImportFromCsv. Die Antwort ist HTTP 202. Der Job POST /api/materialImport/importMaterialsPerJob verlangt materialImportId und antwortet { "success": true } oder false, wenn die Vorlage fehlt. Anlegen aus dem Marktplatz: POST /api/materialImport/createMaterials. Unbekannter Marktplatz: marketplace.not.found.

Export ausführen: POST /api/materialExport/exportMaterials mit materialExport. Alle Zeilen der Vorlage: POST /api/materialExport/addAllMaterialExportItem mit id.

Kampagne zuordnen und wieder lösen:

json
{ "campaigns": [9301], "materialIds": [10482] }
json
{ "campaignId": 9301, "materialIds": [10482] }

Der zweite Körper geht an DELETE /api/materialCampaign/removeCampaignFromMaterials. Unbekannte Id: HTTP 404.

Kalkulation einem Artikel geben und neu rechnen:

json
{ "schemeId": 9201, "materialIds": [10482] }

POST /api/calculationScheme/assignCalculationForMaterial. Unbekanntes Schema: resource.not.found. Neuberechnung: POST /api/calculationScheme/doMassRecalculationForMaterial mit materialIds. Formel übersetzen: POST /api/calculationScheme/formulaToMathString mit formula. Auswertung: POST /api/calculationScheme/processMathString mit mathString. Ein Lauf: GET /api/calculationHead/{id}.

MethodePfadBedeutung
GET/api/attribute/{id}Ein Attribut oder die Liste
POST/api/attribute/Attribut speichern
DELETE/api/attribute/{id}Attribut löschen
GET/api/attribute/getAttributeOption/{id}Optionen
POST/api/attribute/attributeJsonJSON-Beschreibung, Feld domain
POST/api/attribute/getMaterialAttributesWerte eines Artikels, materialId
GET/api/attribute/listAmazonAttributesByCategoryAmazon-Merkmale einer Kategorie
GET/api/attribute/tarifAttributeTarifmerkmale
POST/api/attributeOption/Option speichern
DELETE/api/attributeOption/Option löschen
GET/api/attributeGroup/{id}Eine Gruppe oder die Liste
POST/api/attributeGroup/Gruppe speichern
DELETE/api/attributeGroup/{id}Gruppe löschen
GET/api/attributeGroup/getAttributeGroupListGruppenliste
POST/api/attributeGroup/addAttributeAttribut der Gruppe zuordnen
GET/api/materialImport/{id}Eine Importvorlage
POST/api/materialImport/Vorlage speichern
DELETE/api/materialImport/{id}Vorlage löschen
POST/api/materialImport/doMaterialImportFromCsvCSV anstoßen, HTTP 202
POST/api/materialImport/importMaterialsPerJobJob, materialImportId
GET/api/materialImport/getMaterialImportItemsImportzeilen
GET/api/materialImport/getImportFromMarketplaceInfoMarktplatz-Import, Stand
POST/api/materialImport/importMaterialsFromMarketplaceVom Marktplatz
POST/api/materialImport/importMaterialsFromMarketplaceDirectlyDirekt vom Marktplatz
GET/api/materialImport/importMaterialsFromTableDirectlyAus der Tabelle
POST/api/materialImport/createMaterialsArtikel anlegen
POST/api/materialImport/reImportMaterialsFromMarketplace/{id}Erneut vom Marktplatz
POST/api/materialImport/importMaterialPictureBild importieren
POST/api/materialImport/saveMaterialPictureBild speichern
GET/api/materialImport/materialImportReportBericht
POST/api/materialImport/matchColumnsSpalten zuordnen
POST/api/materialImport/checkFtpConnectionFTP prüfen
GET/api/materialExport/{id}Ein Export
POST/api/materialExport/Export speichern
GET/api/materialExport/parameters/{id}Parameter
GET/api/materialExport/feedTokenFeed-Token
POST/api/materialExport/addAllMaterialExportItemAlle Artikel, id
POST/api/materialExport/exportMaterialsExport ausführen
DELETE/api/materialExport/deleteMaterialExportExport löschen
GET/api/materialClone/{id}Ein Klon
POST/api/materialClone/Klon speichern
DELETE/api/materialClone/{id}Klon löschen
GET/api/materialCampaign/{id}Eine Kampagne
POST/api/materialCampaign/Kampagne speichern
DELETE/api/materialCampaign/Kampagne löschen
POST/api/materialCampaign/addMaterialCampaignArtikel zuordnen
DELETE/api/materialCampaign/removeCampaignFromMaterialsZuordnung lösen
GET/api/calculationScheme/{id}Ein Schema
POST/api/calculationScheme/Schema speichern
DELETE/api/calculationScheme/Schema löschen
GET/api/calculationScheme/readDataForMassCalculationDaten der Massenrechnung
POST/api/calculationScheme/assignCalculationForMaterialSchema zuordnen
POST/api/calculationScheme/doMassRecalculationForMaterialNeu rechnen
POST/api/calculationScheme/formulaToMathStringFormel übersetzen
POST/api/calculationScheme/processMathStringAusdruck auswerten
GET/api/calculationHead/{id}Ein Kalkulationslauf

22. Häufige Fehler und ihre Ursachen ​

MeldungUrsache
material.save.matCode.errorKein matCode und kein Nummernkreis an Marke oder Artikelart
material.not.found / material.not.found.error / resource.not.foundId, matCode oder Barcode unbekannt
there.is.more.than.one.recordBarcode trifft mehrere Artikel
material.delete.error.caused.by.stockLöschen bei Menge größer 0
material.has.stockErste Variante, obwohl Bestand offen ist
material.isStocked.book.errorBestandsübernahme auf Artikel mit isStocked=false
material.must.have.to.material.unitStücklistenposition ohne Einheit
message.gtin.already.created.errorGTIN ist schon vergeben
message.max.gtin.reached.errorNummernkreis für GTIN ist erschöpft
sku.defined.for.different.materialSKU oder EAN gehört zu einem anderen Artikel
amazon.asin.sku.mapping.not.foundASIN-Zuordnung existiert nicht
HTTP 500 { "data": { "error" } }Fach-API, u. a. POST /api/material/
HTTP 400 { "error" }Generische Domain-API, ungültiger Filter oder Körper
marketplace.not.foundcreateMaterials ohne Marktplatz
resource.not.foundKalkulationsschema unbekannt
HTTP 404 bei KampagnecampaignId oder materialIds treffen nichts
HTTP 422Wird hier nicht verwendet

Preisnebenwirkung: salesPriceGross > 0 überschreibt den Nettopreis. Kategorien, Rohstoffe und – sobald gesendet – Einheiten, Stückliste und Übersetzungen werden ersetzt, nicht gemerged.

Beispiele ​

Fünf Anlage-Abläufe und zwei Änderungen. Jeder Body ist ein normaler Aufruf, ohne /connector. Stammdaten (matGroup, matStatus, materialType, vatKey, unit) per code ansprechen. Die id aus der Antwort von POST /api/material/ für die Folgeschritte merken: Varianten, Attributwerte und Preisstaffeln verlangen diese Zahl, nicht matCode.

Basis: https://core-backend.reybex.com/api. Kopf: --header "authorization: Basic $TOKEN".

Beispiel 1 – Einfacher Lagerartikel ​

POST /api/material/

json
{
  "name": "Kugelschreiber blau",
  "matCode": "ART-100",
  "sku": "ART-100",
  "isStocked": true,
  "matGroup": { "code": "HAUPT" },
  "matStatus": { "code": "AKTIV" },
  "materialType": { "code": "WARE" },
  "vatKey": { "code": "19" },
  "warehouseUnit": { "code": "ST" },
  "salUnit": { "code": "ST" },
  "salesPrice": 1.5
}

Response: { "id": 10482 }

salesPrice ist netto. Der Bruttobetrag wird aus vatKey.rate berechnet, solange salesPriceGross nicht größer als 0 ist.

Beispiel 2 – Lebensmittel mit Chargenführung und MHD ​

isLotEnabled schaltet die Charge ein, isShelfLife das Mindesthaltbarkeitsdatum. Beides zusammen ist der übliche Fall für Lebensmittel.

POST /api/material/

json
{
  "name": "Vollmilch 3,5 % 1 l",
  "matCode": "LM-MILCH-1L",
  "sku": "LM-MILCH-1L",
  "gtin": "4006381333931",
  "isStocked": true,
  "isLotEnabled": true,
  "isShelfLife": true,
  "matGroup": { "code": "LEBENSMITTEL" },
  "matStatus": { "code": "AKTIV" },
  "materialType": { "code": "WARE" },
  "vatKey": { "code": "7" },
  "warehouseUnit": { "code": "ST" },
  "salUnit": { "code": "ST" },
  "salesPriceGross": 1.19
}

Response: { "id": 10502 }

salesPriceGross > 0 setzt den Nettopreis aus Brutto und Steuersatz. Charge und MHD gelten für den Artikelstamm; das konkrete Chargen- und MHD-Datum entsteht erst bei der Lagerbuchung, nicht in diesem Body.

Beispiel 3 – Set / Bundle mit Stückliste ​

Zuerst den Set-Kopf, dann jede Komponente. Ohne unit an der Position bricht die Stückliste ab.

1. POST /api/material/

json
{
  "name": "Frühstücksset",
  "matCode": "SET-FRUEH",
  "sku": "SET-FRUEH",
  "isSet": true,
  "isStocked": false,
  "matGroup": { "code": "SETS" },
  "matStatus": { "code": "AKTIV" },
  "materialType": { "code": "SET" },
  "vatKey": { "code": "7" },
  "warehouseUnit": { "code": "ST" },
  "salUnit": { "code": "ST" },
  "salesPriceGross": 12.9
}

Response: { "id": 10600 }

2. POST /api/materialBom/ je Komponente

json
{
  "materialBom": {
    "material": { "matCode": "SET-FRUEH" },
    "component": { "matCode": "LM-MILCH-1L" },
    "amount": 1,
    "unit": { "code": "ST" },
    "description": "Milch"
  }
}
json
{
  "materialBom": {
    "material": { "matCode": "SET-FRUEH" },
    "component": { "matCode": "ART-BROT" },
    "amount": 2,
    "unit": { "code": "ST" },
    "description": "Brötchen"
  }
}

Response je Position: { "id": 8801 }

Die Komponenten müssen vorher als eigene Artikel existieren. amount ist mindestens 0,01.

Beispiel 4 – Variantenartikel ​

Der Kopf hat noch keinen Bestand. Sonst lehnt die erste Variante mit material.has.stock ab. Attribut und Option vorher per GET /api/domains/attribute und GET /api/domains/attributeOption lesen. Die Variantenanlage erwartet die numerische id, keinen code.

1. POST /api/material/

json
{
  "name": "T-Shirt",
  "matCode": "SHIRT-1",
  "sku": "SHIRT-1",
  "isStocked": true,
  "matGroup": { "code": "HAUPT" },
  "matStatus": { "code": "AKTIV" },
  "materialType": { "code": "WARE" },
  "vatKey": { "code": "19" },
  "warehouseUnit": { "code": "ST" },
  "salUnit": { "code": "ST" },
  "salesPrice": 19.9
}

Response: { "id": 10620 }

2. POST /api/materialVariant/

attributes ist die Liste der variantenbildenden Merkmale. options sind die gewählten Ausprägungen. Aus dem Kreuzprodukt entstehen die Varianten. SKU wird aus sku des Kopfes, dem Trenner (Standard .) und einer laufenden Nummer gebildet, zum Beispiel SHIRT-1.1.

json
{
  "materialId": 10620,
  "attributes": [
    {
      "id": 21,
      "options": [{ "id": 210 }, { "id": 211 }]
    },
    {
      "id": 22,
      "options": [{ "id": 220 }, { "id": 221 }, { "id": 222 }]
    }
  ]
}

21 / 22 sind die Ids von Farbe und Größe, 210–222 die Ids der Optionen (Rot, Blau, S, M, L). Zwei Farben mal drei Größen ergeben sechs Varianten.

Response: { "success": "success" }

Ein erneuter Aufruf mit einem anderen Attributsatz löscht die bisherigen Varianten und legt sie neu an. Lesen danach: GET /api/materialVariant?materialId=10620.

Beispiel 5 – Artikel mit Attributen (PIM) ​

PIM-Merkmale hängen am Artikel, ohne eigene Varianten-SKUs. Die Werte setzt POST /api/materialAttributeValue/. Dieser Aufruf markiert alle bisherigen Werte des Artikels als gelöscht und schreibt nur die gesendete Liste.

1. POST /api/material/

json
{
  "name": "Olivenöl nativ 500 ml",
  "matCode": "LM-OEL-500",
  "sku": "LM-OEL-500",
  "isStocked": true,
  "isLotEnabled": true,
  "isShelfLife": true,
  "matGroup": { "code": "LEBENSMITTEL" },
  "matStatus": { "code": "AKTIV" },
  "materialType": { "code": "WARE" },
  "vatKey": { "code": "7" },
  "warehouseUnit": { "code": "ST" },
  "salUnit": { "code": "ST" },
  "salesPriceGross": 8.99
}

Response: { "id": 10700 }

2. Attribut und Option nachschlagen, zum Beispiel GET /api/domains/attribute?code=HERKUNFT und GET /api/domains/attributeOption?code=ITALIEN.

3. POST /api/materialAttributeValue/

json
{
  "materialId": 10700,
  "attributeOptions": [
    {
      "attributeId": 30,
      "attributeOptionId": [301],
      "isConstant": true
    },
    {
      "attributeId": 31,
      "stringValue": "Kaltgepresst"
    }
  ]
}

attributeOptionId ist eine Liste von Options-Ids. Freitext ohne Option über die übrigen Felder des Werts (stringValue). Response: HTTP 200 ohne Id.

Beispiel 6 – Preise anpassen ​

Verkaufspreis am Stamm und Staffel sind zwei Aufrufe. Für die Staffel die Artikel-id aus Beispiel 1 verwenden. POST /api/materialPrices/ löst den Artikel nur über material.id.

Listenpreis (Brutto gewinnt) POST /api/material/

json
{
  "id": 10482,
  "salesPriceGross": 2.38,
  "vatKey": { "code": "19" }
}

Response: { "id": 10482 }

Staffel ab Menge 10 POST /api/materialPrices/

json
{
  "material": { "id": 10482 },
  "materialPrices": [
    {
      "price": 1.2,
      "quantity": 10,
      "currency": { "code": "EUR" },
      "unit": { "code": "ST" },
      "validFrom": "2026-10-01",
      "validUntil": "2026-12-31"
    }
  ]
}

Response: { "id": 10482 }

type 0 ist ein fester Preis, type 1 ein Rabatt in Prozent (discount). Bestehende Zeile ändern, indem id der Preiszeile mitgesendet wird.

Beispiel 7 – PIM-Attribute aktualisieren ​

Dieselbe Schnittstelle wie in Beispiel 5. Die neue Liste ersetzt die bisherigen Werte.

POST /api/materialAttributeValue/

json
{
  "materialId": 10700,
  "attributeOptions": [
    {
      "attributeId": 30,
      "attributeOptionId": [302],
      "isConstant": true
    }
  ]
}

302 ist die neue Option, zum Beispiel Spanien statt Italien. Werte, die nicht mehr in der Liste stehen, sind danach gelöscht (isDelete=true). Lesen zur Kontrolle: GET /api/materialAttributeValue?materialId=10700.

Nur für reybex-Partner. Nicht für Endkunden bestimmt.