Darstellung
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
| Bereich | Basis | Zweck |
|---|---|---|
| Artikel | /api/material | Stamm, Suche, Kopie, Massenänderung, GTIN, Bestandssicht |
| Varianten | /api/materialVariant | Varianten lesen, erzeugen, ändern, löschen |
| Stückliste | /api/materialBom | Set-Komponenten |
| Attribute | /api/materialAttribute, /api/materialAttributeValue | Zuordnung und Werte |
| Preise | /api/materialPrices | Staffeln, Aktionen, Kundengruppen |
| Einheiten | /api/materialUnits | Umrechnungen, EAN |
| Übersetzungen | /api/materialTranslation | Sprachtexte |
| Bilder | /api/materialPictures | Reihenfolge, Marktplatz, Attribute |
| Kategorien | /api/materialCategory | Shop-Kategorien |
| Bestand | /api/materialStock | Lagerzeilen, Pickplatz, Wareneingang |
| Marktplatz | /api/materialMarketplace | Kanalzuordnung, Amazon ASIN |
| Prüftabellen | /api/checkTables, /api/domains/{domain} | Artikelgruppe, Status, Einheit, Steuer, Währung |
| Kunden und Lieferanten | /api/customer | Kunde, Lieferant, Adresse, Bank |
| CRM | /api/crmAction, /api/crmOpportunity | Aktivität, Verkaufschance, Angebot aus der Chance |
| Auftragsverwaltung | /api/salesHead | Verkaufsbelege mit diesen Artikeln |
| Kassenverwaltung | /api/cashRegister | Kasse, Schicht, Bon |
| Einkauf-Verwaltung | /api/purHead | Einkaufsbelege mit diesen Artikeln |
| Lager und Inventur | /api/stock, /api/stockHead | Bestand, 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)
| Situation | HTTP | Körper |
|---|---|---|
Fach-API POST /api/material/ – Validierung, fehlende Artikelnummer, unbekanntes Ziel | 500 | { "data": { "error": "…" }, "meta": {} } |
Bestandsübernahme POST /api/material/materialStocks – fachlicher Abbruch | Status aus der Ausnahme, oft 404 | { "error": "…" } |
| Bestandsübernahme – sonstiger Abbruch | 500 | { "error": "…" } |
| Generische Domain-API – ungültiger Filter oder unbekannte Domain | 400 | { "error": "…" } |
| Fehlende Anmeldung | 401 | — |
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.
| Ziel | Suchschlüssel |
|---|---|
| Artikel | matCode, sonst sku |
| Artikelgruppe, Status, Art, Steuer, Einheit, Währung, Marke | code, sonst type, sonst name |
| Lager | code, sonst name |
| Lagerplatz | stockplaceCode 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.
| Feld | Pflicht | Verhalten |
|---|---|---|
name | ja | Bezeichnung, Länge 1–300 |
vatKey | ja | Steuerschlüssel, Suchschlüssel code. rate steuert Brutto/Netto |
warehouseUnit | ja | Lagereinheit, Suchschlüssel code |
matGroup | ja | Artikelgruppe, Suchschlüssel code |
matStatus | ja | Artikelstatus, Suchschlüssel code |
materialType | ja | Artikelart, Suchschlüssel code. Kann den Nummernkreis tragen |
matCode | nein | Sonst Nummernkreis der Marke, dann der Artikelart. Sonst material.save.matCode.error. Länge 1–100 |
sku | nein | Sonst matCode, danach notfalls gtin |
salUnit | nein | Verkaufseinheit |
currency | nein | Währung des Artikels |
isStocked | nein | Standard true |
isSerialManagement | nein | Standard false. Wird true, sobald isSerialNumberRequired gesetzt ist |
isSerialNumberRequired | nein | Standard false |
isLotEnabled | nein | Charge. Standard false |
isShelfLife | nein | MHD. Standard false |
isSet | nein | Set/Bundle. Standard false |
isTemplate | nein | null wird zu false. true macht den Artikel zur Vorlage, siehe 3.10 |
salesPriceGross | nein | Wenn > 0, wird salesPrice aus Brutto und vatKey.rate mit 4 Nachkommastellen berechnet |
salesPrice | nein | Nur wenn Brutto nicht > 0 ist, wird daraus der Bruttobetrag berechnet |
asin | nein | Lä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.
- Angabe – Wert aus dem Auftrag für dieses Feld.
- Vorlage – dasselbe Feld aus
GET /api/material/{id}der Vorlage.id,matCodeundskunicht übernehmen; beiunitsdieidentfernen undisTemplateauffalsesetzen. 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. - Standard – Wert aus der Tabelle. Einen Code per Suchschlüssel laden (
code). Existiert er nicht, Schritt 4. - Domäne –
GET /api/domains/{domain}?take=1&sort=code. Diese Domänen haben keinisDefault. Den Treffer als{ "code": "…" }in den Request setzen. - Stopp – die Domäne ist leer. Artikel nicht anlegen. Den fehlenden Stammdatensatz nennen (
vatKey,unit,matGroup,matStatusodermaterialType).
| Feld | Pflicht | Vorlage | Standard | Domäne |
|---|---|---|---|---|
name | ja | name | — | — |
vatKey | ja | vatKey | GET /api/company/ → configuration.defaultVatKey, sonst code 19 | vatKey |
warehouseUnit | ja | warehouseUnit | code ST (Stück) | unit |
matGroup | ja | matGroup | — | matGroup |
matStatus | ja | matStatus | — | matStatus |
materialType | ja | materialType | — | materialType |
salUnit | nein | salUnit | code ST | unit |
currency | nein | currency | GET /api/company/ → homeCurrency, sonst code EUR | currency |
matCode | nein | nicht übernehmen | Nummernkreis Marke, dann Artikelart | — |
sku | nein | nicht übernehmen | wird 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.
- Vorlagen laden: 4.10 oder 4.11.
GET /api/material/{id}der Vorlage.id,matCodeundskuentfernen,isTemplateauffalsesetzen, bei jedem Eintrag inunitsdieidentfernen.- Felder, die der Auftrag nennt, überschreiben die Vorlage. Fehlende Pflichtfelder danach mit Schritt 3 und 4 aus 3.1 füllen.
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 mitid. - Einheiten ohne
exchangeRatiofallen weg, sobaldunitsmitgeschickt wird oder der Artikel neu ist.warehouseExchangeRatiowird auf 1 gesetzt, wenn es leer ist, und danach aufbaseExchangeRatio. - Stücklistenpositionen ohne Komponente oder Menge fallen weg, sobald
materialBomsgesendet wird. - Übersetzungen ohne
namefallen weg. - Marktplatz-Kategorien werden geleert, wenn Marktplatzdaten im Request stehen.
- Leere Maps werden zu
null.salesUnitCodeaus 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-API | Domain-API | |
|---|---|---|
| Aufruf | DELETE /api/material/ Body { "id": 10482 } | DELETE /api/domains/material?id=10482 |
| Wirkung beim Artikel | Soft Delete, Bestand sperrt | Domänen löschen je nach Modell physikalisch oder per Kennzeichen |
| Response | { "id": 10482 } | { "id": 10482 } |
| Fehler | Bestand: material.delete.error.caused.by.stock | Ungü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}.
| Methode | Pfad | Bedeutung |
|---|---|---|
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/attributeJson | JSON-Beschreibung, Feld domain |
POST | /api/attribute/getMaterialAttributes | Werte eines Artikels, materialId |
GET | /api/attribute/listAmazonAttributesByCategory | Amazon-Merkmale einer Kategorie |
GET | /api/attribute/tarifAttribute | Tarifmerkmale |
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/getAttributeGroupList | Gruppenliste |
POST | /api/attributeGroup/addAttribute | Attribut der Gruppe zuordnen |
GET | /api/materialImport/{id} | Eine Importvorlage |
POST | /api/materialImport/ | Vorlage speichern |
DELETE | /api/materialImport/{id} | Vorlage löschen |
POST | /api/materialImport/doMaterialImportFromCsv | CSV anstoßen, HTTP 202 |
POST | /api/materialImport/importMaterialsPerJob | Job, materialImportId |
GET | /api/materialImport/getMaterialImportItems | Importzeilen |
GET | /api/materialImport/getImportFromMarketplaceInfo | Marktplatz-Import, Stand |
POST | /api/materialImport/importMaterialsFromMarketplace | Vom Marktplatz |
POST | /api/materialImport/importMaterialsFromMarketplaceDirectly | Direkt vom Marktplatz |
GET | /api/materialImport/importMaterialsFromTableDirectly | Aus der Tabelle |
POST | /api/materialImport/createMaterials | Artikel anlegen |
POST | /api/materialImport/reImportMaterialsFromMarketplace/{id} | Erneut vom Marktplatz |
POST | /api/materialImport/importMaterialPicture | Bild importieren |
POST | /api/materialImport/saveMaterialPicture | Bild speichern |
GET | /api/materialImport/materialImportReport | Bericht |
POST | /api/materialImport/matchColumns | Spalten zuordnen |
POST | /api/materialImport/checkFtpConnection | FTP prüfen |
GET | /api/materialExport/{id} | Ein Export |
POST | /api/materialExport/ | Export speichern |
GET | /api/materialExport/parameters/{id} | Parameter |
GET | /api/materialExport/feedToken | Feed-Token |
POST | /api/materialExport/addAllMaterialExportItem | Alle Artikel, id |
POST | /api/materialExport/exportMaterials | Export ausführen |
DELETE | /api/materialExport/deleteMaterialExport | Export 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/addMaterialCampaign | Artikel zuordnen |
DELETE | /api/materialCampaign/removeCampaignFromMaterials | Zuordnung lösen |
GET | /api/calculationScheme/{id} | Ein Schema |
POST | /api/calculationScheme/ | Schema speichern |
DELETE | /api/calculationScheme/ | Schema löschen |
GET | /api/calculationScheme/readDataForMassCalculation | Daten der Massenrechnung |
POST | /api/calculationScheme/assignCalculationForMaterial | Schema zuordnen |
POST | /api/calculationScheme/doMassRecalculationForMaterial | Neu rechnen |
POST | /api/calculationScheme/formulaToMathString | Formel übersetzen |
POST | /api/calculationScheme/processMathString | Ausdruck auswerten |
GET | /api/calculationHead/{id} | Ein Kalkulationslauf |
22. Häufige Fehler und ihre Ursachen
| Meldung | Ursache |
|---|---|
material.save.matCode.error | Kein matCode und kein Nummernkreis an Marke oder Artikelart |
material.not.found / material.not.found.error / resource.not.found | Id, matCode oder Barcode unbekannt |
there.is.more.than.one.record | Barcode trifft mehrere Artikel |
material.delete.error.caused.by.stock | Löschen bei Menge größer 0 |
material.has.stock | Erste Variante, obwohl Bestand offen ist |
material.isStocked.book.error | Bestandsübernahme auf Artikel mit isStocked=false |
material.must.have.to.material.unit | Stücklistenposition ohne Einheit |
message.gtin.already.created.error | GTIN ist schon vergeben |
message.max.gtin.reached.error | Nummernkreis für GTIN ist erschöpft |
sku.defined.for.different.material | SKU oder EAN gehört zu einem anderen Artikel |
amazon.asin.sku.mapping.not.found | ASIN-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.found | createMaterials ohne Marktplatz |
resource.not.found | Kalkulationsschema unbekannt |
| HTTP 404 bei Kampagne | campaignId oder materialIds treffen nichts |
| HTTP 422 | Wird 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.