Zum Hauptinhalt springen

Übersicht

Stapelimporte laufen asynchron: Der POST legt einen Import-Job an und antwortet sofort mit 202 und einer jobId. Ihr System fragt anschließend den Job-Status ab (GET /api/v1/import-jobs/{jobId}), bis der Import abgeschlossen ist, und erhält dort das vollständige Ergebnis — inklusive der Gründe für übersprungene oder fehlgeschlagene Zeilen. Der Import nutzt dieselbe Engine wie der CSV-Import in der App: gleiche Validierung, gleicher idempotenter Abgleich, gleiches Ergebnisformat.
Ein POST mit einem einzelnen Objekt (ohne rows-Array) bleibt synchron und antwortet unverändert mit 201. Nur die Stapel-Form (Array bzw. Objekt mit rows) ist asynchron.Dieser Ablauf gilt für die Endpunkte mit 5.000-Zeilen-Limit — die drei oben und POST /api/v1/ppwr/quantities. Die PPWR-Stammdaten-Endpunkte und POST /api/v1/ppwr/tonnage (1.000-Zeilen-Limit; darüber 400, nicht 413) sind synchron: 200 mit dem Ergebnis im Body, es entsteht kein Job. Siehe PPWR.

Ablauf

  1. Stapel senden — POST mit einem Array von Zeilen oder einem Objekt mit rows:
    Bei Erfolg: 202 mit { "jobId": "…", "status": "queued", "statusUrl": "/api/import-jobs/…" } (auch als Location-Header; statusUrl ist host-relativ — nur an den Ursprung anhängen). Zu diesem Zeitpunkt ist noch nichts importiert. Die Zeilen-Validierung läuft synchron — ein fehlerhafter Stapel wird sofort mit 400 abgelehnt, ohne dass ein Job entsteht. Das erste Element von path in jedem Eintrag von details ist der 0-basierte Index der fehlerhaften Zeile in rows, z. B. [17, "quantity"]. Eine fehlerhafte Zeile lehnt die ganze Anfrage ab, nichts wird angelegt — diese Zeile korrigieren oder entfernen und den Stapel erneut senden.
  2. Status abfragen — GET /api/v1/import-jobs/{jobId} etwa alle 2 Sekunden, bei großen Jobs mit steigendem Abstand (z. B. exponentiell bis ~30 s). completed und failed sind final — danach nicht weiter abfragen.
  3. Ergebnis auswerten — bei status: "completed" enthält result das zusammengeführte Import-Ergebnis (imported, updated, failed, skipped, … je nach Entität). Jeder Eintrag in failed nennt seinen Datensatz (orderNumber, internalArticleNr bzw. name) und trägt error.key — einen stabilen, nicht lokalisierten Schlüssel — und manchmal error.params. Ein failed-Job trägt seinen Grund stattdessen in error (siehe Tabelle unten).

Limits

  • Maximal 5.000 Zeilen pro Anfrage. Darüber: 413 { "error": "batchTooLarge", "maxBatchSize": 5000 } — es wird nichts angelegt. Größere Abgleiche auf mehrere Anfragen aufteilen.
  • ~4,5 MB pro Anfrage (Plattform-Limit, greift vor unserer Anwendung).
  • Für einen großen Erstimport Stapel mit etwa 100 bis 500 Bestellungen (jeweils mit allen Zeilen, bis zum 5.000-Zeilen-Limit) senden statt einer Anfrage je Bestellung: Jede Anfrage wird ein Job, die Jobs eines Unternehmens laufen nur zu wenigen gleichzeitig, und weniger Jobs heißt weniger jobIds zum Abfragen.
  • Ein leeres Array oder ein fehlerhaftes Objekt mit rows → 400.

Teil-Akzeptanz und Idempotenz

  • Gültige Zeilen werden übernommen, auch wenn andere Zeilen in failed landen.
  • Ein Job schreibt in Abschnitten. Bricht er unterwegs ab (workerError, oder lineReplacementRequired nach einer gleichzeitigen Änderung), können frühere Abschnitte schon geschrieben sein. Den Stapel erneut zu senden ist gefahrlos.
  • Ein identischer Import lässt sich gefahrlos wiederholen: bereits vorhandene Zeilen kommen als übersprungen/aktualisiert zurück, es entstehen keine Duplikate.
  • Artikelfelder in Bestellzeilen (hsCode, articleDescription) wirken nur beim Anlegen — siehe Bestellungen.

Fehlerschlüssel (stabil, nicht lokalisiert)

Das error eines fehlgeschlagenen Jobs ist ein Text: entweder ein reiner Schlüssel oder JSON, dessen key der stabile Teil ist. Zeilen- und Bestellschlüssel stehen im Ergebnis eines abgeschlossenen Jobs als failed[].error.key. Die bestellspezifischen Schlüssel (lineReplacementRequired, positionIdMixed, duplicatePositionId, conflictingHsCodeForArticle, conflictingDuplicateOrderRows) erklärt Bestellungen. Ein Bestellschlüssel lässt die ganze Bestellung fehlschlagen; nichts davon wird geschrieben.

Aufbewahrung

Das Job-Ergebnis bleibt abfragbar; die übermittelten Eingabedaten werden ~24 Stunden nach Abschluss gelöscht, der Job-Datensatz ~30 Tage nach Erstellung gelöscht. Fragen Sie das Ergebnis innerhalb dieses Fensters ab und persistieren Sie es auf Ihrer Seite.

Berechtigungen

Der POST erfordert die Schreibberechtigung der Entität (articles:write, suppliers:write, orders:write), das Abfragen des Jobs die jeweilige Leseberechtigung (in der Schreibberechtigung enthalten). Jobs sind strikt mandantengebunden: eine unbekannte jobId und die jobId eines anderen Unternehmens liefern dieselbe 404.

HS-Code auf Bestellzeilen mit Pro-Bestellung-Kopien (hsCode)

Dieser Abschnitt ist umgezogen: Bestellungen.

Herkunft pro Bestellung per ERP

Dieser Abschnitt ist umgezogen: Bestellungen.

Positionen (positionId)

Dieser Abschnitt ist umgezogen: Bestellungen.

Bestellstatus (status)

Dieser Abschnitt ist umgezogen: Bestellungen.

Bestellungen: replaceLines und die Vollständigkeitsregel

Dieser Abschnitt ist umgezogen: Bestellungen.

Delta-Sync (changedSince)

Dieser Abschnitt ist umgezogen: Bestellungen.