{"info":{"title":"Shirtee Merchant API","version":"1.0.0","description":"Shirtee Händler-API / Merchant API.\n\n**Authentifizierung / Authentication:** Kunden-API-Schlüssel als Bearer-Token im\nHeader `Authorization: Bearer <key>`. Send your customer API key as a bearer token.\nJede Operation nennt in `x-customer-scopes` die Scopes, von denen der Schlüssel\nmindestens einen tragen muss. Each operation lists in `x-customer-scopes` the\nscopes of which the key needs at least one.\n\n**Freischaltung / Enablement:** Welche Scopes ein Schlüssel tragen und nutzen\nkann, legt Shirtee fest: ein Standard für alle Händler plus Zusatzrechte je\nHändler. Ohne Freischaltung wirkt kein Scope, und `GET /api/agent-access/me`\nnennt die wirksamen. Which scopes a key may carry and use is set by Shirtee: a\ndefault for all merchants plus additional scopes per merchant. Without it no\nscope works, and `GET /api/agent-access/me` lists the effective ones.\n\n**Vorschau / Preview:** Die Endpunkte `…/preview` schreiben nichts. Sie zeigen,\nwas die Änderung jetzt bewirken würde, samt `fingerprint` und\n`confirmed_summary`. The preview endpoints write nothing and return what the\nchange would do now, including `fingerprint` and `confirmed_summary`. Die\nREST-API verlangt keine vorherige Vorschau. The REST API does not require a\npreview before the change.\n\n**Idempotenz / Idempotency:** `POST /api/orders` akzeptiert den Header\n`Idempotency-Key`. Derselbe Schlüssel mit demselben Body liefert die bereits\nangelegte Bestellung statt einer zweiten. The same key with the same body returns\nthe existing order instead of creating a second one.\n"},"openapi":"3.1.0","servers":[{"url":"/"}],"paths":{"/api/complaints":{"get":{"tags":["Complaints"],"summary":"List complaints","operationId":"ApiComplaintsListComplaints","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","maximum":100.0,"minimum":1.0,"default":20},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anzahl Einträge pro Seite, 1 bis 100, Standard 20. / Entries per page, 1 to 100, default 20."},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0.0,"default":0},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anzahl zu überspringender Einträge, mindestens 0, Standard 0. / Entries to skip, minimum 0, default 0."},{"name":"status","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/ComplaintStatus"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Nur Reklamationen in diesem Status; ohne Angabe alle außer Entwürfen. / Only complaints in this status; if omitted, all except drafts."},{"name":"reason","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/ComplaintReason"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Nur Reklamationen, die mindestens eine Position mit diesem Grund enthalten. / Only complaints that contain at least one item with this reason."},{"name":"customer_id","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}],"minimum":1},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Filter auf die Kunden-ID des Händlers; Händler sehen ohnehin nur eigene Reklamationen, ein fremder Wert ergibt eine leere Liste. / Filter on the merchant customer ID; merchants only see their own complaints anyway, a foreign value returns an empty list."},{"name":"order_id","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}],"minimum":1},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Nur Reklamationen zu dieser Bestell-ID (numerisch, mindestens 1). / Only complaints for this numeric order ID (minimum 1)."},{"name":"order_reference","in":"query","schema":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":100,"minLength":1},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Trifft externe Referenz oder Kennung der Bestellung oder die Reklamationsnummer (`RK-…`), ohne Beachtung der Groß-/Kleinschreibung, 1 bis 100 Zeichen. / Matches the order external reference or order identifier, or the complaint reference (`RK-…`), case-insensitive, 1 to 100 characters."},{"name":"date_from","in":"query","schema":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anlagedatum ab (einschließlich), Format `YYYY-MM-DD`, Tagesgrenze nach Berliner Zeit. / Created on or after this date (inclusive), format `YYYY-MM-DD`, day boundary in Berlin time."},{"name":"date_to","in":"query","schema":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anlagedatum bis (einschließlich), Format `YYYY-MM-DD`, Tagesgrenze nach Berliner Zeit. / Created on or before this date (inclusive), format `YYYY-MM-DD`, day boundary in Berlin time."},{"name":"without_ticket","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"`true`: nur Reklamationen, für die noch kein Support-Vorgang angelegt wurde (Standard `false`, kein Filter). / `true`: only complaints without a support case yet (default `false`, no filter)."}],"responses":{"200":{"description":"Eine Seite der Reklamationsliste. / One page of the complaint list.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintUserPageResponse"},"example":{"items":[{"id":4001,"reference":"RK-MUSTER1","order_id":123456,"order_external_reference":"SHOP-10001","status":"SUBMITTED","submitted_at":"2026-01-15T10:40:00Z","created_at":"2026-01-15T10:30:00Z","item_count":1,"reasons":["STAINS"]}],"limit":20,"offset":0,"total_count":1}}}},"400":{"description":"Ungültige Anfrage (z. B. Parameter außerhalb des erlaubten Bereichs, ungültiger Body). / Invalid request (e.g. parameter out of range or invalid body).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Reklamation, Bestellung, Position oder Foto existiert nicht oder gehört einem anderen Händler; ebenso, wenn die Funktion für dieses Konto nicht verfügbar ist. Nie 403. / Complaint, order, item or photo does not exist or belongs to another merchant; also returned when the feature is not available for this account. Never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"],"description":"Listet die Reklamationen des Händlers, neueste zuerst (nach Anlagezeitpunkt), seitenweise mit `limit`/`offset`; `total_count` ist die Gesamtzahl der Treffer aller Seiten.\n\nOhne `status`-Filter fehlen Entwürfe; `status=DRAFT` zeigt sie. Alle Filter sind optional und werden mit UND verknüpft. Es erscheinen nur eigene Reklamationen. Die Listenzeile enthält keine Fotos; Details liefert `GET /api/complaints/{complaint_id}`. `404`, solange die Reklamationsfunktion für Händler nicht freigeschaltet ist.\n\nLists the merchant's complaints, newest first (by creation time), paginated with `limit`/`offset`; `total_count` is the total number of matches across all pages.\n\nWithout a `status` filter drafts are omitted; `status=DRAFT` shows them. All filters are optional and combined with AND. Only the merchant's own complaints appear. A list row carries no photos; use `GET /api/complaints/{complaint_id}` for details. `404` while the complaint feature is not enabled for merchants."},"post":{"tags":["Complaints"],"summary":"Create a complaint draft","operationId":"ApiComplaintsCreateComplaint","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintCreateRequest"},"example":{"order_id":123456,"items":[{"order_item_id":90001,"reason":"STAINS"}],"comment":"Flecken auf der Vorderseite / Stains on the front"}}},"required":true},"responses":{"201":{"description":"Entwurf angelegt (Status `DRAFT`). / Draft created (status `DRAFT`).","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintResponse"},"example":{"id":4001,"reference":"RK-MUSTER1","order_id":123456,"status":"DRAFT","comment":"Flecken auf der Vorderseite / Stains on the front","submitted_at":null,"created_at":"2026-01-15T10:30:00Z","items":[{"id":5001,"order_item_id":90001,"reason":"STAINS","decision":"NONE","decision_note":null,"attachments":[],"attachment_count":0}]}}}},"400":{"description":"`extra.error = ITEM_NOT_IN_ORDER` (`extra.order_item_ids`) oder ungültiger Body ohne Code (leere Positionsliste, doppelte `order_item_id`, unbekannter Grund). / `extra.error = ITEM_NOT_IN_ORDER` (`extra.order_item_ids`) or an invalid body without code (empty item list, duplicate `order_item_id`, unknown reason).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}},"404":{"description":"Reklamation, Bestellung, Position oder Foto existiert nicht oder gehört einem anderen Händler; ebenso, wenn die Funktion für dieses Konto nicht verfügbar ist. Nie 403. / Complaint, order, item or photo does not exist or belongs to another merchant; also returned when the feature is not available for this account. Never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}},"409":{"description":"Eine gewählte Position ist nicht reklamierbar. `extra.error` ist der Sperrgrund der Bestellung (`ORDER_CANCELED`, `DEADLINE_EXCEEDED`, `ORDER_WITHOUT_CUSTOMER`), `ITEM_ALREADY_REPORTED` (wenn das der einzige Grund ist) oder `ITEM_NOT_ELIGIBLE`; `extra.items` ordnet jeder `order_item_id` ihren Code zu. / A selected item cannot be reported. `extra.error` is the order-level block, `ITEM_ALREADY_REPORTED` (if that is the only reason) or `ITEM_NOT_ELIGIBLE`; `extra.items` maps each `order_item_id` to its code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["merchant_complaint:write"],"description":"Legt eine Reklamation als **Entwurf** (`DRAFT`) an. Der Entwurf sperrt die Positionen noch nicht; die Sperre gegen Doppelmeldungen greift erst beim Einreichen (`POST /api/complaints/{complaint_id}/submit`). Pro Position ist ein Grund (`reason`) anzugeben; jede Position darf nur einmal vorkommen.\n\nVoraussetzungen: die Bestellung gehört zum Händler und jede gewählte Position ist reklamierbar (siehe `GET /api/orders/{order_id}/complaint-eligibility`). Danach Fotos je Position hochladen und den Entwurf einreichen. Ein Entwurf, der nicht eingereicht wird, wird nach einer Frist (derzeit 24 Stunden) automatisch verworfen; seine Fotos werden gelöscht.\n\nFehler: `400` mit `extra.error = ITEM_NOT_IN_ORDER`, wenn eine Position nicht zur Bestellung gehört (`extra.order_item_ids`); `400` ohne Code bei ungültigem Body (leere Positionsliste, doppelte `order_item_id`, unbekannter Grund); `409`, wenn eine Position nicht reklamierbar ist (`extra.error` = Sperrgrund der Bestellung, `ITEM_ALREADY_REPORTED` oder `ITEM_NOT_ELIGIBLE`; `extra.items` ordnet jeder `order_item_id` ihren Code zu); `404` bei fremder oder unbekannter Bestellung.\n\nCreates a complaint as a **draft** (`DRAFT`). A draft does not lock the items yet; the lock against duplicate reports takes effect on submit (`POST /api/complaints/{complaint_id}/submit`). Give one `reason` per item; each item may appear only once.\n\nRequirements: the order belongs to the merchant and every selected item is eligible (see `GET /api/orders/{order_id}/complaint-eligibility`). Then upload photos per item and submit the draft. A draft that is not submitted is discarded automatically after a time limit (currently 24 hours) and its photos are deleted.\n\nErrors: `400` with `extra.error = ITEM_NOT_IN_ORDER` (`extra.order_item_ids`) or a body validation error without code; `409` when an item is not eligible (`extra.error` is the order-level block, `ITEM_ALREADY_REPORTED` or `ITEM_NOT_ELIGIBLE`, `extra.items` maps each `order_item_id` to its code); `404` for an unknown or foreign order."}},"/api/complaints/{complaint_id}":{"get":{"tags":["Complaints"],"summary":"Get a complaint","operationId":"ApiComplaintsComplaintIdGetComplaint","parameters":[{"name":"complaint_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Reklamation (`id` aus Anlegen oder Liste). / ID of the complaint (`id` from create or list)."}],"responses":{"200":{"description":"Reklamation mit Positionen, Fotos und Druckvorschau. / Complaint with items, photos and print previews.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintUserDetailResponse"},"example":{"id":4001,"reference":"RK-MUSTER1","order_id":123456,"status":"WAITING_CUSTOMER","comment":"Flecken auf der Vorderseite / Stains on the front","resolution_order_id":null,"cancel_reason":null,"cancelled_by_role":null,"submitted_at":"2026-01-15T10:40:00Z","info_requested_at":"2026-01-16T09:00:00Z","closed_at":null,"created_at":"2026-01-15T10:30:00Z","items":[{"id":5001,"order_item_id":90001,"reason":"STAINS","decision":"NONE","decision_note":null,"replace_variant_id":null,"attachments":[{"id":7001,"complaint_item_id":5001,"content_type":"image/jpeg","size_bytes":482113,"created_at":"2026-01-15T10:35:00Z","url":"https://files.example.com/complaints/7001.jpg?signature=example"}],"preview_urls":["https://files.example.com/previews/90001.png"]}]}}}},"400":{"description":"Ungültige Anfrage (z. B. Parameter außerhalb des erlaubten Bereichs, ungültiger Body). / Invalid request (e.g. parameter out of range or invalid body).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Reklamation, Bestellung, Position oder Foto existiert nicht oder gehört einem anderen Händler; ebenso, wenn die Funktion für dieses Konto nicht verfügbar ist. Nie 403. / Complaint, order, item or photo does not exist or belongs to another merchant; also returned when the feature is not available for this account. Never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"],"description":"Liefert eine Reklamation mit allen Positionen, Fotos und Druckvorschau. Statusverlauf:\n\n| Status | Bedeutung |\n|---|---|\n| `DRAFT` | Entwurf, noch nicht eingereicht |\n| `SUBMITTED` | eingereicht, Positionen gesperrt |\n| `IN_REVIEW` | in Prüfung beim Support |\n| `WAITING_CUSTOMER` | Rückfrage des Supports offen; Antwort über `supplement` |\n| `RESOLVING` | Abschluss läuft |\n| `RESOLVED` | abgeschlossen, Entscheidungen sichtbar |\n| `CANCELLED` | storniert, Positionen wieder frei |\n\nHändler lösen die Wechsel `DRAFT` → `SUBMITTED` (`submit`), `WAITING_CUSTOMER` → `IN_REVIEW` (`supplement`) und `SUBMITTED`/`IN_REVIEW`/`WAITING_CUSTOMER` → `CANCELLED` (`cancel`) aus; alle anderen Wechsel macht der Support. Nach `WAITING_CUSTOMER` nennt `info_requested_at` den Zeitpunkt der Rückfrage; bleibt sie standardmäßig 14 Tage unbeantwortet, wird die Reklamation automatisch storniert (`cancelled_by_role = SYSTEM`).\n\n**Entscheidungen** (`decision`, `decision_note`, `replace_variant_id`) und `resolution_order_id` sind für Händler erst im Status `RESOLVED` sichtbar; vorher steht `decision` auf `NONE`. Foto-`url` und Druckvorschau (`preview_urls`) gelten je Abruf; die Foto-Links laufen nach 15 Minuten ab. `404`, wenn die Reklamation fehlt oder einem anderen Händler gehört.\n\nReturns a complaint with all items, photos and print previews. Status lifecycle: `DRAFT` (not yet submitted) → `SUBMITTED` (items locked) → `IN_REVIEW` (support is reviewing) ↔ `WAITING_CUSTOMER` (follow-up question open) → `RESOLVING` (resolution running) → `RESOLVED`; `CANCELLED` releases the items.\n\nMerchants trigger `DRAFT` → `SUBMITTED` (`submit`), `WAITING_CUSTOMER` → `IN_REVIEW` (`supplement`) and `SUBMITTED`/`IN_REVIEW`/`WAITING_CUSTOMER` → `CANCELLED` (`cancel`); all other transitions are made by support. If a follow-up question stays unanswered for 14 days (default), the complaint is cancelled automatically (`cancelled_by_role = SYSTEM`).\n\n**Decisions** (`decision`, `decision_note`, `replace_variant_id`) and `resolution_order_id` are visible to merchants only in status `RESOLVED`; before that `decision` is `NONE`. Photo `url` values are generated per request and expire after 15 minutes. `404` if the complaint does not exist or belongs to another merchant."}},"/api/complaints/{complaint_id}/attachments/{attachment_id}":{"delete":{"tags":["Complaints"],"summary":"Remove a photo from a complaint draft","operationId":"ApiComplaintsComplaintIdAttachmentsAttachmentIdDeleteComplaintAttachment","parameters":[{"name":"complaint_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Reklamation, aus der das Foto entfernt wird. / ID of the complaint the photo is removed from."},{"name":"attachment_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID des Fotos (`attachments[].id` aus Upload-Antwort oder Reklamation). / ID of the photo (`attachments[].id` from the upload response or the complaint)."}],"responses":{"204":{"description":"Foto entfernt, kein Body. / Photo removed, no body.","headers":{}},"400":{"description":"Ungültige Anfrage (z. B. Parameter außerhalb des erlaubten Bereichs, ungültiger Body). / Invalid request (e.g. parameter out of range or invalid body).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Reklamation, Bestellung, Position oder Foto existiert nicht oder gehört einem anderen Händler; ebenso, wenn die Funktion für dieses Konto nicht verfügbar ist. Nie 403. / Complaint, order, item or photo does not exist or belongs to another merchant; also returned when the feature is not available for this account. Never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}},"409":{"description":"`extra.error = STATUS_CONFLICT`: Fotos lassen sich nur in `DRAFT` entfernen. / `extra.error = STATUS_CONFLICT`: photos can be removed only in `DRAFT`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["merchant_complaint:write"],"description":"Entfernt ein Foto aus einem Entwurf. Nur in `DRAFT` möglich; nach dem Einreichen oder bei einer Rückfrage (`WAITING_CUSTOMER`) lassen sich Fotos nicht mehr entfernen, nur ergänzen. Das entfernte Foto zählt nicht mehr zur Höchstzahl von 5 je Position und erscheint nicht mehr in der Reklamation.\n\nAntwort `204` ohne Body. `409` mit `extra.error = STATUS_CONFLICT`, wenn die Reklamation kein Entwurf mehr ist. `404`, wenn Reklamation oder aktives Foto fehlen oder fremd sind; ein bereits entferntes Foto ergibt ebenfalls `404`.\n\nRemoves a photo from a draft. Possible only in `DRAFT`; once the complaint is submitted, or while a follow-up question is open (`WAITING_CUSTOMER`), photos can no longer be removed, only added. A removed photo no longer counts toward the limit of 5 per item and no longer appears in the complaint.\n\nResponse `204` without body. `409` with `extra.error = STATUS_CONFLICT` if the complaint is no longer a draft. `404` if the complaint or an active photo does not exist or belongs to another merchant; an already removed photo also returns `404`."}},"/api/complaints/{complaint_id}/cancel":{"post":{"tags":["Complaints"],"summary":"Withdraw a complaint","operationId":"ApiComplaintsComplaintIdCancelCancelComplaint","parameters":[{"name":"complaint_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der zurückzuziehenden Reklamation. / ID of the complaint to withdraw."}],"requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ComplaintCancelRequest"},{"type":"null"}]},"example":{"reason":"Problem wurde anderweitig gelöst. / The problem was solved otherwise."}}},"required":true},"responses":{"200":{"description":"Reklamation zurückgezogen (Status `CANCELLED`), Positionen sind wieder frei. / Complaint withdrawn (status `CANCELLED`), items are released again.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintResponse"},"example":{"id":4001,"reference":"RK-MUSTER1","order_id":123456,"status":"CANCELLED","comment":"Flecken auf der Vorderseite / Stains on the front","submitted_at":"2026-01-15T10:40:00Z","created_at":"2026-01-15T10:30:00Z","items":[{"id":5001,"order_item_id":90001,"reason":"STAINS","decision":"NONE","decision_note":null,"attachments":[{"id":7001,"complaint_item_id":5001,"content_type":"image/jpeg","size_bytes":482113,"created_at":"2026-01-15T10:35:00Z"}],"attachment_count":1}]}}}},"400":{"description":"Ungültige Anfrage (z. B. Parameter außerhalb des erlaubten Bereichs, ungültiger Body). / Invalid request (e.g. parameter out of range or invalid body).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Reklamation, Bestellung, Position oder Foto existiert nicht oder gehört einem anderen Händler; ebenso, wenn die Funktion für dieses Konto nicht verfügbar ist. Nie 403. / Complaint, order, item or photo does not exist or belongs to another merchant; also returned when the feature is not available for this account. Never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}},"409":{"description":"`extra.error = STATUS_CONFLICT`: Zurückziehen ist nur in `SUBMITTED`, `IN_REVIEW` und `WAITING_CUSTOMER` möglich, nicht für einen Entwurf, nicht ab `RESOLVING` und nicht doppelt. / `extra.error = STATUS_CONFLICT`: withdrawing is possible only in `SUBMITTED`, `IN_REVIEW` and `WAITING_CUSTOMER`, not for a draft, not from `RESOLVING` on, not twice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["merchant_complaint:write"],"description":"Zieht eine Reklamation zurück (Status `CANCELLED`). Möglich in `SUBMITTED`, `IN_REVIEW` und `WAITING_CUSTOMER`. Alle Positionen werden sofort wieder freigegeben und können erneut reklamiert werden. Eine Wiedereröffnung gibt es nicht. Ein Entwurf wird nicht zurückgezogen, er verfällt von selbst.\n\n`reason` ist optional (höchstens 1000 Zeichen) und wird für den Support festgehalten; der Body darf `{}` sein. In der Antwort steht die Reklamation im Status `CANCELLED`.\n\n`409` mit `extra.error = STATUS_CONFLICT` für einen Entwurf, ab `RESOLVING` (Abschluss läuft oder ist erfolgt) und für eine bereits stornierte Reklamation. `404` bei fremder oder unbekannter Reklamation.\n\nWithdraws a complaint (status `CANCELLED`). Possible in `SUBMITTED`, `IN_REVIEW` and `WAITING_CUSTOMER`. All items are released immediately and can be reported again. A complaint cannot be reopened. A draft is not withdrawn; it expires on its own.\n\n`reason` is optional (up to 1000 characters) and recorded for support; the body may be `{}`. The response shows the complaint in status `CANCELLED`.\n\n`409` with `extra.error = STATUS_CONFLICT` for a draft, from `RESOLVING` on (resolution running or done) and for an already cancelled complaint. `404` for an unknown or foreign complaint."}},"/api/complaints/{complaint_id}/items/{item_id}/attachments":{"post":{"tags":["Complaints"],"summary":"Attach a photo to a complaint item","operationId":"ApiComplaintsComplaintIdItemsItemIdAttachmentsUploadComplaintAttachment","parameters":[{"name":"complaint_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Reklamation (`id` aus der Antwort von `POST /api/complaints`). / ID of the complaint (`id` from the response of `POST /api/complaints`)."},{"name":"item_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Reklamationsposition (`items[].id` der Reklamation), nicht die `order_item_id`. / ID of the complaint item (`items[].id` of the complaint), not the `order_item_id`."}],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"file":{"type":"string","format":"binary","contentMediaType":"application/octet-stream"}},"type":"object"}}},"required":true},"responses":{"201":{"description":"Foto angehängt. / Photo attached.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintAttachmentResponse"},"example":{"id":7001,"complaint_item_id":5001,"content_type":"image/jpeg","size_bytes":482113,"created_at":"2026-01-15T10:35:00Z"}}}},"400":{"description":"`extra.error` = `FILE_TOO_LARGE` (über 10 MB), `TOO_MANY_ATTACHMENTS` (5 aktive Fotos je Position) oder `INVALID_FILE_TYPE` (Inhalt ist kein JPEG, PNG, WebP oder HEIC). / `extra.error` = `FILE_TOO_LARGE` (over 10 MB), `TOO_MANY_ATTACHMENTS` (5 active photos per item) or `INVALID_FILE_TYPE` (content is not JPEG, PNG, WebP or HEIC).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}},"404":{"description":"Reklamation, Bestellung, Position oder Foto existiert nicht oder gehört einem anderen Händler; ebenso, wenn die Funktion für dieses Konto nicht verfügbar ist. Nie 403. / Complaint, order, item or photo does not exist or belongs to another merchant; also returned when the feature is not available for this account. Never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}},"409":{"description":"`extra.error = STATUS_CONFLICT`: Fotos lassen sich nur in `DRAFT` und `WAITING_CUSTOMER` anhängen. / `extra.error = STATUS_CONFLICT`: photos can be added only in `DRAFT` and `WAITING_CUSTOMER`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["merchant_complaint:write"],"description":"Hängt **ein** Foto an eine Position der Reklamation. Request als `multipart/form-data` mit dem Feld `file`; genau eine Datei je Aufruf.\n\n- Erlaubte Typen: JPEG, PNG, WebP, HEIC. Der Typ wird am Dateiinhalt geprüft, nicht am Dateinamen.\n- Höchstgröße 10 MB je Datei; höchstens 5 aktive Fotos je Position.\n- Statusabhängig: nur in `DRAFT` und `WAITING_CUSTOMER` (Rückfrage des Supports). Ein Upload in `WAITING_CUSTOMER` ändert den Status nicht; erst `POST /api/complaints/{complaint_id}/supplement` beantwortet die Rückfrage.\n- Das Foto wird privat abgelegt; abrufbare Links liefert `GET /api/complaints/{complaint_id}`.\n\nFehler: `400` mit `extra.error` = `FILE_TOO_LARGE`, `TOO_MANY_ATTACHMENTS` oder `INVALID_FILE_TYPE`; `409` mit `STATUS_CONFLICT` in jedem anderen Status; `404`, wenn Reklamation oder Position fehlen, fremd sind oder die Position nicht zu dieser Reklamation gehört.\n\nAttaches **one** photo to an item of the complaint. Send `multipart/form-data` with the field `file`; exactly one file per request.\n\nAllowed types: JPEG, PNG, WebP, HEIC, checked on the file content, not the file name. Maximum 10 MB per file and 5 active photos per item. Allowed only in `DRAFT` and `WAITING_CUSTOMER` (follow-up question from support); an upload in `WAITING_CUSTOMER` does not change the status, only `POST /api/complaints/{complaint_id}/supplement` answers the question. The photo is stored privately; time-limited links are returned by `GET /api/complaints/{complaint_id}`.\n\nErrors: `400` with `extra.error` = `FILE_TOO_LARGE`, `TOO_MANY_ATTACHMENTS` or `INVALID_FILE_TYPE`; `409` `STATUS_CONFLICT` in any other status; `404` if the complaint or item does not exist, belongs to another merchant, or the item is not part of this complaint."}},"/api/complaints/{complaint_id}/submit":{"post":{"tags":["Complaints"],"summary":"Submit a complaint","operationId":"ApiComplaintsComplaintIdSubmitSubmitComplaint","parameters":[{"name":"complaint_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID des einzureichenden Entwurfs. / ID of the draft to submit."}],"responses":{"200":{"description":"Reklamation eingereicht (Status `SUBMITTED`). / Complaint submitted (status `SUBMITTED`).","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintResponse"},"example":{"id":4001,"reference":"RK-MUSTER1","order_id":123456,"status":"SUBMITTED","comment":"Flecken auf der Vorderseite / Stains on the front","submitted_at":"2026-01-15T10:40:00Z","created_at":"2026-01-15T10:30:00Z","items":[{"id":5001,"order_item_id":90001,"reason":"STAINS","decision":"NONE","decision_note":null,"attachments":[{"id":7001,"complaint_item_id":5001,"content_type":"image/jpeg","size_bytes":482113,"created_at":"2026-01-15T10:35:00Z"}],"attachment_count":1}]}}}},"400":{"description":"`extra.error = PHOTO_REQUIRED`: jede Position braucht ein Foto, außer ihr Grund ist `PRODUCT_MISSING`; `extra.complaint_item_ids` nennt die betroffenen Positionen. / `extra.error = PHOTO_REQUIRED`: every item needs a photo unless its reason is `PRODUCT_MISSING`; `extra.complaint_item_ids` names the items.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}},"404":{"description":"Reklamation, Bestellung, Position oder Foto existiert nicht oder gehört einem anderen Händler; ebenso, wenn die Funktion für dieses Konto nicht verfügbar ist. Nie 403. / Complaint, order, item or photo does not exist or belongs to another merchant; also returned when the feature is not available for this account. Never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}},"409":{"description":"`extra.error` = `STATUS_CONFLICT` (kein Entwurf mehr), `ITEM_ALREADY_REPORTED` (eine andere Reklamation sperrt eine Position, auch bei gleichzeitigem Einreichen) oder ein Sperrgrund wie beim Anlegen (`extra.items`). / `extra.error` = `STATUS_CONFLICT` (no longer a draft), `ITEM_ALREADY_REPORTED` (another complaint locks an item, also on concurrent submit) or a block code as for creation (`extra.items`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["merchant_complaint:write"],"description":"Reicht einen Entwurf ein (`DRAFT` → `SUBMITTED`). Beim Einreichen gilt:\n\n- **Fotopflicht:** jede Position braucht mindestens ein Foto, außer ihr Grund ist `PRODUCT_MISSING`. Sonst `400` mit `extra.error = PHOTO_REQUIRED` und den betroffenen `extra.complaint_item_ids`.\n- **Erneute Prüfung der Reklamierbarkeit** wie beim Anlegen; ist inzwischen eine Position gesperrt, kommt `409` mit dem Sperrgrund und `extra.items`.\n- **Sperre:** die Positionen sind danach für weitere Reklamationen gesperrt (`ITEM_ALREADY_REPORTED`), (die Sperre endet beim Stornieren, siehe `POST /api/complaints/{complaint_id}/cancel`). Meldet parallel eine andere Reklamation dieselbe Position, scheitert eine der beiden mit `409` `ITEM_ALREADY_REPORTED`.\n- Der Support-Vorgang zur Reklamation wird erst nach dem Einreichen asynchron angelegt.\n\nWeitere Fehler: `409` mit `STATUS_CONFLICT`, wenn die Reklamation kein Entwurf (mehr) ist, also auch bei erneutem Einreichen; `404` bei fremder oder unbekannter Reklamation. Entscheidungen des Supports erscheinen in der Antwort erst im Status `RESOLVED`.\n\nSubmits a draft (`DRAFT` → `SUBMITTED`). On submit: every item needs at least one photo unless its reason is `PRODUCT_MISSING` (otherwise `400` `PHOTO_REQUIRED` with `extra.complaint_item_ids`); eligibility is checked again (`409` with the block code and `extra.items` if an item became ineligible); the items are then locked against further complaints (the lock ends when the complaint is cancelled). If another complaint reports the same item concurrently, one of the two fails with `409` `ITEM_ALREADY_REPORTED`. The support case for the complaint is created asynchronously after submission.\n\nOther errors: `409` `STATUS_CONFLICT` if the complaint is not a draft (including a repeated submit); `404` for an unknown or foreign complaint. Decisions of support appear in the response only in status `RESOLVED`."}},"/api/complaints/{complaint_id}/supplement":{"post":{"tags":["Complaints"],"summary":"Answer a complaint follow-up question","operationId":"ApiComplaintsComplaintIdSupplementSupplementComplaint","parameters":[{"name":"complaint_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Reklamation, die auf eine Rückfrage wartet. / ID of the complaint awaiting an answer."}],"requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ComplaintSupplementRequest"},{"type":"null"}]},"example":{"text":"Weitere Fotos vom Etikett wurden hochgeladen. / Further photos of the label were uploaded."}}},"required":true},"responses":{"200":{"description":"Rückfrage beantwortet (Status `IN_REVIEW`). / Follow-up question answered (status `IN_REVIEW`).","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintResponse"},"example":{"id":4001,"reference":"RK-MUSTER1","order_id":123456,"status":"IN_REVIEW","comment":"Flecken auf der Vorderseite / Stains on the front","submitted_at":"2026-01-15T10:40:00Z","created_at":"2026-01-15T10:30:00Z","items":[{"id":5001,"order_item_id":90001,"reason":"STAINS","decision":"NONE","decision_note":null,"attachments":[{"id":7001,"complaint_item_id":5001,"content_type":"image/jpeg","size_bytes":482113,"created_at":"2026-01-15T10:35:00Z"}],"attachment_count":1}]}}}},"400":{"description":"Ungültige Anfrage (z. B. Parameter außerhalb des erlaubten Bereichs, ungültiger Body). / Invalid request (e.g. parameter out of range or invalid body).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Reklamation, Bestellung, Position oder Foto existiert nicht oder gehört einem anderen Händler; ebenso, wenn die Funktion für dieses Konto nicht verfügbar ist. Nie 403. / Complaint, order, item or photo does not exist or belongs to another merchant; also returned when the feature is not available for this account. Never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}},"409":{"description":"`extra.error = STATUS_CONFLICT`: Ergänzen ist nur in `WAITING_CUSTOMER` möglich. / `extra.error = STATUS_CONFLICT`: a supplement is possible only in `WAITING_CUSTOMER`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["merchant_complaint:write"],"description":"Beantwortet eine Rückfrage des Supports: `WAITING_CUSTOMER` → `IN_REVIEW`. Fotos vorher über den Upload-Endpunkt hochladen; der Upload allein ändert den Status nicht. Der Text ist optional (höchstens 5000 Zeichen) und geht an den Support; der Body darf `{}` sein.\n\n`409` mit `extra.error = STATUS_CONFLICT` in jedem anderen Status als `WAITING_CUSTOMER`, auch bei einer zweiten Antwort. `404` bei fremder oder unbekannter Reklamation. Entscheidungen des Supports erscheinen in der Antwort erst im Status `RESOLVED`.\n\nAnswers a follow-up question from support: `WAITING_CUSTOMER` → `IN_REVIEW`. Upload photos first via the upload endpoint; an upload alone does not change the status. The text is optional (up to 5000 characters) and is passed to support; the body may be `{}`.\n\n`409` with `extra.error = STATUS_CONFLICT` in any status other than `WAITING_CUSTOMER`, including a second answer. `404` for an unknown or foreign complaint. Decisions of support appear in the response only in status `RESOLVED`."}},"/api/invoices/by-order/{order_id}":{"get":{"tags":["Invoices"],"summary":"List invoices and credit notes of an order","operationId":"ApiInvoicesByOrderOrderIdGetInvoicesByOrder","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Bestellung, deren Belege aufgelistet werden. Fremde oder unbekannte IDs liefern 404. / ID of the order whose documents are listed. Foreign or unknown IDs return 404."},{"name":"limit","in":"query","schema":{"type":"integer","default":20},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Maximale Anzahl Einträge pro Seite, Standard 20; Werte werden auf 1 bis 100 begrenzt. / Maximum number of entries per page, default 20; values are clamped to 1 to 100."},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anzahl der zu überspringenden Einträge, Standard 0; negative Werte werden zu 0. / Number of entries to skip, default 0; negative values become 0."}],"responses":{"200":{"description":"Belege der Bestellung, neueste zuerst; leeres Array ohne Belege. / Documents of the order, newest first; empty array if none.","headers":{},"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/InvoiceUserListResponse"},"type":"array"},"example":[{"id":4712,"invoice_number":"GS-2026-00001","invoice_type":"CREDIT_NOTE","invoice_date":"2026-01-20","order_id":98765,"original_invoice_id":4711,"net_amount":-4200,"tax_amount":-798,"gross_amount":-4998,"vat_rate":19,"delivery_date":"2026-01-14","currency_code":"EUR","credit_note_reason":"Retoure der gesamten Bestellung","created_at":"2026-01-20T08:15:00Z"},{"id":4711,"invoice_number":"RE-2026-00001","invoice_type":"INVOICE","invoice_date":"2026-01-15","order_id":98765,"original_invoice_id":null,"net_amount":4200,"tax_amount":798,"gross_amount":4998,"vat_rate":19,"delivery_date":"2026-01-14","currency_code":"EUR","credit_note_reason":null,"created_at":"2026-01-15T10:30:00Z"}]}}},"400":{"description":"Ungültige Anfrage, z. B. fehlerhafte Parameterwerte. / Invalid request, e.g. malformed parameter values.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Bestellung nicht gefunden oder gehört nicht dem Händler. / Order not found or not owned by the merchant.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_invoice:read"],"description":"Liefert alle Rechnungen und Gutschriften einer Bestellung des Händlers als Liste. Die Bestellung muss dem Händler gehören; bei fremden oder unbekannten Bestellungen antwortet die API mit `404`, nie mit `403`.\n\nDie Liste ist nach Erstellungszeitpunkt absteigend sortiert (neueste zuerst), bei gleichem Zeitpunkt nach `id` absteigend. `limit` wird auf 1 bis 100 begrenzt, `offset` auf mindestens 0; Werte außerhalb werden angepasst und nicht abgelehnt. Die Antwort ist ein reines Array ohne Gesamtzahl; die Liste ist zu Ende, wenn weniger Einträge als `limit` zurückkommen. Eine Bestellung ohne Belege liefert ein leeres Array. Die PDF-Datei eines Belegs liefert `GET /api/invoices/user/{invoice_id}/pdf`.\n\nErforderlicher Scope: `merchant_invoice:read`.\n\nReturns all invoices and credit notes of one of the merchant's orders as an array. The order must belong to the merchant; for foreign or unknown orders the API responds with `404`, never `403`.\n\nThe list is sorted by creation time, newest first, with `id` descending as tie-breaker. `limit` is clamped to 1 to 100 and `offset` to at least 0; out-of-range values are adjusted, not rejected. The response is a plain array without a total count; the list is exhausted when fewer than `limit` entries come back. An order without documents returns an empty array. Use `GET /api/invoices/user/{invoice_id}/pdf` to obtain the PDF file of a document.\n\nRequired scope: `merchant_invoice:read`."}},"/api/invoices/user":{"get":{"tags":["Invoices"],"summary":"List invoices and credit notes","operationId":"ApiInvoicesUserGetUserInvoices","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":20},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Maximale Anzahl Einträge pro Seite, Standard 20; Werte werden auf 1 bis 100 begrenzt. / Maximum number of entries per page, default 20; values are clamped to 1 to 100."},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anzahl der zu überspringenden Einträge, Standard 0; negative Werte werden zu 0. / Number of entries to skip, default 0; negative values become 0."},{"name":"invoice_type","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/InvoiceType"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Nur Belege dieser Art (`INVOICE`, `CREDIT_NOTE` oder `BONUS_CREDIT`); ohne Angabe alle Arten. / Only documents of this type (`INVOICE`, `CREDIT_NOTE` or `BONUS_CREDIT`); all types if omitted."},{"name":"date_from","in":"query","schema":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Frühestes Belegdatum (`invoice_date`), inklusive, Format `YYYY-MM-DD`; ohne Angabe keine untere Grenze. / Earliest document date (`invoice_date`), inclusive, format `YYYY-MM-DD`; no lower bound if omitted."},{"name":"date_to","in":"query","schema":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Spätestes Belegdatum (`invoice_date`), inklusive, Format `YYYY-MM-DD`; ohne Angabe keine obere Grenze. / Latest document date (`invoice_date`), inclusive, format `YYYY-MM-DD`; no upper bound if omitted."},{"name":"amount_min","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":2147483647,"minimum":-2147483648},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Kleinster Bruttobetrag (`gross_amount`) in Cent, inklusive; Gutschriften sind negativ. Ganzzahl im 32-Bit-Bereich. / Smallest gross amount (`gross_amount`) in cents, inclusive; credit notes are negative. Integer within the 32-bit range."},{"name":"amount_max","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":2147483647,"minimum":-2147483648},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Größter Bruttobetrag (`gross_amount`) in Cent, inklusive; Gutschriften sind negativ. Ganzzahl im 32-Bit-Bereich. / Largest gross amount (`gross_amount`) in cents, inclusive; credit notes are negative. Integer within the 32-bit range."}],"responses":{"200":{"description":"Seite der Belegliste mit Gesamtzahl der Treffer. / Page of the document list with the total match count.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceUserPageResponse"},"example":{"items":[{"id":4712,"invoice_number":"GS-2026-00001","invoice_type":"CREDIT_NOTE","invoice_date":"2026-01-20","order_id":98765,"original_invoice_id":4711,"net_amount":-4200,"tax_amount":-798,"gross_amount":-4998,"vat_rate":19,"delivery_date":"2026-01-14","currency_code":"EUR","credit_note_reason":"Retoure der gesamten Bestellung","created_at":"2026-01-20T08:15:00Z"},{"id":4711,"invoice_number":"RE-2026-00001","invoice_type":"INVOICE","invoice_date":"2026-01-15","order_id":98765,"original_invoice_id":null,"net_amount":4200,"tax_amount":798,"gross_amount":4998,"vat_rate":19,"delivery_date":"2026-01-14","currency_code":"EUR","credit_note_reason":null,"created_at":"2026-01-15T10:30:00Z"}],"limit":20,"offset":0,"total_count":2}}}},"400":{"description":"Ungültige Anfrage, z. B. fehlerhafte Parameterwerte. / Invalid request, e.g. malformed parameter values.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}}},"deprecated":false,"x-customer-scopes":["merchant_invoice:read"],"description":"Liefert eine seitenweise Liste aller Rechnungen und Gutschriften des Händlers über alle Bestellungen hinweg. Der Händler ergibt sich ausschließlich aus dem Zugangstoken; ein Parameter dafür existiert nicht.\n\nSortierung: Erstellungszeitpunkt absteigend (neueste zuerst), bei gleichem Zeitpunkt `id` absteigend. `limit` wird auf 1 bis 100 begrenzt, `offset` auf mindestens 0; Werte außerhalb werden angepasst und nicht abgelehnt. `total_count` nennt die Gesamtzahl der Treffer nach Anwendung der Filter, unabhängig von `limit` und `offset`.\n\nFilter (alle optional, miteinander kombinierbar): `invoice_type` filtert nach Belegart, `date_from` und `date_to` begrenzen das Belegdatum (`invoice_date`) inklusive beider Grenzen, `amount_min` und `amount_max` begrenzen den Bruttobetrag (`gross_amount`) in Cent inklusive beider Grenzen. Gutschriften tragen negative Beträge. Ungültige Filterwerte liefern `400`.\n\nDie PDF-Datei eines Belegs liefert `GET /api/invoices/user/{invoice_id}/pdf`. Erforderlicher Scope: `merchant_invoice:read`.\n\nReturns a paginated list of all invoices and credit notes of the merchant across all orders. The merchant is derived solely from the access token; there is no parameter for it.\n\nSorting: creation time descending (newest first), with `id` descending as tie-breaker. `limit` is clamped to 1 to 100 and `offset` to at least 0; out-of-range values are adjusted, not rejected. `total_count` is the total number of matches after applying the filters, independent of `limit` and `offset`.\n\nFilters (all optional, combinable): `invoice_type` filters by document type, `date_from` and `date_to` bound the document date (`invoice_date`) inclusively, `amount_min` and `amount_max` bound the gross amount (`gross_amount`) in cents inclusively. Credit notes carry negative amounts. Invalid filter values return `400`.\n\nUse `GET /api/invoices/user/{invoice_id}/pdf` to obtain the PDF file of a document. Required scope: `merchant_invoice:read`."}},"/api/invoices/user/{invoice_id}/pdf":{"get":{"tags":["Invoices"],"summary":"Get the PDF URL of an invoice","operationId":"ApiInvoicesUserInvoiceIdPdfGetUserInvoicePdf","parameters":[{"name":"invoice_id","in":"path","schema":{"type":"integer","maximum":2147483647.0,"minimum":1.0},"required":true,"deprecated":false,"description":"ID des Belegs (Rechnung oder Gutschrift), wie `id` in der Belegliste; Ganzzahl von 1 bis 2147483647, sonst 400. Fremde oder unbekannte IDs liefern 404. / ID of the document (invoice or credit note), as `id` in the document list; integer from 1 to 2147483647, otherwise 400. Foreign or unknown IDs return 404."}],"responses":{"200":{"description":"PDF liegt vor (`status` `ready`, `pdf_url` gesetzt) oder wird nicht mehr erzeugt (`status` `failed`, `pdf_url` `null`). / PDF is available (`status` `ready`, `pdf_url` set) or will not be generated anymore (`status` `failed`, `pdf_url` `null`).","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoicePdfResponse"},"example":{"pdf_url":"https://files.example.com/invoices/RE-2026-00001.pdf?signature=beispiel","status":"ready"}}}},"400":{"description":"Ungültige Anfrage, z. B. `invoice_id` außerhalb von 1 bis 2147483647. / Invalid request, e.g. `invoice_id` outside 1 to 2147483647.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"202":{"description":"PDF wird erzeugt (`status` `generating`, `pdf_url` `null`); denselben Aufruf später wiederholen. / PDF is being generated (`status` `generating`, `pdf_url` `null`); repeat the same call later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoicePdfResponse"}}}},"404":{"description":"Beleg nicht gefunden oder gehört nicht dem Händler. / Document not found or not owned by the merchant.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_invoice:read"],"description":"Liefert die Download-URL der PDF eines Belegs des Händlers. Rechnungs-PDFs werden erst beim ersten Abruf im Hintergrund erzeugt; der Aufruf kann deshalb statt der URL einen Zwischenstand melden. Die Antwort unterscheidet drei Fälle über `status` und den HTTP-Statuscode:\n\n| Fall | HTTP | `status` | `pdf_url` |\n|---|---|---|---|\n| PDF liegt vor | `200` | `ready` | signierte URL |\n| PDF wird erzeugt | `202` | `generating` | `null` |\n| PDF kommt nicht mehr | `200` | `failed` | `null` |\n\n`failed` kommt mit `200`, nicht mit `202` und nicht als Fehler: Wer nur auf den HTTP-Statuscode prüft, muss diesen Fall zusätzlich über `status` erkennen.\n\n**Abrufverhalten (Polling):** Solange `202` mit `generating` kommt, denselben Aufruf wiederholen. Der erste Abruf stößt die Erzeugung an. Weitere Abrufe innerhalb von 5 Minuten nach einem Anstoß stoßen sie nicht erneut an. Nach Ablauf dieses Fensters ohne fertige PDF wird die Erzeugung erneut angestoßen, insgesamt höchstens 3-mal. `failed` meldet die API erst, wenn 3 Anstöße erfolgt sind und das Fenster des letzten Anstoßes abgelaufen ist, also frühestens etwa 15 Minuten nach dem ersten Abruf. Eine gerade angefragte Rechnung meldet `generating`, auch wenn sie am Ende scheitert. Bei `failed` stößt ein weiterer Abruf nichts mehr an. Eine bereits vorhandene PDF wird immer als `ready` geliefert, auch nach der dritten Erzeugung.\n\nDie URL in `pdf_url` ist signiert und 15 Minuten gültig. Nach Ablauf mit einem neuen Aufruf eine frische URL holen. Der Beleg muss dem Händler gehören; bei fremden oder unbekannten IDs antwortet die API mit `404`, nie mit `403`. Erforderlicher Scope: `merchant_invoice:read`.\n\nReturns the download URL of the PDF of one of the merchant's documents. Invoice PDFs are generated in the background on first request, so the call may report an intermediate state instead of the URL. The response distinguishes three cases via `status` and the HTTP status code (see the table above).\n\n`failed` is returned with `200`, not `202` and not as an error: clients that branch only on the HTTP status code must also detect this case through `status`.\n\n**Polling behavior:** While `202` with `generating` is returned, repeat the same call. The first request triggers generation. Further requests within 5 minutes of a trigger do not trigger it again. Once that window has passed without a finished PDF, generation is triggered again, at most 3 times in total. The API reports `failed` only after 3 triggers have happened and the window of the last trigger has elapsed, i.e. roughly 15 minutes after the first request at the earliest. A freshly requested invoice reports `generating` even if it will eventually fail. After `failed`, further requests trigger nothing. An existing PDF is always returned as `ready`, even after the third generation.\n\nThe URL in `pdf_url` is signed and valid for 15 minutes. After it expires, call again to get a fresh URL. The document must belong to the merchant; for foreign or unknown IDs the API responds with `404`, never `403`. Required scope: `merchant_invoice:read`."}},"/api/orders":{"get":{"tags":["Orders"],"summary":"List orders","operationId":"ApiOrdersListOrders","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Seitengröße; Werte außerhalb von 1 bis 200 werden auf diesen Bereich begrenzt. Die Antwort nennt den angewendeten Wert. / Page size; values outside 1 to 200 are clamped to that range. The response reports the applied value."},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anzahl der zu überspringenden Treffer; negative Werte gelten als 0. / Number of matches to skip; negative values are treated as 0."},{"name":"designer_id","in":"query","schema":{"oneOf":[{"type":"string"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Filter auf die Händlerkennung der Bestellung (exakter Treffer). Für Händler ist das die eigene Kennung; jeder andere Wert liefert eine leere Liste. / Filter on the merchant identifier of the order (exact match). For merchants this is the own identifier; any other value returns an empty list."},{"name":"platform_key","in":"query","schema":{"oneOf":[{"type":"string"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Filter auf die Herkunftsplattform der Bestellung (exakter Treffer, Text). / Filter on the originating platform of the order (exact match, text)."},{"name":"status","in":"query","schema":{"oneOf":[{"items":{"$ref":"#/components/schemas/OrderStatus"},"type":"array"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Filter auf einen oder mehrere Bestellstatus (`OrderStatus`); Parameter wiederholen, mehrere Werte gelten als ODER. / Filter on one or more order statuses (`OrderStatus`); repeat the parameter, several values combine with OR."},{"name":"retention_reason_id","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Filter auf einen Rückhaltegrund (ID aus `GET /api/orders/retention-reasons`); nur Bestellungen, die aus diesem Grund angehalten sind. / Filter on one retention reason (ID from `GET /api/orders/retention-reasons`); only orders held for that reason."},{"name":"retention_reason_ids","in":"query","schema":{"oneOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Filter auf mehrere Rückhaltegründe (IDs); Parameter wiederholen, mehrere Werte gelten als ODER. Zusammen mit `retention_reason_id` müssen beide Bedingungen erfüllt sein. / Filter on several retention reasons (IDs); repeat the parameter, several values combine with OR. Combined with `retention_reason_id`, both conditions must hold."},{"name":"routing_causes","in":"query","schema":{"oneOf":[{"items":{"$ref":"#/components/schemas/RoutingCause"},"type":"array"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Filter auf Ursachen, aus denen einer Bestellung noch kein Produktionspartner zugewiesen werden konnte (`RoutingCause`); wiederholbar, ODER. Wirkt nur auf Bestellungen im Status `CHECK` oder `ERROR`. / Filter on causes why no production partner could be assigned to an order yet (`RoutingCause`); repeatable, OR. Only matches orders in status `CHECK` or `ERROR`."},{"name":"mockup_gap_reasons","in":"query","schema":{"oneOf":[{"items":{"$ref":"#/components/schemas/MockupGapReason"},"type":"array"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Filter auf Gründe, aus denen für mindestens eine Druckposition der Bestellung kein eigenes Vorschaubild (Mockup) entstanden ist (`MockupGapReason`); wiederholbar, ODER. / Filter on reasons why at least one print position of the order has no own preview image (mockup) (`MockupGapReason`); repeatable, OR."},{"name":"manufacturer_id","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Filter auf Bestellungen, die mindestens einen Fertigungsauftrag bei dem Produktionspartner mit dieser ID haben. / Filter on orders with at least one manufacturing order at the production partner with this ID."},{"name":"reordered_from_order_id","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Umkehrsuche zur Nachbestellung: nur Bestellungen, die per `POST /api/orders/{order_id}/reorder` aus der Bestellung mit dieser ID entstanden sind. / Reverse lookup for re-orders: only orders created via `POST /api/orders/{order_id}/reorder` from the order with this ID."},{"name":"supplier_stock_issue","in":"query","schema":{"oneOf":[{"items":{"$ref":"#/components/schemas/SupplierStockIssue"},"type":"array"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händler; der Wert wird ignoriert. / Has no effect for merchants; the value is ignored."},{"name":"subscribed_by_me","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händler; der Wert wird ignoriert. / Has no effect for merchants; the value is ignored."},{"name":"backlog_bucket","in":"query","schema":{"oneOf":[{"type":"string"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händler; der Wert wird ignoriert und nicht geprüft. / Has no effect for merchants; the value is ignored and not validated."},{"name":"express","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händler; der Wert wird ignoriert. / Has no effect for merchants; the value is ignored."},{"name":"sort","in":"query","schema":{"oneOf":[{"type":"string"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Sortierung nach Eingangszeitpunkt: `created_at:asc` oder `created_at:desc` (Standard). Jeder andere Wert ergibt 400. Bei gleichem Zeitpunkt folgt die Bestell-ID in derselben Richtung. / Sort by creation time: `created_at:asc` or `created_at:desc` (default). Any other value returns 400. For equal timestamps, the order ID follows in the same direction."}],"responses":{"200":{"description":"Seite mit Bestellungen des Händlers, eventuell leer. / Page of the merchant orders, possibly empty.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserPageResponse"},"example":{"items":[{"id":900002,"slug":"CL-8M2QX4A","internal_reference":null,"external_reference":"SHOP-10046","reordered_from_order_id":null,"designer_id":"4711","status":"CHECK","created_at":"2026-01-16T09:12:00Z","updated_at":"2026-01-16T09:12:30Z","retention":{"reason_id":7,"reason_name":"Fehler - Adresse"}},{"id":900001,"slug":"CL-7K3M9QX","internal_reference":null,"external_reference":"SHOP-10045","reordered_from_order_id":null,"designer_id":"4711","status":"TRANSFERRED","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T14:05:00Z","retention":null}],"limit":50,"offset":0,"total_count":2}}}},"400":{"description":"Ungültiger Filterwert (z. B. unbekannter Status) oder ungültiges `sort`. Korrigieren und erneut senden. / Invalid filter value (e.g. unknown status) or invalid `sort`. Correct it and resend.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"],"description":"Liefert die Bestellungen des authentifizierten Händlers seitenweise (Scope `merchant_order:read`). Fremde Bestellungen sind nie enthalten, auch nicht über `designer_id`. Ohne Filter werden alle Status geliefert, auch `CANCELED`. Standardsortierung: Eingangszeitpunkt absteigend (neueste zuerst), Standard-Seitengröße 50, maximal 200.\n\nAlle Filter gelten gleichzeitig (UND). Mehrwertige Filter (`status`, `retention_reason_ids`, `routing_causes`, `mockup_gap_reasons`) werden durch Wiederholen des Parameters angegeben, z. B. `status=CHECK&status=ERROR`; mehrere Werte desselben Parameters gelten als ODER. Ungültige Werte dieser Filter und ein ungültiges `sort` ergeben 400. Die Parameter `supplier_stock_issue`, `subscribed_by_me`, `backlog_bucket` und `express` haben für Händler keine Wirkung. Die Einträge enthalten die Kopfdaten der Bestellung ohne Positionen; Positionen, Sendungsverfolgung und Zahlungsangaben liefert `GET /api/orders/{order_id}`. `total_count` ist die Trefferzahl vor der Seitenbildung.\n\nReturns the orders of the authenticated merchant, paginated (scope `merchant_order:read`). Orders of other merchants are never included, not even via `designer_id`. Without filters, all statuses are returned, including `CANCELED`. Default sort: creation time descending (newest first), default page size 50, maximum 200.\n\nAll filters apply together (AND). Multi-value filters (`status`, `retention_reason_ids`, `routing_causes`, `mockup_gap_reasons`) are passed by repeating the parameter, e.g. `status=CHECK&status=ERROR`; several values of one parameter combine with OR. Invalid values of these filters and an invalid `sort` return 400. The parameters `supplier_stock_issue`, `subscribed_by_me`, `backlog_bucket` and `express` have no effect for merchants. Entries contain the order header without line items; line items, shipment tracking and payment data are returned by `GET /api/orders/{order_id}`. `total_count` is the number of matches before pagination."},"post":{"tags":["Orders"],"summary":"Create an order","description":"Legt eine Bestellung für den authentifizierten Händler an (Scope `merchant_order:create` oder `merchant_order:write`). Erlaubt sind nur die im Request-Schema genannten Felder. Preise, Versandart, Hersteller-Wahl, Zahlungs- und Steuerangaben sind nicht Teil des Requests: Preise stammen aus dem Katalog, alles Übrige legt das System fest. Wird ein anderes Feld gesendet, auch verschachtelt in Positionen oder Veredelungen, antwortet die API mit 403 und nennt die Feldpfade; eine `designer_id` im Body muss der eigenen Kennung entsprechen. Ohne `external_reference` vergibt das System eine eigene. Eine Position mit `amount` n wird als n einzelne Stücke angelegt. Veredelungen werden nur bei veredelbaren Artikeln übernommen; ist für den Artikel genau ein Veredelungsverfahren hinterlegt und weicht die Angabe ab, wird das hinterlegte verwendet. Mit `POST /api/orders/preview` lässt sich der Entwurf vorab prüfen.\n\nDie Antwort (201) enthält die Bestellung im Status direkt nach der Anlage. Normalerweise ist das `PENDING`, die Verarbeitung (Zuweisung, Produktion) startet danach automatisch. Je nach Prüfergebnis kann der Status stattdessen `PAUSE` (kurze Wartezeit vor der Zuweisung), `CHECK` oder `ERROR` sein; dann nennt `retention` den Grund. Beispiele sind eine inaktive Variante oder kein verfügbarer Produktionspartner (`CHECK`) sowie fehlende Preise (`ERROR`). Diese Fälle sind kein HTTP-Fehler: die Bestellung existiert. Als Fehler antwortet die API mit 400 bei unbekannter oder mehrdeutiger SKU, nicht konfiguriertem Veredelungsverfahren und bei einer SKU in `additional_products`, die kein Zusatzprodukt ist; mit 422 bei ungültigem Body.\n\nMit dem optionalen Header `Idempotency-Key` ist der Aufruf wiederholbar: Derselbe Schlüssel mit demselben Body liefert die beim ersten Aufruf angelegte Bestellung erneut (201, gleicher Inhalt) und legt keine zweite an. Derselbe Schlüssel mit anderem Body ergibt 422 mit `extra.error=IDEMPOTENCY_KEY_REUSED`. Der Schlüssel gilt je Händler; parallele Wiederholungen warten auf den ersten Aufruf. Ohne Header legt jeder Aufruf eine neue Bestellung an.\n\nCreates an order for the authenticated merchant (scope `merchant_order:create` or `merchant_order:write`). Only the fields named in the request schema are allowed. Prices, shipping method, manufacturer choice, payment and tax data are not part of the request: prices come from the catalog, everything else is set by the system. If any other field is sent, also nested in items or processings, the API responds with 403 and names the field paths; a `designer_id` in the body must match the own identifier. Without `external_reference` the system assigns one. An item with `amount` n is created as n single pieces. Processings are only taken over for articles that can be finished; if the article has exactly one stored processing method and the value sent differs, the stored one is used. Use `POST /api/orders/preview` to check the draft beforehand.\n\nThe response (201) contains the order in the status right after creation. Normally this is `PENDING`, and processing (assignment, production) starts automatically afterwards. Depending on the checks, the status can instead be `PAUSE` (short wait before assignment), `CHECK` or `ERROR`; then `retention` names the reason. Examples are an inactive variant or no available production partner (`CHECK`) and missing prices (`ERROR`). These cases are not HTTP errors: the order exists. The API responds with 400 for an unknown or ambiguous SKU, an unconfigured processing method and a SKU in `additional_products` that is not an additional product; with 422 for an invalid body.\n\nWith the optional `Idempotency-Key` header the call is repeatable: the same key with the same body returns the order created by the first call again (201, same content) and does not create a second one. The same key with a different body returns 422 with `extra.error=IDEMPOTENCY_KEY_REUSED`. The key is scoped per merchant; concurrent retries wait for the first call. Without the header every call creates a new order.","operationId":"ApiOrdersCreateOrder","parameters":[{"name":"Idempotency-Key","in":"header","schema":{"oneOf":[{"type":"string"},{"type":"null"}],"pattern":"^[!-~]{1,128}$"},"description":"Optional. 1 bis 128 sichtbare ASCII-Zeichen (z. B. eine UUID). Wiederholung mit demselben Schlüssel und Body liefert die erste Bestellung erneut; anderer Body ergibt 422 `IDEMPOTENCY_KEY_REUSED`. / Optional. 1 to 128 visible ASCII characters (e.g. a UUID). A repeat with the same key and body returns the first order again; a different body returns 422 `IDEMPOTENCY_KEY_REUSED`.","required":false,"deprecated":false}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserCreateRequest"},"example":{"external_reference":"SHOP-10045","delivery_address":{"first_name":"Max","last_name":"Mustermann","street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"billing_address":{"first_name":"Max","last_name":"Mustermann","street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"items":[{"sku":"TSHIRT-SCHWARZ-M","external_id":"LINE-1","amount":2,"processings":[{"processing_type":"DTG","position":"FRONT","design_url":"https://example.com/designs/motiv-001.png"}]}]}}},"required":true},"responses":{"201":{"description":"Bestellung angelegt; die Antwort zeigt Status und gegebenenfalls Rückhaltegrund. Bei Wiederholung mit gleichem `Idempotency-Key` und Body kommt dieselbe Bestellung erneut. / Order created; the response shows status and, if any, retention reason. A repeat with the same `Idempotency-Key` and body returns the same order.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserResponse"},"example":{"id":900001,"slug":"CL-7K3M9QX","internal_reference":null,"external_reference":"SHOP-10045","reordered_from_order_id":null,"designer_id":"4711","status":"PENDING","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","delivery_address":{"id":5001,"address_id":7001,"title":null,"company":null,"first_name":"Max","last_name":"Mustermann","care_of":null,"street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"billing_address":{"id":5002,"address_id":7002,"title":null,"company":null,"first_name":"Max","last_name":"Mustermann","care_of":null,"street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"retention":null}}}},"400":{"description":"Unbekannte oder mehrdeutige SKU, nicht konfiguriertes Veredelungsverfahren, kein Zusatzprodukt in `additional_products` oder ungültiger Header `Idempotency-Key`. Nichts wurde angelegt. / Unknown or ambiguous SKU, unconfigured processing method, no additional product in `additional_products`, or invalid `Idempotency-Key` header. Nothing was created.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Der Body enthält Felder, die ein Händler nicht setzen darf (Feldpfade in `detail`), oder eine `designer_id`, die nicht zum eigenen Konto passt. Nichts wurde angelegt. / The body contains fields a merchant may not set (field paths in `detail`), or a `designer_id` that does not match the own account. Nothing was created.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"422":{"description":"Der Body ist ungültig (fehlende Pflichtfelder, falsche Typen oder Längen), oder der `Idempotency-Key` wurde mit anderem Body wiederverwendet (`extra.error=IDEMPOTENCY_KEY_REUSED`). / The body is invalid (missing required fields, wrong types or lengths), or the `Idempotency-Key` was reused with a different body (`extra.error=IDEMPOTENCY_KEY_REUSED`).","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:create","merchant_order:write"]}},"/api/orders/by-external-reference/{external_reference}":{"get":{"tags":["Orders"],"summary":"Get an order by external reference","operationId":"ApiOrdersByExternalReferenceExternalReferenceGetOrderByExternalReference","parameters":[{"name":"external_reference","in":"path","schema":{"type":"string"},"required":true,"deprecated":false,"description":"Eigene Bestellreferenz, wie bei der Anlage gesendet; exakter Treffer mit Beachtung der Schreibweise. / Own order reference as sent at creation; exact, case-sensitive match."},{"name":"mos","in":"query","schema":{"type":"boolean","default":true},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händler; Fertigungsaufträge erscheinen nur mit `tracking=true`. / Has no effect for merchants; manufacturing orders only appear with `tracking=true`."},{"name":"log","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Muss für Händler `false` bleiben; `true` ergibt 403. / Must stay `false` for merchants; `true` returns 403."},{"name":"payment","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händler; Zahlungsangaben sind immer enthalten, sofern vorhanden. / Has no effect for merchants; payment data is always included when available."},{"name":"tracking","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"`true` füllt `manufacturing_orders` mit den Sendungen der Teilaufträge; Standard `false` (leere Liste). / `true` fills `manufacturing_orders` with the shipments of the partial orders; default `false` (empty list)."},{"name":"invoices","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Muss für Händler `false` bleiben; `true` ergibt 403. / Must stay `false` for merchants; `true` returns 403."},{"name":"payload","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Muss für Händler `false` bleiben; `true` ergibt 403. / Must stay `false` for merchants; `true` returns 403."}],"responses":{"200":{"description":"Die Bestellung mit Adressen, Positionen und Zahlungsangaben. / The order with addresses, items and payment data.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserDetailResponse"},"example":{"id":900001,"slug":"CL-7K3M9QX","internal_reference":null,"external_reference":"SHOP-10045","reordered_from_order_id":null,"designer_id":"4711","status":"PENDING","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:05Z","delivery_address":{"id":5001,"address_id":7001,"title":null,"company":null,"first_name":"Max","last_name":"Mustermann","care_of":null,"street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"billing_address":{"id":5002,"address_id":7002,"title":null,"company":null,"first_name":"Max","last_name":"Mustermann","care_of":null,"street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"is_billing_address_editable":true,"retention":null,"items":[{"id":900101,"order_id":900001,"product_variant_id":3001,"item_group":"0f8fad5b-d9cb-469f-a165-70867728950e","external_id":"LINE-1","item_id":null,"created_at":"2026-01-15T10:30:00Z","article":{"sku":"TSHIRT-SCHWARZ-M","product_name":"Basic T-Shirt"}}],"manufacturing_orders":[],"payment":{"integration_payment_id":"0192f3a4-5b6c-7d8e-9f01-23456789abcd","integration_payment_reference":"SHOP-10045","integration_payment_timestamp":"2026-01-15T10:30:00Z","integration_payment_gateway":"collective_invoice"},"linked_support_tickets":[],"hold_until":null}}}},"400":{"description":"Ungültiger Query-Parameter. / Invalid query parameter.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"`log`, `invoices` oder `payload` wurde mit `true` angefragt; diese Bereiche sind für Händler nicht verfügbar. / `log`, `invoices` or `payload` was requested as `true`; these sections are not available to merchants.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"404":{"description":"Keine eigene Bestellung mit dieser `external_reference`. / No own order with this `external_reference`.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"],"description":"Liefert eine Bestellung des authentifizierten Händlers über die eigene `external_reference` (Scope `merchant_order:read`). Antwortform, Query-Parameter und Einschränkungen sind identisch zu `GET /api/orders/{order_id}`.\n\nDie `external_reference` ist nicht eindeutig: Stornierte Bestellungen geben sie wieder frei, sodass sie mehrfach vorkommen kann. Es wird genau eine Bestellung geliefert; nicht stornierte Bestellungen haben Vorrang vor stornierten, innerhalb davon gewinnt die neueste. Existieren nur stornierte Bestellungen, wird die neueste davon geliefert. Der Treffer ist exakt und unterscheidet Groß- und Kleinschreibung. Gibt es keine eigene Bestellung mit dieser Referenz, ist die Antwort 404; fremde Bestellungen mit gleicher Referenz bleiben unsichtbar. Die Suche nach Teilen oder ohne Beachtung der Schreibweise leistet `GET /api/orders/search`.\n\nReturns an order of the authenticated merchant by its own `external_reference` (scope `merchant_order:read`). Response shape, query parameters and restrictions are identical to `GET /api/orders/{order_id}`.\n\nThe `external_reference` is not unique: canceled orders release it, so it can occur more than once. Exactly one order is returned; non-canceled orders take precedence over canceled ones and, within that, the newest wins. If only canceled orders exist, the newest of them is returned. Matching is exact and case-sensitive. Without an own order for this reference the response is 404; orders of other merchants with the same reference stay invisible. Case-insensitive search is provided by `GET /api/orders/search`."}},"/api/orders/preview":{"post":{"tags":["Orders"],"summary":"Preview order creation","description":"Prüft einen Bestellentwurf, ohne etwas zu speichern (Scope `merchant_order:read`). Der Request-Body ist derselbe wie bei `POST /api/orders` und durchläuft dieselbe Bereinigung: Felder, die ein Händler nicht setzen darf, ergeben 403 mit den Feldpfaden. Die Antwort zeigt je Position SKU, Produktname, Stückzahl und Preise, die Adressen, Netto- und Bruttobetrag in Cent, ob die Bestellung produzierbar wäre (`is_feasible`, mit `unassignable_skus`), sowie `fingerprint` und `confirmed_summary`. Zwei Vorschauen desselben Entwurfs mit unverändertem Stand liefern denselben `fingerprint`.\n\nDas Guthaben des Händlers wird nicht geprüft (`wallet_coverage_checked` ist immer `false`). Ein fehlender Katalogpreis ergibt `null` bei Preisen und Beträgen. Ein nicht produzierbarer Entwurf ist kein Fehler, sondern steht im 200-Body. Fehler im Request selbst ergeben 422 mit `extra.error`: `INVALID_FIELDS` (mit `extra.fields`, Liste aus Feldpfad und Fehlercode), `UNKNOWN_SKU`, `AMBIGUOUS_SKU` (mit `extra.candidate_skus`), `VARIANT_INACTIVE` (mit `extra.alternative_variant_ids`), `UNKNOWN_PROCESSING_TYPE` und `NOT_AN_ADDITIONAL_PRODUCT`. Ein Body, der kein JSON-Objekt ist, ergibt 422 `INVALID_FIELDS`. Die Anlage selbst verhält sich bei inaktiven Varianten anders, siehe `POST /api/orders`.\n\nValidates an order draft without saving anything (scope `merchant_order:read`). The request body is the same as for `POST /api/orders` and goes through the same sanitisation: fields a merchant may not set return 403 with the field paths. The response shows per position SKU, product name, quantity and prices, the addresses, net and gross amount in cents, whether the order could be produced (`is_feasible`, with `unassignable_skus`), plus `fingerprint` and `confirmed_summary`. Two previews of the same draft in an unchanged state return the same `fingerprint`.\n\nThe merchant balance is not checked (`wallet_coverage_checked` is always `false`). A missing catalog price yields `null` for prices and amounts. A draft that cannot be produced is not an error but stated in the 200 body. Errors in the request itself return 422 with `extra.error`: `INVALID_FIELDS` (with `extra.fields`, a list of field path and error code), `UNKNOWN_SKU`, `AMBIGUOUS_SKU` (with `extra.candidate_skus`), `VARIANT_INACTIVE` (with `extra.alternative_variant_ids`), `UNKNOWN_PROCESSING_TYPE` and `NOT_AN_ADDITIONAL_PRODUCT`. A body that is not a JSON object returns 422 `INVALID_FIELDS`. Creation itself behaves differently for inactive variants, see `POST /api/orders`.","operationId":"ApiOrdersPreviewPreviewOrder","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserCreateRequest"},"example":{"external_reference":"SHOP-10045","delivery_address":{"first_name":"Max","last_name":"Mustermann","street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"billing_address":{"first_name":"Max","last_name":"Mustermann","street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"items":[{"sku":"TSHIRT-SCHWARZ-M","external_id":"LINE-1","amount":2,"processings":[{"processing_type":"DTG","position":"FRONT","design_url":"https://example.com/designs/motiv-001.png"}]}]}}},"required":true},"responses":{"200":{"description":"Vorschau des Entwurfs; nichts wurde gespeichert. Ein nicht produzierbarer Entwurf steht in `is_feasible`, nicht als Fehler. / Preview of the draft; nothing was saved. A draft that cannot be produced is stated in `is_feasible`, not as an error.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderMerchantPreviewResponse"},"example":{"is_feasible":true,"unassignable_skus":[],"positions":[{"sku":"TSHIRT-SCHWARZ-M","product_name":"Basic T-Shirt","description":"Schwarz, Größe M","amount":2,"unit_price_net":1490,"line_price_net":2980}],"delivery_address":{"first_name":"Max","last_name":"Mustermann","street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"billing_address":{"first_name":"Max","last_name":"Mustermann","street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"net_amount":2980,"gross_amount":3546,"currency":"EUR","payment_gateway":"collective_invoice","wallet_coverage_checked":false,"fingerprint":"9b74c9897bac770ffc029102a200c5de1c6a9a3d4f6b7e5d3c2b1a0f9e8d7c6b","confirmed_summary":"35.46 EUR"}}}},"400":{"description":"Ungültiger Header oder Parameter der Anfrage. / Invalid header or parameter of the request.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"422":{"description":"Der Entwurf selbst ist fehlerhaft; `extra.error` nennt die Ursache (`INVALID_FIELDS`, `UNKNOWN_SKU`, `AMBIGUOUS_SKU`, `VARIANT_INACTIVE`, `UNKNOWN_PROCESSING_TYPE`, `NOT_AN_ADDITIONAL_PRODUCT`). / The draft itself is faulty; `extra.error` names the cause (`INVALID_FIELDS`, `UNKNOWN_SKU`, `AMBIGUOUS_SKU`, `VARIANT_INACTIVE`, `UNKNOWN_PROCESSING_TYPE`, `NOT_AN_ADDITIONAL_PRODUCT`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderErrorResponse"}}}},"403":{"description":"Der Body enthält Felder, die ein Händler nicht setzen darf (Feldpfade in `detail`), oder eine `designer_id`, die nicht zum eigenen Konto passt. / The body contains fields a merchant may not set (field paths in `detail`), or a `designer_id` that does not match the own account.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"]}},"/api/orders/retention-reasons":{"get":{"tags":["Orders"],"summary":"List retention reasons","operationId":"ApiOrdersRetentionReasonsGetRetentionReasons","responses":{"200":{"description":"Liste der aktiven Rückhaltegründe. / List of the active retention reasons.","headers":{},"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/OrderUserRetentionReasonResponse"},"type":"array"},"example":[{"id":12,"name":"Fehler - Produkt"},{"id":7,"name":"Fehler - Adresse"}]}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"],"description":"Liefert die aktiven Rückhaltegründe (Scope `merchant_order:read`): die Gründe, aus denen eine Bestellung angehalten sein kann. Die Liste ist nicht seitenweise und nach Anlagezeitpunkt des Grundes absteigend sortiert. Jeder Eintrag hat `id` und `name`. Die `id` ist der stabile Schlüssel und passt zu `retention.reason_id` an Bestellungen sowie zu den Filtern `retention_reason_id` und `retention_reason_ids` von `GET /api/orders`; der `name` ist ein Anzeigetext, der sich ändern kann und nicht für Logik verwendet werden sollte. Deaktivierte Gründe fehlen.\n\nReturns the active retention reasons (scope `merchant_order:read`): the reasons why an order can be held. The list is not paginated and sorted by creation time of the reason, newest first. Each entry has `id` and `name`. The `id` is the stable key and matches `retention.reason_id` on orders as well as the filters `retention_reason_id` and `retention_reason_ids` of `GET /api/orders`; the `name` is a display text that may change and should not be used for logic. Deactivated reasons are missing."}},"/api/orders/retention-summary":{"get":{"tags":["Orders"],"summary":"Order counts per retention reason","operationId":"ApiOrdersRetentionSummarySummarizeRetentionReasons","parameters":[{"name":"status","in":"query","schema":{"oneOf":[{"items":{"$ref":"#/components/schemas/OrderStatus"},"type":"array"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Beschränkt die Zählung auf einen oder mehrere Bestellstatus (`OrderStatus`); Parameter wiederholen, mehrere Werte gelten als ODER. Ohne Angabe zählen alle Status. / Restricts the count to one or more order statuses (`OrderStatus`); repeat the parameter, several values combine with OR. Without it all statuses count."}],"responses":{"200":{"description":"Zählung je Rückhaltegrund und Gesamtsumme. / Count per retention reason and total.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionSummaryResponse"},"example":{"counts":[{"retention_reason_id":7,"count":3},{"retention_reason_id":12,"count":1}],"total_count":4}}}},"400":{"description":"Ungültiger Statuswert im Filter `status`. / Invalid status value in the `status` filter.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"],"description":"Zählt die angehaltenen Bestellungen des Händlers je Rückhaltegrund (Scope `merchant_order:read`), in einer Anfrage statt einer Listenabfrage je Grund. Nur aktive Gründe werden gezählt; Gründe ohne Bestellung fehlen in `counts` und sind nicht als 0 enthalten. `counts` ist nach `retention_reason_id` aufsteigend sortiert. Eine Bestellung hat höchstens einen Grund, `total_count` ist daher die Summe aller `count`. Mit dem Parameter `status` lässt sich auf dieselbe Statusmenge einschränken wie in `GET /api/orders`, damit die Zahlen zur dortigen Liste passen; ohne `status` zählen alle Status.\n\nCounts the held orders of the merchant per retention reason (scope `merchant_order:read`), in one request instead of one list query per reason. Only active reasons are counted; reasons without an order are missing from `counts` and not included as 0. `counts` is sorted by `retention_reason_id` ascending. An order has at most one reason, so `total_count` is the sum of all `count` values. The `status` parameter restricts to the same set of statuses as in `GET /api/orders`, so the numbers match the list there; without `status` all statuses count."}},"/api/orders/search":{"get":{"tags":["Orders"],"summary":"Search orders","operationId":"ApiOrdersSearchSearchOrders","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"required":true,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Suchbegriff: Bestellnummer (`CL-…`), numerische Bestell-ID oder `external_reference`; Pflicht, höchstens 255 Zeichen wirksam. / Search term: order number (`CL-…`), numeric order ID or `external_reference`; required, at most 255 characters take effect."},{"name":"limit","in":"query","schema":{"type":"integer","default":50},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Seitengröße; Werte außerhalb von 1 bis 200 werden auf diesen Bereich begrenzt. / Page size; values outside 1 to 200 are clamped to that range."},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anzahl der zu überspringenden Treffer; negative Werte gelten als 0. / Number of matches to skip; negative values are treated as 0."},{"name":"subscribed_by_me","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händler; der Wert wird ignoriert. / Has no effect for merchants; the value is ignored."}],"responses":{"200":{"description":"Seite mit Treffern, leer bei keinem Treffer. / Page of matches, empty if nothing matches.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserPageResponse"},"example":{"items":[{"id":900001,"slug":"CL-7K3M9QX","internal_reference":null,"external_reference":"SHOP-10045","reordered_from_order_id":null,"designer_id":"4711","status":"TRANSFERRED","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T14:05:00Z","retention":null}],"limit":50,"offset":0,"total_count":1}}}},"400":{"description":"`q` fehlt, ist leer oder besteht nur aus Leerzeichen, oder ein Parameter ist ungültig. / `q` is missing, empty or whitespace-only, or a parameter is invalid.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"],"description":"Sucht Bestellungen des authentifizierten Händlers über die Bestellnummer (`slug`, beginnt mit `CL-`), die numerische Bestell-ID oder die `external_reference` (Scope `merchant_order:read`). Der Treffer ist exakt und ohne Beachtung der Groß-/Kleinschreibung; führende und nachfolgende Leerzeichen in `q` werden entfernt. Es gibt keine Teilwort- oder Präfixsuche.\n\nAblauf: Beginnt `q` mit `CL-` oder `CO-`, wird zuerst die Bestellnummer geprüft und nur bei keinem eigenen Treffer als `external_reference` gesucht. Eine Zahl wird zuerst als `external_reference` gesucht, bei keinem Treffer als Bestell-ID. Alles andere wird als `external_reference` gesucht. Ein Treffer über Bestellnummer oder ID ist höchstens eine Bestellung; bei `offset` über 0 ist `items` dann leer, `total_count` bleibt 1. Mehrere Bestellungen mit gleicher `external_reference` kommen neueste zuerst. Kein Treffer, ein fremder Treffer und ein `q` über 255 Zeichen ergeben eine leere Liste (`total_count` 0), nie einen Fehler. Ein leeres oder nur aus Leerzeichen bestehendes `q` ergibt 400. Die Antwort hat dieselbe Form wie `GET /api/orders`.\n\nSearches the orders of the authenticated merchant by order number (`slug`, starts with `CL-`), numeric order ID or `external_reference` (scope `merchant_order:read`). Matching is exact and case-insensitive; leading and trailing whitespace in `q` is removed. There is no partial-word or prefix search.\n\nFlow: if `q` starts with `CL-` or `CO-`, the order number is checked first and only without an own match searched as `external_reference`. A number is searched as `external_reference` first and, without a match, as order ID. Anything else is searched as `external_reference`. A hit by order number or ID is at most one order; with `offset` above 0, `items` is empty and `total_count` stays 1. Several orders with the same `external_reference` are returned newest first. No match, a match owned by someone else and a `q` longer than 255 characters return an empty list (`total_count` 0), never an error. An empty or whitespace-only `q` returns 400. The response has the same shape as `GET /api/orders`."}},"/api/orders/status-gates":{"get":{"tags":["Orders"],"summary":"Order statuses that allow each action","operationId":"ApiOrdersStatusGatesGetStatusGates","responses":{"200":{"description":"Tabelle der Aktionen mit den zulässigen Bestellstatus. / Table of actions with the permitted order statuses.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusGatesResponse"},"example":{"cancel":["CHECK","ERROR","PARTIALLY_CANCELED","PARTIALLY_TRANSFERRED","PAUSE","PENDING","READY","SHIPPED","TRANSFERRED"],"restart":["CANCELED","CHECK","ERROR","PARTIALLY_TRANSFERRED","PAUSE","PENDING","READY"],"item_mod":["CHECK","ERROR","PAUSE","PENDING","READY"],"reorder":["CANCELED","CANCELLATION_PENDING","CHECK","ERROR","PARTIALLY_CANCELED","PARTIALLY_TRANSFERRED","PAUSE","PENDING","READY","SHIPPED","TRANSFERRED"]}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"],"description":"Liefert je Aktion die Bestellstatus, in denen sie angenommen wird (Scope `merchant_order:read`). Die Tabelle gilt für alle Bestellungen gleich und hängt nicht vom Händler ab. Sie spiegelt die tatsächlich erzwungenen Regeln. Eine Aufnahme in die Liste ist notwendig, aber nicht immer hinreichend: `item_mod` setzt zusätzlich voraus, dass kein Fertigungsauftrag mehr dagegen spricht (z. B. schon an den Produktionspartner übergeben), und bei `cancel` entscheidet je Fertigungsauftrag, was sich tatsächlich stornieren lässt. Die Statuslisten sind alphabetisch sortiert.\n\nReturns for each action the order statuses in which it is accepted (scope `merchant_order:read`). The table is the same for all orders and does not depend on the merchant. It mirrors the rules that are actually enforced. Being listed is necessary but not always sufficient: `item_mod` additionally requires that no manufacturing order speaks against it (e.g. already handed over to the production partner), and for `cancel` each manufacturing order decides what can actually be canceled. The status lists are sorted alphabetically."}},"/api/orders/{order_id}":{"get":{"tags":["Orders"],"summary":"Get an order","operationId":"ApiOrdersOrderIdGetOrder","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Numerische Bestell-ID (`id` aus der Anlage- oder Listenantwort). / Numeric order ID (`id` from the create or list response)."},{"name":"mos","in":"query","schema":{"type":"boolean","default":true},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händler; Fertigungsaufträge erscheinen nur mit `tracking=true`. / Has no effect for merchants; manufacturing orders only appear with `tracking=true`."},{"name":"log","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Muss für Händler `false` bleiben; `true` ergibt 403. / Must stay `false` for merchants; `true` returns 403."},{"name":"payment","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händler; Zahlungsangaben sind immer enthalten, sofern vorhanden. / Has no effect for merchants; payment data is always included when available."},{"name":"tracking","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"`true` füllt `manufacturing_orders` mit den Sendungen der Teilaufträge; Standard `false` (leere Liste). / `true` fills `manufacturing_orders` with the shipments of the partial orders; default `false` (empty list)."},{"name":"invoices","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Muss für Händler `false` bleiben; `true` ergibt 403. / Must stay `false` for merchants; `true` returns 403."},{"name":"payload","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Muss für Händler `false` bleiben; `true` ergibt 403. / Must stay `false` for merchants; `true` returns 403."}],"responses":{"200":{"description":"Die Bestellung mit Adressen, Positionen und Zahlungsangaben. / The order with addresses, items and payment data.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserDetailResponse"},"example":{"id":900001,"slug":"CL-7K3M9QX","internal_reference":null,"external_reference":"SHOP-10045","reordered_from_order_id":null,"designer_id":"4711","status":"TRANSFERRED","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T14:05:00Z","delivery_address":{"id":5001,"address_id":7001,"title":null,"company":null,"first_name":"Max","last_name":"Mustermann","care_of":null,"street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"billing_address":{"id":5002,"address_id":7002,"title":null,"company":null,"first_name":"Max","last_name":"Mustermann","care_of":null,"street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"is_billing_address_editable":true,"retention":null,"items":[{"id":900101,"order_id":900001,"product_variant_id":3001,"item_group":"0f8fad5b-d9cb-469f-a165-70867728950e","external_id":"LINE-1","item_id":null,"created_at":"2026-01-15T10:30:00Z","processings":[{"id":910001,"processing_type_id":1,"processing_type":"DTG","position":"FRONT","preview_url":null,"status":"RENDERED"}],"article":{"sku":"TSHIRT-SCHWARZ-M","product_name":"Basic T-Shirt"}}],"manufacturing_orders":[{"id":920001,"manufacturer_name":"Musterproduktion GmbH","shipments":[{"id":930001,"tracking_number":"00340434161094042557","tracking_link":"https://tracking.example.com/00340434161094042557","status":"SHIPPED","carrier_name":"DHL"}]}],"payment":{"integration_payment_id":"0192f3a4-5b6c-7d8e-9f01-23456789abcd","integration_payment_reference":"SHOP-10045","integration_payment_timestamp":"2026-01-15T10:30:00Z","integration_payment_gateway":"collective_invoice"},"linked_support_tickets":[],"hold_until":null}}}},"400":{"description":"Ungültiger Pfad- oder Query-Parameter, z. B. eine nicht numerische Bestell-ID. / Invalid path or query parameter, e.g. a non-numeric order ID.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"`log`, `invoices` oder `payload` wurde mit `true` angefragt; diese Bereiche sind für Händler nicht verfügbar. / `log`, `invoices` or `payload` was requested as `true`; these sections are not available to merchants.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"404":{"description":"Bestellung unbekannt oder gehört einem anderen Händler; beides ist bewusst nicht unterscheidbar. / Order unknown or owned by another merchant; the two cases are deliberately indistinguishable.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"],"description":"Liefert eine Bestellung des authentifizierten Händlers mit Adressen, Positionen, Zahlungsangaben, Rückhaltegrund und verknüpften Support-Tickets (Scope `merchant_order:read`). Die Bestellung wird über die numerische Bestell-ID adressiert; eine fremde oder unbekannte ID ergibt 404.\n\nDie Query-Parameter steuern, was zusätzlich geladen wird. `tracking=true` ergänzt `manufacturing_orders` mit den Sendungen (Tracking-Nummer, Link, Versanddienstleister); ohne diesen Parameter ist `manufacturing_orders` leer. `log=true`, `invoices=true` und `payload=true` sind für Händler nicht zulässig und ergeben 403, auch bei Bestellungen des Händlers selbst. `payment` und `mos` haben für Händler keine Wirkung: Zahlungsangaben sind immer enthalten, sofern vorhanden.\n\nReturns an order of the authenticated merchant with addresses, line items, payment data, retention reason and linked support tickets (scope `merchant_order:read`). The order is addressed by its numeric order ID; an ID owned by someone else or unknown returns 404.\n\nThe query parameters control what is loaded in addition. `tracking=true` adds `manufacturing_orders` with the shipments (tracking number, link, carrier); without it `manufacturing_orders` is empty. `log=true`, `invoices=true` and `payload=true` are not allowed for merchants and return 403, even for the merchant own orders. `payment` and `mos` have no effect for merchants: payment data is always included when available."}},"/api/orders/{order_id}/billing-address":{"put":{"tags":["Orders"],"summary":"Correct the billing address","operationId":"ApiOrdersOrderIdBillingAddressUpdateBillingAddress","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Bestell-ID (`id` der Bestellung, ganze Zahl) / Order ID (`id` of the order, integer). Eine fremde oder unbekannte Bestellung antwortet mit 404."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBillingAddressRequest"},"example":{"first_name":"Max","last_name":"Mustermann","company":"Mustermann GmbH","street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"}}},"required":true},"responses":{"200":{"description":"Rechnungsadresse geändert, Antwort ist die aktualisierte Bestellung / Billing address changed, the response is the updated order.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserResponse"},"example":{"id":123456,"slug":"ord-123456","internal_reference":null,"external_reference":"SHOP-10042","status":"PENDING","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T11:00:00Z","delivery_address":{"id":801,"address_id":701,"title":null,"company":null,"first_name":"Max","last_name":"Mustermann","care_of":null,"street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"billing_address":{"id":802,"address_id":702,"title":null,"company":null,"first_name":"Max","last_name":"Mustermann","care_of":null,"street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"}}}}},"400":{"description":"Adresse strukturell ungültig, `detail` nennt die Mängel / Address structurally invalid, `detail` lists the problems.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Bestellung nicht gefunden oder gehört nicht zum Konto / Order not found or not owned by the account.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"409":{"description":"Aktive Rechnung vorhanden oder Landwechsel versucht / An active invoice exists or a country change was attempted.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"422":{"description":"Die Bestellung hat keine Lieferadresse, aus der das Land abgeleitet werden könnte / The order has no delivery address to derive the country from.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:address","merchant_order:write"],"description":"Korrigiert die Rechnungsadresse einer Bestellung. Die Adresse ersetzt die bisherige vollständig; alle Pflichtfelder (`first_name`, `last_name`, `street`, `postcode`, `city`, `country`) müssen gesendet werden. Die Operation ändert nur Adressfelder, keine Steuerangaben (USt-IdNr. u. Ä.).\n\n**Wann möglich:** solange zur Bestellung keine aktive Rechnung existiert. Der Bestellstatus spielt dafür keine Rolle. Sobald eine aktive Rechnung vorliegt, antwortet die Operation mit 409; eine stornierte Rechnung (Gutschrift mit Neuausstellung) öffnet das Fenster wieder.\n\n**Land:** Ist bereits eine Rechnungsadresse hinterlegt, muss `country` dem hinterlegten Land entsprechen (Groß-/Kleinschreibung egal), sonst 409. Fehlt noch eine Rechnungsadresse, muss `country` dem Land der Lieferadresse entsprechen (sonst 409); hat die Bestellung keine Lieferadresse, ist die Antwort 422. Ein Landwechsel ist über die Händler-API nicht möglich, weil er die steuerliche Behandlung ändert.\n\n**Validierung:** Die Adresse wird strukturell geprüft (Hausnummer, Postleitzahl-Format, plausible Straße); bei einem Fehler antwortet die Operation mit 400 und nennt die Mängel in `detail`. Eine Zustellbarkeitsprüfung beim Paketdienst findet nicht statt, Packstationen werden nicht ausgenommen. Antwort: die aktualisierte Bestellung.\n\nCorrects the billing address of an order. The new address replaces the old one completely; all required fields (`first_name`, `last_name`, `street`, `postcode`, `city`, `country`) must be sent. Only address fields change, no tax details (VAT ID etc.).\n\n**When possible:** as long as the order has no active invoice. The order status does not matter. As soon as an active invoice exists the operation answers 409; a reversed invoice (credit note with re-issue) reopens the window.\n\n**Country:** If a billing address already exists, `country` must equal the stored country (case-insensitive), otherwise 409. If there is no billing address yet, `country` must equal the delivery country (otherwise 409); an order without a delivery address answers 422. A country change is not possible through the merchant API because it changes the tax treatment.\n\n**Validation:** The address is checked structurally (house number, postal code format, plausible street); on failure the operation answers 400 and lists the problems in `detail`. No deliverability check with the carrier takes place and Packstations are not exempt. Response: the updated order."}},"/api/orders/{order_id}/cancel":{"post":{"tags":["Orders"],"summary":"Cancel an order","operationId":"ApiOrdersOrderIdCancelCancelOrder","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Bestell-ID (`id` der Bestellung, ganze Zahl) / Order ID (`id` of the order, integer). Eine fremde oder unbekannte Bestellung antwortet mit 404."}],"requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/OrderCancelRequest"},{"type":"null"}]},"example":{"reason":"Bestellung vom Endkunden storniert","accept_cost":false}}},"required":true},"responses":{"201":{"description":"Ergebnis der Stornierung in `overall_outcome` (auch wenn nichts storniert wurde) / Result of the cancellation in `overall_outcome` (also when nothing was canceled).","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserCancelResponse"},"example":{"order_id":123456,"overall_outcome":"FULLY_CANCELED","paid_cancel_available":false,"phoenix_order_status_before":"PENDING","phoenix_order_status_after":"CANCELED"}}}},"400":{"description":"Ungültige Anfrage (Body oder Parameter) / Invalid request (body or parameters).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Bestellung nicht gefunden oder gehört nicht zum Konto / Order not found or not owned by the account.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"409":{"description":"Bestellung ist bereits `CANCELED` oder `CANCELLATION_PENDING` / The order is already `CANCELED` or `CANCELLATION_PENDING`.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:cancel","merchant_order:write"],"description":"Storniert eine Bestellung als Ganzes (alles oder nichts). Der Body ist optional. `force` wird für Händlerschlüssel ignoriert. Vorab zeigt `POST /api/orders/{order_id}/cancel/preview`, was die Stornierung jetzt bewirken würde.\n\n**Ablauf:** Shirtee prüft live, ob die Teile der Bestellung noch stornierbar sind. Ist eines in Produktion, versendet oder gerade in Übergabe, oder lässt sich sein Stand nicht prüfen, wird nichts storniert und `overall_outcome` ist `ABORTED_NOT_ELIGIBLE`. Fallen für die Stornierung Kosten an, bricht die Operation ebenfalls mit `ABORTED_NOT_ELIGIBLE` ab und setzt `paid_cancel_available` auf `true`; mit `accept_cost: true` wird sie dann kostenpflichtig ausgeführt (Rechnung und Guthabenbelastung für diese Positionen bleiben bestehen, es gibt dafür keine Gutschrift). Wurde zuvor eine Stornierung angestoßen und ist noch nicht bestätigt, führt ein erneuter Aufruf zu `ABORTED_NOT_ELIGIBLE` oder `CANCEL_PENDING_VERIFICATION`, ohne eine zweite Stornierung auszulösen.\n\n**Statuscodes:** 201 mit dem Ergebnis (auch bei nicht ausgeführter Stornierung, das Ergebnis steht in `overall_outcome`). 404 bei fremder oder unbekannter Bestellung. 409, wenn die Bestellung bereits den Status `CANCELED` oder `CANCELLATION_PENDING` hat; für einen Wiederholungsaufruf heißt das: erledigt bzw. in Klärung. Nach vollständiger Stornierung ist `phoenix_order_status_after` `CANCELED`, oder `CANCELLATION_PENDING`, solange die Bestätigung des Herstellers aussteht. `reason` ist für den Protokolleintrag; fehlt er, setzt Shirtee einen Standardtext.\n\nCancels an order as a whole (all or nothing). The body is optional. `force` is ignored for merchant keys. `POST /api/orders/{order_id}/cancel/preview` shows beforehand what the cancellation would do now.\n\n**Flow:** Shirtee checks live whether the parts of the order can still be canceled. If one is in production, shipped or being handed over, or its state cannot be verified, nothing is canceled and `overall_outcome` is `ABORTED_NOT_ELIGIBLE`. If the cancellation incurs costs, the operation also aborts with `ABORTED_NOT_ELIGIBLE` and sets `paid_cancel_available` to `true`; with `accept_cost: true` it is then executed against cost (invoice and wallet debit for these positions stand, no credit note is issued for them). If a cancellation was requested earlier and is not yet confirmed, a repeated call yields `ABORTED_NOT_ELIGIBLE` or `CANCEL_PENDING_VERIFICATION` without triggering a second cancellation.\n\n**Status codes:** 201 with the result (also when nothing was canceled; the outcome is in `overall_outcome`). 404 for a foreign or unknown order. 409 if the order is already `CANCELED` or `CANCELLATION_PENDING`; for a retry that means: done, or in clarification. After a full cancellation `phoenix_order_status_after` is `CANCELED`, or `CANCELLATION_PENDING` while the manufacturer's confirmation is outstanding. `reason` goes to the audit trail; if omitted, Shirtee uses a default text."}},"/api/orders/{order_id}/cancel/preview":{"post":{"tags":["Orders"],"summary":"Preview order cancellation","description":"Zeigt, was `POST /api/orders/{order_id}/cancel` für diese Bestellung jetzt tun würde. Es wird nichts storniert und nichts geschrieben. Die Vorschau fragt dieselben Live-Stände ab wie die Stornierung (nur lesend) und bewertet sie mit den Regeln für Händlerschlüssel (ohne `force`, ohne `accept_cost`). Kein Body.\n\n**`outcome`:** `CANCELABLE` (Stornierung würde gelingen), `CANCELABLE_WITH_COST` (nur kostenpflichtig, die Stornierung braucht `accept_cost: true`), `PENDING_MANUFACTURER_CONFIRMATION` (eine Stornierung läuft, die Bestätigung steht aus), `ALREADY_CANCELED` (eine weitere Stornierung würde mit 409 antworten; bei einem Wiederholungsaufruf bedeutet das: erledigt) oder `REJECTED` (mit `reasons`). Der Stand kann sich zwischen Vorschau und Stornierung ändern; maßgeblich ist die Stornierung selbst. Der Bestellzustand ist hier nie ein Fehler, sondern steht in der 200-Antwort; 404 nur bei fremder oder unbekannter Bestellung. Die REST-API verlangt die Vorschau nicht vor der Stornierung.\n\nShows what `POST /api/orders/{order_id}/cancel` would do for this order now. Nothing is canceled and nothing is written. The preview queries the same live states as the cancellation (read-only) and evaluates them with the rules for merchant keys (no `force`, no `accept_cost`). No body.\n\n**`outcome`:** `CANCELABLE` (the cancellation would succeed), `CANCELABLE_WITH_COST` (only against cost, the cancellation needs `accept_cost: true`), `PENDING_MANUFACTURER_CONFIRMATION` (a cancellation is under way, confirmation outstanding), `ALREADY_CANCELED` (another cancellation would answer 409; for a retry that means: done) or `REJECTED` (with `reasons`). The state can change between preview and cancellation; the cancellation itself is authoritative. The state of the order is never an error here but part of the 200 response; 404 only for a foreign or unknown order. The REST API does not require the preview before the cancellation.","operationId":"ApiOrdersOrderIdCancelPreviewPreviewCancelOrder","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Bestell-ID (`id` der Bestellung, ganze Zahl) / Order ID (`id` of the order, integer). Eine fremde oder unbekannte Bestellung antwortet mit 404."}],"responses":{"200":{"description":"Vorschau der Stornierung, nichts wurde geschrieben / Cancellation preview, nothing was written.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderCancelPreviewResponse"},"example":{"order_id":123456,"external_reference":"SHOP-10042","order_status":"PENDING","outcome":"CANCELABLE","reasons":[],"paid_cancel_available":false,"fingerprint":"a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90","confirmed_summary":"Storno Bestellung SHOP-10042"}}}},"400":{"description":"Ungültige Anfrage (Body oder Parameter) / Invalid request (body or parameters).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Bestellung nicht gefunden oder gehört nicht zum Konto / Order not found or not owned by the account.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"]}},"/api/orders/{order_id}/complaint-eligibility":{"get":{"tags":["Complaints"],"summary":"Complaint eligibility of an order","operationId":"ApiOrdersOrderIdComplaintEligibilityGetComplaintEligibility","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Numerische ID der Bestellung, wie sie die Bestell-Endpunkte liefern; fremde IDs ergeben 404. / Numeric order ID as returned by the order endpoints; IDs of other merchants return 404."}],"responses":{"200":{"description":"Reklamierbarkeit der Bestellung und ihrer Positionen. / Eligibility of the order and its items.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintEligibilityResponse"},"example":{"order_id":123456,"eligible":true,"code":null,"items":[{"order_item_id":90001,"eligible":true,"code":null},{"order_item_id":90002,"eligible":false,"code":"NOT_SHIPPED"}]}}}},"400":{"description":"Ungültige Anfrage (z. B. Parameter außerhalb des erlaubten Bereichs, ungültiger Body). / Invalid request (e.g. parameter out of range or invalid body).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Reklamation, Bestellung, Position oder Foto existiert nicht oder gehört einem anderen Händler; ebenso, wenn die Funktion für dieses Konto nicht verfügbar ist. Nie 403. / Complaint, order, item or photo does not exist or belongs to another merchant; also returned when the feature is not available for this account. Never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplaintErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"],"description":"Prüft, ob und welche Positionen einer Bestellung reklamiert werden können. Der Aufruf liest nur und ändert nichts; dieselben Regeln gelten beim Anlegen und beim Einreichen einer Reklamation.\n\n- Sperrgründe der **Bestellung** (`code`, gelten für jede Position): `ORDER_CANCELED`, `ORDER_WITHOUT_CUSTOMER`, `DEADLINE_EXCEEDED`. Die Frist beträgt standardmäßig 150 Tage ab Bestelldatum (Datum in Berlin, Tag 150 eingeschlossen).\n- Sperrgründe je **Position** (`items[].code`): `ITEM_INACTIVE` (Position in der Bestellung nicht mehr aktiv), `ITEM_ALREADY_REPORTED` (Position steckt in einer eingereichten, nicht stornierten Reklamation), `NOT_SHIPPED` (Position ist noch nicht vollständig versendet).\n- `eligible` auf oberster Ebene ist `true`, sobald mindestens eine Position reklamierbar ist. `items[].eligible` ist `false`, wenn die Bestellung oder die Position gesperrt ist; `items[].code` nennt dabei nur den Grund der Position, den der Bestellung nennt `code`.\n\nEine fremde oder unbekannte Bestellung liefert `404`. `404` kommt auch, solange die Reklamationsfunktion für Händler nicht freigeschaltet ist.\n\nChecks whether and which items of an order can be reported as a complaint. The call is read-only; the same rules apply when a complaint is created and when it is submitted.\n\nOrder-level blocks (`code`) apply to every item: `ORDER_CANCELED`, `ORDER_WITHOUT_CUSTOMER`, `DEADLINE_EXCEEDED` (default window: 150 days from the order date, Berlin date, day 150 included). Item-level blocks (`items[].code`): `ITEM_INACTIVE`, `ITEM_ALREADY_REPORTED`, `NOT_SHIPPED`. Top-level `eligible` is `true` when at least one item can be reported; `items[].code` carries only the item's own reason, the order-level reason is in `code`.\n\nAn unknown or foreign order returns `404`, and so does every call while the complaint feature is not enabled for merchants."}},"/api/orders/{order_id}/delivery-address":{"put":{"tags":["Orders"],"summary":"Change the delivery address","operationId":"ApiOrdersOrderIdDeliveryAddressUpdateDeliveryAddress","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Bestell-ID (`id` der Bestellung, ganze Zahl) / Order ID (`id` of the order, integer). Eine fremde oder unbekannte Bestellung antwortet mit 404."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeliveryAddressRequest"},"example":{"first_name":"Max","last_name":"Mustermann","street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"}}},"required":true},"responses":{"200":{"description":"Lieferadresse geändert, Antwort ist die aktualisierte Bestellung / Delivery address changed, the response is the updated order.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserResponse"},"example":{"id":123456,"slug":"ord-123456","internal_reference":null,"external_reference":"SHOP-10042","status":"PENDING","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T11:00:00Z","delivery_address":{"id":801,"address_id":701,"title":null,"company":null,"first_name":"Max","last_name":"Mustermann","care_of":null,"street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"billing_address":{"id":802,"address_id":702,"title":null,"company":null,"first_name":"Max","last_name":"Mustermann","care_of":null,"street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"}}}}},"400":{"description":"Adresse ungültig (bei Packstationen `extra.error` = `INVALID_PACKSTATION`) oder Bestellung in einem Zustand, der keine Änderung erlaubt / Address invalid (for Packstations `extra.error` = `INVALID_PACKSTATION`) or the order is in a state that does not allow changes.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Bestellung nicht gefunden oder gehört nicht zum Konto / Order not found or not owned by the account.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"409":{"description":"Versandetikett bereits erstellt, Änderung vom Hersteller abgelehnt oder Rechnung trägt schon eine Gutschrift / Shipping label already created, change rejected by the manufacturer, or the invoice already carries a credit note.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"422":{"description":"Der Hersteller der Bestellung unterstützt keine Adressänderung, stornieren und neu anlegen / The order's manufacturer does not support address changes, cancel and re-create.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"502":{"description":"Übermittlung an den Hersteller fehlgeschlagen, später erneut versuchen / Forwarding to the manufacturer failed, retry later.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:address","merchant_order:write"],"description":"Ändert die Lieferadresse einer Bestellung. Die Adresse ersetzt die bisherige vollständig; alle Pflichtfelder (`first_name`, `last_name`, `street`, `postcode`, `city`, `country`) müssen gesendet werden. Vorab zeigt `POST /api/orders/{order_id}/delivery-address/preview`, ob und wie die Änderung greifen würde.\n\n**Wann möglich und was passiert:**\n\n| Zustand der Bestellung | Wirkung |\n|---|---|\n| Status `CHECK`, nichts an den Hersteller übergeben | Adresse wird gespeichert, die Bestellung verlässt `CHECK` und wird fortgesetzt (bei Bedarf neu zugeteilt). Bei Abrechnung über das Guthaben: reicht es nicht, wird nur die Adresse gespeichert und die Bestellung bleibt angehalten. |\n| Status `PAUSE`, nichts an den Hersteller übergeben | Adresse wird gespeichert, die Bestellung bleibt in `PAUSE`. |\n| Teile sind an den Hersteller übergeben oder in Klärung | Die Änderung wird an den Hersteller übermittelt und erst bei Annahme gespeichert. Versendet der Hersteller über ein von Shirtee erzeugtes Versandetikett, das noch nicht erstellt ist, bleibt die Änderung bei Shirtee und das Etikett entsteht mit der neuen Adresse. |\n\nIst ein Teil der Bestellung gerade in Übergabe oder bereits versendet, ist die Änderung nicht mehr möglich (400). Ohne an den Hersteller übergebene Teile ist jeder andere Bestellstatus als `CHECK`/`PAUSE` ebenfalls 400.\n\n**Fehler:** 400 bei ungültiger Adresse (Mängel in `detail`; bei Packstationen `extra.error` = `INVALID_PACKSTATION`), bei nicht änderbarem Zustand; 404 bei fremder oder unbekannter Bestellung; 409 wenn das Versandetikett schon erstellt ist, der Hersteller die Änderung ablehnt oder auf der Rechnung bereits eine Gutschrift steht; 422 wenn der Hersteller der Bestellung Adressänderungen nicht unterstützt (dann stornieren und neu anlegen); 502 wenn die Übermittlung an den Hersteller scheitert (später erneut versuchen).\n\n**Nebenwirkung:** Eine für die Bestellung bereits ausgestellte Rechnung wird per Gutschrift storniert und bei der nächsten Übergabe an die Produktion neu ausgestellt. Antwort: die aktualisierte Bestellung.\n\nChanges the delivery address of an order. The new address replaces the old one completely; all required fields (`first_name`, `last_name`, `street`, `postcode`, `city`, `country`) must be sent. `POST /api/orders/{order_id}/delivery-address/preview` shows beforehand whether and how the change would apply.\n\n**When possible and what happens:**\n\n| State of the order | Effect |\n|---|---|\n| Status `CHECK`, nothing handed to the manufacturer | The address is saved, the order leaves `CHECK` and continues (routed again if needed). When billed via the wallet balance: if it does not cover the order, only the address is saved and the order stays on hold. |\n| Status `PAUSE`, nothing handed to the manufacturer | The address is saved, the order stays in `PAUSE`. |\n| Parts are handed to the manufacturer or in clarification | The change is sent to the manufacturer and saved only if accepted. If the manufacturer ships on a Shirtee-generated label that has not been created yet, the change stays with Shirtee and the label is built with the new address. |\n\nIf a part of the order is being handed over or already shipped, the change is no longer possible (400). Without parts handed to the manufacturer, any order status other than `CHECK`/`PAUSE` is 400 as well.\n\n**Errors:** 400 for an invalid address (problems in `detail`; for Packstations `extra.error` = `INVALID_PACKSTATION`) or a state that cannot be changed; 404 for a foreign or unknown order; 409 if the shipping label already exists, the manufacturer rejects the change, or the invoice already carries a credit note; 422 if the order's manufacturer does not support address changes (cancel and re-create instead); 502 if forwarding to the manufacturer fails (retry later).\n\n**Side effect:** An invoice already issued for the order is reversed by a credit note and re-issued at the next handover to production. Response: the updated order."}},"/api/orders/{order_id}/delivery-address/preview":{"post":{"tags":["Orders"],"summary":"Preview delivery address change","description":"Zeigt, was `PUT /api/orders/{order_id}/delivery-address` mit derselben Adresse jetzt bewirken würde. Es wird nichts gespeichert und nichts an einen Hersteller gesendet. Der Body ist identisch zur Änderung.\n\n**Antwort 200:** `is_editable` und `blockers` sagen, ob die Änderung jetzt möglich ist (Zustand der Bestellung, kein Fehler); `mode` sagt, wie sie angewendet würde (`null`, wenn sie blockiert ist); `address` ist die geprüfte Adresse; `fingerprint` und `confirmed_summary` kennzeichnen den Vorschaustand, siehe Schema. Die Vorschau prüft nicht, ob der Hersteller eine übermittelte Änderung annimmt; das zeigt sich erst bei der Änderung.\n\n**Antwort 422:** Die Anfrage selbst ist nicht vorschaubar. `extra.error` ist `INVALID_FIELDS` (mit `extra.fields`), `INVALID_DELIVERY_ADDRESS` (mit `extra.issues`: `HOUSE_NUMBER_MISSING`, `POSTCODE_INVALID`, `STREET_IMPLAUSIBLE`, `HOUSE_NUMBER_IMPLAUSIBLE`, `ADDRESS_UNVERIFIED`) oder `INVALID_PACKSTATION`. 404 bei fremder oder unbekannter Bestellung. Die REST-API verlangt die Vorschau nicht vor der Änderung.\n\nShows what `PUT /api/orders/{order_id}/delivery-address` would do now with the same address. Nothing is saved and nothing is sent to a manufacturer. The body is identical to the change.\n\n**Response 200:** `is_editable` and `blockers` say whether the change is possible now (state of the order, not an error); `mode` says how it would apply (`null` if blocked); `address` is the validated address; `fingerprint` and `confirmed_summary` identify the previewed state, see the schema. The preview does not tell whether the manufacturer accepts a forwarded change; that only shows when the change is made.\n\n**Response 422:** The request itself cannot be previewed. `extra.error` is `INVALID_FIELDS` (with `extra.fields`), `INVALID_DELIVERY_ADDRESS` (with `extra.issues`: `HOUSE_NUMBER_MISSING`, `POSTCODE_INVALID`, `STREET_IMPLAUSIBLE`, `HOUSE_NUMBER_IMPLAUSIBLE`, `ADDRESS_UNVERIFIED`) or `INVALID_PACKSTATION`. 404 for a foreign or unknown order. The REST API does not require the preview before the change.","operationId":"ApiOrdersOrderIdDeliveryAddressPreviewPreviewDeliveryAddress","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Bestell-ID (`id` der Bestellung, ganze Zahl) / Order ID (`id` of the order, integer). Eine fremde oder unbekannte Bestellung antwortet mit 404."}],"requestBody":{"content":{"application/json":{"schema":{},"example":{"first_name":"Max","last_name":"Mustermann","street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"}}},"required":true},"responses":{"200":{"description":"Vorschau; Bestellzustand steht in `is_editable`/`blockers`, nichts wurde gespeichert / Preview; the order state is in `is_editable`/`blockers`, nothing was saved.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderDeliveryAddressPreviewResponse"},"example":{"order_id":123456,"external_reference":"SHOP-10042","order_status":"CHECK","is_editable":true,"blockers":[],"mode":"LOCAL_REROUTE","address":{"title":null,"company":null,"first_name":"Max","last_name":"Mustermann","care_of":null,"street":"Musterstraße","house_number":"1","postcode":"50667","city":"Köln","country":"DE","email":"max.mustermann@example.com"},"fingerprint":"a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90","confirmed_summary":"Lieferadresse Bestellung SHOP-10042: Musterstraße 1, 50667 Köln, DE"}}}},"400":{"description":"Ungültige Anfrage (Body oder Parameter) / Invalid request (body or parameters).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"422":{"description":"Anfrage nicht vorschaubar; `extra.error` ist `INVALID_FIELDS` (mit `extra.fields`), `INVALID_DELIVERY_ADDRESS` (mit `extra.issues`) oder `INVALID_PACKSTATION` / Request cannot be previewed; `extra.error` is `INVALID_FIELDS` (with `extra.fields`), `INVALID_DELIVERY_ADDRESS` (with `extra.issues`) or `INVALID_PACKSTATION`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderErrorResponse"}}}},"404":{"description":"Bestellung nicht gefunden oder gehört nicht zum Konto / Order not found or not owned by the account.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"]}},"/api/orders/{order_id}/delivery-receipt":{"post":{"tags":["Orders"],"summary":"Upload a delivery receipt insert","operationId":"ApiOrdersOrderIdDeliveryReceiptUploadDeliveryReceipt","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Numerische ID der Bestellung, zu der der Lieferschein gehört. / Numeric ID of the order the delivery receipt belongs to."}],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"file":{"type":"string","format":"binary","contentMediaType":"application/octet-stream"}},"type":"object"}}},"required":true},"responses":{"201":{"description":"Lieferschein gespeichert; `per_mo` nennt je Fertigungsauftrag, ob er mitgegeben wird. / Delivery receipt stored; `per_mo` states per manufacturing order whether it is handed over.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadDeliveryReceiptResponse"},"example":{"document_id":940001,"overall":"PARTIAL","per_mo":[{"manufacturing_order_id":920001,"manufacturer_id":11,"outcome":"WILL_ATTACH","message":"Wird beim Transfer an den Hersteller mitgegeben."},{"manufacturing_order_id":920002,"manufacturer_id":12,"outcome":"TOO_LATE","message":"Zu spät — der Auftrag wurde bereits an den Hersteller übertragen."}]}}}},"400":{"description":"Ungültige Bestell-ID oder fehlerhafter Multipart-Body. / Invalid order ID or malformed multipart body.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Bestellung unbekannt oder gehört einem anderen Händler. / Order unknown or owned by another merchant.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"409":{"description":"Für diese Bestellung läuft bereits ein Upload; später erneut senden. / An upload for this order is already in progress; send again later.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"413":{"description":"Die Datei ist größer als 25 MiB. / The file is larger than 25 MiB.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"422":{"description":"Der Dateityp ist nicht erlaubt; zulässig sind PDF, PNG und JPEG. / The file type is not allowed; PDF, PNG and JPEG are accepted.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:create","merchant_order:write"],"description":"Lädt einen eigenen Lieferschein (Beileger) für eine Bestellung des Händlers hoch (Scope `merchant_order:create` oder `merchant_order:write`). Der Request ist `multipart/form-data` mit einer Datei im Feld `file`. Erlaubt sind PDF, PNG und JPEG bis 25 MiB; der Dateityp wird am Inhalt erkannt, nicht am Dateinamen oder Content-Type. Die Datei wird immer gespeichert. Ein zuvor hochgeladener Lieferschein derselben Bestellung wird dadurch ersetzt.\n\nDer Lieferschein wird nur bei der Übergabe an den Produktionspartner mitgegeben; es findet kein Aufruf beim Partner statt. Die Antwort nennt je Fertigungsauftrag, was passiert (`per_mo`): `WILL_ATTACH` (wird bei der Übergabe mitgegeben), `TOO_LATE` (bereits übergeben, wird nicht mehr mitgegeben) oder `UNSUPPORTED` (der Partner unterstützt keine Lieferscheine). `overall` fasst zusammen: `OK` (alle Fertigungsaufträge nehmen ihn mit), `PARTIAL` (nur ein Teil) oder `STORED_ONLY` (keiner, oder es gibt noch keinen Fertigungsauftrag). Eine fremde oder unbekannte Bestell-ID ergibt 404. Ein nicht erlaubter Dateityp ergibt 422, eine zu große Datei einen Fehler wegen der Request-Größe (413), ein gleichzeitiger zweiter Upload für dieselbe Bestellung 409.\n\nUploads an own delivery receipt (insert) for an order of the merchant (scope `merchant_order:create` or `merchant_order:write`). The request is `multipart/form-data` with one file in the field `file`. PDF, PNG and JPEG up to 25 MiB are allowed; the file type is detected from the content, not from the file name or content type. The file is always stored. A previously uploaded receipt of the same order is replaced by it.\n\nThe receipt is only handed over at transfer to the production partner; no call to the partner takes place now. The response states per manufacturing order what happens (`per_mo`): `WILL_ATTACH` (handed over at transfer), `TOO_LATE` (already transferred, no longer handed over) or `UNSUPPORTED` (the partner does not support delivery receipts). `overall` summarises: `OK` (all manufacturing orders take it along), `PARTIAL` (only some) or `STORED_ONLY` (none, or there is no manufacturing order yet). An order ID owned by someone else or unknown returns 404. A file type that is not allowed returns 422, a file that is too large a request-size error (413), a concurrent second upload for the same order 409."}},"/api/orders/{order_id}/items":{"post":{"tags":["Orders"],"summary":"Add an order item","operationId":"ApiOrdersOrderIdItemsAddOrderItem","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Bestell-ID (`id` der Bestellung, ganze Zahl) / Order ID (`id` of the order, integer). Eine fremde oder unbekannte Bestellung antwortet mit 404."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderItemAddRequest"},"example":{"sku":"TSHIRT-BLK-M","external_id":"POS-3","processings":[{"processing_type":"DTG","position":"FRONT","design_url":"https://designs.example.com/motiv-1.png"}],"reason":"Zusätzliche Position auf Kundenwunsch"}}},"required":true},"responses":{"201":{"description":"Position hinzugefügt, Antwort ist die neue Position / Item added, the response is the new item.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserItemResponse"},"example":{"id":9003,"order_id":123456,"product_variant_id":502,"item_group":"3f2b8c1e-5d4a-4e7b-9a10-2c6d8e4f1a77","external_id":"POS-3","item_id":null,"sales_price":null,"product_price":1290,"created_at":"2026-01-15T10:30:00Z","processings":[{"id":77003,"processing_type_id":2,"processing_type":"DTG","position":"FRONT","preview_url":null,"status":"PENDING"}],"article":{"sku":"TSHIRT-BLK-M","product_name":"Basic T-Shirt"}}}}},"400":{"description":"Ungültiger Body, z. B. doppelte `position`, `design_url` ohne `https` oder weder `design_url` noch `design_reference` / Invalid body, e.g. duplicate `position`, `design_url` without `https`, or neither `design_url` nor `design_reference`.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Das Feld ist für Händlerschlüssel nicht erlaubt (Preise, Branding, Integrationsdaten, Druckgeometrie); `detail` nennt die Felder / A field is not allowed for merchant keys (prices, branding, integration data, print geometry); `detail` names the fields.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"404":{"description":"Bestellung nicht gefunden oder gehört nicht zum Konto / Order not found or not owned by the account.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"409":{"description":"Bestellung ist nicht mehr änderbar, `extra.blockers` nennt die Gründe / Order is no longer changeable, `extra.blockers` lists the reasons.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"422":{"description":"Unbekannte, inaktive oder mehrdeutige `sku`, `external_id`/`item_id` schon vergeben oder eine aktive Rechnung blockiert die Änderung / an active invoice blocks the change.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"503":{"description":"Der Stand der Bestellung ist gerade nicht abgleichbar, später erneut versuchen / Order state cannot be reconciled right now, retry later.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:items","merchant_order:write"],"description":"Fügt einer bestehenden Bestellung eine Position hinzu (Menge immer 1). Der Preis kommt aus dem Katalog; Preis-, Branding- und Integrationsfelder sowie Druckgeometrie sind für Händlerschlüssel nicht erlaubt (403, `detail` nennt die Felder).\n\nVoraussetzung: Die Bestellung ist noch änderbar. Das trifft zu, wenn der Bestellstatus `PENDING`, `READY`, `ERROR`, `CHECK` oder `PAUSE` ist, kein Teil der Bestellung gerade an die Produktion übergeben wird, bereits übergeben, angelegt, versendet oder storniert ist und keine automatische Motivprüfung (DTF) läuft. Andernfalls antwortet die Operation mit 409; `extra.blockers` nennt die Gründe (Werte von `EditabilityBlocker`).\n\n**Wirkung:** Bereits erzeugte Zuteilungen an Hersteller werden verworfen, die Verarbeitung der Bestellung wird angehalten und die Bestellung muss neu zugeteilt werden. Über die Händler-API gibt es dafür keinen Neustart-Aufruf; `PUT /api/orders/{order_id}/items/variants` stößt den Neustart selbst an. Eine aktive Rechnung blockiert das Hinzufügen (422).\n\n**Fehler:** 403 bei nicht erlaubten Feldern; 404 bei fremder oder unbekannter Bestellung; 409 bei nicht änderbarer Bestellung; 422 bei unbekanntem oder inaktivem `sku`, mehrdeutigem `sku`, bereits vergebener `external_id` oder `item_id` unter den aktiven Positionen, aktiver Rechnung; 400 bei ungültigem Body (z. B. doppelte `position` in `processings`, kein `https`-`design_url`, weder `design_url` noch `design_reference`); 503 wenn der Stand der Bestellung gerade nicht abgleichbar ist. Antwort 201: die neue Position.\n\nAdds an item to an existing order (quantity is always 1). The price comes from the catalog; price, branding and integration fields as well as print geometry are not allowed for merchant keys (403, `detail` names the fields).\n\nPrecondition: the order is still changeable. That holds when the order status is `PENDING`, `READY`, `ERROR`, `CHECK` or `PAUSE`, no part of the order is being handed to production, has been handed over, created, shipped or canceled, and no automatic motif check (DTF) is running. Otherwise the operation answers 409; `extra.blockers` lists the reasons (values of `EditabilityBlocker`).\n\n**Effect:** Manufacturer assignments already created are discarded, processing of the order is paused and the order must be routed again. The merchant API has no restart call for this; `PUT /api/orders/{order_id}/items/variants` triggers the restart itself. An active invoice blocks adding (422).\n\n**Errors:** 403 for disallowed fields; 404 for a foreign or unknown order; 409 if the order is not changeable; 422 for an unknown or inactive `sku`, an ambiguous `sku`, an `external_id` or `item_id` already used by an active item, or an active invoice; 400 for an invalid body (e.g. duplicate `position` in `processings`, a non-`https` `design_url`, neither `design_url` nor `design_reference`); 503 if the state of the order cannot be reconciled right now. Response 201: the new item."}},"/api/orders/{order_id}/items/preview":{"post":{"tags":["Orders"],"summary":"Preview variant swap","description":"Zeigt, was `PUT /api/orders/{order_id}/items/variants` mit denselben Positionen jetzt bewirken würde. Es wird nichts geschrieben. Der Body ist identisch zum Sammel-Tausch (`items` und optional `reason`).\n\n**Antwort 200:** Jede Position wird mit den Regeln des Sammel-Tauschs geprüft (nur Varianten desselben Produkts) und erscheint in `positions` mit alter und neuer Variante. `is_editable` und `blockers` zeigen, ob die Bestellung jetzt änderbar ist (Zustand der Bestellung, kein Fehler). Die Vorschau sperrt und gleicht nichts ab; Bestellungen mit fehlgeschlagener Übergabe können daher `MO_RECONCILE_UNAVAILABLE` melden, obwohl der Tausch nach dem Abgleich gelingt. `restart_follows` und `further_changes_blocked_after_restart` beschreiben die Folge: Nach dem Tausch folgt ein Neustart, danach sind keine weiteren Änderungen mehr möglich, sobald die Bestellung wieder zugeteilt ist.\n\n**Antwort 422:** `extra.error` nennt die Ursache mit `extra.item_id` der ersten abgelehnten Position: `INVALID_FIELDS`, `ITEM_NOT_FOUND`, `ITEM_INACTIVE`, `DUPLICATE_ITEM`, `VARIANT_NOT_FOUND`, `SAME_VARIANT`, `CROSS_PRODUCT_SWAP`, `VARIANT_INACTIVE` (mit `extra.alternative_variant_ids`, ggf. leer) oder `PLACEHOLDER_ITEM`. 404 bei fremder oder unbekannter Bestellung. Die REST-API verlangt die Vorschau nicht vor dem Tausch.\n\nShows what `PUT /api/orders/{order_id}/items/variants` would do now with the same positions. Nothing is written. The body is identical to the batch swap (`items` and optional `reason`).\n\n**Response 200:** Each position is checked with the rules of the batch swap (variants of the same product only) and appears in `positions` with old and new variant. `is_editable` and `blockers` show whether the order is changeable now (state of the order, not an error). The preview takes no lock and runs no reconciliation; orders with a failed handover can therefore report `MO_RECONCILE_UNAVAILABLE` although the swap succeeds after the reconciliation. `restart_follows` and `further_changes_blocked_after_restart` describe the consequence: a restart follows the swap, after which no further changes are possible once the order is routed again.\n\n**Response 422:** `extra.error` names the cause, with `extra.item_id` of the first rejected position: `INVALID_FIELDS`, `ITEM_NOT_FOUND`, `ITEM_INACTIVE`, `DUPLICATE_ITEM`, `VARIANT_NOT_FOUND`, `SAME_VARIANT`, `CROSS_PRODUCT_SWAP`, `VARIANT_INACTIVE` (with `extra.alternative_variant_ids`, possibly empty) or `PLACEHOLDER_ITEM`. 404 for a foreign or unknown order. The REST API does not require the preview before the swap.","operationId":"ApiOrdersOrderIdItemsPreviewPreviewItemsVariantSwap","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Bestell-ID (`id` der Bestellung, ganze Zahl) / Order ID (`id` of the order, integer). Eine fremde oder unbekannte Bestellung antwortet mit 404."}],"requestBody":{"content":{"application/json":{"schema":{},"example":{"items":[{"item_id":9001,"product_variant_id":503},{"item_id":9002,"product_variant_id":513}],"reason":"Kunde wünscht Größe L"}}},"required":true},"responses":{"200":{"description":"Vorschau des Sammel-Tauschs, nichts wurde geschrieben / Preview of the batch swap, nothing was written.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderItemsVariantSwapPreviewResponse"},"example":{"order_id":123456,"external_reference":"SHOP-10042","order_status":"PENDING","is_editable":true,"blockers":[],"positions":[{"item_id":9001,"current_product_variant_id":502,"current_sku":"TSHIRT-BLK-M","new_product_variant_id":503,"new_sku":"TSHIRT-BLK-L","product_price":1290},{"item_id":9002,"current_product_variant_id":512,"current_sku":"TSHIRT-WHT-M","new_product_variant_id":513,"new_sku":"TSHIRT-WHT-L","product_price":1290}],"restart_follows":true,"further_changes_blocked_after_restart":true,"fingerprint":"a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90","confirmed_summary":"Variantentausch Bestellung SHOP-10042: 2 Position(en)"}}}},"400":{"description":"Ungültige Anfrage (Body oder Parameter) / Invalid request (body or parameters).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"422":{"description":"Position nicht vorschaubar; `extra.error` nennt die Ursache, `extra.item_id` die Position / Position cannot be previewed; `extra.error` names the cause, `extra.item_id` the position.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderErrorResponse"}}}},"404":{"description":"Bestellung nicht gefunden oder gehört nicht zum Konto / Order not found or not owned by the account.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:read"]}},"/api/orders/{order_id}/items/variants":{"put":{"tags":["Orders"],"summary":"Swap the variants of several order items","operationId":"ApiOrdersOrderIdItemsVariantsReplaceOrderItemVariants","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Bestell-ID (`id` der Bestellung, ganze Zahl) / Order ID (`id` of the order, integer). Eine fremde oder unbekannte Bestellung antwortet mit 404."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderItemsVariantSwapRequest"},"example":{"items":[{"item_id":9001,"product_variant_id":503},{"item_id":9002,"product_variant_id":513}],"reason":"Kunde wünscht Größe L"}}},"required":true},"responses":{"200":{"description":"Varianten getauscht; `restart_triggered` und `restart_required` zeigen den Neustart-Stand / Variants swapped; `restart_triggered` and `restart_required` show the restart state.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserItemsVariantSwapResponse"},"example":{"items":[{"id":9001,"order_id":123456,"product_variant_id":503,"item_group":"3f2b8c1e-5d4a-4e7b-9a10-2c6d8e4f1a77","external_id":null,"item_id":null,"sales_price":null,"product_price":1290,"created_at":"2026-01-15T10:30:00Z","processings":[{"id":77001,"processing_type_id":2,"processing_type":"DTG","position":"FRONT","preview_url":null,"status":"PENDING"}],"article":{"sku":"TSHIRT-BLK-L","product_name":"Basic T-Shirt"}},{"id":9002,"order_id":123456,"product_variant_id":513,"item_group":"3f2b8c1e-5d4a-4e7b-9a10-2c6d8e4f1a77","external_id":null,"item_id":null,"sales_price":null,"product_price":1290,"created_at":"2026-01-15T10:30:00Z","processings":[{"id":77002,"processing_type_id":2,"processing_type":"DTG","position":"FRONT","preview_url":null,"status":"PENDING"}],"article":{"sku":"TSHIRT-WHT-L","product_name":"Basic T-Shirt"}}],"restart_triggered":true,"restart_required":false,"restart_error":null,"restart_detail":null}}}},"400":{"description":"Ungültige Anfrage (Body oder Parameter) / Invalid request (body or parameters).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Bestellung, Position oder Zielvariante nicht gefunden (`extra.error` `ITEM_NOT_FOUND`/`VARIANT_NOT_FOUND`) / Order, item or target variant not found (`extra.error` `ITEM_NOT_FOUND`/`VARIANT_NOT_FOUND`).","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"409":{"description":"Bestellung nicht änderbar (`extra.blockers`) oder gleichzeitige Änderung einer Position / Order not changeable (`extra.blockers`) or a concurrent change of an item.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"410":{"description":"Eine Position wurde bereits entfernt (`extra.error` `ITEM_INACTIVE`) / An item has already been removed (`extra.error` `ITEM_INACTIVE`).","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"422":{"description":"Position abgelehnt (`extra.error`: `SAME_VARIANT`, `CROSS_PRODUCT_SWAP`, `VARIANT_INACTIVE`, `DUPLICATE_ITEM`, `PLACEHOLDER_ITEM`, mit `extra.item_id`) oder eine aktive Rechnung blockiert die Änderung / an active invoice blocks the change.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"503":{"description":"Der Stand der Bestellung ist gerade nicht abgleichbar, später erneut versuchen / Order state cannot be reconciled right now, retry later.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:items","merchant_order:write"],"description":"Tauscht die Varianten mehrerer Positionen in **einer** Transaktion gegen andere Varianten desselben Produkts und startet danach den Neustart der Bestellung. Scheitert eine Position, wird nichts geschrieben (alles oder nichts). Vorab zeigt `POST /api/orders/{order_id}/items/preview`, was der Tausch bewirken würde.\n\nVoraussetzung: Die Bestellung ist noch änderbar. Das trifft zu, wenn der Bestellstatus `PENDING`, `READY`, `ERROR`, `CHECK` oder `PAUSE` ist, kein Teil der Bestellung gerade an die Produktion übergeben wird, bereits übergeben, angelegt, versendet oder storniert ist und keine automatische Motivprüfung (DTF) läuft. Andernfalls antwortet die Operation mit 409; `extra.blockers` nennt die Gründe (Werte von `EditabilityBlocker`).\n\n**Neustart:** Der Tausch wird zuerst festgeschrieben, danach wird die Bestellung im selben Aufruf neu angestoßen. Verweigert der Neustart die Ausführung, bleibt der Tausch bestehen; die Antwort hat dann `restart_triggered: false`, `restart_required: true` sowie `restart_error` (Code) und `restart_detail` (Text). Mögliche Codes sind u. a. `NOT_RESTARTABLE`, `NO_ELIGIBLE_MANUFACTURER`, `ORDER_NOT_FOUND`, `CANCELLATION_PENDING`, `MO_DELETE_RESTRICTED`, `UNCONFIRMED_CANCEL`, `CREDIT_NOTE_MISSING`, `SUBSET_ITEMS_ALREADY_COVERED`, `UNCANCELED_DIRECT_DISPATCH`, `TESTLAUF_STRANDED`, `ACTIVE_REORDER_EXISTS`.\n\n**Fehler:** 404 bei fremder oder unbekannter Bestellung, Position oder Zielvariante (`extra.error` `ITEM_NOT_FOUND`/`VARIANT_NOT_FOUND`); 409 bei nicht änderbarer Bestellung (`extra.blockers`) oder gleichzeitiger Änderung; 410 bei entfernter Position (`ITEM_INACTIVE`); 422 bei `SAME_VARIANT`, `CROSS_PRODUCT_SWAP`, `VARIANT_INACTIVE`, `DUPLICATE_ITEM`, `PLACEHOLDER_ITEM` (jeweils `extra.error` und `extra.item_id`) oder aktiver Rechnung; 503 wenn der Stand der Bestellung gerade nicht abgleichbar ist. Antwort 200: die getauschten Positionen und der Neustart-Stand.\n\nSwaps the variants of several items for other variants of the same product in **one** transaction and then restarts the order. If one position fails, nothing is written (all or nothing). `POST /api/orders/{order_id}/items/preview` shows beforehand what the swap would do.\n\nPrecondition: the order is still changeable. That holds when the order status is `PENDING`, `READY`, `ERROR`, `CHECK` or `PAUSE`, no part of the order is being handed to production, has been handed over, created, shipped or canceled, and no automatic motif check (DTF) is running. Otherwise the operation answers 409; `extra.blockers` lists the reasons (values of `EditabilityBlocker`).\n\n**Restart:** The swap is committed first, then the order is restarted within the same call. If the restart refuses to run, the swap stands; the response then has `restart_triggered: false`, `restart_required: true`, plus `restart_error` (code) and `restart_detail` (text). Possible codes include `NOT_RESTARTABLE`, `NO_ELIGIBLE_MANUFACTURER`, `ORDER_NOT_FOUND`, `CANCELLATION_PENDING`, `MO_DELETE_RESTRICTED`, `UNCONFIRMED_CANCEL`, `CREDIT_NOTE_MISSING`, `SUBSET_ITEMS_ALREADY_COVERED`, `UNCANCELED_DIRECT_DISPATCH`, `TESTLAUF_STRANDED`, `ACTIVE_REORDER_EXISTS`.\n\n**Errors:** 404 for a foreign or unknown order, item or target variant (`extra.error` `ITEM_NOT_FOUND`/`VARIANT_NOT_FOUND`); 409 if the order is not changeable (`extra.blockers`) or on a concurrent change; 410 for a removed item (`ITEM_INACTIVE`); 422 for `SAME_VARIANT`, `CROSS_PRODUCT_SWAP`, `VARIANT_INACTIVE`, `DUPLICATE_ITEM`, `PLACEHOLDER_ITEM` (each with `extra.error` and `extra.item_id`) or an active invoice; 503 if the state of the order cannot be reconciled right now. Response 200: the swapped items and the restart state."}},"/api/orders/{order_id}/items/{item_id}":{"delete":{"tags":["Orders"],"summary":"Remove an order item","operationId":"ApiOrdersOrderIdItemsItemIdSoftDeleteOrderItem","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Bestell-ID (`id` der Bestellung, ganze Zahl) / Order ID (`id` of the order, integer). Eine fremde oder unbekannte Bestellung antwortet mit 404."},{"name":"item_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Positions-ID (`id` aus der Bestellung, ganze Zahl) / Item ID (`id` of the order item, integer). Eine Position, die nicht zur Bestellung gehört, antwortet mit 404."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderItemDeleteRequest"},"example":{"reason":"CUSTOMER_CANCELLATION","note":"Endkunde hat die Position abbestellt"}}},"required":true},"responses":{"204":{"description":"Position entfernt, kein Body / Item removed, no body.","headers":{}},"400":{"description":"Ungültige Anfrage (Body oder Parameter) / Invalid request (body or parameters).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"`apply_wallet_correction` darf ein Händlerschlüssel nicht setzen / A merchant key must not set `apply_wallet_correction`.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"404":{"description":"Bestellung oder Position nicht gefunden / Order or item not found.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"409":{"description":"Bestellung ist nicht mehr änderbar, `extra.blockers` nennt die Gründe / Order is no longer changeable, `extra.blockers` lists the reasons.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"410":{"description":"Position wurde bereits entfernt / The item has already been removed.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"422":{"description":"Letzte aktive Position (stattdessen die Bestellung stornieren) oder eine aktive Rechnung blockiert die Änderung / an active invoice blocks the change.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"503":{"description":"Der Stand der Bestellung ist gerade nicht abgleichbar, später erneut versuchen / Order state cannot be reconciled right now, retry later.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:items","merchant_order:write"],"description":"Entfernt eine Position aus der Bestellung. Die Position wird deaktiviert, nicht physisch gelöscht; sie erscheint danach nicht mehr als aktive Position. Der Body ist Pflicht (`reason`).\n\nVoraussetzung: Die Bestellung ist noch änderbar. Das trifft zu, wenn der Bestellstatus `PENDING`, `READY`, `ERROR`, `CHECK` oder `PAUSE` ist, kein Teil der Bestellung gerade an die Produktion übergeben wird, bereits übergeben, angelegt, versendet oder storniert ist und keine automatische Motivprüfung (DTF) läuft. Andernfalls antwortet die Operation mit 409; `extra.blockers` nennt die Gründe (Werte von `EditabilityBlocker`).\n\n**Wirkung:** Bereits erzeugte Zuteilungen an Hersteller werden verworfen und die Verarbeitung der Bestellung wird angehalten; sie muss neu zugeteilt werden (über die Händler-API gibt es dafür keinen Neustart-Aufruf). Ob und wie der Betrag der Position auf dem Guthaben berücksichtigt wird, hängt vom Grund ab; `apply_wallet_correction` darf ein Händlerschlüssel nicht setzen (403).\n\n**Fehler:** 404 bei fremder oder unbekannter Bestellung oder Position; 409 bei nicht änderbarer Bestellung; 410 wenn die Position bereits entfernt ist (ein wiederholter Aufruf ist damit erkennbar); 422, wenn es die letzte aktive Position ist (stattdessen die Bestellung stornieren) oder eine aktive Rechnung die Änderung blockiert; 503 wenn der Stand der Bestellung gerade nicht abgleichbar ist. Antwort 204 ohne Body.\n\nRemoves an item from the order. The item is deactivated, not physically deleted; it no longer appears as an active item. The body is required (`reason`).\n\nPrecondition: the order is still changeable. That holds when the order status is `PENDING`, `READY`, `ERROR`, `CHECK` or `PAUSE`, no part of the order is being handed to production, has been handed over, created, shipped or canceled, and no automatic motif check (DTF) is running. Otherwise the operation answers 409; `extra.blockers` lists the reasons (values of `EditabilityBlocker`).\n\n**Effect:** Manufacturer assignments already created are discarded and processing of the order is paused; the order must be routed again (the merchant API has no restart call for this). Whether and how the item amount is reflected on the wallet depends on the reason; a merchant key must not set `apply_wallet_correction` (403).\n\n**Errors:** 404 for a foreign or unknown order or item; 409 if the order is not changeable; 410 if the item is already removed (so a repeated call is recognizable); 422 if it is the last active item (cancel the order instead) or an active invoice blocks the change; 503 if the state of the order cannot be reconciled right now. Response 204 without a body."},"patch":{"tags":["Orders"],"summary":"Swap the variant of an order item","operationId":"ApiOrdersOrderIdItemsItemIdReplaceOrderItemVariant","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Bestell-ID (`id` der Bestellung, ganze Zahl) / Order ID (`id` of the order, integer). Eine fremde oder unbekannte Bestellung antwortet mit 404."},{"name":"item_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Positions-ID (`id` aus der Bestellung, ganze Zahl) / Item ID (`id` of the order item, integer). Eine Position, die nicht zur Bestellung gehört, antwortet mit 404."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderItemReplaceVariantRequest"},"example":{"product_variant_id":503,"reason":"Kunde wünscht Größe L"}}},"required":true},"responses":{"200":{"description":"Variante getauscht, Antwort ist die aktualisierte Position / Variant swapped, the response is the updated item.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserItemResponse"},"example":{"id":9001,"order_id":123456,"product_variant_id":503,"item_group":"3f2b8c1e-5d4a-4e7b-9a10-2c6d8e4f1a77","external_id":null,"item_id":null,"sales_price":null,"product_price":1290,"created_at":"2026-01-15T10:30:00Z","processings":[{"id":77001,"processing_type_id":2,"processing_type":"DTG","position":"FRONT","preview_url":null,"status":"PENDING"}],"article":{"sku":"TSHIRT-BLK-L","product_name":"Basic T-Shirt"}}}}},"400":{"description":"Ungültige Anfrage (Body oder Parameter) / Invalid request (body or parameters).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Bestellung, Position oder Zielvariante nicht gefunden / Order, item or target variant not found.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"409":{"description":"Bestellung nicht änderbar (`extra.blockers` nennt die Gründe) oder die Variante der Position hat sich gleichzeitig geändert / Order not changeable (`extra.blockers` lists the reasons) or the item's variant changed concurrently.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"410":{"description":"Position wurde bereits entfernt / The item has already been removed.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"422":{"description":"Zielvariante inaktiv, identisch mit der aktuellen oder aus einem anderen Produkt, oder eine aktive Rechnung blockiert die Änderung / an active invoice blocks the change.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"503":{"description":"Der Stand der Bestellung ist gerade nicht abgleichbar, später erneut versuchen / Order state cannot be reconciled right now, retry later.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:items","merchant_order:write"],"description":"Tauscht die Variante (Farbe/Größe) einer einzelnen Position gegen eine andere Variante **desselben Produkts**. Für mehrere Positionen auf einmal gibt es `PUT /api/orders/{order_id}/items/variants`, das zusätzlich den Neustart auslöst. Die Position behält Motiv und Druckdaten; nur die Variante ändert sich.\n\nVoraussetzung: Die Bestellung ist noch änderbar. Das trifft zu, wenn der Bestellstatus `PENDING`, `READY`, `ERROR`, `CHECK` oder `PAUSE` ist, kein Teil der Bestellung gerade an die Produktion übergeben wird, bereits übergeben, angelegt, versendet oder storniert ist und keine automatische Motivprüfung (DTF) läuft. Andernfalls antwortet die Operation mit 409; `extra.blockers` nennt die Gründe (Werte von `EditabilityBlocker`).\n\n**Wirkung:** Bereits erzeugte Zuteilungen an Hersteller werden verworfen und die Verarbeitung der Bestellung wird angehalten; die Bestellung muss neu zugeteilt werden. Dieser Aufruf startet das nicht selbst (anders als der Sammel-Tausch); über die Händler-API gibt es dafür keinen Neustart-Aufruf. Eigene Mockups der Position werden ungültig.\n\n**Fehler:** 404 bei fremder oder unbekannter Bestellung, Position oder Zielvariante; 409 bei nicht änderbarer Bestellung oder wenn sich die Variante der Position gleichzeitig geändert hat; 410 bei bereits entfernter Position; 422, wenn die Zielvariante (oder ihr Produkt) inaktiv ist, der aktuellen Variante entspricht, zu einem anderen Produkt gehört oder eine aktive Rechnung die Änderung blockiert; 503 wenn der Stand der Bestellung gerade nicht abgleichbar ist. Antwort 200: die aktualisierte Position.\n\nSwaps the variant (color/size) of a single item for another variant **of the same product**. For several items at once use `PUT /api/orders/{order_id}/items/variants`, which also triggers the restart. The item keeps its motif and print data; only the variant changes.\n\nPrecondition: the order is still changeable. That holds when the order status is `PENDING`, `READY`, `ERROR`, `CHECK` or `PAUSE`, no part of the order is being handed to production, has been handed over, created, shipped or canceled, and no automatic motif check (DTF) is running. Otherwise the operation answers 409; `extra.blockers` lists the reasons (values of `EditabilityBlocker`).\n\n**Effect:** Manufacturer assignments already created are discarded and processing of the order is paused; the order must be routed again. This call does not start that itself (unlike the batch swap); the merchant API has no restart call for it. Own mockups of the item become invalid.\n\n**Errors:** 404 for a foreign or unknown order, item or target variant; 409 if the order is not changeable or the item's variant changed concurrently; 410 for an already removed item; 422 if the target variant (or its product) is inactive, equals the current one, belongs to another product, or an active invoice blocks the change; 503 if the state of the order cannot be reconciled right now. Response 200: the updated item."}},"/api/orders/{order_id}/reorder":{"post":{"tags":["Orders"],"summary":"Reorder an existing order","operationId":"ApiOrdersOrderIdReorderReorderOrder","parameters":[{"name":"order_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"Numerische ID der Quellbestellung, die nachbestellt wird. / Numeric ID of the source order to re-order."},{"name":"pricing","in":"query","schema":{"$ref":"#/components/schemas/ReorderPricingMode"},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Preismodus. Für Händler wird immer `original` angewendet; abweichende Werte werden ignoriert. / Pricing mode. For merchants `original` always applies; other values are ignored."},{"name":"Idempotency-Key","in":"header","schema":{"oneOf":[{"type":"string"},{"type":"null"}],"pattern":"^[!-~]{1,128}$"},"description":"Optional. 1 bis 128 sichtbare ASCII-Zeichen (z. B. eine UUID). Wiederholung mit demselben Schlüssel für dieselbe Quellbestellung liefert die erste Nachbestellung erneut, ohne zweite Belastung des Guthabens. / Optional. 1 to 128 visible ASCII characters (e.g. a UUID). A repeat with the same key for the same source order returns the first re-order again, without a second balance charge.","required":false,"deprecated":false}],"requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/OrderReorderRequest"},{"type":"null"}]},"example":{"item_ids":[900101]}}},"required":true},"responses":{"201":{"description":"Nachbestellung angelegt. Bei Wiederholung mit gleichem `Idempotency-Key` kommt dieselbe Nachbestellung erneut. / Re-order created. A repeat with the same `Idempotency-Key` returns the same re-order.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUserResponse"},"example":{"id":900003,"slug":"CL-3N6TQ8B","internal_reference":null,"external_reference":"RE-SHOP-10045","reordered_from_order_id":900001,"designer_id":"4711","status":"PENDING","created_at":"2026-01-20T08:00:00Z","updated_at":"2026-01-20T08:00:00Z","retention":null}}}},"400":{"description":"Die Bestellung lässt sich nicht nachbilden oder die Auswahl ist ungültig; `extra.error` nennt die Ursache (`SOURCE_VARIANT_UNAVAILABLE`, `SKU_NOT_FOUND`, `PROCESSING_TYPE_NOT_FOUND`, `INVALID_DELIVERY_ADDRESS`, `ITEM_NOT_IN_ORDER`, `NO_LINE_ITEMS`). Ohne Änderung nicht wiederholbar. / The order cannot be reconstructed or the selection is invalid; `extra.error` names the cause (`SOURCE_VARIANT_UNAVAILABLE`, `SKU_NOT_FOUND`, `PROCESSING_TYPE_NOT_FOUND`, `INVALID_DELIVERY_ADDRESS`, `ITEM_NOT_IN_ORDER`, `NO_LINE_ITEMS`). Do not retry unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderErrorResponse"}}}},"403":{"description":"Der Body enthält `variant_overrides`, `delivery_address` oder `allow_open_source`; diese Optionen sind für Händler nicht verfügbar. / The body contains `variant_overrides`, `delivery_address` or `allow_open_source`; these options are not available to merchants.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderErrorResponse"}}}},"404":{"description":"Quellbestellung unbekannt oder gehört einem anderen Händler. / Source order unknown or owned by another merchant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderErrorResponse"}}}},"409":{"description":"Ohne `extra.error`: kurzzeitiger Konflikt bei der Referenzvergabe, unverändert wiederholbar. Mit `extra.error=SOURCE_STILL_IN_PRODUCTION`: Die Produktion der Quelle läuft noch (`extra.open_manufacturing_order_count`), nichts wurde angelegt. / Without `extra.error`: short-lived conflict while assigning the reference, retry unchanged. With `extra.error=SOURCE_STILL_IN_PRODUCTION`: production of the source is still running (`extra.open_manufacturing_order_count`), nothing was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["merchant_order:create","merchant_order:write"],"description":"Legt aus einer bestehenden Bestellung des Händlers eine neue Bestellung an (Scope `merchant_order:create` oder `merchant_order:write`). Die neue Bestellung übernimmt Positionen, Veredelungen, Adressen und Preise der Quellbestellung und durchläuft die normale Anlage mit neuer Zuweisung. Ihre `external_reference` erhält das Präfix `RE-` (bei weiteren Nachbestellungen `RE2-`, `RE3-` …), `reordered_from_order_id` verweist auf die Quelle. Für Händler gilt immer `pricing=original`: Die Preise der Quelle werden 1:1 übernommen und der Betrag wird dem Guthaben des Händlers belastet; der Parameter `pricing` wird ignoriert. Der Body ist optional; wirksam ist nur `item_ids`, um nur einen Teil der Positionen nachzubestellen. `variant_overrides`, `delivery_address` und `allow_open_source` sind für Händler nicht erlaubt und ergeben 403.\n\nEine Bestellung mit noch laufender Produktion kann nicht nachbestellt werden: Hat sie einen Fertigungsauftrag, der weder versendet noch storniert ist, antwortet die API mit 409 und `extra.error=SOURCE_STILL_IN_PRODUCTION` sowie `extra.open_manufacturing_order_count`; es wurde nichts angelegt, ein Wiederholen hilft erst nach Ende oder Storno der Produktion. Bei einer Teil-Nachbestellung blockieren nur offene Fertigungsaufträge, die eine gewählte Position enthalten. Ein 409 ohne `extra.error` ist ein kurzzeitiger Konflikt bei der Referenzvergabe und kann ohne Änderung wiederholt werden. 400 mit `extra.error` heißt, dass sich die Bestellung nicht nachbilden lässt (`SOURCE_VARIANT_UNAVAILABLE`, `SKU_NOT_FOUND`, `PROCESSING_TYPE_NOT_FOUND`, `INVALID_DELIVERY_ADDRESS` mit `extra.issues`, `ITEM_NOT_IN_ORDER`, `NO_LINE_ITEMS`); ein Wiederholen ohne Änderung hilft nicht. Eine fremde oder unbekannte Quell-ID ergibt 404.\n\nMit dem optionalen Header `Idempotency-Key` ist der Aufruf wiederholbar: Derselbe Schlüssel für dieselbe Quellbestellung liefert die erste Nachbestellung erneut (201, gleicher Inhalt) und belastet das Guthaben kein zweites Mal. `pricing` und `item_ids` einer Wiederholung werden nicht mit dem ersten Aufruf verglichen; die erste Nachbestellung gilt.\n\nCreates a new order from an existing order of the merchant (scope `merchant_order:create` or `merchant_order:write`). The new order takes over items, processings, addresses and prices of the source order and goes through normal creation with a fresh assignment. Its `external_reference` gets the prefix `RE-` (`RE2-`, `RE3-` … for further re-orders), and `reordered_from_order_id` points to the source. For merchants `pricing=original` always applies: the source prices are taken over 1:1 and the amount is charged to the merchant balance; the `pricing` parameter is ignored. The body is optional; only `item_ids` takes effect, to re-order just part of the items. `variant_overrides`, `delivery_address` and `allow_open_source` are not allowed for merchants and return 403.\n\nAn order whose production is still running cannot be re-ordered: if it has a manufacturing order that is neither shipped nor canceled, the API responds with 409 and `extra.error=SOURCE_STILL_IN_PRODUCTION` plus `extra.open_manufacturing_order_count`; nothing was created, and retrying only helps once production has ended or been canceled. For a partial re-order, only open manufacturing orders containing a selected item block. A 409 without `extra.error` is a short-lived conflict while assigning the reference and can be retried unchanged. 400 with `extra.error` means the order cannot be reconstructed (`SOURCE_VARIANT_UNAVAILABLE`, `SKU_NOT_FOUND`, `PROCESSING_TYPE_NOT_FOUND`, `INVALID_DELIVERY_ADDRESS` with `extra.issues`, `ITEM_NOT_IN_ORDER`, `NO_LINE_ITEMS`); retrying unchanged does not help. A source ID owned by someone else or unknown returns 404.\n\nWith the optional `Idempotency-Key` header the call is repeatable: the same key for the same source order returns the first re-order again (201, same content) and does not charge the balance a second time. `pricing` and `item_ids` of a repeat are not compared with the first call; the first re-order wins."}},"/api/product-colors":{"get":{"tags":["Product Colors"],"summary":"List product colors","operationId":"ApiProductColorsGetProductColors","responses":{"200":{"description":"Erfolg, die Antwort enthält die Daten / Success, the response contains the data.","headers":{},"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ProductColorResponse"},"type":"array"},"example":[{"id":21,"primary_color":"Navy","primary_hex":"#1f2a44","secondary_color":null,"secondary_hex":null}]}}},"403":{"description":"Der Schlüssel trägt keinen für diese Operation erforderlichen Scope / The key does not hold a scope required for this operation.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_catalog:read"],"description":"Liefert alle Farben des Katalogs. Das ist eine globale Nachschlageliste ohne Paginierung und ohne Filter, unabhängig vom Händler. Eine Variante verweist über `color_id` auf einen Eintrag; die Liste dient dazu, Farbfelder mit Anzeigename und Hex-Wert darzustellen. Die Anzeigebezeichnung einer Variante steht bereits in `color_label`. Ein Schlüssel ohne den erforderlichen Scope erhält 403, ein ungültiger Aufruf (z. B. Parameter mit falschem Typ) 400.\n\nReturns all colors of the catalog. This is a global lookup list without pagination or filters, independent of the merchant. A variant references an entry through `color_id`; use the list to render color swatches with display name and hex value. The display label of a variant is already in `color_label`. A key without the required scope receives 403; an invalid call (for example a parameter of the wrong type) receives 400."}},"/api/product-colors/{color_id}":{"get":{"tags":["Product Colors"],"summary":"Get a product color","operationId":"ApiProductColorsColorIdGetProductColor","parameters":[{"name":"color_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Farbe (Feld `color_id` einer Variante bzw. `id` in der Farbliste); unbekannte IDs ergeben 404 / Color ID (`color_id` of a variant, `id` in the color list); unknown IDs return 404."}],"responses":{"200":{"description":"Erfolg, die Antwort enthält die Daten / Success, the response contains the data.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductColorResponse"},"example":{"id":21,"primary_color":"Navy","primary_hex":"#1f2a44","secondary_color":null,"secondary_hex":null}}}},"400":{"description":"Ungültige Anfrage, z. B. ein Parameter mit falschem Typ oder Wert / Invalid request, for example a parameter of the wrong type or value.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Der Schlüssel trägt keinen für diese Operation erforderlichen Scope / The key does not hold a scope required for this operation.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"404":{"description":"Nicht gefunden: die ID bzw. SKU ist unbekannt oder gehört einem anderen Händler / Not found: the ID or SKU is unknown or belongs to another merchant.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_catalog:read"],"description":"Liefert eine einzelne Farbe anhand ihrer ID, zum Beispiel die `color_id` einer Variante. Die Farben sind global und nicht an einen Händler gebunden. Eine unbekannte ID ergibt 404. Ein Schlüssel ohne den erforderlichen Scope erhält 403, ein ungültiger Aufruf (z. B. Parameter mit falschem Typ) 400.\n\nReturns a single color by ID, for example the `color_id` of a variant. Colors are global and not bound to a merchant. An unknown ID yields 404. A key without the required scope receives 403; an invalid call (for example a parameter of the wrong type) receives 400."}},"/api/product-sizes":{"get":{"tags":["Product Sizes"],"summary":"List product sizes","operationId":"ApiProductSizesGetProductSizes","responses":{"200":{"description":"Erfolg, die Antwort enthält die Daten / Success, the response contains the data.","headers":{},"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ProductSizeResponse"},"type":"array"},"example":[{"id":3,"name":"M"}]}}},"403":{"description":"Der Schlüssel trägt keinen für diese Operation erforderlichen Scope / The key does not hold a scope required for this operation.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_catalog:read"],"description":"Liefert alle Größen des Katalogs. Das ist eine globale Nachschlageliste ohne Paginierung und ohne Filter, unabhängig vom Händler. Eine Variante verweist über `size_id` auf einen Eintrag. Die Anzeigebezeichnung einer Variante steht bereits in `size_label`. Ein Schlüssel ohne den erforderlichen Scope erhält 403, ein ungültiger Aufruf (z. B. Parameter mit falschem Typ) 400.\n\nReturns all sizes of the catalog. This is a global lookup list without pagination or filters, independent of the merchant. A variant references an entry through `size_id`. The display label of a variant is already in `size_label`. A key without the required scope receives 403; an invalid call (for example a parameter of the wrong type) receives 400."}},"/api/product-sizes/{size_id}":{"get":{"tags":["Product Sizes"],"summary":"Get a product size","operationId":"ApiProductSizesSizeIdGetProductSize","parameters":[{"name":"size_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Größe (Feld `size_id` einer Variante bzw. `id` in der Größenliste); unbekannte IDs ergeben 404 / Size ID (`size_id` of a variant, `id` in the size list); unknown IDs return 404."}],"responses":{"200":{"description":"Erfolg, die Antwort enthält die Daten / Success, the response contains the data.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductSizeResponse"},"example":{"id":3,"name":"M"}}}},"400":{"description":"Ungültige Anfrage, z. B. ein Parameter mit falschem Typ oder Wert / Invalid request, for example a parameter of the wrong type or value.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Der Schlüssel trägt keinen für diese Operation erforderlichen Scope / The key does not hold a scope required for this operation.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"404":{"description":"Nicht gefunden: die ID bzw. SKU ist unbekannt oder gehört einem anderen Händler / Not found: the ID or SKU is unknown or belongs to another merchant.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_catalog:read"],"description":"Liefert eine einzelne Größe anhand ihrer ID, zum Beispiel die `size_id` einer Variante. Die Größen sind global und nicht an einen Händler gebunden. Eine unbekannte ID ergibt 404. Ein Schlüssel ohne den erforderlichen Scope erhält 403, ein ungültiger Aufruf (z. B. Parameter mit falschem Typ) 400.\n\nReturns a single size by ID, for example the `size_id` of a variant. Sizes are global and not bound to a merchant. An unknown ID yields 404. A key without the required scope receives 403; an invalid call (for example a parameter of the wrong type) receives 400."}},"/api/product-variants":{"get":{"tags":["Product Variants"],"summary":"List product variants","operationId":"ApiProductVariantsGetProductVariants","parameters":[{"name":"product_id","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Nur Varianten dieses Produkts (ID aus `GET /api/products`); ohne Angabe alle sichtbaren Produkte / Only variants of this product (ID from `GET /api/products`); omitted means all visible products."},{"name":"limit","in":"query","schema":{"type":"integer","default":100},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Maximale Anzahl Einträge pro Antwort, Standard 100; die API begrenzt den Wert nicht / Maximum number of entries per response, default 100; the API does not clamp the value."},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anzahl zu überspringender Einträge, Standard 0; für die nächste Seite um `limit` erhöhen / Number of entries to skip, default 0; increase by `limit` for the next page."},{"name":"stock","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Bei `true` werden Bestandsfelder (`stock_total`, `gross_stock`, `reserved`, `available`, `stock_display`) berechnet, Standard `false` / When `true`, the stock fields are computed; default `false`."},{"name":"manufacturer_stock","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händlerschlüssel; Herstellerbestände werden nicht ausgeliefert / No effect for merchant keys; manufacturer stock is never returned."},{"name":"fulfillment_type","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/FulfillmentType"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Nur Varianten von Produkten dieser Fertigungsart (`ON_DEMAND`, `WAREHOUSE`, `ADDITIONAL_PRODUCT`); ohne Angabe alle / Only variants of products of this fulfillment type; omitted means all types."}],"responses":{"200":{"description":"Erfolg, die Antwort enthält die Daten / Success, the response contains the data.","headers":{},"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ProductVariantUserResponse"},"type":"array"},"example":[{"id":5001,"product_id":1001,"color_id":21,"size_id":3,"sku":"MUSTER-TS-01_Navy_M","description":null,"product_image_url":"https://example.com/bilder/muster-shirt-navy.jpg","status":"ACTIVE","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","warehouse_color":null,"warehouse_size":null,"size_label":"M","color_label":"Navy","images":[],"stock_total":120,"gross_stock":120,"reserved":20,"available":100,"stock_display":{"kind":"IN_STOCK","available_balance":100}}]}}},"400":{"description":"Ungültige Anfrage, z. B. ein Parameter mit falschem Typ oder Wert / Invalid request, for example a parameter of the wrong type or value.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Der Schlüssel trägt keinen für diese Operation erforderlichen Scope / The key does not hold a scope required for this operation.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_catalog:read"],"description":"Liefert Produktvarianten als einfache Liste: pro Eintrag eine bestellbare Einheit mit eindeutiger `sku`, Farbe (`color_id`, `color_label`) und Größe (`size_id`, `size_label`). Die Liste ist nach `sku` aufsteigend sortiert und wird mit `limit` (Standard 100) und `offset` (Standard 0) paginiert; sie liefert keine Gesamtzahl. Für Suche, Verfügbarkeitsfilter, Sortierung nach Produkt und eine Gesamtzahl ist `GET /api/product-variants/paged` gedacht; diese Liste eignet sich, um alle Varianten eines Produkts (`product_id`) oder einer Fertigungsart (`fulfillment_type`) abzuholen.\n\nSichtbar sind Varianten eigener Produkte und der gemeinsamen, keinem Händler zugeordneten `ON_DEMAND`-Produkte. Eine fremde `product_id` liefert eine leere Liste, kein 404. Inaktive Varianten sind enthalten (Feld `status`). Ohne `stock=true` bleiben die Bestandsfelder (`stock_total`, `gross_stock`, `reserved`, `available`, `stock_display`) leer; mit `stock=true` werden sie berechnet. `available` ist die verfügbare Menge: Gesamtbestand minus Reservierung, nie negativ; `stock_display` gibt an, ob die Variante ab Lager lieferbar (`IN_STOCK`) oder Auftragsware (`JIT`) ist. Ein Schlüssel ohne den erforderlichen Scope erhält 403, ein ungültiger Aufruf (z. B. Parameter mit falschem Typ) 400.\n\nReturns product variants as a plain list: each entry is one orderable unit with a unique `sku`, color (`color_id`, `color_label`) and size (`size_id`, `size_label`). The list is sorted by `sku` ascending and paginated with `limit` (default 100) and `offset` (default 0); it returns no total count. For search, availability filter, sorting by product and a total count use `GET /api/product-variants/paged`; this list suits fetching all variants of one product (`product_id`) or one fulfillment type (`fulfillment_type`).\n\nVisible are variants of own products and of the shared `ON_DEMAND` products that belong to no merchant. A foreign `product_id` yields an empty list, not 404. Inactive variants are included (field `status`). Without `stock=true` the stock fields (`stock_total`, `gross_stock`, `reserved`, `available`, `stock_display`) stay empty; with `stock=true` they are computed. `available` is the available quantity: total stock minus reservations, never negative; `stock_display` tells whether the variant is deliverable from stock (`IN_STOCK`) or made to order (`JIT`). A key without the required scope receives 403; an invalid call (for example a parameter of the wrong type) receives 400."}},"/api/product-variants/by-sku/{sku}":{"get":{"tags":["Product Variants"],"summary":"Get a product variant by SKU","operationId":"ApiProductVariantsBySkuGetProductVariantDetailBySku","parameters":[{"name":"sku","in":"path","schema":{"type":"string"},"required":true,"deprecated":false,"description":"SKU der Variante (Feld `sku`), ohne Beachtung der Groß-/Kleinschreibung; unbekannte oder fremde SKUs ergeben 404 / Variant SKU (field `sku`), case-insensitive; unknown or foreign SKUs return 404."}],"responses":{"200":{"description":"Erfolg, die Antwort enthält die Daten / Success, the response contains the data.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductVariantUserResponse"},"example":{"id":5001,"product_id":1001,"color_id":21,"size_id":3,"sku":"MUSTER-TS-01_Navy_M","description":null,"product_image_url":"https://example.com/bilder/muster-shirt-navy.jpg","status":"ACTIVE","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","warehouse_color":null,"warehouse_size":null,"size_label":"M","color_label":"Navy","images":[]}}}},"400":{"description":"Ungültige Anfrage, z. B. ein Parameter mit falschem Typ oder Wert / Invalid request, for example a parameter of the wrong type or value.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Der Schlüssel trägt keinen für diese Operation erforderlichen Scope / The key does not hold a scope required for this operation.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"404":{"description":"Nicht gefunden: die ID bzw. SKU ist unbekannt oder gehört einem anderen Händler / Not found: the ID or SKU is unknown or belongs to another merchant.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_catalog:read","warehouse:read"],"description":"Löst eine SKU in die zugehörige Variante auf, etwa um aus einer Bestellposition oder einer externen Artikelnummer die `product_id` und die Variante zu ermitteln. Die SKU wird ohne Beachtung der Groß-/Kleinschreibung verglichen (`MUSTER-TS-01_NAVY_M` findet `MUSTER-TS-01_Navy_M`). Gesucht wird nur unter sichtbaren Produkten (eigene und gemeinsame `ON_DEMAND`-Produkte). Eine unbekannte oder fremde SKU ergibt 404, ohne zu verraten, ob sie existiert. Gesucht wird nach der `sku`, nicht nach `brand_sku` oder EAN; dafür dient `GET /api/product-variants/paged`.\n\nDie Antwort hat die Form der Variante wie bei `GET /api/product-variants/{variant_id}`, enthält aber keine Bestandszahlen; diese liefern die ID-Abfrage oder die Listen mit `stock=true`. Ein Schlüssel ohne den erforderlichen Scope erhält 403, ein ungültiger Aufruf (z. B. Parameter mit falschem Typ) 400.\n\nResolves a SKU to the matching variant, for example to determine the `product_id` and the variant from an order line or an external article number. The SKU is compared case-insensitively (`MUSTER-TS-01_NAVY_M` finds `MUSTER-TS-01_Navy_M`). Only visible products are searched (own and shared `ON_DEMAND` products). An unknown or foreign SKU yields 404 without revealing whether it exists. The lookup matches the `sku` only, not `brand_sku` or EAN; use `GET /api/product-variants/paged` for those.\n\nThe response has the variant shape of `GET /api/product-variants/{variant_id}` but contains no stock figures; the lookup by ID or the lists with `stock=true` return them. A key without the required scope receives 403; an invalid call (for example a parameter of the wrong type) receives 400."}},"/api/product-variants/paged":{"get":{"tags":["Product Variants"],"summary":"List product variants (paged)","operationId":"ApiProductVariantsPagedGetProductVariantsPaged","parameters":[{"name":"product_id","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Nur Varianten dieses Produkts (ID aus `GET /api/products`); ohne Angabe alle sichtbaren Produkte / Only variants of this product (ID from `GET /api/products`); omitted means all visible products."},{"name":"limit","in":"query","schema":{"type":"integer","default":20},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Einträge pro Seite, Standard 20, wird auf 1 bis 100 begrenzt / Entries per page, default 20, clamped to 1 to 100."},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anzahl zu überspringender Einträge, Standard 0, negative Werte gelten als 0 / Number of entries to skip, default 0, negative values count as 0."},{"name":"stock","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Bei `true` werden Bestandsfelder (`stock_total`, `gross_stock`, `reserved`, `available`, `stock_display`) berechnet, Standard `false`; die Filter wirken unabhängig davon / When `true`, the stock fields are computed, default `false`; the filters work independently of it."},{"name":"manufacturer_stock","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händlerschlüssel; Herstellerbestände werden nicht ausgeliefert / No effect for merchant keys; manufacturer stock is never returned."},{"name":"fulfillment_type","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/FulfillmentType"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Nur Varianten von Produkten dieser Fertigungsart (`ON_DEMAND`, `WAREHOUSE`, `ADDITIONAL_PRODUCT`); ohne Angabe alle / Only variants of products of this fulfillment type; omitted means all types."},{"name":"search","in":"query","schema":{"oneOf":[{"type":"string"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Suchtext, Teilstring ohne Beachtung der Groß-/Kleinschreibung in Produktname, `sku`, `brand_sku` und Farbbezeichnung; leer oder fehlend = kein Filter / Search text, case-insensitive substring of product name, `sku`, `brand_sku` and color label; blank or omitted means no filter."},{"name":"availability","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/VariantAvailability"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"`AVAILABLE` = verfügbare Menge größer 0, `SOLD_OUT` = nicht größer 0; ohne Angabe beides / `AVAILABLE` = available quantity greater than 0, `SOLD_OUT` = not greater than 0; omitted means both."},{"name":"customer_id","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}],"minimum":1},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Ohne Wirkung für Händlerschlüssel, der Händler ergibt sich aus dem Schlüssel; Wert mindestens 1 / No effect for merchant keys, the merchant is derived from the key; value at least 1."},{"name":"ean","in":"query","schema":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":100,"minLength":1},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Exakter Treffer auf die EAN der Variante, 1 bis 100 Zeichen, umgebende Leerzeichen werden ignoriert; findet nur Varianten eigener Produkte / Exact match on the variant EAN, 1 to 100 characters, surrounding blanks ignored; finds only variants of own products."},{"name":"sort","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/VariantListSort"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Reihenfolge der Produkte: `name_asc` (Standard) nach Produktname, `created_desc` zuletzt angelegtes Produkt zuerst / Order of products: `name_asc` (default) by product name, `created_desc` most recently created product first."}],"responses":{"200":{"description":"Erfolg, die Antwort enthält die Daten / Success, the response contains the data.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductVariantUserPageResponse"},"example":{"items":[{"id":5001,"product_id":1001,"color_id":21,"size_id":3,"sku":"MUSTER-TS-01_Navy_M","description":null,"product_image_url":"https://example.com/bilder/muster-shirt-navy.jpg","status":"ACTIVE","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","warehouse_color":null,"warehouse_size":null,"size_label":"M","color_label":"Navy","images":[],"stock_total":120,"gross_stock":120,"reserved":20,"available":100,"stock_display":{"kind":"IN_STOCK","available_balance":100},"product_name":"Muster Basic T-Shirt"}],"limit":20,"offset":0,"total_count":1}}}},"400":{"description":"Ungültige Anfrage, z. B. ein Parameter mit falschem Typ oder Wert / Invalid request, for example a parameter of the wrong type or value.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Der Schlüssel trägt keinen für diese Operation erforderlichen Scope / The key does not hold a scope required for this operation.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_catalog:read","warehouse:read"],"description":"Liefert Produktvarianten seitenweise im Umschlag `{items, limit, offset, total_count}`. Das ist die Operation für Katalogansichten, Artikelsuche und Abgleiche: Sie bietet gegenüber `GET /api/product-variants` zusätzlich die Filter `search`, `availability` und `ean`, die Sortierung `sort`, die Gesamtzahl `total_count` und liefert je Eintrag `product_name`. Sichtbarkeit, Filter `product_id`/`fulfillment_type` und Bestandsfelder (`stock=true`) sind identisch zur Liste.\n\n**Sortierung:** nach Produkt (Standard: Produktname aufsteigend, mit `sort=created_desc` das zuletzt angelegte Produkt zuerst), innerhalb eines Produkts nach Farbbezeichnung, dann nach Größe in Tragereihenfolge (S, M, L, XL …; Buchstabengrößen zuerst, dann Größen mit führender Zahl, dann die übrigen), zuletzt nach `sku`. Die Varianten eines Produkts stehen immer in einem Block, und die Reihenfolge ist eindeutig, sodass `offset`-Paginierung keine Zeile auslässt oder wiederholt.\n\n**Paginierung:** `limit` Standard 20, wird auf 1 bis 100 begrenzt; `offset` mindestens 0. Die Antwort nennt die tatsächlich verwendeten (begrenzten) Werte. `total_count` zählt alle Treffer der Filter.\n\n**Filter:** `search` sucht ohne Beachtung der Groß-/Kleinschreibung als Teilstring in Produktname, `sku`, `brand_sku` und Farbbezeichnung (leer = kein Filter). `availability` filtert auf `AVAILABLE` (`available` größer 0) oder `SOLD_OUT` (`available` nicht größer 0). `ean` ist ein exakter Treffer (umgebende Leerzeichen werden entfernt) und findet nur Varianten eigener Produkte. `brand_sku` und `ean` stehen in der Antwort nur bei eigenen Produkten. Ein Schlüssel ohne den erforderlichen Scope erhält 403, ein ungültiger Aufruf (z. B. Parameter mit falschem Typ) 400.\n\nReturns product variants page by page in the envelope `{items, limit, offset, total_count}`. This is the operation for catalog views, article search and reconciliation: compared to `GET /api/product-variants` it adds the filters `search`, `availability` and `ean`, the sort option `sort`, the total count `total_count`, and returns `product_name` on every entry. Visibility, the `product_id`/`fulfillment_type` filters and the stock fields (`stock=true`) are identical to the list.\n\n**Sorting:** by product (default: product name ascending; with `sort=created_desc` the most recently created product first), within a product by color label, then by size in wearing order (S, M, L, XL ...; letter sizes first, then sizes with a leading number, then the rest), finally by `sku`. The variants of one product always form one block, and the order is total, so `offset` pagination never skips or repeats a row.\n\n**Pagination:** `limit` defaults to 20 and is clamped to 1 to 100; `offset` is at least 0. The response states the values actually used (clamped). `total_count` counts all matches of the filters.\n\n**Filters:** `search` is a case-insensitive substring match on product name, `sku`, `brand_sku` and color label (blank = no filter). `availability` filters on `AVAILABLE` (`available` greater than 0) or `SOLD_OUT` (`available` not greater than 0). `ean` is an exact match (surrounding blanks are ignored) and finds only variants of own products. `brand_sku` and `ean` appear in the response only for own products. A key without the required scope receives 403; an invalid call (for example a parameter of the wrong type) receives 400."}},"/api/product-variants/{variant_id}":{"get":{"tags":["Product Variants"],"summary":"Get a product variant","operationId":"ApiProductVariantsVariantIdGetProductVariant","parameters":[{"name":"variant_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Variante aus den Variantenlisten (Feld `id`); unbekannte oder fremde IDs ergeben 404 / Variant ID from the variant lists (field `id`); unknown or foreign IDs return 404."}],"responses":{"200":{"description":"Erfolg, die Antwort enthält die Daten / Success, the response contains the data.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductVariantUserResponse"},"example":{"id":5001,"product_id":1001,"color_id":21,"size_id":3,"sku":"MUSTER-TS-01_Navy_M","description":null,"product_image_url":"https://example.com/bilder/muster-shirt-navy.jpg","status":"ACTIVE","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","warehouse_color":null,"warehouse_size":null,"size_label":"M","color_label":"Navy","images":[],"gross_stock":120,"reserved":20,"available":100}}}},"400":{"description":"Ungültige Anfrage, z. B. ein Parameter mit falschem Typ oder Wert / Invalid request, for example a parameter of the wrong type or value.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Der Schlüssel trägt keinen für diese Operation erforderlichen Scope / The key does not hold a scope required for this operation.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"404":{"description":"Nicht gefunden: die ID bzw. SKU ist unbekannt oder gehört einem anderen Händler / Not found: the ID or SKU is unknown or belongs to another merchant.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_catalog:read","warehouse:read"],"description":"Liefert eine einzelne Variante anhand ihrer ID. Die Variante muss zu einem sichtbaren Produkt gehören (eigenes oder gemeinsames, keinem Händler zugeordnetes `ON_DEMAND`-Produkt); sonst antwortet die API mit 404, ohne zu verraten, ob die ID existiert. Eine Variante ist eindeutig durch ihre `sku` bestimmt; Farbe und Größe stehen in `color_id`/`color_label` und `size_id`/`size_label`.\n\nDie Bestandszahlen `gross_stock` (Gesamtbestand), `reserved` (Reservierung) und `available` (verfügbare Menge, nie negativ) sind hier immer gefüllt, ohne `stock`-Parameter; sie sind `null`, wenn für die Variante keine Bestandsdaten vorliegen. `stock_total` und `stock_display` liefert diese Operation nicht, sie stehen nur in den Listen mit `stock=true`. Ein Schlüssel ohne den erforderlichen Scope erhält 403, ein ungültiger Aufruf (z. B. Parameter mit falschem Typ) 400.\n\nReturns a single variant by ID. The variant must belong to a visible product (own product or shared `ON_DEMAND` product that belongs to no merchant); otherwise the API answers 404 without revealing whether the ID exists. A variant is uniquely identified by its `sku`; color and size are in `color_id`/`color_label` and `size_id`/`size_label`.\n\nThe stock figures `gross_stock` (total stock), `reserved` (reservations) and `available` (available quantity, never negative) are always filled here, without a `stock` parameter; they are `null` when no stock data exists for the variant. This operation does not return `stock_total` and `stock_display`; they appear only in the lists with `stock=true`. A key without the required scope receives 403; an invalid call (for example a parameter of the wrong type) receives 400."}},"/api/products":{"get":{"tags":["Products"],"summary":"List products","operationId":"ApiProductsGetProducts","responses":{"200":{"description":"Erfolg, die Antwort enthält die Daten / Success, the response contains the data.","headers":{},"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ProductUserResponse"},"type":"array"},"example":[{"id":1001,"name":"Muster Basic T-Shirt","description":"Unisex T-Shirt aus Baumwolle","type_id":12,"fulfillment_type":"ON_DEMAND","production_type":"PRODUCEABLE","status":"ACTIVE","is_organic":true,"material":"100 % Baumwolle","sku":"MUSTER-TS-01","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","image_url":"https://example.com/bilder/muster-shirt-front.jpg","images":[{"id":4711,"source_url":"https://example.com/bilder/muster-shirt-front.jpg","is_production":false,"sort_order":0}]}]}}},"403":{"description":"Der Schlüssel trägt keinen für diese Operation erforderlichen Scope / The key does not hold a scope required for this operation.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_catalog:read"],"description":"Liefert alle Produkte, die der Händler sehen darf, als einfache Liste ohne Paginierung und ohne Filter, aufsteigend nach Produktname sortiert. Sichtbar sind die eigenen Produkte des Händlers sowie die gemeinsamen Produkte der Auftragsware (`ON_DEMAND`), die keinem Händler gehören. Lagerartikel (`WAREHOUSE`) anderer Händler und frei verfügbare Lagerartikel erscheinen nie. Es gibt keinen Statusfilter: aktive und inaktive Produkte sind enthalten, der Zustand steht im Feld `status`.\n\nEin Produkt ist die Hülle über seinen Varianten; die bestellbaren Einheiten (Farbe, Größe, SKU) liefern `GET /api/product-variants` und `GET /api/product-variants/paged`. Das Feld `image_url` ist das repräsentative Katalogbild, aus dem Bild einer Variante abgeleitet; es ist `null`, wenn keine Variante ein Bild hat. Ein Schlüssel ohne den erforderlichen Scope erhält 403, ein ungültiger Aufruf (z. B. Parameter mit falschem Typ) 400.\n\nReturns every product the merchant may see as a plain list without pagination or filters, sorted by product name ascending. Visible are the merchant's own products and the shared made-to-order products (`ON_DEMAND`) that belong to no merchant. Warehouse articles (`WAREHOUSE`) of other merchants and unowned warehouse articles never appear. There is no status filter: active and inactive products are included, see the `status` field.\n\nA product is the container for its variants; the orderable units (color, size, SKU) are returned by `GET /api/product-variants` and `GET /api/product-variants/paged`. `image_url` is the representative catalog image derived from a variant image; it is `null` when no variant has an image. A key without the required scope receives 403; an invalid call (for example a parameter of the wrong type) receives 400."}},"/api/products/highlights":{"get":{"tags":["Products"],"summary":"Newest and best-selling public catalog products","operationId":"ApiProductsHighlightsGetProductHighlights","responses":{"200":{"description":"Erfolg, die Antwort enthält die Daten / Success, the response contains the data.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductHighlightsResponse"},"example":{"newest":[{"id":1001,"name":"Muster Basic T-Shirt","description":"Unisex T-Shirt aus Baumwolle","type_id":12,"fulfillment_type":"ON_DEMAND","production_type":"PRODUCEABLE","status":"ACTIVE","is_organic":true,"material":"100 % Baumwolle","sku":"MUSTER-TS-01","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","image_url":"https://example.com/bilder/muster-shirt-front.jpg","images":[{"id":4711,"source_url":"https://example.com/bilder/muster-shirt-front.jpg","is_production":false,"sort_order":0}]}],"bestsellers":[{"id":1001,"name":"Muster Basic T-Shirt","description":"Unisex T-Shirt aus Baumwolle","type_id":12,"fulfillment_type":"ON_DEMAND","production_type":"PRODUCEABLE","status":"ACTIVE","is_organic":true,"material":"100 % Baumwolle","sku":"MUSTER-TS-01","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","image_url":"https://example.com/bilder/muster-shirt-front.jpg","images":[{"id":4711,"source_url":"https://example.com/bilder/muster-shirt-front.jpg","is_production":false,"sort_order":0}],"rank":1}]}}}},"403":{"description":"Der Schlüssel trägt keinen für diese Operation erforderlichen Scope / The key does not hold a scope required for this operation.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_catalog:read"],"description":"Liefert die Kacheln für die Startseite eines Händlers: bis zu vier neueste und bis zu vier meistbestellte Produkte aus dem gemeinsamen Katalog der Auftragsware. Berücksichtigt werden nur aktive `ON_DEMAND`-Produkte ohne Händlerzuordnung, nie das Produkt eines anderen Händlers. `newest` ist nach Anlagedatum absteigend sortiert. `bestsellers` ist nach Rang aufsteigend sortiert (Rang 1 = am häufigsten bestellt); gezählt werden die Händler, die das Produkt in den letzten 30 Tagen bestellt haben, und nur Produkte mit mindestens drei verschiedenen Händlern erscheinen. Die Antwort nennt nur den Rang, keine Mengen. Daher kann `bestsellers` weniger als vier oder keine Einträge enthalten.\n\nDie Antwort ist für alle Händler gleich und wird je Kalendertag (Zeitzone Europe/Berlin) bis zu eine Stunde zwischengespeichert; neue Produkte können dadurch verzögert erscheinen. Ein Schlüssel ohne den erforderlichen Scope erhält 403, ein ungültiger Aufruf (z. B. Parameter mit falschem Typ) 400.\n\nReturns the tiles for a merchant's home page: up to four newest and up to four best-selling products from the shared catalog of made-to-order products. Only active `ON_DEMAND` products without an owner are considered, never another merchant's product. `newest` is sorted by creation date, newest first. `bestsellers` is sorted by rank ascending (rank 1 = ordered most often); it counts the merchants that ordered the product in the last 30 days, and only products with at least three distinct merchants appear. The response carries the rank only, no quantities. Therefore `bestsellers` may hold fewer than four entries or none.\n\nThe response is identical for all merchants and cached for up to one hour per calendar day (time zone Europe/Berlin); new products may therefore appear with a delay. A key without the required scope receives 403; an invalid call (for example a parameter of the wrong type) receives 400."}},"/api/products/{product_id}":{"get":{"tags":["Products"],"summary":"Get a product","operationId":"ApiProductsProductIdGetProduct","parameters":[{"name":"product_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID des Produkts aus `GET /api/products` (Feld `id`); unbekannte oder fremde IDs ergeben 404 / Product ID from `GET /api/products` (field `id`); unknown or foreign IDs return 404."}],"responses":{"200":{"description":"Erfolg, die Antwort enthält die Daten / Success, the response contains the data.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductUserResponse"},"example":{"id":1001,"name":"Muster Basic T-Shirt","description":"Unisex T-Shirt aus Baumwolle","type_id":12,"fulfillment_type":"ON_DEMAND","production_type":"PRODUCEABLE","status":"ACTIVE","is_organic":true,"material":"100 % Baumwolle","sku":"MUSTER-TS-01","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","image_url":"https://example.com/bilder/muster-shirt-front.jpg","images":[{"id":4711,"source_url":"https://example.com/bilder/muster-shirt-front.jpg","is_production":false,"sort_order":0}]}}}},"400":{"description":"Ungültige Anfrage, z. B. ein Parameter mit falschem Typ oder Wert / Invalid request, for example a parameter of the wrong type or value.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Der Schlüssel trägt keinen für diese Operation erforderlichen Scope / The key does not hold a scope required for this operation.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}},"404":{"description":"Nicht gefunden: die ID bzw. SKU ist unbekannt oder gehört einem anderen Händler / Not found: the ID or SKU is unknown or belongs to another merchant.","content":{"application/json":{"schema":{"type":"object","required":["status_code","detail"],"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode / HTTP status code"},"detail":{"type":"string","description":"Fehlermeldung / error message"},"extra":{"type":["null","object","array"],"additionalProperties":{},"description":"Maschinenlesbare Details, oft mit `error`-Code / machine-readable details, often with an `error` code"}}}}}}},"deprecated":false,"x-customer-scopes":["merchant_catalog:read"],"description":"Liefert ein einzelnes Produkt anhand seiner ID. Das Produkt muss für den Händler sichtbar sein (eigenes Produkt oder gemeinsames, keinem Händler zugeordnetes `ON_DEMAND`-Produkt, siehe `GET /api/products`). Ist die ID unbekannt oder gehört das Produkt einem anderen Händler, antwortet die API mit 404; die beiden Fälle sind absichtlich nicht unterscheidbar.\n\nDie Antwort entspricht einem Eintrag von `GET /api/products`, einschließlich `image_url` und `images`. Die Varianten des Produkts liefert `GET /api/product-variants?product_id=<id>`. Ein Schlüssel ohne den erforderlichen Scope erhält 403, ein ungültiger Aufruf (z. B. Parameter mit falschem Typ) 400.\n\nReturns a single product by ID. The product must be visible to the merchant (own product or a shared `ON_DEMAND` product that belongs to no merchant, see `GET /api/products`). If the ID is unknown or the product belongs to another merchant, the API answers 404; the two cases are deliberately indistinguishable.\n\nThe response matches one entry of `GET /api/products`, including `image_url` and `images`. The variants of the product are returned by `GET /api/product-variants?product_id=<id>`. A key without the required scope receives 403; an invalid call (for example a parameter of the wrong type) receives 400."}},"/api/warehouse/products":{"get":{"tags":["Warehouse Products"],"summary":"List own warehouse products","operationId":"ApiWarehouseProductsListProducts","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","maximum":100.0,"minimum":1.0,"default":20},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anzahl Artikel pro Seite, 1 bis 100, Standard 20 / Number of products per page, 1 to 100, default 20."},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0.0,"default":0},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anzahl zu überspringender Artikel, mindestens 0, Standard 0 / Number of products to skip, minimum 0, default 0."},{"name":"review_status","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/WarehouseProductReviewStatus"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Nur Artikel mit diesem Prüfstatus: `DRAFT`, `IN_REVIEW`, `APPROVED` oder `DECLINED`. Ohne Angabe kein Filter / Only products with this review status. Not set: no filter."},{"name":"search","in":"query","schema":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":100,"minLength":1},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Suchbegriff, 1 bis 100 Zeichen: Teilstring ohne Beachtung der Groß-/Kleinschreibung in Name und SKU des Artikels sowie in SKU, EAN, Hersteller-SKU und Farbe der Varianten. Leerzeichen am Rand werden ignoriert / Search term, 1 to 100 characters: case-insensitive substring of product name and SKU and of variant SKU, EAN, brand SKU and color. Surrounding whitespace is ignored."},{"name":"sort","in":"query","schema":{"$ref":"#/components/schemas/WarehouseProductListSort"},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Reihenfolge: `created_desc` (Standard, neueste Anlage zuerst), `updated_desc` (zuletzt geändert zuerst), `submitted_asc` (am längsten wartende Einreichung zuerst, nie eingereichte am Ende), `name_asc` (Name aufsteigend). Gleichstand entscheidet die ID / Sort order: `created_desc` (default, newest first), `updated_desc` (last changed first), `submitted_asc` (longest waiting submission first, never submitted last), `name_asc` (name ascending). Ties are broken by ID."},{"name":"include_unreviewed","in":"query","schema":{"type":"boolean","default":false},"description":"Mit `true` auch eigene Lagerartikel ohne Prüfstatus aufnehmen (nicht über die Händler-Anlage entstanden); sie haben `review_status` `null`, `customer_can_edit` `false` und nicht immer eine `sku`. Standard `false` / With `true`, own warehouse products without a review status are included too; they have `review_status` `null`, `customer_can_edit` `false` and not always a `sku`. Default `false`.","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false},{"name":"availability","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/VariantAvailability"},{"type":"null"}]},"description":"Filter auf Artikelebene: `AVAILABLE` = mindestens eine Variante mit `available` > 0, `SOLD_OUT` = keine (Artikel ohne Varianten eingeschlossen). Ohne Angabe kein Filter / Product-level filter: `AVAILABLE` = at least one variant with `available` > 0, `SOLD_OUT` = none (products without variants included). Not set: no filter.","required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false}],"responses":{"200":{"description":"Seite der eigenen Lagerartikel / Page of the own warehouse products.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductPageResponse"},"example":{"items":[{"id":120045,"sku":"SWP_EX4MPL01","name":"Muster-T-Shirt Basic","description":"Unisex-T-Shirt aus Bio-Baumwolle, Musterartikel.","customer_id":100123,"status":"INACTIVE","review_status":"IN_REVIEW","review_note":null,"submitted_at":"2026-01-16T09:00:00Z","reviewed_at":null,"supplier_number":"LIEF-0001","is_packaged":true,"allow_return_restock":true,"recommended_price":1999,"image_url":null,"customer_can_edit":false,"created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","variants":[{"id":880011,"sku":"SWP_EX4MPL01__Schwarz__M","status":"INACTIVE","size_id":7,"color_id":31,"size":"M","color":"Schwarz","warehouse_size":"M","warehouse_color":"Schwarz","ean":"4006381333931","weight_g":180,"width_mm":300,"height_mm":400,"depth_mm":20,"stock_number":null,"gross_stock":14,"available":10,"available_unbuffered":12,"safety_stock":2},{"id":880012,"sku":"SWP_EX4MPL01__Schwarz__L","status":"INACTIVE","size_id":8,"color_id":31,"size":"L","color":"Schwarz","warehouse_size":"L","warehouse_color":"Schwarz","ean":null,"weight_g":190,"width_mm":null,"height_mm":null,"depth_mm":null,"stock_number":null,"gross_stock":14,"available":10,"available_unbuffered":12,"safety_stock":2}]}],"limit":20,"offset":0,"total_count":1}}}},"400":{"description":"Ungültiger Parameter, z. B. `limit` außerhalb 1 bis 100 / Invalid parameter, e.g. `limit` outside 1 to 100.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Dem Schlüssel fehlt der erforderliche Scope, oder das Token gehört keinem Kunden / The key lacks the required scope, or the token does not belong to a customer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}},"404":{"description":"Die Funktion ist für dieses Konto nicht verfügbar / The feature is not available for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:read"],"description":"Listet die eigenen Lagerartikel des Händlers mit Varianten und Bestand, seitenweise.\n\nOhne Filter erscheinen die Artikel, die über die Händler-Anlage (`POST /api/warehouse/products`) entstanden sind, neueste zuerst (`sort=created_desc`). Mit `include_unreviewed=true` kommen eigene Lagerartikel ohne Prüfstatus hinzu (`review_status` ist dann `null`, `customer_can_edit` `false`). Andere Händler sind nie sichtbar. `total_count` ist die Zahl aller Treffer nach Filtern, unabhängig von `limit` und `offset`. Pro Variante enthält die Liste `gross_stock` und `available`; ist ein Sicherheitsbestand wirksam, kommen `available_unbuffered` und `safety_stock` hinzu.\n\n**Prüfstatus (`review_status`):** `DRAFT` (Entwurf) -> `IN_REVIEW` (eingereicht) -> `APPROVED` (freigegeben) oder `DECLINED` (abgelehnt, mit Begründung in `review_note`). Ein abgelehnter Artikel wird durch eine Änderung per `PUT` wieder zum `DRAFT` und muss erneut eingereicht werden.\n\nErfordert den Scope `warehouse:read`. Fehler: 400 bei ungültigen Parametern, 403 bei fehlendem Scope oder Token ohne Kundenbezug, 404 wenn die Funktion für Händler nicht freigeschaltet ist.\n\nLists the merchant's own warehouse products with variants and stock, paged.\n\nWithout filters the list contains the products created through the merchant flow (`POST /api/warehouse/products`), newest first (`sort=created_desc`). With `include_unreviewed=true` own warehouse products without a review status are added (`review_status` is `null`, `customer_can_edit` is `false`). Other merchants are never visible. `total_count` is the number of all matches after filtering, independent of `limit` and `offset`. Each variant carries `gross_stock` and `available`; if a safety stock applies, `available_unbuffered` and `safety_stock` are added.\n\n**Review status (`review_status`):** `DRAFT` -> `IN_REVIEW` (submitted) -> `APPROVED` or `DECLINED` (with the reason in `review_note`). Changing a declined product with `PUT` turns it back into `DRAFT`; it must be submitted again.\n\nRequires the scope `warehouse:read`. Errors: 400 for invalid parameters, 403 for a missing scope or a token without a customer, 404 if the feature is not enabled for merchants."},"post":{"tags":["Warehouse Products"],"summary":"Create a warehouse product draft","operationId":"ApiWarehouseProductsCreateProduct","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductWriteRequest"},"example":{"name":"Muster-T-Shirt Basic","description":"Unisex-T-Shirt aus Bio-Baumwolle, Musterartikel.","supplier_number":"LIEF-0001","is_packaged":true,"allow_return_restock":true,"recommended_price":1999,"variants":[{"size":"M","color":"Schwarz","ean":"4006381333931","weight_g":180,"width_mm":300,"height_mm":400,"depth_mm":20},{"size":"L","color":"Schwarz","ean":null,"weight_g":190,"width_mm":null,"height_mm":null,"depth_mm":null}]}}},"required":true},"responses":{"201":{"description":"Entwurf angelegt; die Antwort enthält den Artikel mit `review_status` `DRAFT` / Draft created; the response contains the product with `review_status` `DRAFT`.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductResponse"},"example":{"id":120045,"sku":"SWP_EX4MPL01","name":"Muster-T-Shirt Basic","description":"Unisex-T-Shirt aus Bio-Baumwolle, Musterartikel.","customer_id":100123,"status":"INACTIVE","review_status":"DRAFT","review_note":null,"submitted_at":null,"reviewed_at":null,"supplier_number":"LIEF-0001","is_packaged":true,"allow_return_restock":true,"recommended_price":1999,"image_url":null,"customer_can_edit":true,"created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","variants":[{"id":880011,"sku":"SWP_EX4MPL01__Schwarz__M","status":"INACTIVE","size_id":7,"color_id":31,"size":"M","color":"Schwarz","warehouse_size":"M","warehouse_color":"Schwarz","ean":"4006381333931","weight_g":180,"width_mm":300,"height_mm":400,"depth_mm":20,"stock_number":null,"gross_stock":null,"available":null},{"id":880012,"sku":"SWP_EX4MPL01__Schwarz__L","status":"INACTIVE","size_id":8,"color_id":31,"size":"L","color":"Schwarz","warehouse_size":"L","warehouse_color":"Schwarz","ean":null,"weight_g":190,"width_mm":null,"height_mm":null,"depth_mm":null,"stock_number":null,"gross_stock":null,"available":null}]}}}},"400":{"description":"Ungültige Varianten (`extra.error` = `INVALID_VARIANTS`) oder ungültiger Request-Body / Invalid variants (`extra.error` = `INVALID_VARIANTS`) or invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}},"403":{"description":"Dem Schlüssel fehlt der erforderliche Scope, oder das Token gehört keinem Kunden / The key lacks the required scope, or the token does not belong to a customer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}},"404":{"description":"Die Funktion ist für dieses Konto nicht verfügbar / The feature is not available for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:write"],"description":"Legt einen Lagerartikel mit seinen Varianten als Entwurf (`DRAFT`) an. Die Antwort ist der angelegte Artikel mit Status 201.\n\nDer Artikel gehört immer dem Kunden des Tokens. Die Artikel-SKU (`SWP_` plus 8 Zeichen aus `A-Z0-9`) vergibt der Server; die Varianten-SKU lautet `<Artikel-SKU>__<Farbe>__<Größe>` und ändert sich nie. Größe und Farbe werden als Namen übergeben; bekannte Schreibweisen und Aliase wie `2XL`, `2xl` und `XXL` landen auf derselben Größe, unbekannte Namen legt der Server an. Der Artikel ist zunächst `INACTIVE`; erst nach der Freigabe sind Artikel und Varianten `ACTIVE`. Bestandsfelder der Varianten sind in dieser Antwort `null`; sie stehen in `GET /api/warehouse/products/{product_id}`. Der Entwurf wird erst durch `POST /api/warehouse/products/{product_id}/submit` zur Prüfung eingereicht.\n\n**Prüfstatus (`review_status`):** `DRAFT` (Entwurf) -> `IN_REVIEW` (eingereicht) -> `APPROVED` (freigegeben) oder `DECLINED` (abgelehnt, mit Begründung in `review_note`). Ein abgelehnter Artikel wird durch eine Änderung per `PUT` wieder zum `DRAFT` und muss erneut eingereicht werden.\n\nErfordert den Scope `warehouse:write`. Fehler: 400 mit `extra.error` = `INVALID_VARIANTS` (keine Variante, leere Größe oder Farbe, dieselbe Kombination aus Größe und Farbe doppelt - auch nach Aliasen -, oder Farbe/Größe ohne Buchstaben oder Ziffern), 403 bei fehlendem Scope oder Token ohne Kundenbezug, 404 wenn die Funktion für Händler nicht freigeschaltet ist.\n\nCreates a warehouse product with its variants as a draft (`DRAFT`). The response is the created product with status 201.\n\nThe product always belongs to the customer of the token. The server assigns the product SKU (`SWP_` plus 8 characters from `A-Z0-9`); the variant SKU is `<product SKU>__<color>__<size>` and never changes. Size and color are passed as names; known spellings and aliases such as `2XL`, `2xl` and `XXL` resolve to the same size, unknown names are created by the server. The product starts as `INACTIVE`; product and variants become `ACTIVE` only on approval. Stock fields of the variants are `null` in this response; they are available from `GET /api/warehouse/products/{product_id}`. The draft is only sent for review by `POST /api/warehouse/products/{product_id}/submit`.\n\n**Review status (`review_status`):** `DRAFT` -> `IN_REVIEW` (submitted) -> `APPROVED` or `DECLINED` (with the reason in `review_note`). Changing a declined product with `PUT` turns it back into `DRAFT`; it must be submitted again.\n\nRequires the scope `warehouse:write`. Errors: 400 with `extra.error` = `INVALID_VARIANTS` (no variant, blank size or color, the same size and color combination twice - also after aliases - or a color/size without letters or digits), 403 for a missing scope or a token without a customer, 404 if the feature is not enabled for merchants."}},"/api/warehouse/products/{product_id}":{"get":{"tags":["Warehouse Products"],"summary":"Get a warehouse product","operationId":"ApiWarehouseProductsProductIdGetProduct","parameters":[{"name":"product_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID des Lagerartikels, wie in `id` der Artikelantwort / ID of the warehouse product, as returned in `id` of the product response."}],"responses":{"200":{"description":"Der Lagerartikel mit Varianten und Bestand / The warehouse product with variants and stock.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductResponse"},"example":{"id":120045,"sku":"SWP_EX4MPL01","name":"Muster-T-Shirt Basic","description":"Unisex-T-Shirt aus Bio-Baumwolle, Musterartikel.","customer_id":100123,"status":"ACTIVE","review_status":"APPROVED","review_note":null,"submitted_at":null,"reviewed_at":"2026-01-17T08:00:00Z","supplier_number":"LIEF-0001","is_packaged":true,"allow_return_restock":true,"recommended_price":1999,"image_url":null,"customer_can_edit":false,"created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","variants":[{"id":880011,"sku":"SWP_EX4MPL01__Schwarz__M","status":"INACTIVE","size_id":7,"color_id":31,"size":"M","color":"Schwarz","warehouse_size":"M","warehouse_color":"Schwarz","ean":"4006381333931","weight_g":180,"width_mm":300,"height_mm":400,"depth_mm":20,"stock_number":null,"gross_stock":14,"available":10,"available_unbuffered":12,"safety_stock":2},{"id":880012,"sku":"SWP_EX4MPL01__Schwarz__L","status":"INACTIVE","size_id":8,"color_id":31,"size":"L","color":"Schwarz","warehouse_size":"L","warehouse_color":"Schwarz","ean":null,"weight_g":190,"width_mm":null,"height_mm":null,"depth_mm":null,"stock_number":null,"gross_stock":14,"available":10,"available_unbuffered":12,"safety_stock":2}]}}}},"400":{"description":"Ungültiger Pfadparameter / Invalid path parameter.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Dem Schlüssel fehlt der erforderliche Scope, oder das Token gehört keinem Kunden / The key lacks the required scope, or the token does not belong to a customer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}},"404":{"description":"Artikel unbekannt oder gehört einem anderen Kunden (nie 403), oder die Funktion ist für dieses Konto nicht verfügbar / Product unknown or owned by another customer (never 403), or the feature is not available for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:read"],"description":"Liefert einen eigenen Lagerartikel mit Varianten, Bestand, Prüfstatus und der Begründung der letzten Ablehnung (`review_note`).\n\nAuch Lagerartikel ohne Prüfstatus (nicht über die Händler-Anlage entstanden) sind lesbar; sie haben `review_status` `null` und `customer_can_edit` `false`. Pro Variante stehen `gross_stock` und `available`; ist ein Sicherheitsbestand wirksam, kommen `available_unbuffered` und `safety_stock` hinzu. Die Begründung einer Ablehnung bleibt nach der Korrektur stehen und wird erst mit der erneuten Einreichung geleert.\n\n**Prüfstatus (`review_status`):** `DRAFT` (Entwurf) -> `IN_REVIEW` (eingereicht) -> `APPROVED` (freigegeben) oder `DECLINED` (abgelehnt, mit Begründung in `review_note`). Ein abgelehnter Artikel wird durch eine Änderung per `PUT` wieder zum `DRAFT` und muss erneut eingereicht werden.\n\nErfordert den Scope `warehouse:read`. Fehler: 403 bei fehlendem Scope oder Token ohne Kundenbezug, 404 wenn der Artikel nicht existiert, einem anderen Kunden gehört (nie 403) oder die Funktion für Händler nicht freigeschaltet ist.\n\nReturns one own warehouse product with variants, stock, review status and the reason of the last decline (`review_note`).\n\nWarehouse products without a review status (not created through the merchant flow) can be read as well; they have `review_status` `null` and `customer_can_edit` `false`. Each variant carries `gross_stock` and `available`; if a safety stock applies, `available_unbuffered` and `safety_stock` are added. The reason of a decline stays after the correction and is cleared only when the product is submitted again.\n\n**Review status (`review_status`):** `DRAFT` -> `IN_REVIEW` (submitted) -> `APPROVED` or `DECLINED` (with the reason in `review_note`). Changing a declined product with `PUT` turns it back into `DRAFT`; it must be submitted again.\n\nRequires the scope `warehouse:read`. Errors: 403 for a missing scope or a token without a customer, 404 if the product does not exist, belongs to another customer (never 403) or the feature is not enabled for merchants."},"put":{"tags":["Warehouse Products"],"summary":"Replace a warehouse product","operationId":"ApiWarehouseProductsProductIdUpdateProduct","parameters":[{"name":"product_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID des Lagerartikels, wie in `id` der Artikelantwort / ID of the warehouse product, as returned in `id` of the product response."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductWriteRequest"},"example":{"name":"Muster-T-Shirt Basic","description":"Unisex-T-Shirt aus Bio-Baumwolle, Musterartikel.","supplier_number":"LIEF-0001","is_packaged":true,"allow_return_restock":true,"recommended_price":1999,"variants":[{"size":"M","color":"Schwarz","ean":"4006381333931","weight_g":180,"width_mm":300,"height_mm":400,"depth_mm":20},{"size":"L","color":"Schwarz","ean":null,"weight_g":190,"width_mm":null,"height_mm":null,"depth_mm":null}]}}},"required":true},"responses":{"200":{"description":"Artikel ersetzt; die Antwort zeigt den neuen Stand (Bestandsfelder `null`) / Product replaced; the response shows the new state (stock fields `null`).","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductResponse"},"example":{"id":120045,"sku":"SWP_EX4MPL01","name":"Muster-T-Shirt Basic","description":"Unisex-T-Shirt aus Bio-Baumwolle, Musterartikel.","customer_id":100123,"status":"INACTIVE","review_status":"DRAFT","review_note":null,"submitted_at":null,"reviewed_at":null,"supplier_number":"LIEF-0001","is_packaged":true,"allow_return_restock":true,"recommended_price":1999,"image_url":null,"customer_can_edit":true,"created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","variants":[{"id":880011,"sku":"SWP_EX4MPL01__Schwarz__M","status":"INACTIVE","size_id":7,"color_id":31,"size":"M","color":"Schwarz","warehouse_size":"M","warehouse_color":"Schwarz","ean":"4006381333931","weight_g":180,"width_mm":300,"height_mm":400,"depth_mm":20,"stock_number":null,"gross_stock":null,"available":null},{"id":880012,"sku":"SWP_EX4MPL01__Schwarz__L","status":"INACTIVE","size_id":8,"color_id":31,"size":"L","color":"Schwarz","warehouse_size":"L","warehouse_color":"Schwarz","ean":null,"weight_g":190,"width_mm":null,"height_mm":null,"depth_mm":null,"stock_number":null,"gross_stock":null,"available":null}]}}}},"400":{"description":"Ungültige Varianten (`extra.error` = `INVALID_VARIANTS`) oder ungültiger Request-Body / Invalid variants (`extra.error` = `INVALID_VARIANTS`) or invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}},"403":{"description":"Dem Schlüssel fehlt der erforderliche Scope, oder das Token gehört keinem Kunden / The key lacks the required scope, or the token does not belong to a customer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}},"404":{"description":"Artikel unbekannt oder gehört einem anderen Kunden (nie 403), oder die Funktion ist für dieses Konto nicht verfügbar / Product unknown or owned by another customer (never 403), or the feature is not available for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}},"409":{"description":"Der Artikel ist nicht änderbar (`extra.error` = `NOT_EDITABLE`; `extra.review_status` nennt den aktuellen Prüfstatus) / The product cannot be changed (`extra.error` = `NOT_EDITABLE`; `extra.review_status` carries the current review status).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:write"],"description":"Ersetzt den gesamten Stand eines eigenen Lagerartikels: Artikelfelder und Variantenliste. Es gibt kein Teil-Update; die Variantenliste im Request ist der gewünschte Endstand.\n\n**Wann änderbar:** nur in `DRAFT` und `DECLINED` (`customer_can_edit` = `true`). Eingereichte (`IN_REVIEW`) und freigegebene (`APPROVED`) Artikel lassen sich nicht ändern; der Aufruf antwortet 409 mit `extra.error` = `NOT_EDITABLE`. Eine Änderung aus `DECLINED` setzt den Artikel auf `DRAFT`; danach erneut einreichen.\n\n**Varianten:** Sie werden über die Kombination aus Größe und Farbe abgeglichen. Vorhandene Varianten behalten ID und SKU und übernehmen EAN, Gewicht, Maße und die eingegebenen Bezeichnungen neu. Neue Kombinationen werden angelegt. Nicht mehr genannte Kombinationen werden entfernt, solange der Artikel nie freigegeben war; ein bereits freigegebener Artikel behält sie als `INACTIVE`.\n\n**`recommended_price`:** Fehlt das Feld im Request, bleibt der gespeicherte Wert; `null` löscht ihn. Die übrigen optionalen Artikelfelder werden dagegen mit dem Request-Wert überschrieben, fehlende Felder werden zu `null`.\n\nErfordert den Scope `warehouse:write`. Fehler: 400 mit `extra.error` = `INVALID_VARIANTS` (wie beim Anlegen), 403 bei fehlendem Scope oder Token ohne Kundenbezug, 404 bei unbekanntem oder fremdem Artikel oder nicht freigeschalteter Funktion, 409 mit `extra.error` = `NOT_EDITABLE` (Artikel nicht in `DRAFT`/`DECLINED`; `extra.review_status` nennt den aktuellen Wert). Bestandsfelder der Varianten sind in der Antwort `null`.\n\nReplaces the complete state of an own warehouse product: product fields and variant list. There is no partial update; the variant list in the request is the desired final state.\n\n**When editable:** only in `DRAFT` and `DECLINED` (`customer_can_edit` = `true`). Submitted (`IN_REVIEW`) and approved (`APPROVED`) products cannot be changed; the call answers 409 with `extra.error` = `NOT_EDITABLE`. A change from `DECLINED` sets the product to `DRAFT`; submit it again afterwards.\n\n**Variants:** They are matched by the combination of size and color. Existing variants keep ID and SKU and take over EAN, weight, dimensions and the entered labels. New combinations are created. Combinations no longer listed are removed as long as the product was never approved; an already approved product keeps them as `INACTIVE`.\n\n**`recommended_price`:** If the field is missing from the request the stored value is kept; `null` clears it. The other optional product fields are overwritten with the request value, missing fields become `null`.\n\nRequires the scope `warehouse:write`. Errors: 400 with `extra.error` = `INVALID_VARIANTS` (as on create), 403 for a missing scope or a token without a customer, 404 for an unknown or foreign product or a feature that is not enabled, 409 with `extra.error` = `NOT_EDITABLE` (product not in `DRAFT`/`DECLINED`; `extra.review_status` carries the current value). Stock fields of the variants are `null` in the response."}},"/api/warehouse/products/{product_id}/safety-stock":{"get":{"tags":["Warehouse Safety Stock"],"summary":"Get the safety stock of one own article","operationId":"ApiWarehouseProductsProductIdSafetyStockGetProduct","parameters":[{"name":"product_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID des Lagerartikels, wie in `id` der Artikelantwort / ID of the warehouse product, as returned in `id` of the product response."}],"responses":{"200":{"description":"Ausnahme, Standard und wirksame Staffel des Artikels / Override, default and effective tiers of the product.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductSafetyStockResponse"},"example":{"product_id":120045,"customer_id":100123,"override":null,"default":{"customer_id":100123,"enabled":true,"rule":{"buffer":2,"threshold":10,"low_buffer":1,"preview":[{"free":0,"reported":0},{"free":1,"reported":0},{"free":9,"reported":8},{"free":10,"reported":8},{"free":12,"reported":10}]},"updated_at":"2026-01-15T10:30:00Z","updated_by":"user:4711"},"effective":{"buffer":2,"threshold":10,"low_buffer":1,"preview":[{"free":0,"reported":0},{"free":1,"reported":0},{"free":9,"reported":8},{"free":10,"reported":8},{"free":12,"reported":10}]},"source":"DEFAULT"}}}},"400":{"description":"Ungültiger Pfadparameter / Invalid path parameter.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Dem Schlüssel fehlt der erforderliche Scope, oder das Token gehört keinem Kunden / The key lacks the required scope, or the token does not belong to a customer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SafetyStockErrorResponse"}}}},"404":{"description":"Artikel unbekannt, gehört einem anderen Kunden (nie 403) oder ist kein Lagerartikel, oder die Funktion ist für dieses Konto nicht verfügbar / Product unknown, owned by another customer (never 403) or not a warehouse product, or the feature is not available for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SafetyStockErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:read"],"description":"Liefert den Sicherheitsbestand eines eigenen Lagerartikels: die Ausnahme am Artikel (`override`), den Standard des Händlers (`default`) und die daraus wirksame Staffel (`effective`).\n\nDer **Sicherheitsbestand** hält einen Teil des freien Bestands einer Variante zurück: `available` in der Artikelantwort ist der freie Bestand abzüglich dieses Puffers (nie negativ). Er gilt nur für Lagerartikel. Die Staffel hat drei Werte: ab `threshold` freien Stück hält der Puffer `buffer` zurück, darunter `low_buffer`. Gemeldet wird `max(0, frei - Puffer)`. Die Staffel ist bewusst nicht monoton (siehe `preview`).\n\n**Auflösung:** Eine Ausnahme am Artikel gilt vor dem Standard. Ausnahme `CUSTOM` = eigene Staffel, Ausnahme `NONE` = kein Puffer trotz Standard. Ohne Ausnahme gilt der Standard, sofern er eingeschaltet ist (`default.enabled`), sonst gibt es keinen Puffer. `source` nennt die Herkunft: `OVERRIDE`, `DEFAULT` oder `NONE`; bei `NONE` ist `effective` `null`.\n\nErfordert den Scope `warehouse:read`. Der Artikel kann in jedem Prüfstatus abgefragt werden, solange er ein Lagerartikel mit Besitzer ist. Fehler: 403 bei fehlendem Scope oder Token ohne Kundenbezug, 404 bei unbekanntem oder fremdem Artikel, Artikel, der kein Lagerartikel ist, oder nicht freigeschalteter Funktion. Die Referenz enthält nur lesende Aufrufe zum Sicherheitsbestand.\n\nReturns the safety stock of an own warehouse product: the override on the product (`override`), the merchant default (`default`) and the tiers that apply as a result (`effective`).\n\nThe **safety stock** holds back part of the free stock of a variant: `available` in the product response is the free stock minus this buffer (never negative). It applies to warehouse products only. The tiers have three values: from `threshold` free pieces upwards the buffer held back is `buffer`, below it `low_buffer`. The reported quantity is `max(0, free - buffer)`. The tiers are deliberately not monotonic (see `preview`).\n\n**Resolution:** An override on the product takes precedence over the default. Override `CUSTOM` = own tiers, override `NONE` = no buffer despite the default. Without an override the default applies if it is switched on (`default.enabled`), otherwise there is no buffer. `source` names the origin: `OVERRIDE`, `DEFAULT` or `NONE`; with `NONE`, `effective` is `null`.\n\nRequires the scope `warehouse:read`. The product can be queried in any review status as long as it is a warehouse product with an owner. Errors: 403 for a missing scope or a token without a customer, 404 for an unknown or foreign product, a product that is no warehouse product, or a feature that is not enabled. This reference contains only read calls for the safety stock."}},"/api/warehouse/products/{product_id}/submit":{"post":{"tags":["Warehouse Products"],"summary":"Submit a warehouse product for review","operationId":"ApiWarehouseProductsProductIdSubmitSubmitProduct","parameters":[{"name":"product_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID des Lagerartikels, wie in `id` der Artikelantwort / ID of the warehouse product, as returned in `id` of the product response."}],"responses":{"200":{"description":"Artikel eingereicht; `review_status` ist `IN_REVIEW` / Product submitted; `review_status` is `IN_REVIEW`.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductResponse"},"example":{"id":120045,"sku":"SWP_EX4MPL01","name":"Muster-T-Shirt Basic","description":"Unisex-T-Shirt aus Bio-Baumwolle, Musterartikel.","customer_id":100123,"status":"INACTIVE","review_status":"IN_REVIEW","review_note":null,"submitted_at":"2026-01-16T09:00:00Z","reviewed_at":null,"supplier_number":"LIEF-0001","is_packaged":true,"allow_return_restock":true,"recommended_price":1999,"image_url":null,"customer_can_edit":false,"created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","variants":[{"id":880011,"sku":"SWP_EX4MPL01__Schwarz__M","status":"INACTIVE","size_id":7,"color_id":31,"size":"M","color":"Schwarz","warehouse_size":"M","warehouse_color":"Schwarz","ean":"4006381333931","weight_g":180,"width_mm":300,"height_mm":400,"depth_mm":20,"stock_number":null,"gross_stock":null,"available":null},{"id":880012,"sku":"SWP_EX4MPL01__Schwarz__L","status":"INACTIVE","size_id":8,"color_id":31,"size":"L","color":"Schwarz","warehouse_size":"L","warehouse_color":"Schwarz","ean":null,"weight_g":190,"width_mm":null,"height_mm":null,"depth_mm":null,"stock_number":null,"gross_stock":null,"available":null}]}}}},"400":{"description":"Ungültiger Pfadparameter / Invalid path parameter.","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"403":{"description":"Dem Schlüssel fehlt der erforderliche Scope, oder das Token gehört keinem Kunden / The key lacks the required scope, or the token does not belong to a customer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}},"404":{"description":"Artikel unbekannt oder gehört einem anderen Kunden (nie 403), oder die Funktion ist für dieses Konto nicht verfügbar / Product unknown or owned by another customer (never 403), or the feature is not available for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}},"409":{"description":"Der Artikel ist nicht (mehr) im Entwurf (`extra.error` = `REVIEW_STATE_CHANGED`; `extra.review_status` nennt den aktuellen Prüfstatus) / The product is not (or no longer) a draft (`extra.error` = `REVIEW_STATE_CHANGED`; `extra.review_status` carries the current review status).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseProductErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:write"],"description":"Reicht einen Entwurf zur Prüfung ein: `DRAFT` -> `IN_REVIEW`. Die Antwort ist der Artikel im neuen Stand.\n\nDie Einreichung setzt `submitted_at` und leert eine frühere Entscheidung (`review_note`, `reviewed_at`). Danach ist der Artikel nicht mehr änderbar (`customer_can_edit` = `false`), bis er abgelehnt wird. Die Prüfung erfolgt durch Shirtee; bei Freigabe und bei Ablehnung (mit Begründung) geht eine E-Mail an das Login des Händlers. Erst ein freigegebener Artikel (`APPROVED`) ist `ACTIVE`. Ein abgelehnter Artikel (`DECLINED`) kann nicht direkt eingereicht werden: erst per `PUT` korrigieren (das setzt `DRAFT`), dann einreichen. Der Aufruf braucht keinen Request-Body. Bestandsfelder der Varianten sind in der Antwort `null`.\n\n**Prüfstatus (`review_status`):** `DRAFT` (Entwurf) -> `IN_REVIEW` (eingereicht) -> `APPROVED` (freigegeben) oder `DECLINED` (abgelehnt, mit Begründung in `review_note`). Ein abgelehnter Artikel wird durch eine Änderung per `PUT` wieder zum `DRAFT` und muss erneut eingereicht werden.\n\nErfordert den Scope `warehouse:write`. Fehler: 403 bei fehlendem Scope oder Token ohne Kundenbezug, 404 bei unbekanntem oder fremdem Artikel oder nicht freigeschalteter Funktion, 409 mit `extra.error` = `REVIEW_STATE_CHANGED`, wenn der Artikel nicht (mehr) `DRAFT` ist; `extra.review_status` nennt den aktuellen Wert. Wiederholtes Einreichen eines bereits eingereichten Artikels liefert daher 409, keine zweite Einreichung.\n\nSubmits a draft for review: `DRAFT` -> `IN_REVIEW`. The response is the product in its new state.\n\nSubmitting sets `submitted_at` and clears an earlier decision (`review_note`, `reviewed_at`). The product can then no longer be changed (`customer_can_edit` = `false`) until it is declined. Shirtee performs the review; on approval and on decline (with a reason) an email goes to the merchant's login. Only an approved product (`APPROVED`) is `ACTIVE`. A declined product (`DECLINED`) cannot be submitted directly: correct it with `PUT` first (which sets `DRAFT`), then submit. The call needs no request body. Stock fields of the variants are `null` in the response.\n\n**Review status (`review_status`):** `DRAFT` -> `IN_REVIEW` (submitted) -> `APPROVED` or `DECLINED` (with the reason in `review_note`). Changing a declined product with `PUT` turns it back into `DRAFT`; it must be submitted again.\n\nRequires the scope `warehouse:write`. Errors: 403 for a missing scope or a token without a customer, 404 for an unknown or foreign product or a feature that is not enabled, 409 with `extra.error` = `REVIEW_STATE_CHANGED` if the product is not (or no longer) `DRAFT`; `extra.review_status` carries the current value. Submitting an already submitted product therefore answers 409 and does not submit a second time."}},"/api/warehouse/safety-stock":{"get":{"tags":["Warehouse Safety Stock"],"summary":"Get own safety-stock default","operationId":"ApiWarehouseSafetyStockGetDefault","responses":{"200":{"description":"Standard-Sicherheitsbestand des Händlers / The merchant's default safety stock.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerSafetyStockResponse"},"example":{"customer_id":100123,"enabled":true,"rule":{"buffer":2,"threshold":10,"low_buffer":1,"preview":[{"free":0,"reported":0},{"free":1,"reported":0},{"free":9,"reported":8},{"free":10,"reported":8},{"free":12,"reported":10}]},"updated_at":"2026-01-15T10:30:00Z","updated_by":"user:4711"}}}},"403":{"description":"Dem Schlüssel fehlt der erforderliche Scope, oder das Token gehört keinem Kunden / The key lacks the required scope, or the token does not belong to a customer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SafetyStockErrorResponse"}}}},"404":{"description":"Die Funktion ist für dieses Konto nicht verfügbar / The feature is not available for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SafetyStockErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:read"],"description":"Liefert den Standard-Sicherheitsbestand des Händlers. Er gilt für alle eigenen Lagerartikel, die keine eigene Ausnahme haben (siehe `GET /api/warehouse/products/{product_id}/safety-stock`).\n\nDer **Sicherheitsbestand** hält einen Teil des freien Bestands einer Variante zurück: `available` in der Artikelantwort ist der freie Bestand abzüglich dieses Puffers (nie negativ). Er gilt nur für Lagerartikel. Solange nie ein Standard gesetzt wurde, ist `rule` `null`, `enabled` `false` und `updated_at`/`updated_by` sind `null`. Ist ein Standard gesetzt, aber ausgeschaltet, bleiben die Werte in `rule` sichtbar und `enabled` ist `false`; sie wirken dann nicht. `rule.preview` zeigt an Stützpunkten, wie viele Stück bei welchem freien Bestand gemeldet werden.\n\nErfordert den Scope `warehouse:read`. Fehler: 403 bei fehlendem Scope oder Token ohne Kundenbezug, 404 wenn die Funktion nicht freigeschaltet ist.\n\nReturns the merchant's default safety stock. It applies to all own warehouse products without an override of their own (see `GET /api/warehouse/products/{product_id}/safety-stock`).\n\nThe **safety stock** holds back part of the free stock of a variant: `available` in the product response is the free stock minus this buffer (never negative). It applies to warehouse products only. As long as no default was ever set, `rule` is `null`, `enabled` is `false` and `updated_at`/`updated_by` are `null`. If a default is set but switched off, its values stay visible in `rule` and `enabled` is `false`; they then have no effect. `rule.preview` shows at sample points how many pieces are reported for a given free stock.\n\nRequires the scope `warehouse:read`. Errors: 403 for a missing scope or a token without a customer, 404 if the feature is not enabled."}},"/api/warehouse/shipments":{"get":{"tags":["Warehouse Shipments"],"summary":"List inbound shipments","operationId":"ApiWarehouseShipmentsListShipments","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","maximum":100.0,"minimum":1.0,"default":20},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Maximale Anzahl Einträge je Seite, 1 bis 100, Standard 20 / Maximum number of entries per page, 1 to 100, default 20."},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0.0,"default":0},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Anzahl der zu überspringenden Einträge für die Paginierung, mindestens 0, Standard 0 / Number of entries to skip for pagination, minimum 0, default 0."},{"name":"status","in":"query","schema":{"oneOf":[{"$ref":"#/components/schemas/WarehouseShipmentStatus"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Nur Anlieferungen in diesem Status: `ANNOUNCED`, `RECEIVED` oder `CANCELED`. Ohne Angabe alle Status / Only shipments in this status: `ANNOUNCED`, `RECEIVED` or `CANCELED`. Omit for all statuses."},{"name":"customer_id","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}],"minimum":1},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Optionaler Filter auf eine Kunden-ID, mindestens 1. Er schränkt nur ein: Fremde Kunden-IDs liefern eine leere Liste / Optional filter on a customer ID, minimum 1. It only narrows the result: other customers' IDs yield an empty list."},{"name":"date_from","in":"query","schema":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Untere Datumsgrenze (inklusiv), Format `YYYY-MM-DD`, bezogen auf `planned_inbound_on`, ersatzweise `expected_on`. Schaltet die Sortierung nach Tag ein / Lower date bound (inclusive), format `YYYY-MM-DD`, applied to `planned_inbound_on`, otherwise `expected_on`. Switches to sorting by day."},{"name":"date_to","in":"query","schema":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}]},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Obere Datumsgrenze (inklusiv), Format `YYYY-MM-DD`, bezogen auf `planned_inbound_on`, ersatzweise `expected_on`; darf nicht vor `date_from` liegen / Upper date bound (inclusive), format `YYYY-MM-DD`, applied to `planned_inbound_on`, otherwise `expected_on`; must not be before `date_from`."},{"name":"include_undated","in":"query","schema":{"type":"boolean","default":false},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Mit `true` erscheinen auch Anlieferungen ohne Tag (weder `planned_inbound_on` noch `expected_on`) am Ende; wirkt nur mit `date_from` oder `date_to`, Standard `false` / With `true`, shipments without a day (neither `planned_inbound_on` nor `expected_on`) are included at the end; only effective with `date_from` or `date_to`, default `false`."}],"responses":{"200":{"description":"Seite der Anlieferungen / Page of shipments.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentPageResponse"},"example":{"items":[{"id":90412,"reference":"WHS_90412","customer_id":100234,"status":"ANNOUNCED","notice":"Bitte vor 12 Uhr anliefern","expected_on":"2026-02-10","planned_inbound_on":null,"package_count":3,"pallet_count":1,"carrier":"Spedition Mustermann","tracking_number":"MUSTER-0001234","received_at":null,"canceled_at":null,"created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","arrived_at":null,"customer_edit_locked_from":"2026-02-07","customer_can_edit":true,"target_manufacturer_id":null,"target_sync_status":null,"target_external_reference":null,"target_sync_error_code":null,"target_sync_error_message":null,"is_internal":false,"items":[{"id":551201,"product_variant_id":48213,"announced_quantity":120,"received_quantity":null,"damaged_quantity":0,"note":"Karton 1 bis 3","deviation_quantity":null}],"documents":[],"warnings":[],"zoho_po_number":null,"zoho_po_state":"NONE","zoho_receipt_synced_at":null,"zoho_unmatched_lines":[]},{"id":90377,"reference":"WHS_90377","customer_id":100234,"status":"RECEIVED","notice":null,"expected_on":"2026-01-08","planned_inbound_on":null,"package_count":2,"pallet_count":null,"carrier":"Spedition Mustermann","tracking_number":null,"received_at":"2026-01-09T14:20:00Z","canceled_at":null,"created_at":"2026-01-02T09:00:00Z","updated_at":"2026-01-09T14:20:00Z","arrived_at":"2026-01-09T08:05:00Z","customer_edit_locked_from":"2026-01-05","customer_can_edit":false,"target_manufacturer_id":null,"target_sync_status":null,"target_external_reference":null,"target_sync_error_code":null,"target_sync_error_message":null,"is_internal":false,"items":[{"id":551100,"product_variant_id":48213,"announced_quantity":120,"received_quantity":118,"damaged_quantity":2,"note":null,"deviation_quantity":-2}],"documents":[{"id":7301,"filename":"Packliste-2026-02.xlsx","content_type":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","size_bytes":18432,"created_at":"2026-01-15T10:35:00Z"}],"warnings":[],"zoho_po_number":null,"zoho_po_state":"NONE","zoho_receipt_synced_at":null,"zoho_unmatched_lines":[]}],"limit":20,"offset":0,"total_count":2}}}},"400":{"description":"`extra.error` = `INVALID_DATE_RANGE`: `date_to` liegt vor `date_from`; sonst ungültiger Parameterwert / `extra.error` = `INVALID_DATE_RANGE`: `date_to` is before `date_from`; otherwise invalid parameter value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"404":{"description":"Die Funktion ist für dieses Konto nicht verfügbar / The feature is not available for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:read"],"description":"Listet die Anlieferungen ans Lager, die zum Händlerkonto gehören, seitenweise. Jeder Eintrag hat dieselbe Form wie bei `GET /api/warehouse/shipments/{shipment_id}`, also mit Positionen und aktiven Dokumenten. Interne Umlagerungen des Lagers erscheinen nie.\n\n**Sortierung:** ohne Datumsfilter die zuletzt angelegten zuerst. Sobald `date_from` oder `date_to` gesetzt ist, aufsteigend nach Kalendertag (`planned_inbound_on`, ersatzweise `expected_on`), dann nach `id`; Anlieferungen ohne Tag stehen am Ende. Beide Datumsgrenzen gelten inklusive. `include_undated=true` nimmt Anlieferungen ohne Tag in das Ergebnis auf und wirkt nur zusammen mit einer Datumsgrenze. Liegt `date_to` vor `date_from`, antwortet der Aufruf mit 400 und `extra.error` = `INVALID_DATE_RANGE`.\n\nDie Antwort enthält `total_count` (Treffer insgesamt) sowie `limit` und `offset` der Anfrage. Ein `customer_id`, das nicht zum Händlerkonto gehört, liefert eine leere Liste. Benötigter Scope: `warehouse:read`. Ist die Anlieferungsfunktion für dieses Konto nicht verfügbar, antworten alle Aufrufe mit 404.\n\nLists the inbound shipments to the warehouse that belong to the merchant account, page by page. Each entry has the same shape as `GET /api/warehouse/shipments/{shipment_id}`, including items and active documents. Internal transfers of the warehouse never appear.\n\n**Sorting:** without a date filter, most recently created first. As soon as `date_from` or `date_to` is set, ascending by calendar day (`planned_inbound_on`, otherwise `expected_on`), then by `id`; shipments without a day come last. Both date bounds are inclusive. `include_undated=true` adds shipments without a day to the result and only has an effect together with a date bound. If `date_to` is before `date_from`, the call answers 400 with `extra.error` = `INVALID_DATE_RANGE`.\n\nThe response carries `total_count` (all matches) plus the `limit` and `offset` of the request. A `customer_id` that does not belong to the merchant account yields an empty list. Required scope: `warehouse:read`. If the inbound shipment feature is not available for this account, every call answers 404."},"post":{"tags":["Warehouse Shipments"],"summary":"Announce an inbound shipment","operationId":"ApiWarehouseShipmentsCreateShipment","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentCreateRequest"},"example":{"items":[{"product_variant_id":48213,"announced_quantity":120,"note":"Karton 1 bis 3"}],"notice":"Bitte vor 12 Uhr anliefern","expected_on":"2026-02-10","package_count":3,"pallet_count":1,"carrier":"Spedition Mustermann","tracking_number":"MUSTER-0001234"}}},"required":true},"responses":{"201":{"description":"Anlieferung angelegt, Status `ANNOUNCED` / Shipment created with status `ANNOUNCED`.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentResponse"},"example":{"id":90412,"reference":"WHS_90412","customer_id":100234,"status":"ANNOUNCED","notice":"Bitte vor 12 Uhr anliefern","expected_on":"2026-02-10","planned_inbound_on":null,"package_count":3,"pallet_count":1,"carrier":"Spedition Mustermann","tracking_number":"MUSTER-0001234","received_at":null,"canceled_at":null,"created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","arrived_at":null,"customer_edit_locked_from":"2026-02-07","customer_can_edit":true,"target_manufacturer_id":null,"target_sync_status":null,"target_external_reference":null,"target_sync_error_code":null,"target_sync_error_message":null,"is_internal":false,"items":[{"id":551201,"product_variant_id":48213,"announced_quantity":120,"received_quantity":null,"damaged_quantity":0,"note":"Karton 1 bis 3","deviation_quantity":null}],"documents":[],"warnings":[],"zoho_po_number":null,"zoho_po_state":"NONE","zoho_receipt_synced_at":null,"zoho_unmatched_lines":[]}}}},"400":{"description":"`extra.error` = `INVALID_ITEMS` (keine oder doppelte Positionen) oder `VARIANT_INACTIVE` (deaktivierte Variante, `extra.product_variant_ids`); sonst ungültige Werte ohne Code / `extra.error` = `INVALID_ITEMS` (no or duplicate items) or `VARIANT_INACTIVE` (deactivated variant, `extra.product_variant_ids`); otherwise invalid values without a code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"404":{"description":"Eine `product_variant_id` ist unbekannt, gehört zu einem anderen Händler oder ist kein Lagerartikel, oder die Funktion ist nicht verfügbar / A `product_variant_id` is unknown, belongs to another merchant or is not a warehouse article, or the feature is not available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:shipment_write","warehouse:write"],"description":"Kündigt eine Anlieferung ans Lager an. Die neue Anlieferung entsteht im Status `ANNOUNCED` und bekommt die Anlieferungsnummer `reference` = `WHS_<id>`. Der Aufruf ist nicht idempotent: Jeder erfolgreiche Aufruf legt eine weitere Anlieferung an.\n\n**Positionen:** `items` braucht mindestens eine Position, jede Variante höchstens einmal (sonst 400 mit `extra.error` = `INVALID_ITEMS`). Jede `product_variant_id` muss eine Lagerartikel-Variante des eigenen Händlerkontos sein, sonst 404. Eine deaktivierte Variante wird nicht neu angenommen: 400 mit `extra.error` = `VARIANT_INACTIVE` und `extra.product_variant_ids`. Verstöße gegen Wertebereiche und Längen der Felder liefern 400 ohne `extra.error`.\n\n**Händler-Besonderheiten:** Der Kunde ergibt sich aus dem Zugang; `customer_id`, `planned_inbound_on`, `target_manufacturer_id` und `is_internal` im Body werden ignoriert. `planned_inbound_on` setzt das Lager. Liegt der gespeicherte Termin bereits im Sperrfenster, ist gespeichert und die Antwort enthält die Warnung `EDIT_WINDOW_CLOSED`: Ab dann ändert nur noch das Lager. Als Händler lassen sich Anlieferungen nur im Status `ANNOUNCED` und vor dem Stichtag ändern. Stichtag ist der Kalendertag (Zeitzone Europe/Berlin), der drei Tage vor dem vom Lager gesetzten Eingangstermin (`planned_inbound_on`, ersatzweise vor `expected_on`) liegt; am Stichtag selbst ist bereits gesperrt. Ohne beide Termine gibt es keinen Stichtag. Eine im Lagersystem bereits angelegte Einkaufsbestellung (`zoho_po_state` ungleich `NONE`) sperrt ebenfalls, auch vor dem Stichtag. `customer_can_edit` in der Antwort zeigt, ob noch geändert werden darf.\n\nBenötigter Scope: `warehouse:shipment_write` oder `warehouse:write`. Ist die Anlieferungsfunktion für dieses Konto nicht verfügbar, antworten alle Aufrufe mit 404.\n\nAnnounces an inbound shipment to the warehouse. The new shipment is created with status `ANNOUNCED` and gets the shipment number `reference` = `WHS_<id>`. The call is not idempotent: every successful call creates another shipment.\n\n**Items:** `items` needs at least one item, each variant at most once (otherwise 400 with `extra.error` = `INVALID_ITEMS`). Every `product_variant_id` must be a warehouse-stock variant of the merchant's own account, otherwise 404. A deactivated variant is not accepted as a new item: 400 with `extra.error` = `VARIANT_INACTIVE` and `extra.product_variant_ids`. Violations of value ranges and lengths return 400 without `extra.error`.\n\n**Merchant specifics:** the customer is derived from the credentials; `customer_id`, `planned_inbound_on`, `target_manufacturer_id` and `is_internal` in the body are ignored. The warehouse sets `planned_inbound_on`. If the stored date already lies in the lock window, the shipment is saved and the response carries the warning `EDIT_WINDOW_CLOSED`: from then on only the warehouse can change it. As a merchant you can change shipments only while the status is `ANNOUNCED` and before the cut-off date. The cut-off is the calendar day (time zone Europe/Berlin) three days before the inbound date set by the warehouse (`planned_inbound_on`, otherwise `expected_on`); the cut-off day itself is already locked. Without either date there is no cut-off. A purchase order already created in the warehouse system (`zoho_po_state` other than `NONE`) also locks the shipment, even before the cut-off. `customer_can_edit` in the response tells whether changes are still allowed.\n\nRequired scope: `warehouse:shipment_write` or `warehouse:write`. If the inbound shipment feature is not available for this account, every call answers 404."}},"/api/warehouse/shipments/import":{"post":{"tags":["Warehouse Shipments"],"summary":"Translate a shipping list into a shipment proposal","description":"Liest eine Excel-Versandliste (Shippingliste, `.xlsx`) ein und liefert daraus einen Vorschlag für eine Anlieferung. Der Aufruf legt nichts an und ändert nichts. Die Datei kommt als `multipart/form-data` im Feld `file`; größer als 20 MB wird sie abgewiesen.\n\n**Format der Datei:** Gelesen wird nur das erste Tabellenblatt. Die Kopfzeile muss in den ersten 20 Zeilen stehen und eine Artikelspalte sowie eine Mengenspalte enthalten. Die Überschriften werden ohne Beachtung von Groß-/Kleinschreibung, Leer- und Sonderzeichen erkannt. Artikel: `SKU`, `Artikelnummer`, `Artikelnr`, `ArtNr`, `Item Number`, `Item No`, `Product Number`, `Produktnummer`, `Varianten-SKU`, `Variant SKU`, `Eigene SKU`, `Custom SKU` oder EAN: `EAN`, `EAN13`, `EAN-Code`, `GTIN`, `GTIN13`, `Barcode`, `Strichcode`. Menge: `Menge`, `Anzahl`, `Qty`, `Quantity`, `Stück`, `Stk`, `Pcs`, `Pieces`, `Stückzahl`. Optional: `Notiz`, `Bemerkung`, `Note`, `Notes`, `Kommentar`, `Comment`, `Hinweis`. `Amount` zählt nicht als Mengenspalte. Eine Menge ist eine ganze Zahl größer 0 (Zahl oder Ziffernfolge); leere Zeilen werden übersprungen. Höchstens 5.000 Datenzeilen.\n\n**Zuordnung:** Jede Zeile wird den eigenen Lagerartikeln des Händlerkontos zugeordnet, je Kennung in der Reihenfolge SKU, Marken-SKU, EAN; die SKU-Spalte hat Vorrang vor der EAN-Spalte. Zeilen mit derselben Variante werden aufsummiert (`rows` nennt die Excel-Zeilen, Notizen werden mit `; ` verbunden und auf 512 Zeichen gekürzt). Was nicht zugeordnet wurde, steht in `unmatched` (kein Treffer), `ambiguous` (mehrere aktive Treffer) oder `invalid` (Zeile unbrauchbar, Grund in `reason`). Eine Summe über 100.000 je Variante verwirft alle beteiligten Zeilen mit `QUANTITY_TOO_LARGE`. `columns` nennt die erkannten Spalten mit ihrer Beschriftung.\n\n**Weiterverarbeitung:** Für `POST /api/warehouse/shipments` je Position nur `product_variant_id`, `announced_quantity` und `note` übernehmen; `sku` und `rows` kennt das Anlegen nicht. Die Datei selbst lässt sich danach als Dokument an die Anlieferung hängen.\n\n**Fehler:** Ist die Datei nicht lesbar, antwortet der Aufruf mit 400, `extra.error` = `INVALID_SHIPPING_LIST` und `extra.reason`: `NOT_XLSX` (keine lesbare xlsx-Datei), `FILE_REJECTED` (Datei entpackt unverhältnismäßig groß), `HEADER_NOT_FOUND` (keine Kopfzeile mit Artikel- und Mengenspalte) oder `TOO_MANY_ROWS` (mehr als 5.000 Datenzeilen oder mehr als 20.000 gelesene Zeilen einschließlich leerer). Eine Datei über 20 MB liefert 400 mit `extra.error` = `FILE_TOO_LARGE`; ist schon der Request über 20 MB zuzüglich Multipart-Rahmen, 413 ohne `extra.error`. Benötigter Scope: `warehouse:shipment_write` oder `warehouse:write`. Ist die Anlieferungsfunktion für dieses Konto nicht verfügbar, antworten alle Aufrufe mit 404.\n\nReads an Excel shipping list (`.xlsx`) and returns a proposal for an inbound shipment. The call creates and changes nothing. The file is sent as `multipart/form-data` in the field `file`; files larger than 20 MB are rejected.\n\n**File format:** only the first worksheet is read. The header row must be within the first 20 rows and contain an article column and a quantity column. Headings are matched ignoring case, spaces and special characters. Article: `SKU`, `Artikelnummer`, `Artikelnr`, `ArtNr`, `Item Number`, `Item No`, `Product Number`, `Produktnummer`, `Varianten-SKU`, `Variant SKU`, `Eigene SKU`, `Custom SKU`, or EAN: `EAN`, `EAN13`, `EAN-Code`, `GTIN`, `GTIN13`, `Barcode`, `Strichcode`. Quantity: `Menge`, `Anzahl`, `Qty`, `Quantity`, `Stück`, `Stk`, `Pcs`, `Pieces`, `Stückzahl`. Optional: `Notiz`, `Bemerkung`, `Note`, `Notes`, `Kommentar`, `Comment`, `Hinweis`. `Amount` does not count as a quantity column. A quantity is a whole number greater than 0 (number or string of digits); empty rows are skipped. At most 5,000 data rows.\n\n**Matching:** every row is matched against the merchant account's own warehouse articles, per identifier in the order SKU, brand SKU, EAN; the SKU column takes precedence over the EAN column. Rows with the same variant are summed (`rows` lists the Excel rows, notes are joined with `; ` and cut to 512 characters). Whatever could not be matched is listed in `unmatched` (no hit), `ambiguous` (several active hits) or `invalid` (row unusable, reason in `reason`). A sum above 100,000 per variant discards all contributing rows with `QUANTITY_TOO_LARGE`. `columns` names the detected columns with their label in the file.\n\n**Next step:** for `POST /api/warehouse/shipments` take only `product_variant_id`, `announced_quantity` and `note` per item; creating does not accept `sku` and `rows`. The file itself can then be attached to the shipment as a document.\n\n**Errors:** if the file cannot be read, the call answers 400 with `extra.error` = `INVALID_SHIPPING_LIST` and `extra.reason`: `NOT_XLSX` (not a readable xlsx file), `FILE_REJECTED` (file expands disproportionately), `HEADER_NOT_FOUND` (no header row with an article and a quantity column) or `TOO_MANY_ROWS` (more than 5,000 data rows or more than 20,000 scanned rows including empty ones). A file over 20 MB yields 400 with `extra.error` = `FILE_TOO_LARGE`; if the whole request exceeds 20 MB plus multipart overhead, 413 without `extra.error`. Required scope: `warehouse:shipment_write` or `warehouse:write`. If the inbound shipment feature is not available for this account, every call answers 404.","operationId":"ApiWarehouseShipmentsImportImportShippingList","parameters":[{"name":"customer_id","in":"query","schema":{"oneOf":[{"type":"integer"},{"type":"null"}],"minimum":1},"required":false,"deprecated":false,"allowEmptyValue":false,"allowReserved":false,"description":"Hat für Händler keine Wirkung: Der Kunde ergibt sich aus dem Zugang / Has no effect for merchants: the customer is derived from the credentials."}],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"file":{"type":"string","format":"binary","contentMediaType":"application/octet-stream"}},"type":"object"}}},"required":true},"responses":{"200":{"description":"Vorschlag aus der Versandliste; es wurde nichts angelegt / Proposal from the shipping list; nothing was created.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShippingListImportResponse"},"example":{"items":[{"product_variant_id":48213,"sku":"MUSTER-TS-BLK-M","announced_quantity":120,"rows":[2,5],"note":"Karton 1"}],"unmatched":[{"row":4,"value":"MUSTER-XX-1","reason":"NOT_FOUND"}],"ambiguous":[{"row":6,"value":"4012345678901","candidates":[48214,48215]}],"invalid":[{"row":7,"reason":"QUANTITY_INVALID"}],"columns":{"sku":"Artikelnummer","quantity":"Menge","note":"Bemerkung"}}}}},"400":{"description":"`extra.error` = `INVALID_SHIPPING_LIST` mit `extra.reason` (`NOT_XLSX`, `FILE_REJECTED`, `HEADER_NOT_FOUND`, `TOO_MANY_ROWS`) oder `FILE_TOO_LARGE` (Datei über 20 MB) / `extra.error` = `INVALID_SHIPPING_LIST` with `extra.reason` (`NOT_XLSX`, `FILE_REJECTED`, `HEADER_NOT_FOUND`, `TOO_MANY_ROWS`) or `FILE_TOO_LARGE` (file over 20 MB).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"404":{"description":"Die Funktion ist für dieses Konto nicht verfügbar / The feature is not available for this account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"413":{"description":"Request größer als 20 MB zuzüglich Multipart-Rahmen; abgewiesen ohne `extra.error` / Request larger than 20 MB plus multipart overhead; rejected without `extra.error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:shipment_write","warehouse:write"]}},"/api/warehouse/shipments/{shipment_id}":{"get":{"tags":["Warehouse Shipments"],"summary":"Get an inbound shipment","operationId":"ApiWarehouseShipmentsShipmentIdGetShipment","parameters":[{"name":"shipment_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Anlieferung (`id` aus Anlegen oder Liste) / ID of the inbound shipment (`id` from create or list)."}],"responses":{"200":{"description":"Anlieferung mit Positionen und aktiven Dokumenten / Shipment with items and active documents.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentResponse"},"example":{"id":90412,"reference":"WHS_90412","customer_id":100234,"status":"ANNOUNCED","notice":"Bitte vor 12 Uhr anliefern","expected_on":"2026-02-10","planned_inbound_on":null,"package_count":3,"pallet_count":1,"carrier":"Spedition Mustermann","tracking_number":"MUSTER-0001234","received_at":null,"canceled_at":null,"created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-15T10:30:00Z","arrived_at":null,"customer_edit_locked_from":"2026-02-07","customer_can_edit":true,"target_manufacturer_id":null,"target_sync_status":null,"target_external_reference":null,"target_sync_error_code":null,"target_sync_error_message":null,"is_internal":false,"items":[{"id":551201,"product_variant_id":48213,"announced_quantity":120,"received_quantity":null,"damaged_quantity":0,"note":"Karton 1 bis 3","deviation_quantity":null}],"documents":[],"warnings":[],"zoho_po_number":null,"zoho_po_state":"NONE","zoho_receipt_synced_at":null,"zoho_unmatched_lines":[]}}}},"400":{"description":"Anfrage ungültig: Wert außerhalb des erlaubten Bereichs, falsches Format oder fehlendes Pflichtfeld (ohne `extra.error`) / Invalid request: value out of range, wrong format or missing required field (without `extra.error`).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Anlieferung, Dokument oder Variante nicht gefunden, gehört zu einem anderen Händler oder die Funktion ist für dieses Konto nicht verfügbar; nie 403 / Shipment, document or variant not found, belongs to another merchant, or the feature is not available for this account; never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:read"],"description":"Liefert eine Anlieferung mit allen Positionen und den aktiven (nicht entfernten) Dokumenten. Anlieferungen anderer Händler, interne Umlagerungen des Lagers und unbekannte IDs antworten gleichermaßen mit 404, nie mit 403. Die Anlieferung ist in jedem Status abrufbar, auch nach Wareneingang oder Storno.\n\nBenötigter Scope: `warehouse:read`. Ist die Anlieferungsfunktion für dieses Konto nicht verfügbar, antworten alle Aufrufe mit 404.\n\nReturns an inbound shipment with all items and the active (not removed) documents. Shipments of other merchants, internal transfers of the warehouse and unknown IDs all answer 404, never 403. The shipment can be retrieved in every status, also after goods receipt or cancellation.\n\nRequired scope: `warehouse:read`. If the inbound shipment feature is not available for this account, every call answers 404."},"put":{"tags":["Warehouse Shipments"],"summary":"Replace an inbound shipment","operationId":"ApiWarehouseShipmentsShipmentIdUpdateShipment","parameters":[{"name":"shipment_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der zu ersetzenden Anlieferung / ID of the inbound shipment to replace."}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentWriteRequest"},"example":{"items":[{"product_variant_id":48213,"announced_quantity":150,"note":"Karton 1 bis 4"},{"product_variant_id":48220,"announced_quantity":40,"note":null}],"notice":"Bitte vor 12 Uhr anliefern","expected_on":"2026-02-12","package_count":4,"pallet_count":1,"carrier":"Spedition Mustermann","tracking_number":"MUSTER-0001234","expected_updated_at":"2026-01-15T10:30:00Z"}}},"required":true},"responses":{"200":{"description":"Neuer Stand der Anlieferung / New state of the shipment.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentResponse"},"example":{"id":90412,"reference":"WHS_90412","customer_id":100234,"status":"ANNOUNCED","notice":"Bitte vor 12 Uhr anliefern","expected_on":"2026-02-12","planned_inbound_on":null,"package_count":4,"pallet_count":1,"carrier":"Spedition Mustermann","tracking_number":"MUSTER-0001234","received_at":null,"canceled_at":null,"created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-16T08:00:00Z","arrived_at":null,"customer_edit_locked_from":"2026-02-09","customer_can_edit":true,"target_manufacturer_id":null,"target_sync_status":null,"target_external_reference":null,"target_sync_error_code":null,"target_sync_error_message":null,"is_internal":false,"items":[{"id":551201,"product_variant_id":48213,"announced_quantity":150,"received_quantity":null,"damaged_quantity":0,"note":"Karton 1 bis 4","deviation_quantity":null},{"id":551202,"product_variant_id":48220,"announced_quantity":40,"received_quantity":null,"damaged_quantity":0,"note":null,"deviation_quantity":null}],"documents":[],"warnings":[],"zoho_po_number":null,"zoho_po_state":"NONE","zoho_receipt_synced_at":null,"zoho_unmatched_lines":[]}}}},"400":{"description":"`extra.error` = `INVALID_ITEMS` oder `VARIANT_INACTIVE`; sonst ungültige Werte ohne Code / `extra.error` = `INVALID_ITEMS` or `VARIANT_INACTIVE`; otherwise invalid values without a code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"404":{"description":"Anlieferung, Dokument oder Variante nicht gefunden, gehört zu einem anderen Händler oder die Funktion ist für dieses Konto nicht verfügbar; nie 403 / Shipment, document or variant not found, belongs to another merchant, or the feature is not available for this account; never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"409":{"description":"`extra.error` = `SHIPMENT_NOT_EDITABLE` (Status nicht mehr `ANNOUNCED`), `SHIPMENT_LOCKED` (Stichtag erreicht oder Einkaufsbestellung angelegt) oder `SHIPMENT_STALE` (`expected_updated_at` weicht vom gespeicherten Stand ab; neu laden und wiederholen) / `extra.error` = `SHIPMENT_NOT_EDITABLE` (status no longer `ANNOUNCED`), `SHIPMENT_LOCKED` (cut-off reached or purchase order created) or `SHIPMENT_STALE` (`expected_updated_at` differs from the stored state; reload and retry).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"503":{"description":"Tritt nur bei Bearbeitung durch das Lager auf, nicht für Händler-Zugänge / Occurs only when the warehouse edits, not for merchant credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:shipment_write","warehouse:write"],"description":"Ersetzt den gesamten Stand einer Anlieferung (Kopfdaten und Positionen); es ist kein Teil-Update. Felder, die fehlen oder `null` sind, werden geleert. Positionen, die im Body nicht mehr vorkommen, werden entfernt; vorhandene Varianten erhalten Menge und Notiz neu, neue Varianten werden ergänzt. Für `items` gelten dieselben Regeln wie beim Anlegen (mindestens eine Position, keine doppelte Variante, nur eigene Lagerartikel, deaktivierte Varianten nicht neu; bereits enthaltene deaktivierte Varianten dürfen bleiben).\n\n**Voraussetzungen:** Die Anlieferung muss im Status `ANNOUNCED` sein, sonst 409 mit `extra.error` = `SHIPMENT_NOT_EDITABLE` und `extra.status`. Nach dem Stichtag antwortet der Aufruf mit 409 und `extra.error` = `SHIPMENT_LOCKED`. Geprüft wird dabei der gespeicherte Stand, nicht der neue: Ein verschobener Termin im Body hebt die Sperre nicht auf. Als Händler lassen sich Anlieferungen nur im Status `ANNOUNCED` und vor dem Stichtag ändern. Stichtag ist der Kalendertag (Zeitzone Europe/Berlin), der drei Tage vor dem vom Lager gesetzten Eingangstermin (`planned_inbound_on`, ersatzweise vor `expected_on`) liegt; am Stichtag selbst ist bereits gesperrt. Ohne beide Termine gibt es keinen Stichtag. Eine im Lagersystem bereits angelegte Einkaufsbestellung (`zoho_po_state` ungleich `NONE`) sperrt ebenfalls, auch vor dem Stichtag. `customer_can_edit` in der Antwort zeigt, ob noch geändert werden darf.\n\n**Optimistische Sperre:** Wird `expected_updated_at` mitgesendet (der `updated_at`-Wert des bearbeiteten Stands, Vergleich auf Millisekunden), antwortet der Aufruf mit 409 und `extra.error` = `SHIPMENT_STALE`, wenn die Anlieferung inzwischen geändert wurde. Ohne das Feld wird nicht geprüft.\n\n`customer_id` gibt es hier nicht. `planned_inbound_on`, `target_manufacturer_id` und `is_internal` werden für Händler ignoriert; der gespeicherte Eingangstermin bleibt unverändert. Liegt der gespeicherte Termin nach dem Speichern im Sperrfenster, enthält die Antwort die Warnung `EDIT_WINDOW_CLOSED`. Benötigter Scope: `warehouse:shipment_write` oder `warehouse:write`. Ist die Anlieferungsfunktion für dieses Konto nicht verfügbar, antworten alle Aufrufe mit 404.\n\nReplaces the complete state of an inbound shipment (header data and items); it is not a partial update. Fields that are missing or `null` are cleared. Items no longer present in the body are removed; existing variants get their quantity and note replaced, new variants are added. `items` follows the same rules as on create (at least one item, no duplicate variant, own warehouse articles only, deactivated variants not as new items; deactivated variants already on the shipment may stay).\n\n**Preconditions:** the shipment must have status `ANNOUNCED`, otherwise 409 with `extra.error` = `SHIPMENT_NOT_EDITABLE` and `extra.status`. After the cut-off the call answers 409 with `extra.error` = `SHIPMENT_LOCKED`. The stored state is checked, not the new one: moving the date in the body does not lift the lock. As a merchant you can change shipments only while the status is `ANNOUNCED` and before the cut-off date. The cut-off is the calendar day (time zone Europe/Berlin) three days before the inbound date set by the warehouse (`planned_inbound_on`, otherwise `expected_on`); the cut-off day itself is already locked. Without either date there is no cut-off. A purchase order already created in the warehouse system (`zoho_po_state` other than `NONE`) also locks the shipment, even before the cut-off. `customer_can_edit` in the response tells whether changes are still allowed.\n\n**Optimistic lock:** if `expected_updated_at` is sent (the `updated_at` value of the state you edited, compared to the millisecond), the call answers 409 with `extra.error` = `SHIPMENT_STALE` when the shipment has changed in the meantime. Without the field nothing is checked.\n\nThere is no `customer_id` here. `planned_inbound_on`, `target_manufacturer_id` and `is_internal` are ignored for merchants; the stored inbound date stays unchanged. If the stored date lies in the lock window after saving, the response carries the warning `EDIT_WINDOW_CLOSED`. Required scope: `warehouse:shipment_write` or `warehouse:write`. If the inbound shipment feature is not available for this account, every call answers 404."},"delete":{"tags":["Warehouse Shipments"],"summary":"Cancel an inbound shipment","operationId":"ApiWarehouseShipmentsShipmentIdCancelShipment","parameters":[{"name":"shipment_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der zu stornierenden Anlieferung / ID of the inbound shipment to cancel."}],"responses":{"200":{"description":"Stornierte Anlieferung, Status `CANCELED` / Canceled shipment with status `CANCELED`.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentResponse"},"example":{"id":90412,"reference":"WHS_90412","customer_id":100234,"status":"CANCELED","notice":"Bitte vor 12 Uhr anliefern","expected_on":"2026-02-10","planned_inbound_on":null,"package_count":3,"pallet_count":1,"carrier":"Spedition Mustermann","tracking_number":"MUSTER-0001234","received_at":null,"canceled_at":"2026-01-17T09:00:00Z","created_at":"2026-01-15T10:30:00Z","updated_at":"2026-01-17T09:00:00Z","arrived_at":null,"customer_edit_locked_from":"2026-02-07","customer_can_edit":false,"target_manufacturer_id":null,"target_sync_status":null,"target_external_reference":null,"target_sync_error_code":null,"target_sync_error_message":null,"is_internal":false,"items":[{"id":551201,"product_variant_id":48213,"announced_quantity":120,"received_quantity":null,"damaged_quantity":0,"note":"Karton 1 bis 3","deviation_quantity":null}],"documents":[],"warnings":[],"zoho_po_number":null,"zoho_po_state":"NONE","zoho_receipt_synced_at":null,"zoho_unmatched_lines":[]}}}},"400":{"description":"Anfrage ungültig: Wert außerhalb des erlaubten Bereichs, falsches Format oder fehlendes Pflichtfeld (ohne `extra.error`) / Invalid request: value out of range, wrong format or missing required field (without `extra.error`).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Anlieferung, Dokument oder Variante nicht gefunden, gehört zu einem anderen Händler oder die Funktion ist für dieses Konto nicht verfügbar; nie 403 / Shipment, document or variant not found, belongs to another merchant, or the feature is not available for this account; never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"409":{"description":"Nicht änderbar: `extra.error` = `SHIPMENT_NOT_EDITABLE` (Status nicht mehr `ANNOUNCED`, siehe `extra.status`) oder `SHIPMENT_LOCKED` (Stichtag erreicht oder Einkaufsbestellung angelegt) / Not changeable: `extra.error` = `SHIPMENT_NOT_EDITABLE` (status no longer `ANNOUNCED`, see `extra.status`) or `SHIPMENT_LOCKED` (cut-off reached or purchase order created).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:shipment_cancel","warehouse:write"],"description":"Storniert eine Anlieferung. Nichts wird gelöscht: Die Anlieferung bleibt mit Status `CANCELED` und `canceled_at` abrufbar und ist danach nicht mehr änderbar. Der Aufruf liefert die stornierte Anlieferung mit Status 200 zurück.\n\n**Voraussetzungen:** Nur eine Anlieferung im Status `ANNOUNCED` lässt sich stornieren; sonst 409 mit `extra.error` = `SHIPMENT_NOT_EDITABLE` und `extra.status`. Das gilt auch für einen wiederholten Aufruf auf eine bereits stornierte Anlieferung. Nach dem Stichtag antwortet der Aufruf mit 409 und `extra.error` = `SHIPMENT_LOCKED`. Als Händler lassen sich Anlieferungen nur im Status `ANNOUNCED` und vor dem Stichtag ändern. Stichtag ist der Kalendertag (Zeitzone Europe/Berlin), der drei Tage vor dem vom Lager gesetzten Eingangstermin (`planned_inbound_on`, ersatzweise vor `expected_on`) liegt; am Stichtag selbst ist bereits gesperrt. Ohne beide Termine gibt es keinen Stichtag. Eine im Lagersystem bereits angelegte Einkaufsbestellung (`zoho_po_state` ungleich `NONE`) sperrt ebenfalls, auch vor dem Stichtag. `customer_can_edit` in der Antwort zeigt, ob noch geändert werden darf.\n\nBenötigter Scope: `warehouse:shipment_cancel` oder `warehouse:write`. Ist die Anlieferungsfunktion für dieses Konto nicht verfügbar, antworten alle Aufrufe mit 404.\n\nCancels an inbound shipment. Nothing is deleted: the shipment stays retrievable with status `CANCELED` and `canceled_at` and can no longer be changed. The call returns the canceled shipment with status 200.\n\n**Preconditions:** only a shipment with status `ANNOUNCED` can be canceled; otherwise 409 with `extra.error` = `SHIPMENT_NOT_EDITABLE` and `extra.status`. This also applies to a repeated call on an already canceled shipment. After the cut-off the call answers 409 with `extra.error` = `SHIPMENT_LOCKED`. As a merchant you can change shipments only while the status is `ANNOUNCED` and before the cut-off date. The cut-off is the calendar day (time zone Europe/Berlin) three days before the inbound date set by the warehouse (`planned_inbound_on`, otherwise `expected_on`); the cut-off day itself is already locked. Without either date there is no cut-off. A purchase order already created in the warehouse system (`zoho_po_state` other than `NONE`) also locks the shipment, even before the cut-off. `customer_can_edit` in the response tells whether changes are still allowed.\n\nRequired scope: `warehouse:shipment_cancel` or `warehouse:write`. If the inbound shipment feature is not available for this account, every call answers 404."}},"/api/warehouse/shipments/{shipment_id}/documents":{"post":{"tags":["Warehouse Shipments"],"summary":"Attach a document to an inbound shipment","operationId":"ApiWarehouseShipmentsShipmentIdDocumentsUploadDocument","parameters":[{"name":"shipment_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Anlieferung, an die das Dokument gehängt wird / ID of the inbound shipment the document is attached to."}],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"file":{"type":"string","format":"binary","contentMediaType":"application/octet-stream"}},"type":"object"}}},"required":true},"responses":{"201":{"description":"Dokument angehängt / Document attached.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentDocumentResponse"},"example":{"id":7301,"filename":"Packliste-2026-02.xlsx","content_type":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","size_bytes":18432,"created_at":"2026-01-15T10:35:00Z"}}}},"400":{"description":"`extra.error` = `INVALID_FILE_TYPE` (weder xlsx noch PDF) oder `FILE_TOO_LARGE` (über 20 MB) / `extra.error` = `INVALID_FILE_TYPE` (neither xlsx nor PDF) or `FILE_TOO_LARGE` (over 20 MB).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"404":{"description":"Anlieferung, Dokument oder Variante nicht gefunden, gehört zu einem anderen Händler oder die Funktion ist für dieses Konto nicht verfügbar; nie 403 / Shipment, document or variant not found, belongs to another merchant, or the feature is not available for this account; never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"409":{"description":"Nicht änderbar: `extra.error` = `SHIPMENT_NOT_EDITABLE` (Status nicht mehr `ANNOUNCED`, siehe `extra.status`) oder `SHIPMENT_LOCKED` (Stichtag erreicht oder Einkaufsbestellung angelegt) / Not changeable: `extra.error` = `SHIPMENT_NOT_EDITABLE` (status no longer `ANNOUNCED`, see `extra.status`) or `SHIPMENT_LOCKED` (cut-off reached or purchase order created).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"413":{"description":"Request größer als 20 MB zuzüglich Multipart-Rahmen; abgewiesen ohne `extra.error` / Request larger than 20 MB plus multipart overhead; rejected without `extra.error`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:document_write","warehouse:write"],"description":"Hängt ein Dokument an eine Anlieferung, etwa die Excel-Versandliste oder einen Lieferschein. Die Datei kommt als `multipart/form-data` im Feld `file`, eine Datei je Aufruf. Erlaubt sind Excel-Dateien (`.xlsx`) und PDF, höchstens 20 MB. Der Dateityp wird am Inhalt geprüft, nicht am Dateinamen; CSV und das alte `.xls`-Format werden daher abgewiesen (400, `extra.error` = `INVALID_FILE_TYPE`). Eine Datei über 20 MB liefert 400 mit `extra.error` = `FILE_TOO_LARGE`; ist schon der Request über 20 MB zuzüglich Multipart-Rahmen, 413 ohne `extra.error`. Dateinamen über 255 Zeichen werden unter Beibehaltung der Endung gekürzt.\n\n**Voraussetzungen:** Als Händler nur bei Status `ANNOUNCED` (sonst 409, `extra.error` = `SHIPMENT_NOT_EDITABLE`) und vor dem Stichtag (sonst 409, `extra.error` = `SHIPMENT_LOCKED`). Als Händler lassen sich Anlieferungen nur im Status `ANNOUNCED` und vor dem Stichtag ändern. Stichtag ist der Kalendertag (Zeitzone Europe/Berlin), der drei Tage vor dem vom Lager gesetzten Eingangstermin (`planned_inbound_on`, ersatzweise vor `expected_on`) liegt; am Stichtag selbst ist bereits gesperrt. Ohne beide Termine gibt es keinen Stichtag. Eine im Lagersystem bereits angelegte Einkaufsbestellung (`zoho_po_state` ungleich `NONE`) sperrt ebenfalls, auch vor dem Stichtag. `customer_can_edit` in der Antwort zeigt, ob noch geändert werden darf.\n\nDas Dokument erscheint danach in `documents` der Anlieferung. Benötigter Scope: `warehouse:document_write` oder `warehouse:write`. Ist die Anlieferungsfunktion für dieses Konto nicht verfügbar, antworten alle Aufrufe mit 404.\n\nAttaches a document to an inbound shipment, for example the Excel shipping list or a delivery note. The file is sent as `multipart/form-data` in the field `file`, one file per call. Excel files (`.xlsx`) and PDF are allowed, at most 20 MB. The file type is checked on the content, not the file name; CSV and the old `.xls` format are therefore rejected (400, `extra.error` = `INVALID_FILE_TYPE`). A file over 20 MB yields 400 with `extra.error` = `FILE_TOO_LARGE`; if the whole request exceeds 20 MB plus multipart overhead, 413 without `extra.error`. File names over 255 characters are shortened, keeping the extension.\n\n**Preconditions:** as a merchant only with status `ANNOUNCED` (otherwise 409, `extra.error` = `SHIPMENT_NOT_EDITABLE`) and before the cut-off (otherwise 409, `extra.error` = `SHIPMENT_LOCKED`). As a merchant you can change shipments only while the status is `ANNOUNCED` and before the cut-off date. The cut-off is the calendar day (time zone Europe/Berlin) three days before the inbound date set by the warehouse (`planned_inbound_on`, otherwise `expected_on`); the cut-off day itself is already locked. Without either date there is no cut-off. A purchase order already created in the warehouse system (`zoho_po_state` other than `NONE`) also locks the shipment, even before the cut-off. `customer_can_edit` in the response tells whether changes are still allowed.\n\nThe document then appears in `documents` of the shipment. Required scope: `warehouse:document_write` or `warehouse:write`. If the inbound shipment feature is not available for this account, every call answers 404."}},"/api/warehouse/shipments/{shipment_id}/documents/{document_id}":{"delete":{"tags":["Warehouse Shipments"],"summary":"Remove a shipment document","operationId":"ApiWarehouseShipmentsShipmentIdDocumentsDocumentIdDeleteDocument","parameters":[{"name":"shipment_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Anlieferung, zu der das Dokument gehört / ID of the inbound shipment the document belongs to."},{"name":"document_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID des zu entfernenden Dokuments (`id` aus `documents` der Anlieferung) / ID of the document to remove (`id` from `documents` of the shipment)."}],"responses":{"204":{"description":"Dokument entfernt, kein Body / Document removed, no body.","headers":{}},"400":{"description":"Anfrage ungültig: Wert außerhalb des erlaubten Bereichs, falsches Format oder fehlendes Pflichtfeld (ohne `extra.error`) / Invalid request: value out of range, wrong format or missing required field (without `extra.error`).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Anlieferung, Dokument oder Variante nicht gefunden, gehört zu einem anderen Händler oder die Funktion ist für dieses Konto nicht verfügbar; nie 403 / Shipment, document or variant not found, belongs to another merchant, or the feature is not available for this account; never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}},"409":{"description":"Nicht änderbar: `extra.error` = `SHIPMENT_NOT_EDITABLE` (Status nicht mehr `ANNOUNCED`, siehe `extra.status`) oder `SHIPMENT_LOCKED` (Stichtag erreicht oder Einkaufsbestellung angelegt) / Not changeable: `extra.error` = `SHIPMENT_NOT_EDITABLE` (status no longer `ANNOUNCED`, see `extra.status`) or `SHIPMENT_LOCKED` (cut-off reached or purchase order created).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:document_write","warehouse:write"],"description":"Entfernt ein Dokument von einer Anlieferung. Das Dokument verschwindet aus `documents` und aus `GET …/documents/{document_id}/url` (404); es wird nicht physisch gelöscht, sondern deaktiviert. Bei Erfolg antwortet der Aufruf mit 204 ohne Body.\n\n**Voraussetzungen:** Dieselben Regeln wie beim Hochladen: Als Händler nur bei Status `ANNOUNCED` (sonst 409, `SHIPMENT_NOT_EDITABLE`) und vor dem Stichtag (sonst 409, `SHIPMENT_LOCKED`). Ein unbekanntes oder bereits entferntes Dokument sowie ein Dokument einer anderen Anlieferung ergibt 404. Benötigter Scope: `warehouse:document_write` oder `warehouse:write`. Ist die Anlieferungsfunktion für dieses Konto nicht verfügbar, antworten alle Aufrufe mit 404.\n\nRemoves a document from an inbound shipment. The document disappears from `documents` and from `GET …/documents/{document_id}/url` (404); it is deactivated, not physically deleted. On success the call answers 204 without a body.\n\n**Preconditions:** the same rules as for upload: as a merchant only with status `ANNOUNCED` (otherwise 409, `SHIPMENT_NOT_EDITABLE`) and before the cut-off (otherwise 409, `SHIPMENT_LOCKED`). An unknown or already removed document, or a document of another shipment, yields 404. Required scope: `warehouse:document_write` or `warehouse:write`. If the inbound shipment feature is not available for this account, every call answers 404."}},"/api/warehouse/shipments/{shipment_id}/documents/{document_id}/url":{"get":{"tags":["Warehouse Shipments"],"summary":"Get a signed download URL for a shipment document","operationId":"ApiWarehouseShipmentsShipmentIdDocumentsDocumentIdUrlGetDocumentUrl","parameters":[{"name":"shipment_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID der Anlieferung, zu der das Dokument gehört / ID of the inbound shipment the document belongs to."},{"name":"document_id","in":"path","schema":{"type":"integer"},"required":true,"deprecated":false,"description":"ID des Dokuments (`id` aus `documents` der Anlieferung) / ID of the document (`id` from `documents` of the shipment)."}],"responses":{"200":{"description":"Signierte Download-URL, 15 Minuten gültig / Signed download URL, valid for 15 minutes.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentDocumentUrlResponse"},"example":{"url":"https://files.example.com/warehouse-shipments/90412/Packliste-2026-02.xlsx?signature=EXAMPLE","expires_in_seconds":900}}}},"400":{"description":"Anfrage ungültig: Wert außerhalb des erlaubten Bereichs, falsches Format oder fehlendes Pflichtfeld (ohne `extra.error`) / Invalid request: value out of range, wrong format or missing required field (without `extra.error`).","content":{"application/json":{"schema":{"properties":{"status_code":{"type":"integer"},"detail":{"type":"string"},"extra":{"additionalProperties":{},"type":["null","object","array"]}},"type":"object","required":["detail","status_code"],"description":"Validation Exception","examples":[{"status_code":400,"detail":"Bad Request","extra":{}}]}}}},"404":{"description":"Anlieferung, Dokument oder Variante nicht gefunden, gehört zu einem anderen Händler oder die Funktion ist für dieses Konto nicht verfügbar; nie 403 / Shipment, document or variant not found, belongs to another merchant, or the feature is not available for this account; never 403.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseShipmentErrorResponse"}}}}},"deprecated":false,"x-customer-scopes":["warehouse:read"],"description":"Erzeugt eine signierte Download-URL für ein Dokument einer Anlieferung. Die URL ist 15 Minuten gültig (`expires_in_seconds` = 900); danach muss eine neue angefordert werden. Wer die URL kennt, kann die Datei in dieser Zeit ohne weitere Anmeldung herunterladen, die URL ist daher vertraulich zu behandeln und nicht zu speichern. Jeder Aufruf erzeugt eine neue URL.\n\nDie URL ist in jedem Status der Anlieferung abrufbar, auch nach Wareneingang oder Storno. Ein unbekanntes oder entferntes Dokument sowie ein Dokument einer anderen Anlieferung ergibt 404. Benötigter Scope: `warehouse:read`. Ist die Anlieferungsfunktion für dieses Konto nicht verfügbar, antworten alle Aufrufe mit 404.\n\nCreates a signed download URL for a document of an inbound shipment. The URL is valid for 15 minutes (`expires_in_seconds` = 900); after that a new one must be requested. Anyone who knows the URL can download the file during that time without further authentication, so treat the URL as confidential and do not store it. Every call creates a new URL.\n\nThe URL can be requested in every shipment status, also after goods receipt or cancellation. An unknown or removed document, or a document of another shipment, yields 404. Required scope: `warehouse:read`. If the inbound shipment feature is not available for this account, every call answers 404."}}},"components":{"schemas":{"AdditionalProductInput":{"properties":{"sku":{"type":"string","maxLength":100,"description":"SKU eines Zusatzprodukts aus dem Katalog, höchstens 100 Zeichen; eine SKU eines anderen Produkttyps wird abgewiesen. / SKU of an additional product from the catalog, at most 100 characters; a SKU of another product type is rejected."},"amount":{"type":"integer","minimum":1.0,"default":1,"description":"Stückzahl, mindestens 1, Standard 1. / Quantity, at least 1, default 1."}},"type":"object","required":["sku"],"title":"AdditionalProductInput","description":"Zusatzprodukt ohne Veredelung, das der Bestellung beigelegt wird. / Additional product without finishing that is added to the order."},"AddressInput":{"properties":{"title":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":20,"description":"Anrede oder Titel, höchstens 20 Zeichen; `null` = keine Angabe. / Salutation or title, at most 20 characters; `null` = not given."},"company":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":200,"description":"Firmenname, höchstens 200 Zeichen; `null` = Privatadresse. / Company name, at most 200 characters; `null` = private address."},"first_name":{"type":"string","maxLength":100,"example":"Max","description":"Vorname des Empfängers, höchstens 100 Zeichen. / First name of the recipient, at most 100 characters."},"last_name":{"type":"string","maxLength":100,"example":"Mustermann","description":"Nachname des Empfängers, höchstens 100 Zeichen. / Last name of the recipient, at most 100 characters."},"care_of":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":200,"description":"Adresszusatz („c/o“), höchstens 200 Zeichen; `null` = keiner. / Address line addition (care of), at most 200 characters; `null` = none."},"street":{"type":"string","maxLength":200,"example":"Musterstraße","description":"Straßenname, höchstens 200 Zeichen; die Hausnummer steht getrennt in `house_number`. / Street name, at most 200 characters; the house number goes separately into `house_number`."},"house_number":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":20,"example":"1","description":"Hausnummer samt Zusatz (z. B. „12a“), höchstens 20 Zeichen; `null` = nicht angegeben. / House number including suffix (e.g. 12a), at most 20 characters; `null` = not given."},"postcode":{"type":"string","maxLength":20,"example":"50667","description":"Postleitzahl, höchstens 20 Zeichen. / Postal code, at most 20 characters."},"city":{"type":"string","maxLength":100,"example":"Köln","description":"Ort, höchstens 100 Zeichen. / City, at most 100 characters."},"country":{"type":"string","maxLength":2,"minLength":2,"example":"DE","description":"Ländercode nach ISO 3166-1 alpha-2, genau 2 Zeichen (z. B. `DE`). / Country code per ISO 3166-1 alpha-2, exactly 2 characters (e.g. `DE`)."},"email":{"oneOf":[{"type":"string","format":"email"},{"type":"null"}],"example":"max.mustermann@example.com","description":"E-Mail-Adresse des Empfängers im gültigen E-Mail-Format; `null` = keine Angabe. / Email address of the recipient in valid email format; `null` = not given."}},"type":"object","required":["city","country","first_name","last_name","postcode","street"],"title":"AddressInput","description":"Postadresse für Lieferung oder Rechnung. Pflicht sind Vor- und Nachname, Straße, Postleitzahl, Ort und Land. / Postal address for delivery or billing. First and last name, street, postcode, city and country are required."},"BrandingReferenceType":{"type":"string","enum":["label","imprint","hangtag","product_packaging"],"title":"BrandingReferenceType","default":"label","description":"Art einer Branding-Referenz: `label`, `imprint`, `hangtag` oder `product_packaging`. Standard ist `label`. / Type of a branding reference: `label`, `imprint`, `hangtag` or `product_packaging`. Default is `label`."},"CancelPreviewOutcome":{"type":"string","enum":["CANCELABLE","CANCELABLE_WITH_COST","PENDING_MANUFACTURER_CONFIRMATION","ALREADY_CANCELED","REJECTED"],"title":"CancelPreviewOutcome","description":"Ergebnis der Stornovorschau. `CANCELABLE`: Stornierung würde gelingen. `CANCELABLE_WITH_COST`: nur kostenpflichtig (`accept_cost: true`). `PENDING_MANUFACTURER_CONFIRMATION`: Stornierung läuft, Bestätigung steht aus. `ALREADY_CANCELED`: bereits storniert (eine weitere Stornierung würde 409 liefern). `REJECTED`: nicht stornierbar, Gründe in `reasons`. / Result of the cancel preview. `CANCELABLE`: the cancellation would succeed. `CANCELABLE_WITH_COST`: only against cost (`accept_cost: true`). `PENDING_MANUFACTURER_CONFIRMATION`: cancellation under way, confirmation outstanding. `ALREADY_CANCELED`: already canceled (another cancellation would answer 409). `REJECTED`: not cancelable, reasons in `reasons`."},"CancelPreviewReason":{"type":"string","enum":["IN_PRODUCTION_OR_SHIPPED","TRANSFER_IN_PROGRESS","MANUFACTURER_STATUS_UNAVAILABLE","NOTHING_TO_CANCEL"],"title":"CancelPreviewReason","description":"Grund einer abgelehnten Stornovorschau. `IN_PRODUCTION_OR_SHIPPED`: Teile sind in Produktion oder versendet. `TRANSFER_IN_PROGRESS`: Übergabe an die Produktion läuft. `MANUFACTURER_STATUS_UNAVAILABLE`: der Stand lässt sich gerade nicht prüfen. `NOTHING_TO_CANCEL`: es gibt nichts zu stornieren. / Reason of a rejected cancel preview. `IN_PRODUCTION_OR_SHIPPED`: parts are in production or shipped. `TRANSFER_IN_PROGRESS`: handover to production is under way. `MANUFACTURER_STATUS_UNAVAILABLE`: the state cannot be verified right now. `NOTHING_TO_CANCEL`: there is nothing to cancel."},"ComplaintAttachmentResponse":{"properties":{"id":{"type":"integer","example":7001,"description":"ID des Fotos; für das Entfernen im Entwurf. / ID of the photo; used to remove it from a draft."},"complaint_item_id":{"type":"integer","example":5001,"description":"ID der Reklamationsposition (`items[].id`), an der das Foto hängt. / ID of the complaint item (`items[].id`) the photo belongs to."},"content_type":{"type":"string","example":"image/jpeg","description":"Erkannter Medientyp des Fotos: `image/jpeg`, `image/png`, `image/webp` oder `image/heic`. / Detected media type of the photo: `image/jpeg`, `image/png`, `image/webp` or `image/heic`."},"size_bytes":{"type":"integer","example":482113,"description":"Größe der hochgeladenen Datei in Byte (höchstens 10 MB). / Size of the uploaded file in bytes (at most 10 MB)."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:35:00Z","description":"Zeitpunkt des Uploads (UTC, ISO 8601). / Time of the upload (UTC, ISO 8601)."}},"type":"object","required":["complaint_item_id","content_type","created_at","id","size_bytes"],"title":"ComplaintAttachmentResponse","description":"Ein an eine Reklamationsposition angehängtes Foto. / A photo attached to a complaint item."},"ComplaintCancelRequest":{"properties":{"reason":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":1000,"example":"Problem wurde anderweitig gelöst. / The problem was solved otherwise.","description":"Begründung des Händlers, höchstens 1000 Zeichen; `null` oder weglassen für keine. / Merchant explanation, up to 1000 characters; `null` or omit for none."}},"type":"object","required":[],"title":"ComplaintCancelRequest","description":"Optionaler Body zum Zurückziehen einer Reklamation. / Optional body for withdrawing a complaint."},"ComplaintCancelledByRole":{"type":"string","enum":["MERCHANT","STAFF","SYSTEM"],"title":"ComplaintCancelledByRole","description":"Wer die Reklamation storniert hat: `MERCHANT` der Händler, der Shirtee-Support (dritter Wert der Liste) oder `SYSTEM` automatisch (Rückfrage unbeantwortet). / Who cancelled the complaint: the merchant, Shirtee support (third value of the list), or the system (follow-up question unanswered)."},"ComplaintCreateRequest":{"properties":{"order_id":{"type":"integer","example":123456,"description":"ID der Bestellung, zu der reklamiert wird; muss dem Händler gehören (sonst 404). / ID of the order the complaint refers to; must belong to the merchant (otherwise 404)."},"items":{"items":{"$ref":"#/components/schemas/ComplaintItemCreateRequest"},"type":"array","minItems":1,"description":"Zu reklamierende Positionen, mindestens eine, jede `order_item_id` höchstens einmal. / Items to report, at least one, each `order_item_id` at most once."},"comment":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":5000,"example":"Flecken auf der Vorderseite / Stains on the front","description":"Freitext zur gesamten Reklamation, höchstens 5000 Zeichen; `null` oder weglassen für keinen Kommentar. / Free text for the whole complaint, up to 5000 characters; `null` or omit for none."}},"type":"object","required":["items","order_id"],"title":"ComplaintCreateRequest","description":"Body zum Anlegen eines Reklamationsentwurfs. / Body for creating a complaint draft."},"ComplaintDecision":{"type":"string","enum":["NONE","REPLACE","CREDIT","REJECT"],"title":"ComplaintDecision","description":"Entscheidung des Supports je Position: `NONE` noch nicht entschieden oder noch nicht sichtbar, `REPLACE` Ersatz, `CREDIT` Gutschrift, `REJECT` abgelehnt. Für Händler erst im Status `RESOLVED` sichtbar. / Support decision per item: not decided or not yet visible, replacement, credit, rejected. Visible to merchants only in status `RESOLVED`."},"ComplaintEligibilityCode":{"type":"string","enum":["ORDER_CANCELED","DEADLINE_EXCEEDED","ORDER_WITHOUT_CUSTOMER","NOT_SHIPPED","ITEM_INACTIVE","ITEM_ALREADY_REPORTED"],"title":"ComplaintEligibilityCode","description":"Sperrgrund der Reklamierbarkeit. Bestellung: `ORDER_CANCELED` storniert, `DEADLINE_EXCEEDED` Frist überschritten, `ORDER_WITHOUT_CUSTOMER` Bestellung ohne zugeordneten Händler. Position: `NOT_SHIPPED` noch nicht versendet, `ITEM_INACTIVE` Position nicht mehr aktiv, `ITEM_ALREADY_REPORTED` bereits in einer Reklamation gemeldet. / Block reason for complaints. Order level: canceled, deadline exceeded, order without merchant. Item level: not shipped, item inactive, already reported."},"ComplaintEligibilityResponse":{"properties":{"order_id":{"type":"integer","example":123456,"description":"ID der geprüften Bestellung. / ID of the checked order."},"eligible":{"type":"boolean","example":true,"description":"`true`, wenn mindestens eine Position reklamiert werden kann. / `true` if at least one item can be reported."},"code":{"oneOf":[{"$ref":"#/components/schemas/ComplaintEligibilityCode"},{"type":"null"}],"description":"Sperrgrund der Bestellung, der für jede Position gilt; `null`, wenn die Bestellung nicht gesperrt ist. / Order-level block reason that applies to every item; `null` if the order is not blocked."},"items":{"items":{"$ref":"#/components/schemas/ComplaintItemEligibilityResponse"},"type":"array","description":"Reklamierbarkeit je Bestellposition. / Eligibility per order item."}},"type":"object","required":["eligible","items","order_id"],"title":"ComplaintEligibilityResponse","description":"Reklamierbarkeit einer Bestellung und ihrer Positionen. / Eligibility of an order and its items."},"ComplaintErrorResponse":{"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode des Fehlers. / HTTP status code of the error."},"detail":{"type":"string","description":"Lesbare Fehlermeldung in Englisch; nicht für Programmlogik geeignet. / Human-readable English message; not for program logic."},"extra":{"oneOf":[{"type":"object"},{"type":"array"},{"type":"null"}],"description":"Zusatzdaten; bei Reklamationsfehlern ein Objekt mit `error` (Code wie `STATUS_CONFLICT`, `PHOTO_REQUIRED`, `FILE_TOO_LARGE`) und je nach Fehler `items`, `order_item_ids` oder `complaint_item_ids`; sonst `null`. / Additional data; for complaint errors an object with `error` (code such as `STATUS_CONFLICT`) and, depending on the error, `items`, `order_item_ids` or `complaint_item_ids`; otherwise `null`."}},"type":"object","required":["detail","status_code"],"title":"ComplaintErrorResponse","description":"Fehlerform der Reklamations-Endpunkte; `extra.error` trägt den maschinenlesbaren Code. / Error shape of the complaint endpoints; `extra.error` carries the machine-readable code."},"ComplaintItemCreateRequest":{"properties":{"order_item_id":{"type":"integer","example":90001,"description":"ID der Bestellposition aus der Bestellung (`order_id`); muss zur Bestellung gehören und reklamierbar sein. / ID of the order item; must belong to the order and be eligible."},"reason":{"$ref":"#/components/schemas/ComplaintReason","description":"Reklamationsgrund; außer `PRODUCT_MISSING` verlangt jeder Grund mindestens ein Foto beim Einreichen. / Complaint reason; every reason except `PRODUCT_MISSING` requires at least one photo on submit."}},"type":"object","required":["order_item_id","reason"],"title":"ComplaintItemCreateRequest","description":"Eine zu reklamierende Position mit Grund. / One item to report with its reason."},"ComplaintItemEligibilityResponse":{"properties":{"order_item_id":{"type":"integer","example":90001,"description":"ID der Bestellposition. / ID of the order item."},"eligible":{"type":"boolean","example":true,"description":"`true`, wenn die Position reklamiert werden kann (weder Bestellung noch Position gesperrt). / `true` if the item can be reported (neither order nor item is blocked)."},"code":{"oneOf":[{"$ref":"#/components/schemas/ComplaintEligibilityCode"},{"type":"null"}],"description":"Sperrgrund der Position selbst; `null`, wenn die Position nicht gesperrt ist. Ein Sperrgrund der Bestellung steht nur oben in `code`. / Block reason of the item itself; `null` if not blocked. An order-level block appears only in the top-level `code`."}},"type":"object","required":["eligible","order_item_id"],"title":"ComplaintItemEligibilityResponse","description":"Reklamierbarkeit einer einzelnen Position. / Eligibility of a single item."},"ComplaintItemResponse":{"properties":{"id":{"type":"integer","example":5001,"description":"ID der Reklamationsposition; für den Foto-Upload (`item_id`). / ID of the complaint item; used for photo upload (`item_id`)."},"order_item_id":{"type":"integer","example":90001,"description":"ID der reklamierten Bestellposition. / ID of the reported order item."},"reason":{"$ref":"#/components/schemas/ComplaintReason","description":"Reklamationsgrund dieser Position. / Complaint reason of this item."},"decision":{"$ref":"#/components/schemas/ComplaintDecision","description":"Entscheidung des Supports zu dieser Position; für Händler erst im Status `RESOLVED` sichtbar, vorher `NONE`. / Support decision for this item; visible to merchants only in status `RESOLVED`, `NONE` before that."},"decision_note":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Begründung oder Hinweis des Supports zur Entscheidung; `null`, solange nicht `RESOLVED` oder ohne Notiz. / Explanation by support for the decision; `null` until `RESOLVED` or if there is no note."},"attachments":{"items":{"$ref":"#/components/schemas/ComplaintAttachmentResponse"},"type":"array","description":"Aktive Fotos der Position. / Active photos of the item."},"attachment_count":{"type":"integer","readOnly":true,"example":0,"description":"Anzahl der aktiven Fotos; höchstens 5. / Number of active photos; at most 5."}},"type":"object","required":["attachment_count","attachments","decision","id","order_item_id","reason"],"title":"ComplaintItemResponse","description":"Position einer Reklamation in der Antwort der Schreibaufrufe. / Complaint item in write responses."},"ComplaintPhotoResponse":{"properties":{"id":{"type":"integer","example":7001,"description":"ID des Fotos; für das Entfernen im Entwurf. / ID of the photo; used to remove it from a draft."},"complaint_item_id":{"type":"integer","example":5001,"description":"ID der Reklamationsposition (`items[].id`), an der das Foto hängt. / ID of the complaint item (`items[].id`) the photo belongs to."},"content_type":{"type":"string","example":"image/jpeg","description":"Erkannter Medientyp des Fotos: `image/jpeg`, `image/png`, `image/webp` oder `image/heic`. / Detected media type of the photo: `image/jpeg`, `image/png`, `image/webp` or `image/heic`."},"size_bytes":{"type":"integer","example":482113,"description":"Größe der hochgeladenen Datei in Byte (höchstens 10 MB). / Size of the uploaded file in bytes (at most 10 MB)."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:35:00Z","description":"Zeitpunkt des Uploads (UTC, ISO 8601). / Time of the upload (UTC, ISO 8601)."},"url":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"https://files.example.com/complaints/7001.jpg?signature=example","description":"Signierter Link zum Foto, 15 Minuten gültig und bei jedem Abruf neu erzeugt; `null`, wenn die Datei nicht verfügbar ist. / Signed link to the photo, valid for 15 minutes and generated anew on every request; `null` if the file is not available."}},"type":"object","required":["complaint_item_id","content_type","created_at","id","size_bytes"],"title":"ComplaintPhotoResponse","description":"Foto einer Reklamationsposition mit abrufbarem Link. / Photo of a complaint item with a download link."},"ComplaintReason":{"type":"string","enum":["WRONG_PRODUCT","WRONG_TEXTILE_SIZE","WRONG_MOTIVE","PRINT_NOT_SATISFACTORY","PRINT_MISSING","PRINT_WASHED_OUT","STAINS","PRODUCT_DEFECTIVE","NO_BRANDING","PRODUCT_MISSING","EMBROIDERY_INCORRECT","WRONG_IMAGE_SIZE"],"title":"ComplaintReason","description":"Reklamationsgrund je Position: `WRONG_PRODUCT` falsches Produkt, `WRONG_TEXTILE_SIZE` falsche Textilgröße, `WRONG_MOTIVE` falsches Motiv, `PRINT_NOT_SATISFACTORY` Druck nicht zufriedenstellend, `PRINT_MISSING` Druck fehlt, `PRINT_WASHED_OUT` Druck verblasst, `STAINS` Flecken, `PRODUCT_DEFECTIVE` Produkt defekt, `NO_BRANDING` Branding fehlt, `PRODUCT_MISSING` Produkt fehlt (einziger Grund ohne Fotopflicht), `EMBROIDERY_INCORRECT` Stickerei fehlerhaft, `WRONG_IMAGE_SIZE` falsche Motivgröße. / Complaint reason per item (wrong product, wrong size, wrong motif, print unsatisfactory, print missing, print washed out, stains, defective, no branding, missing product (the only reason without a photo requirement), incorrect embroidery, wrong image size)."},"ComplaintResponse":{"properties":{"id":{"type":"integer","example":4001,"description":"ID der Reklamation für alle Folgeaufrufe. / ID of the complaint for all follow-up calls."},"reference":{"type":"string","example":"RK-MUSTER1","description":"Reklamationsnummer, `RK-` plus Kennung der Bestellung, ab der zweiten Reklamation derselben Bestellung mit Zähler (`-2`). / Complaint number: `RK-` plus order identifier, with a counter (`-2`) from the second complaint of the same order."},"order_id":{"type":"integer","example":123456,"description":"ID der Bestellung, auf die sich die Reklamation bezieht. / ID of the order the complaint refers to."},"status":{"$ref":"#/components/schemas/ComplaintStatus","description":"Aktueller Status im Ablauf, siehe `ComplaintStatus`. / Current status in the lifecycle, see `ComplaintStatus`."},"comment":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Flecken auf der Vorderseite / Stains on the front","description":"Freitext der Reklamation; `null`, wenn keiner angegeben wurde. / Free text of the complaint; `null` if none was given."},"submitted_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"example":"2026-01-15T10:40:00Z","description":"Zeitpunkt des Einreichens (UTC); `null` solange Entwurf. / Time of submission (UTC); `null` while a draft."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der Anlage des Entwurfs (UTC, ISO 8601). / Time the draft was created (UTC, ISO 8601)."},"items":{"items":{"$ref":"#/components/schemas/ComplaintItemResponse"},"type":"array","description":"Reklamierte Positionen mit Grund und Fotos. / Reported items with reason and photos."}},"type":"object","required":["created_at","id","items","order_id","reference","status"],"title":"ComplaintResponse","description":"Reklamation in der Antwort von Anlegen, Einreichen, Ergänzen und Zurückziehen. / Complaint in the response of create, submit, supplement and cancel."},"ComplaintStatus":{"type":"string","enum":["DRAFT","SUBMITTED","IN_REVIEW","WAITING_CUSTOMER","RESOLVING","RESOLVED","CANCELLED"],"title":"ComplaintStatus","description":"Status einer Reklamation: `DRAFT` Entwurf, `SUBMITTED` eingereicht, `IN_REVIEW` in Prüfung, `WAITING_CUSTOMER` Rückfrage offen, `RESOLVING` Abschluss läuft, `RESOLVED` abgeschlossen, `CANCELLED` storniert. / Status of a complaint: draft, submitted, in review, follow-up question open, resolution running, resolved, cancelled."},"ComplaintSupplementRequest":{"properties":{"text":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":5000,"example":"Weitere Fotos vom Etikett wurden hochgeladen. / Further photos of the label were uploaded.","description":"Antworttext an den Support, höchstens 5000 Zeichen; `null`, leer oder weglassen ist erlaubt. / Answer text for support, up to 5000 characters; `null`, empty or omitted is allowed."}},"type":"object","required":[],"title":"ComplaintSupplementRequest","description":"Optionaler Body zum Beantworten einer Rückfrage. / Optional body for answering a follow-up question."},"ComplaintUserDetailResponse":{"properties":{"id":{"type":"integer","example":4001,"description":"ID der Reklamation. / ID of the complaint."},"reference":{"type":"string","example":"RK-MUSTER1","description":"Reklamationsnummer, z. B. `RK-MUSTER1`. / Complaint number, e.g. `RK-MUSTER1`."},"order_id":{"type":"integer","example":123456,"description":"ID der Bestellung, auf die sich die Reklamation bezieht. / ID of the order the complaint refers to."},"status":{"$ref":"#/components/schemas/ComplaintStatus","description":"Aktueller Status im Ablauf, siehe `ComplaintStatus`. / Current status in the lifecycle, see `ComplaintStatus`."},"comment":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Flecken auf der Vorderseite / Stains on the front","description":"Freitext des Händlers; `null`, wenn keiner angegeben wurde. / Merchant free text; `null` if none was given."},"resolution_order_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"ID der Ersatzbestellung, wenn der Abschluss eine angelegt hat; für Händler erst im Status `RESOLVED` sichtbar, sonst `null`. / ID of the replacement order if the resolution created one; visible to merchants only in status `RESOLVED`, otherwise `null`."},"cancel_reason":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Begründung der Stornierung; `null`, wenn nicht storniert oder keine angegeben. / Reason for cancellation; `null` if not cancelled or none given."},"cancelled_by_role":{"oneOf":[{"$ref":"#/components/schemas/ComplaintCancelledByRole"},{"type":"null"}],"description":"Wer storniert hat; `null`, solange nicht `CANCELLED`. / Who cancelled; `null` unless `CANCELLED`."},"submitted_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"example":"2026-01-15T10:40:00Z","description":"Zeitpunkt des Einreichens (UTC); `null` solange Entwurf. / Time of submission (UTC); `null` while a draft."},"info_requested_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"example":"2026-01-16T09:00:00Z","description":"Zeitpunkt der letzten Rückfrage des Supports (UTC); `null`, wenn es keine gab. Ab hier läuft die Frist für die automatische Stornierung. / Time of the latest follow-up question (UTC); `null` if there was none. The auto-cancel deadline counts from here."},"closed_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Zeitpunkt des Abschlusses oder der Stornierung (UTC); `null`, solange offen. / Time of resolution or cancellation (UTC); `null` while open."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der Anlage des Entwurfs (UTC, ISO 8601). / Time the draft was created (UTC, ISO 8601)."},"items":{"items":{"$ref":"#/components/schemas/ComplaintUserItemDetailResponse"},"type":"array","description":"Reklamierte Positionen mit Fotos und Vorschau. / Reported items with photos and previews."}},"type":"object","required":["created_at","id","items","order_id","reference","status"],"title":"ComplaintUserDetailResponse","description":"Reklamation im Detail für Händler. / Complaint in detail for merchants."},"ComplaintUserItemDetailResponse":{"properties":{"id":{"type":"integer","example":5001,"description":"ID der Reklamationsposition; für den Foto-Upload (`item_id`). / ID of the complaint item; used for photo upload (`item_id`)."},"order_item_id":{"type":"integer","example":90001,"description":"ID der reklamierten Bestellposition. / ID of the reported order item."},"reason":{"$ref":"#/components/schemas/ComplaintReason","description":"Reklamationsgrund dieser Position. / Complaint reason of this item."},"decision":{"$ref":"#/components/schemas/ComplaintDecision","description":"Entscheidung des Supports zu dieser Position; für Händler erst im Status `RESOLVED` sichtbar, vorher `NONE`. / Support decision for this item; visible to merchants only in status `RESOLVED`, `NONE` before that."},"decision_note":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Begründung oder Hinweis des Supports zur Entscheidung; `null`, solange nicht `RESOLVED` oder ohne Notiz. / Explanation by support for the decision; `null` until `RESOLVED` or if there is no note."},"replace_variant_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Ersatzvariante, falls als Ersatz mit anderer Variante entschieden wurde; für Händler erst im Status `RESOLVED` sichtbar, sonst `null`. / Replacement variant if support chose a different variant; visible to merchants only in status `RESOLVED`, otherwise `null`."},"attachments":{"items":{"$ref":"#/components/schemas/ComplaintPhotoResponse"},"type":"array","description":"Aktive Fotos der Position mit Link. / Active photos of the item with link."},"preview_urls":{"items":{"type":"string","example":"https://files.example.com/previews/90001.png"},"type":"array","description":"Links zur Druckvorschau der Bestellposition; leer, wenn keine Vorschau vorliegt. / Links to the print preview of the order item; empty if no preview exists."}},"type":"object","required":["attachments","decision","id","order_item_id","preview_urls","reason"],"title":"ComplaintUserItemDetailResponse","description":"Position einer Reklamation im Detail mit Fotos und Druckvorschau. / Complaint item in detail with photos and print previews."},"ComplaintUserListItemResponse":{"properties":{"id":{"type":"integer","example":4001,"description":"ID der Reklamation für den Detailaufruf. / ID of the complaint for the detail call."},"reference":{"type":"string","example":"RK-MUSTER1","description":"Reklamationsnummer, z. B. `RK-MUSTER1`. / Complaint number, e.g. `RK-MUSTER1`."},"order_id":{"type":"integer","example":123456,"description":"ID der Bestellung, auf die sich die Reklamation bezieht. / ID of the order the complaint refers to."},"order_external_reference":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"SHOP-10001","description":"Externe Referenz der Bestellung (z. B. Shop-Bestellnummer); `null`, wenn keine hinterlegt ist. / External reference of the order (e.g. shop order number); `null` if none is stored."},"status":{"$ref":"#/components/schemas/ComplaintStatus","description":"Aktueller Status im Ablauf, siehe `ComplaintStatus`. / Current status in the lifecycle, see `ComplaintStatus`."},"submitted_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"example":"2026-01-15T10:40:00Z","description":"Zeitpunkt des Einreichens (UTC); `null` solange Entwurf. / Time of submission (UTC); `null` while a draft."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der Anlage des Entwurfs (UTC, ISO 8601). / Time the draft was created (UTC, ISO 8601)."},"item_count":{"type":"integer","readOnly":true,"example":1,"description":"Anzahl der reklamierten Positionen. / Number of reported items."},"reasons":{"items":{"$ref":"#/components/schemas/ComplaintReason"},"type":"array","readOnly":true,"description":"Gründe der Positionen ohne Doppelte, in Positionsreihenfolge. / Reasons of the items without duplicates, in item order."}},"type":"object","required":["created_at","id","item_count","order_id","reasons","reference","status"],"title":"ComplaintUserListItemResponse","description":"Zeile der Reklamationsliste. / Row of the complaint list."},"ComplaintUserPageResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ComplaintUserListItemResponse"},"type":"array","description":"Reklamationen dieser Seite, neueste zuerst. / Complaints on this page, newest first."},"limit":{"type":"integer","example":20,"description":"Verwendete Seitengröße (Echo des Parameters `limit`). / Page size used (echo of the `limit` parameter)."},"offset":{"type":"integer","example":0,"description":"Verwendeter Versatz (Echo des Parameters `offset`). / Offset used (echo of the `offset` parameter)."},"total_count":{"type":"integer","example":1,"description":"Gesamtzahl der Treffer über alle Seiten. / Total number of matches across all pages."}},"type":"object","required":["items","limit","offset","total_count"],"title":"ComplaintUserPageResponse","description":"Eine Seite der Reklamationsliste. / One page of the complaint list."},"CustomerSafetyStockResponse":{"properties":{"customer_id":{"type":"integer","example":100123,"description":"Kunden-ID des Händlers / Customer ID of the merchant."},"enabled":{"type":"boolean","example":true,"description":"`true`, wenn der Standard wirkt; `false` = ausgeschaltet oder nie gesetzt / `true` if the default is in effect; `false` = switched off or never set."},"rule":{"oneOf":[{"$ref":"#/components/schemas/SafetyStockRuleResponse"},{"type":"null"}],"description":"Gespeicherte Staffel; `null` = nie ein Standard gesetzt. Bei `enabled` `false` bleiben gespeicherte Werte sichtbar, wirken aber nicht / Stored tiers; `null` = no default ever set. With `enabled` `false` stored values stay visible but have no effect."},"updated_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der letzten Änderung (UTC, ISO 8601); `null` = nie gesetzt / Time of the last change (UTC, ISO 8601); `null` = never set."},"updated_by":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"user:4711","description":"Kennung des letzten Änderers, z. B. `user:4711` oder `customer-key:<ID>`; `null` = nie gesetzt / Identifier of the last editor, e.g. `user:4711` or `customer-key:<ID>`; `null` = never set."}},"type":"object","required":["customer_id","enabled","rule","updated_at","updated_by"],"title":"CustomerSafetyStockResponse","description":"Der Standard-Sicherheitsbestand des Händlers.\n\nThe merchant's default safety stock."},"DeliveryAddressPreviewBlocker":{"type":"string","enum":["IN_TRANSFER_OR_SHIPPED","ORDER_STATUS","INVOICE_CREDIT_NOTED","SHIPPING_LABEL_CREATED"],"title":"DeliveryAddressPreviewBlocker","description":"Grund, warum die Lieferadressänderung jetzt abgelehnt würde. `IN_TRANSFER_OR_SHIPPED`: Teile sind in Übergabe oder versendet. `ORDER_STATUS`: der Bestellstatus erlaubt keine Änderung. `INVOICE_CREDIT_NOTED`: die Rechnung trägt schon eine Gutschrift. `SHIPPING_LABEL_CREATED`: das Versandetikett ist bereits erstellt. / Reason why the delivery address change would be rejected now. `IN_TRANSFER_OR_SHIPPED`: parts are being handed over or shipped. `ORDER_STATUS`: the order status does not allow a change. `INVOICE_CREDIT_NOTED`: the invoice already carries a credit note. `SHIPPING_LABEL_CREATED`: the shipping label already exists."},"DeliveryAddressPreviewMode":{"type":"string","enum":["LOCAL_REROUTE","LOCAL_HELD","MANUFACTURER_SYNC","LOCAL_PHOENIX_LABEL"],"title":"DeliveryAddressPreviewMode","description":"Wie die Lieferadressänderung angewendet würde. `LOCAL_REROUTE`: bei Shirtee gespeichert, die Bestellung verlässt `CHECK` und wird fortgesetzt. `LOCAL_HELD`: bei Shirtee gespeichert, die Bestellung bleibt angehalten. `MANUFACTURER_SYNC`: an den Hersteller übermittelt, der sie ablehnen kann. `LOCAL_PHOENIX_LABEL`: nur bei Shirtee gespeichert, das Versandetikett entsteht später mit der neuen Adresse. / How the delivery address change would be applied. `LOCAL_REROUTE`: saved at Shirtee, the order leaves `CHECK` and continues. `LOCAL_HELD`: saved at Shirtee, the order stays on hold. `MANUFACTURER_SYNC`: forwarded to the manufacturer, who may reject it. `LOCAL_PHOENIX_LABEL`: saved at Shirtee only, the shipping label is created later with the new address."},"DeliveryReceiptMoOutcomeResponse":{"properties":{"manufacturing_order_id":{"type":"integer","example":920001,"description":"ID des Fertigungsauftrags (Teilauftrag der Bestellung), auf den sich das Ergebnis bezieht. / ID of the manufacturing order (partial order) the result refers to."},"manufacturer_id":{"type":"integer","example":11,"description":"ID des Produktionspartners, bei dem der Fertigungsauftrag liegt. / ID of the production partner holding the manufacturing order."},"outcome":{"$ref":"#/components/schemas/DeliveryReceiptOutcome","description":"Ob der Lieferschein mitgegeben wird: `WILL_ATTACH`, `TOO_LATE` oder `UNSUPPORTED`. / Whether the receipt is handed over: `WILL_ATTACH`, `TOO_LATE` or `UNSUPPORTED`."},"message":{"type":"string","example":"Wird beim Transfer an den Hersteller mitgegeben.","description":"Erklärender Text zum Ergebnis (deutsch). Zum Auswerten `outcome` verwenden, der Wortlaut ist nicht zugesagt. / Explanatory text for the result (German). Use `outcome` for evaluation; the wording is not guaranteed."}},"type":"object","required":["manufacturer_id","manufacturing_order_id","message","outcome"],"title":"DeliveryReceiptMoOutcomeResponse","description":"Ergebnis des Lieferschein-Uploads für einen Fertigungsauftrag der Bestellung. / Result of the delivery receipt upload for one manufacturing order of the order."},"DeliveryReceiptOutcome":{"type":"string","enum":["WILL_ATTACH","TOO_LATE","UNSUPPORTED"],"title":"DeliveryReceiptOutcome","description":"Was mit einem hochgeladenen Lieferschein für einen Fertigungsauftrag geschieht. `WILL_ATTACH`: der Auftrag ist noch nicht übergeben und der Partner unterstützt Lieferscheine, der Lieferschein wird bei der Übergabe mitgegeben. `TOO_LATE`: der Auftrag ist bereits übergeben. `UNSUPPORTED`: der Partner unterstützt keine Lieferscheine. / What happens to an uploaded delivery receipt for one manufacturing order. `WILL_ATTACH`: the order is not yet transferred and the partner supports delivery receipts, so the receipt is handed over at transfer. `TOO_LATE`: the order is already transferred. `UNSUPPORTED`: the partner does not support delivery receipts."},"EditabilityBlocker":{"type":"string","enum":["ORDER_STATUS","MO_TRANSFERRING","MO_TRANSFERRED","MO_CREATED","MO_SHIPPED","MO_CANCELED","MO_RECONCILE_PROMOTED","MO_RECONCILE_UNAVAILABLE","MO_DTF_VERIFY_PENDING"],"title":"EditabilityBlocker","description":"Grund, warum eine Bestellung nicht änderbar ist. `ORDER_STATUS`: Bestellstatus erlaubt keine Änderung (änderbar sind `PENDING`, `READY`, `ERROR`, `CHECK`, `PAUSE`). `MO_TRANSFERRING`: ein Teil wird gerade an die Produktion übergeben. `MO_TRANSFERRED`: ein Teil ist bereits übergeben. `MO_CREATED`: ein Teil ist beim Hersteller angelegt. `MO_SHIPPED`: ein Teil ist versendet. `MO_CANCELED`: ein Teil ist storniert. `MO_RECONCILE_UNAVAILABLE`: Stand einer fehlgeschlagenen Übergabe ist noch nicht abgeglichen (nur in Vorschauen). `MO_DTF_VERIFY_PENDING`: die automatische Motivprüfung läuft noch. `MO_RECONCILE_PROMOTED` wird derzeit nicht ausgegeben. / Reason why an order is not changeable. `ORDER_STATUS`: the order status does not allow changes (changeable are `PENDING`, `READY`, `ERROR`, `CHECK`, `PAUSE`). `MO_TRANSFERRING`: a part is being handed to production. `MO_TRANSFERRED`: a part has been handed over. `MO_CREATED`: a part is created at the manufacturer. `MO_SHIPPED`: a part has shipped. `MO_CANCELED`: a part is canceled. `MO_RECONCILE_UNAVAILABLE`: the state of a failed handover is not reconciled yet (previews only). `MO_DTF_VERIFY_PENDING`: the automatic motif check is still running. `MO_RECONCILE_PROMOTED` is currently not emitted."},"FulfillmentType":{"type":"string","enum":["ON_DEMAND","WAREHOUSE","ADDITIONAL_PRODUCT"],"title":"FulfillmentType","description":"Fertigungsart eines Produkts / Fulfillment type of a product. `ON_DEMAND`: wird je Bestellung bedruckt (made to order). `WAREHOUSE`: Lagerartikel mit Bestand. `ADDITIONAL_PRODUCT`: Beistellartikel."},"InvoicePdfResponse":{"properties":{"pdf_url":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"https://files.example.com/invoices/RE-2026-00001.pdf?signature=beispiel","description":"Signierte Download-URL der PDF, 15 Minuten gültig; `null`, solange `status` nicht `ready` ist. / Signed download URL of the PDF, valid for 15 minutes; `null` unless `status` is `ready`."},"status":{"$ref":"#/components/schemas/InvoicePdfStatus","description":"Zustand der PDF-Erzeugung: `ready`, `generating` oder `failed`. / State of PDF generation: `ready`, `generating` or `failed`."}},"type":"object","required":["status"],"title":"InvoicePdfResponse","description":"Ergebnis des PDF-Abrufs eines Belegs: Zustand der Erzeugung und, wenn fertig, die Download-URL. / Result of a document PDF request: generation state and, once finished, the download URL."},"InvoicePdfStatus":{"type":"string","enum":["ready","generating","failed"],"title":"InvoicePdfStatus","description":"Zustand der PDF-Erzeugung eines Belegs: `ready` (PDF liegt vor, `pdf_url` gesetzt), `generating` (wird erzeugt, später erneut abrufen) oder `failed` (kommt nicht mehr, weitere Abrufe stoßen nichts mehr an). / State of PDF generation of a document: `ready` (PDF available, `pdf_url` set), `generating` (in progress, request again later) or `failed` (will not arrive, further requests trigger nothing)."},"InvoiceType":{"type":"string","enum":["INVOICE","CREDIT_NOTE","BONUS_CREDIT"],"title":"InvoiceType","description":"Belegart: `INVOICE` (Rechnung), `CREDIT_NOTE` (Gutschrift zu einer Rechnung, mit negativen Beträgen und Verweis auf die Ursprungsrechnung) oder `BONUS_CREDIT` (Gutschrift ohne Ursprungsrechnung, z. B. Umsatzbonus). / Document type: `INVOICE`, `CREDIT_NOTE` (credit note for an invoice, with negative amounts and a reference to the original invoice) or `BONUS_CREDIT` (credit note without an original invoice, e.g. a revenue bonus)."},"InvoiceUserListResponse":{"properties":{"id":{"type":"integer","example":4712,"description":"Eindeutige Beleg-ID; wird für den PDF-Abruf verwendet. / Unique document ID; used to request the PDF."},"invoice_number":{"type":"string","example":"GS-2026-00001","description":"Belegnummer wie auf dem Beleg gedruckt, z. B. `RE-2026-00001`; Präfix nach Belegart (`RE` Rechnung, `GS` Gutschrift, `BO` Bonusgutschrift). / Document number as printed on the document, e.g. `RE-2026-00001`; prefix by type (`RE` invoice, `GS` credit note, `BO` bonus credit)."},"invoice_type":{"$ref":"#/components/schemas/InvoiceType","description":"Belegart: `INVOICE`, `CREDIT_NOTE` oder `BONUS_CREDIT`. / Document type: `INVOICE`, `CREDIT_NOTE` or `BONUS_CREDIT`."},"invoice_date":{"type":"string","format":"date","example":"2026-01-20","description":"Ausstellungsdatum des Belegs, Format `YYYY-MM-DD`, Datum nach deutscher Zeit; Bezugsfeld der Filter `date_from`/`date_to`. / Issue date of the document, format `YYYY-MM-DD`, date in German time; the field the `date_from`/`date_to` filters apply to."},"order_id":{"type":"integer","example":98765,"description":"ID der Bestellung, zu der der Beleg gehört. / ID of the order the document belongs to."},"original_invoice_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":4711,"description":"Bei `CREDIT_NOTE` die `id` der Ursprungsrechnung; sonst `null` (Rechnungen und Bonusgutschriften). / For `CREDIT_NOTE` the `id` of the original invoice; otherwise `null` (invoices and bonus credits)."},"net_amount":{"type":"integer","example":-4200,"description":"Nettobetrag in Cent (ganze Zahl); bei Gutschriften negativ. / Net amount in cents (integer); negative for credit notes."},"tax_amount":{"type":"integer","example":-798,"description":"Steuerbetrag in Cent (ganze Zahl); bei Gutschriften negativ. / Tax amount in cents (integer); negative for credit notes."},"gross_amount":{"type":"integer","example":-4998,"description":"Bruttobetrag in Cent (ganze Zahl), Nettobetrag plus Steuerbetrag; bei Gutschriften negativ; Bezugsfeld der Filter `amount_min`/`amount_max`. / Gross amount in cents (integer), net plus tax; negative for credit notes; the field the `amount_min`/`amount_max` filters apply to."},"vat_rate":{"type":"integer","example":19,"description":"Umsatzsteuersatz in ganzen Prozent, z. B. `19` für 19 %; `0` bei steuerfreien Belegen. / VAT rate in whole percent, e.g. `19` for 19 %; `0` for tax-exempt documents."},"delivery_date":{"type":"string","format":"date","example":"2026-01-14","description":"Liefer- bzw. Leistungsdatum, Format `YYYY-MM-DD`; bei Gutschriften zu einer Rechnung das der Ursprungsrechnung. / Delivery or service date, format `YYYY-MM-DD`; for credit notes to an invoice, the date of the original invoice."},"currency_code":{"type":"string","example":"EUR","description":"Währung als dreistelliger ISO-4217-Code; derzeit immer `EUR`. / Currency as three-letter ISO 4217 code; currently always `EUR`."},"credit_note_reason":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Retoure der gesamten Bestellung","description":"Begründungstext bei Gutschriften (`CREDIT_NOTE`, `BONUS_CREDIT`), höchstens 1000 Zeichen; `null` bei Rechnungen. / Reason text for credit notes (`CREDIT_NOTE`, `BONUS_CREDIT`), at most 1000 characters; `null` for invoices."},"created_at":{"type":"string","format":"date-time","example":"2026-01-20T08:15:00Z","description":"Zeitpunkt der Erstellung des Belegs, ISO 8601 mit Zeitzone; bestimmt die Sortierung der Liste. / Time the document was created, ISO 8601 with time zone; determines the list order."}},"type":"object","required":["created_at","currency_code","delivery_date","gross_amount","id","invoice_date","invoice_number","invoice_type","net_amount","order_id","tax_amount","vat_rate"],"title":"InvoiceUserListResponse","description":"Ein Beleg (Rechnung oder Gutschrift) in der Belegliste. Beträge in Cent, Gutschriften mit negativen Beträgen. / One document (invoice or credit note) in the document list. Amounts in cents, credit notes with negative amounts."},"InvoiceUserPageResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/InvoiceUserListResponse"},"type":"array","description":"Belege dieser Seite, neueste zuerst; leer, wenn nichts passt. / Documents on this page, newest first; empty if nothing matches."},"limit":{"type":"integer","example":20,"description":"Tatsächlich angewendete Seitengröße nach Begrenzung auf 1 bis 100. / Page size actually applied after clamping to 1 to 100."},"offset":{"type":"integer","example":0,"description":"Tatsächlich angewendeter Versatz nach Begrenzung auf mindestens 0. / Offset actually applied after clamping to at least 0."},"total_count":{"type":"integer","example":2,"description":"Gesamtzahl der Belege, die die Filter treffen, unabhängig von `limit` und `offset`. / Total number of documents matching the filters, independent of `limit` and `offset`."}},"type":"object","required":["items","limit","offset","total_count"],"title":"InvoiceUserPageResponse","description":"Eine Seite der Belegliste mit Paginierungsangaben. / A page of the document list with pagination metadata."},"ItemProcessingCreateRequest":{"properties":{"design_url":{"oneOf":[{"type":"string","format":"url"},{"type":"null"}],"example":"https://designs.example.com/motiv-1.png","description":"HTTPS-URL der Motivdatei; es muss `design_url` oder `design_reference` gesetzt sein, `http` wird abgelehnt / HTTPS URL of the motif file; `design_url` or `design_reference` must be set, `http` is rejected."},"design_reference":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Design-Referenz statt URL, max. 64 Zeichen aus `A-Z a-z 0-9 . _ -`; es muss `design_url` oder `design_reference` gesetzt sein / Design reference instead of a URL, max. 64 characters from `A-Z a-z 0-9 . _ -`; `design_url` or `design_reference` must be set."},"campaign_number":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Kampagnennummer, max. 64 Zeichen aus `A-Z a-z 0-9 . _ -`; wird beim Hinzufügen einer Position nicht ausgewertet / Campaign number, max. 64 characters from `A-Z a-z 0-9 . _ -`; not evaluated when adding an item."},"embroidery_palette":{"oneOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"description":"Garnfarben als Hex-Werte ohne `#`; für Händlerschlüssel nicht erlaubt (403) / Thread colors as hex values without `#`; not allowed for merchant keys (403)."},"preview_url":{"oneOf":[{"type":"string","format":"url"},{"type":"null"}],"description":"URL eines Vorschaubilds; wird beim Hinzufügen einer Position nicht ausgewertet / URL of a preview image; not evaluated when adding an item."},"processing_type":{"$ref":"#/components/schemas/ProcessingTypeEnum","description":"Veredelungsart: `DTG`, `DTF`, `EMBROIDERY`, `SEWING`, `SUBLIMATION` oder `DIGITAL` / Finishing type: `DTG`, `DTF`, `EMBROIDERY`, `SEWING`, `SUBLIMATION` or `DIGITAL`."},"position":{"$ref":"#/components/schemas/PrintPosition","description":"Druck- bzw. Stickposition auf dem Artikel (z. B. `FRONT`, `BACK`); je Position nur eine Veredelung pro Artikel / Print or embroidery position on the article (e.g. `FRONT`, `BACK`); only one finishing per position and item."},"processingposition":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Freitext zur Position; für Händlerschlüssel nicht erlaubt (403) / Free text on the position; not allowed for merchant keys (403)."},"width":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Breite des Motivs, ganze Zahl größer 0; für Händlerschlüssel nicht erlaubt (403) / Motif width, integer greater than 0; not allowed for merchant keys (403)."},"height":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Höhe des Motivs, ganze Zahl größer 0; für Händlerschlüssel nicht erlaubt (403) / Motif height, integer greater than 0; not allowed for merchant keys (403)."},"offset_center":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Horizontaler Versatz des Motivs; für Händlerschlüssel nicht erlaubt (403) / Horizontal offset of the motif; not allowed for merchant keys (403)."},"offset_top":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Vertikaler Abstand des Motivs von oben; für Händlerschlüssel nicht erlaubt (403) / Vertical distance of the motif from the top; not allowed for merchant keys (403)."},"integration_data":{"oneOf":[{"type":"object"},{"type":"null"}],"description":"Freies JSON-Objekt für Integrationen; für Händlerschlüssel nicht erlaubt (403) / Free JSON object for integrations; not allowed for merchant keys (403)."},"auto_choose_processing_type":{"type":"boolean","default":true,"description":"Standard `true`: Shirtee darf die Veredelungsart automatisch wählen; Händlerschlüssel dürfen nur `true` senden (`false` = 403) / Default `true`: Shirtee may choose the finishing type automatically; merchant keys may only send `true` (`false` = 403)."},"processing_price":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Netto-Veredelungspreis in Cent; wird beim Hinzufügen einer Position nicht ausgewertet, der Preis kommt aus dem Katalog / Net finishing price in cents; not evaluated when adding an item, the price comes from the catalog."}},"type":"object","required":["position","processing_type"],"title":"ItemProcessingCreateRequest","description":"Veredelung (Druck/Stick) einer neuen Position. Händlerschlüssel dürfen nur `processing_type`, `position`, `design_url`, `design_reference` und `auto_choose_processing_type` = `true` senden. / Finishing (print/embroidery) of a new item. Merchant keys may only send `processing_type`, `position`, `design_url`, `design_reference` and `auto_choose_processing_type` = `true`."},"ItemProcessingStatus":{"type":"string","enum":["PENDING","DOWNLOADED","RENDERED","ERROR"],"title":"ItemProcessingStatus","description":"Aufbereitungsstand der Druckdatei einer Position (Veredelung). Verlauf: `PENDING` > `DOWNLOADED` > `RENDERED`.\n\n- `PENDING`: die Druckdatei wurde noch nicht geladen.\n- `DOWNLOADED`: die Druckdatei ist geladen und wartet auf das Rendern.\n- `RENDERED`: die Druckdatei ist gerendert und für die Produktion bereit.\n- `ERROR`: Laden oder Rendern ist fehlgeschlagen. Die Bestellung geht dann in der Regel auf `ERROR`.\n\nPreparation state of the print file of an item (processing). Flow: `PENDING` > `DOWNLOADED` > `RENDERED`.\n\n- `PENDING`: the print file has not been loaded yet.\n- `DOWNLOADED`: the print file is loaded and waiting to be rendered.\n- `RENDERED`: the print file is rendered and ready for production.\n- `ERROR`: loading or rendering failed. The order then usually moves to `ERROR`."},"ItemStockDisplayKind":{"type":"string","enum":["IN_STOCK","JIT"],"title":"ItemStockDisplayKind","description":"Art der Bestandsanzeige einer Variante oder Position.\n\n- `IN_STOCK`: Ware ist vorrätig. `available_balance` nennt die freie Menge in Stück.\n- `JIT`: Auftragsware (Made-to-order), es gibt keine verlässliche Bestandszahl. `note` erklärt, dass die Ware nach Bestellung beschafft wird und sich die Lieferung leicht verzögern kann.\n\nKind of stock display of a variant or item.\n\n- `IN_STOCK`: goods are in stock. `available_balance` gives the free quantity in pieces.\n- `JIT`: made-to-order, there is no reliable stock figure. `note` explains that the goods are procured after ordering and delivery can be slightly delayed."},"ItemStockDisplayResponse":{"properties":{"kind":{"$ref":"#/components/schemas/ItemStockDisplayKind","description":"Art der Anzeige: `IN_STOCK` (vorrätig, Menge in `available_balance`) oder `JIT` (Auftragsware) / Kind of display: `IN_STOCK` (in stock, quantity in `available_balance`) or `JIT` (made-to-order)."},"available_balance":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":100,"description":"Freie Menge in Stück (Bestand abzüglich Reservierungen, mindestens 0); bei `IN_STOCK` gesetzt, bei `JIT` nicht / Free quantity in pieces (stock minus reservations, at least 0); set for `IN_STOCK`, not set for `JIT`."},"note":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Hinweistext bei `JIT`: die Ware wird nach Bestellung beschafft, die Lieferung kann sich leicht verzögern. Bei `IN_STOCK` nicht gesetzt / Note text for `JIT`: goods are procured after ordering and delivery can be slightly delayed. Not set for `IN_STOCK`."},"supply_state":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Nachschublage bei `JIT`: `MANUFACTURER_INBOUND` (Zulauf zur Produktion gemeldet), `SUPPLIER_IN_STOCK` (Lieferant hat Bestand), `SUPPLIER_INBOUND` (Lieferant hat 0, Wareneingang angekündigt), `NOT_AVAILABLE` (Lieferant hat 0, kein Wareneingang bekannt). Offener String: unbekannte Werte tolerieren und `note` anzeigen / Supply situation for `JIT`: `MANUFACTURER_INBOUND` (inbound to production reported), `SUPPLIER_IN_STOCK` (supplier has stock), `SUPPLIER_INBOUND` (supplier has 0, goods receipt announced), `NOT_AVAILABLE` (supplier has 0, no goods receipt known). Open string: tolerate unknown values and fall back to `note`."},"supplier_quantity":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Beim Lieferanten verfügbare Menge in Stück; 0 bei `SUPPLIER_INBOUND` und `NOT_AVAILABLE`. Nur bei `JIT` mit Nachschubdaten / Quantity available at the supplier in pieces; 0 for `SUPPLIER_INBOUND` and `NOT_AVAILABLE`. Only for `JIT` with supply data."},"manufacturer_inbound_quantity":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Gemeldete Zulaufmenge zur Produktion in Stück; nur bei `supply_state = MANUFACTURER_INBOUND` / Reported inbound quantity to production in pieces; only with `supply_state = MANUFACTURER_INBOUND`."},"next_inbound_quantity":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Menge des nächsten angekündigten Wareneingangs beim Lieferanten in Stück; nur bei `supply_state = SUPPLIER_INBOUND` / Quantity of the next announced goods receipt at the supplier in pieces; only with `supply_state = SUPPLIER_INBOUND`."},"next_inbound_date":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Datum (`YYYY-MM-DD`) des nächsten angekündigten Wareneingangs beim Lieferanten; es liegt nicht vor heute (Europe/Berlin). Nur bei `supply_state = SUPPLIER_INBOUND` / Date (`YYYY-MM-DD`) of the next announced goods receipt at the supplier; it is not before today (Europe/Berlin). Only with `supply_state = SUPPLIER_INBOUND`."},"as_of":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Stand der Nachschubdaten als Zeitstempel (ISO 8601, mit Zeitzone); bei mehreren Quellen der älteste verwendete Abrufzeitpunkt / Timestamp of the supply data (ISO 8601, with time zone); with several sources, the oldest retrieval time used."},"delay_working_days":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Richtwert in Werktagen, um den sich die Lieferung bei Nachlieferung vom Lieferanten verzögern kann; keine Zusage, die Verzögerung kann länger ausfallen. Nur bei `supply_state = SUPPLIER_IN_STOCK` / Guideline in working days by which delivery can be delayed when goods are supplied by the supplier; not a commitment, the delay can be longer. Only with `supply_state = SUPPLIER_IN_STOCK`."}},"type":"object","required":["kind"],"title":"ItemStockDisplayResponse","description":"Bestandsanzeige für eine Variante oder Bestellposition. Sie zeigt den Bestand der Produktion, die die Position fertigt, oder, solange keine zugewiesen ist, eine Näherung. Nicht belegte Felder fehlen in der Antwort statt `null` zu sein. Die Nachschub-Felder (`supply_state` bis `delay_working_days`) erscheinen nur bei `kind = JIT` und nur, wenn aktuelle Nachschubdaten vorliegen; sonst bleibt es beim Hinweistext `note`.\n\nStock display for a variant or order item. It shows the stock of the production site that makes the item or, as long as none is assigned, an approximation. Fields without a value are omitted from the response instead of being `null`. The supply fields (`supply_state` to `delay_working_days`) only appear for `kind = JIT` and only if current supply data is available; otherwise only the `note` text remains."},"LinkedSupportTicket":{"properties":{"id":{"type":"integer","description":"Ticket-ID im Support-System, unter der das Ticket dort zu finden ist. / Ticket ID in the support system under which the ticket can be found."},"subject":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Betreff des Tickets; `null`, solange er für ältere Tickets noch nicht nachgetragen ist. / Subject of the ticket; `null` while not yet filled in for older tickets."},"status":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Ticket-Status als Text (z. B. `open`, `pending`, `resolved`, `closed`); `null`, solange er für ältere Tickets noch nicht nachgetragen ist. / Ticket status as text (e.g. `open`, `pending`, `resolved`, `closed`); `null` while not yet filled in for older tickets."},"category":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Kategorie des Tickets als Text; `null` = keine Kategorie bekannt. / Category of the ticket as text; `null` = no category known."},"created_at":{"type":"string","format":"date-time","description":"Zeitpunkt der Ticket-Anlage, ISO 8601 mit Zeitzone. / Time the ticket was created, ISO 8601 with time zone."}},"type":"object","required":["created_at","id"],"title":"LinkedSupportTicket","description":"Support-Ticket, das mit der Bestellung verknüpft ist und an den Händler gerichtet war. / Support ticket linked to the order that was addressed to the merchant."},"MerchantPreviewAddressResponse":{"properties":{"title":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Anrede oder Titel des Empfängers, bis 20 Zeichen; `null`, wenn nicht angegeben / Salutation or title of the recipient, up to 20 characters; `null` if not given."},"company":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Firmenname, bis 200 Zeichen; `null` bei Privatadressen / Company name, up to 200 characters; `null` for private addresses."},"first_name":{"type":"string","example":"Max","description":"Vorname des Empfängers, bis 100 Zeichen / First name of the recipient, up to 100 characters."},"last_name":{"type":"string","example":"Mustermann","description":"Nachname des Empfängers, bis 100 Zeichen / Last name of the recipient, up to 100 characters."},"care_of":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Adresszusatz (c/o), bis 200 Zeichen; `null`, wenn nicht angegeben / Address supplement (c/o), up to 200 characters; `null` if not given."},"street":{"type":"string","example":"Musterstraße","description":"Straße ohne Hausnummer, bis 200 Zeichen / Street without house number, up to 200 characters."},"house_number":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"1","description":"Hausnummer samt Zusatz, bis 20 Zeichen; `null`, wenn nicht angegeben / House number including suffix, up to 20 characters; `null` if not given."},"postcode":{"type":"string","example":"50667","description":"Postleitzahl, bis 20 Zeichen / Postcode, up to 20 characters."},"city":{"type":"string","example":"Köln","description":"Ort, bis 100 Zeichen / City, up to 100 characters."},"country":{"type":"string","example":"DE","description":"Ländercode, zwei Buchstaben (ISO 3166-1 alpha-2), zum Beispiel `DE` / Country code, two letters (ISO 3166-1 alpha-2), for example `DE`."},"email":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"max.mustermann@example.com","description":"E-Mail-Adresse des Adressaten, gültiges Format; `null`, wenn nicht angegeben / Email address of the addressee, valid format; `null` if not given."}},"type":"object","required":["city","country","first_name","last_name","postcode","street"],"title":"MerchantPreviewAddressResponse","description":"Adresse so, wie die Vorschau sie verwenden würde (Echo der übermittelten Adresse). Die Bedeutung der Felder entspricht der Adresse einer Bestellung; die Vorschau schreibt nichts.\n\nAddress as the preview would use it (echo of the submitted address). The fields mean the same as the address of an order; the preview writes nothing."},"MerchantPreviewPositionResponse":{"properties":{"sku":{"type":"string","example":"TSHIRT-SCHWARZ-M","description":"SKU des Artikels, auf dem die Position gebaut würde; kann von der gesendeten SKU abweichen, wenn der Katalog einen Ersatzartikel vorsieht. / SKU of the article the position would be built on; can differ from the SKU sent if the catalog defines a substitute article."},"product_name":{"type":"string","example":"Basic T-Shirt","description":"Produktname des Artikels. / Product name of the article."},"description":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Schwarz, Größe M","description":"Beschreibung der Variante (z. B. Farbe und Größe); `null` = keine hinterlegt. / Description of the variant (e.g. colour and size); `null` = none stored."},"amount":{"type":"integer","example":2,"description":"Stückzahl der Position. / Quantity of the position."},"unit_price_net":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":1490,"description":"Nettopreis je Stück in Cent, einschließlich der Veredelungen; `null` = für den Artikel liegt kein Katalogpreis vor. / Net price per piece in cents, including processings; `null` = no catalog price exists for the article."},"line_price_net":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":2980,"description":"Nettopreis der gesamten Position in Cent (Summe über alle Stücke); `null` = für den Artikel liegt kein Katalogpreis vor. / Net price of the whole position in cents (sum over all pieces); `null` = no catalog price exists for the article."}},"type":"object","required":["amount","description","line_price_net","product_name","sku","unit_price_net"],"title":"MerchantPreviewPositionResponse","description":"Eine angefragte Position der Bestellvorschau mit Stückzahl und Preisen. / One requested position of the order preview with quantity and prices."},"MockupGapReason":{"type":"string","enum":["no_assignment","view_not_adjustable","no_settings","settings_estimated","colour_not_renderable","geometry_not_renderable","no_print_file","render_pending","render_failed"],"title":"MockupGapReason","description":"Grund, aus dem für eine Druckposition kein eigenes Vorschaubild (Mockup) entsteht: `no_assignment`, `view_not_adjustable`, `no_settings`, `settings_estimated`, `colour_not_renderable`, `geometry_not_renderable`, `no_print_file`, `render_pending` (Erzeugung läuft noch), `render_failed` (Erzeugung gescheitert). / Reason why a print position gets no own preview image (mockup): `no_assignment`, `view_not_adjustable`, `no_settings`, `settings_estimated`, `colour_not_renderable`, `geometry_not_renderable`, `no_print_file`, `render_pending` (generation still running), `render_failed` (generation failed)."},"OrderAddressResponse":{"properties":{"id":{"type":"integer","example":5001,"description":"Kennung dieses Adress-Schnappschusses an der Bestellung; nicht die Kennung einer gespeicherten Adresse / Identifier of this address snapshot on the order; not the identifier of a stored address."},"address_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":7001,"description":"Kennung der gespeicherten Adresse, aus der der Schnappschuss erzeugt wurde; `null`, wenn es keine gibt oder sie gelöscht wurde / Identifier of the stored address the snapshot was created from; `null` if there is none or it was deleted."},"title":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Anrede oder Titel des Empfängers, Freitext bis 20 Zeichen; `null`, wenn nicht angegeben / Salutation or title of the recipient, free text up to 20 characters; `null` if not given."},"company":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Firmenname, bis 200 Zeichen; `null` bei Privatadressen / Company name, up to 200 characters; `null` for private addresses."},"first_name":{"type":"string","example":"Max","description":"Vorname des Empfängers, bis 100 Zeichen / First name of the recipient, up to 100 characters."},"last_name":{"type":"string","example":"Mustermann","description":"Nachname des Empfängers, bis 100 Zeichen / Last name of the recipient, up to 100 characters."},"care_of":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Adresszusatz (c/o), bis 200 Zeichen; `null`, wenn nicht angegeben / Address supplement (c/o), up to 200 characters; `null` if not given."},"street":{"type":"string","example":"Musterstraße","description":"Straße ohne Hausnummer, bis 200 Zeichen. Bei Packstation oder Postfiliale das Wort mit Stationsnummer / Street without house number, up to 200 characters. For a parcel locker or post office, the word with the station number."},"house_number":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"1","description":"Hausnummer samt Zusatz, bis 20 Zeichen; `null`, wenn nicht angegeben. Ohne Hausnummer wird die Bestellung angehalten, außer bei einer gültigen Packstation / House number including suffix, up to 20 characters; `null` if not given. Without a house number the order is held, except for a valid parcel locker."},"postcode":{"type":"string","example":"50667","description":"Postleitzahl, bis 20 Zeichen, passend zum Format des Landes (`country`) / Postcode, up to 20 characters, matching the format of the country (`country`)."},"city":{"type":"string","example":"Köln","description":"Ort, bis 100 Zeichen; muss gesetzt sein / City, up to 100 characters; must be set."},"country":{"type":"string","example":"DE","description":"Ländercode, zwei Buchstaben (ISO 3166-1 alpha-2), zum Beispiel `DE` / Country code, two letters (ISO 3166-1 alpha-2), for example `DE`."},"email":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"max.mustermann@example.com","description":"E-Mail-Adresse des Adressaten, gültiges Format, bis 254 Zeichen; `null`, wenn nicht angegeben / Email address of the addressee, valid format, up to 254 characters; `null` if not given."}},"type":"object","required":["address_id","care_of","city","company","country","email","first_name","house_number","id","last_name","postcode","street","title"],"title":"OrderAddressResponse","description":"Adresse einer Bestellung als unveränderlicher Schnappschuss zum Zeitpunkt der Bestellung (oder der letzten Adressänderung an der Bestellung). Spätere Änderungen an einer gespeicherten Adresse des Händlers wirken nicht auf die Bestellung zurück.\n\nHinweise zu den Adressfeldern: `country` ist ein zweistelliger Ländercode (ISO 3166-1 alpha-2). Die Postleitzahl wird gegen das Format des Landes geprüft; eine fehlende Hausnummer oder eine ungültige Postleitzahl hält die Bestellung auf `CHECK` an. Für Lieferungen an eine DHL-Packstation oder Postfiliale in Deutschland steht in `street` das Wort `Packstation` bzw. `Postfiliale` mit der Stationsnummer (Packstation 100 bis 999, Postfiliale 401 bis 999); die Postnummer (6 bis 10 Ziffern) steht in einem der Felder `street`, `first_name`, `last_name`, `company`, `house_number` oder `care_of`. Eine Packstation braucht keine Hausnummer.\n\nAddress of an order as an immutable snapshot taken when the order was placed (or when the address of the order was last changed). Later changes to a stored address of the merchant do not affect the order.\n\nNotes on the address fields: `country` is a two-letter country code (ISO 3166-1 alpha-2). The postcode is checked against the format of the country; a missing house number or an invalid postcode holds the order in `CHECK`. For deliveries to a DHL parcel locker or post office in Germany, `street` contains the word `Packstation` or `Postfiliale` with the station number (Packstation 100 to 999, Postfiliale 401 to 999); the post number (6 to 10 digits) is in one of the fields `street`, `first_name`, `last_name`, `company`, `house_number` or `care_of`. A parcel locker does not need a house number."},"OrderCancelOverallOutcome":{"type":"string","enum":["FULLY_CANCELED","PARTIALLY_CANCELED","NOTHING_CANCELED","FORCE_ABANDONED","ABORTED_NOT_ELIGIBLE","CANCEL_PENDING_VERIFICATION","ABORTED_DRIFT"],"title":"OrderCancelOverallOutcome","description":"Gesamtergebnis einer Stornierung. `FULLY_CANCELED`: alle Teile storniert. `PARTIALLY_CANCELED`: nur ein Teil storniert. `NOTHING_CANCELED`: nichts storniert. `ABORTED_NOT_ELIGIBLE`: nicht ausgeführt, weil die Bestellung nicht (kostenfrei) stornierbar ist; mit `paid_cancel_available` = `true` ginge es kostenpflichtig. `CANCEL_PENDING_VERIFICATION`: eine frühere Stornierung ist noch nicht bestätigt, es wurde nichts ausgelöst. `ABORTED_DRIFT`: der Stand änderte sich während der Stornierung, die Bestellung wurde nicht umgestellt. `FORCE_ABANDONED` wird für Händlerschlüssel nicht geliefert. / Overall result of a cancellation. `FULLY_CANCELED`: all parts canceled. `PARTIALLY_CANCELED`: only part canceled. `NOTHING_CANCELED`: nothing canceled. `ABORTED_NOT_ELIGIBLE`: not executed because the order is not cancelable (free of cost); with `paid_cancel_available` = `true` it would work against cost. `CANCEL_PENDING_VERIFICATION`: an earlier cancellation is not confirmed yet, nothing was triggered. `ABORTED_DRIFT`: the state changed during the cancellation, the order was not updated. `FORCE_ABANDONED` is not returned for merchant keys."},"OrderCancelPreviewResponse":{"properties":{"order_id":{"type":"integer","example":123456,"description":"ID der Bestellung / ID of the order."},"external_reference":{"type":"string","example":"SHOP-10042","description":"Ihre Bestellreferenz, wie beim Anlegen vergeben / Your order reference as given at creation."},"order_status":{"$ref":"#/components/schemas/OrderStatus","description":"Aktueller Bestellstatus / Current order status."},"outcome":{"$ref":"#/components/schemas/CancelPreviewOutcome","description":"Was die Stornierung jetzt bewirken würde, siehe `CancelPreviewOutcome` / What the cancellation would do now, see `CancelPreviewOutcome`."},"reasons":{"items":{"$ref":"#/components/schemas/CancelPreviewReason"},"type":"array","description":"Gründe, nur bei `outcome` = `REJECTED`; sonst leer / Reasons, only for `outcome` = `REJECTED`; otherwise empty."},"paid_cancel_available":{"type":"boolean","default":false,"example":false,"description":"`true`, wenn die Stornierung nur mit `accept_cost: true` (kostenpflichtig) möglich ist / `true` if cancelling only works with `accept_cost: true` (against cost)."},"fingerprint":{"type":"string","example":"a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90","description":"SHA-256-Hexwert (64 Zeichen) über die entscheidenden Werte der Vorschau; ändert sich, wenn sich Status, Ergebnis oder Gründe ändern / SHA-256 hex value (64 characters) over the deciding values of the preview; changes when status, outcome or reasons change."},"confirmed_summary":{"type":"string","example":"Storno Bestellung SHOP-10042","description":"Kurztext zur Bestätigung, Format `Storno Bestellung <external_reference>` / Short confirmation text, format `Storno Bestellung <external_reference>`."}},"type":"object","required":["confirmed_summary","external_reference","fingerprint","order_id","order_status","outcome"],"title":"OrderCancelPreviewResponse"},"OrderCancelRequest":{"properties":{"force":{"type":"boolean","default":false,"description":"Wird für Händlerschlüssel ignoriert / Ignored for merchant keys."},"accept_cost":{"type":"boolean","default":false,"example":false,"description":"Standard `false`. Mit `true` stimmen Sie einer kostenpflichtigen Stornierung zu; ohne Zustimmung bricht sie ab, wenn Kosten anfallen / Default `false`. `true` consents to a cancellation against cost; without consent it aborts if costs would arise."},"reason":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":500,"minLength":10,"description":"Grund für das Protokoll, 10 bis 500 Zeichen ohne `<`, `>`, `&`, `\"`, `'` und Steuerzeichen; `null` = Shirtee setzt einen Standardtext / Reason for the audit trail, 10 to 500 characters without `<`, `>`, `&`, `\"`, `'` and control characters; `null` = Shirtee uses a default text.","example":"Bestellung vom Endkunden storniert"}},"type":"object","required":[],"title":"OrderCancelRequest"},"OrderDeliveryAddressPreviewResponse":{"properties":{"order_id":{"type":"integer","example":123456,"description":"ID der Bestellung / ID of the order."},"external_reference":{"type":"string","example":"SHOP-10042","description":"Ihre Bestellreferenz, wie beim Anlegen vergeben / Your order reference as given at creation."},"order_status":{"$ref":"#/components/schemas/OrderStatus","description":"Aktueller Bestellstatus / Current order status."},"is_editable":{"type":"boolean","example":true,"description":"`true`, wenn die Adressänderung jetzt möglich wäre / `true` if the address change would be possible now."},"blockers":{"items":{"$ref":"#/components/schemas/DeliveryAddressPreviewBlocker"},"type":"array","description":"Gründe, warum die Änderung jetzt abgelehnt würde; leer, wenn sie möglich ist / Reasons why the change would be rejected now; empty if it is possible."},"mode":{"oneOf":[{"$ref":"#/components/schemas/DeliveryAddressPreviewMode"},{"type":"null"}],"example":"LOCAL_REROUTE","description":"Wie die Änderung angewendet würde; `null`, wenn sie blockiert ist / How the change would be applied; `null` if it is blocked."},"address":{"$ref":"#/components/schemas/MerchantPreviewAddressResponse","description":"Die geprüfte Adresse, wie gesendet / The validated address as sent."},"fingerprint":{"type":"string","example":"a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90","description":"SHA-256-Hexwert (64 Zeichen) über die entscheidenden Werte der Vorschau; ändert sich, wenn sich Status, Editierbarkeit, Modus oder Adresse ändern / SHA-256 hex value (64 characters) over the deciding values of the preview; changes when status, editability, mode or address change."},"confirmed_summary":{"type":"string","example":"Lieferadresse Bestellung SHOP-10042: Musterstraße 1, 50667 Köln, DE","description":"Kurztext zur Bestätigung, Format `Lieferadresse Bestellung <Referenz>: <Straße Nr>, <PLZ> <Ort>, <Land>` / Short confirmation text, format `Lieferadresse Bestellung <reference>: <street no>, <postcode> <city>, <country>`."}},"type":"object","required":["address","confirmed_summary","external_reference","fingerprint","is_editable","order_id","order_status"],"title":"OrderDeliveryAddressPreviewResponse"},"OrderErrorResponse":{"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode der Antwort, identisch mit dem Statuscode der HTTP-Antwort / HTTP status code of the response, identical to the status code of the HTTP response."},"detail":{"type":"string","description":"Lesbare Fehlerbeschreibung in englischer Sprache, nur zur Anzeige oder Diagnose; zum Verzweigen `extra.error` verwenden / Human-readable error description in English, for display or diagnosis only; branch on `extra.error` instead."},"extra":{"oneOf":[{"type":"object"},{"type":"array"},{"type":"null"}],"description":"Maschinenlesbare Einzelheiten zum Fehler, meist ein Objekt mit `error` (Fehlercode) und weiteren Schlüsseln, bei manchen Validierungsfehlern eine Liste; `null`, wenn es keine gibt / Machine-readable error details, usually an object with `error` (error code) and further keys, a list for some validation errors; `null` if there are none."}},"type":"object","required":["detail","status_code"],"title":"OrderErrorResponse","description":"Fehlerantwort der Bestell-Endpunkte. Sie enthält immer `status_code` und `detail`; `extra` trägt, wenn vorhanden, maschinenlesbare Einzelheiten. Bei geschäftlichen Ablehnungen steht in `extra.error` ein stabiler Fehlercode, nach dem Clients verzweigen sollten (nicht nach dem Text in `detail`). Weitere Schlüssel in `extra` hängen vom Fehler ab, zum Beispiel `retryable` (ob ein Wiederholen sinnvoll ist), `fields` (die fehlerhaften Felder als Liste mit `field` und `code`) oder `issues` (Texte zu einer ungültigen Adresse).\n\nError response of the order endpoints. It always contains `status_code` and `detail`; `extra` carries machine-readable details where present. For business rejections `extra.error` holds a stable error code that clients should branch on (not on the text in `detail`). Other keys in `extra` depend on the error, for example `retryable` (whether repeating the request makes sense), `fields` (the invalid fields as a list with `field` and `code`) or `issues` (texts about an invalid address)."},"OrderItemAddRequest":{"properties":{"sku":{"type":"string","maxLength":100,"example":"TSHIRT-BLK-M","description":"SKU der Variante (Artikel in Farbe und Größe), max. 100 Zeichen; unbekannt, inaktiv oder mehrdeutig = 422 / SKU of the variant (article in color and size), max. 100 characters; unknown, inactive or ambiguous = 422."},"external_id":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":64,"example":"POS-3","description":"Ihre eigene Positionskennung, max. 64 Zeichen; muss unter den aktiven Positionen der Bestellung eindeutig sein (sonst 422); `null` = keine / Your own item identifier, max. 64 characters; must be unique among the active items of the order (otherwise 422); `null` = none."},"item_id":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":255,"description":"Weitere Positionskennung, max. 255 Zeichen; muss unter den aktiven Positionen der Bestellung eindeutig sein (sonst 422); `null` = keine / Further item identifier, max. 255 characters; must be unique among the active items of the order (otherwise 422); `null` = none."},"sales_price":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Verkaufspreis in Cent; für Händlerschlüssel nicht erlaubt (403) / Sales price in cents; not allowed for merchant keys (403)."},"product_price":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Produktpreis in Cent; für Händlerschlüssel nicht erlaubt (403), der Preis kommt aus dem Katalog / Product price in cents; not allowed for merchant keys (403), the price comes from the catalog."},"amount":{"type":"integer","maximum":1.0,"minimum":1.0,"default":1,"description":"Menge, immer 1 (andere Werte werden abgelehnt); für mehr Stück weitere Positionen hinzufügen / Quantity, always 1 (other values are rejected); add further items for more pieces."},"processings":{"items":{"$ref":"#/components/schemas/ItemProcessingCreateRequest"},"type":"array","maxItems":16,"minItems":1,"description":"1 bis 16 Veredelungen der Position; jede `position` darf nur einmal vorkommen / 1 to 16 finishings of the item; each `position` may occur only once."},"branding":{"oneOf":[{"$ref":"#/components/schemas/OrderItemBrandingInput"},{"type":"null"}],"description":"Branding der Position; für Händlerschlüssel nicht erlaubt (403) / Branding of the item; not allowed for merchant keys (403)."},"integration_data":{"oneOf":[{"type":"object"},{"type":"null"}],"description":"Freies JSON-Objekt für Integrationen; für Händlerschlüssel nicht erlaubt (403) / Free JSON object for integrations; not allowed for merchant keys (403)."},"reason":{"type":"string","maxLength":500,"minLength":10,"example":"Zusätzliche Position auf Kundenwunsch","description":"Grund für das Protokoll, 10 bis 500 Zeichen ohne `<`, `>`, `&`, `\"`, `'` und Steuerzeichen / Reason for the audit trail, 10 to 500 characters without `<`, `>`, `&`, `\"`, `'` and control characters."}},"type":"object","required":["processings","reason","sku"],"title":"OrderItemAddRequest"},"OrderItemBrandingInput":{"properties":{"label_reference":{"type":"string","maxLength":64,"description":"Branding-Referenz, max. 64 Zeichen; für Händlerschlüssel nicht erlaubt (403) / Branding reference, max. 64 characters; not allowed for merchant keys (403)."},"reference_type":{"$ref":"#/components/schemas/BrandingReferenceType","description":"Art der Referenz, siehe `BrandingReferenceType`; Standard `label` / Type of the reference, see `BrandingReferenceType`; default `label`."}},"type":"object","required":["label_reference"],"title":"OrderItemBrandingInput"},"OrderItemDeleteReason":{"type":"string","enum":["CUSTOMER_CANCELLATION","DEFECT_BEFORE_PRODUCTION","WRONG_DESIGN_UPLOADED","DUPLICATE_ITEM","INTERNAL_ERROR","REPLACEMENT_BY_ADD_ITEM","SUPPORT_OVERRIDE"],"title":"OrderItemDeleteReason","description":"Grund für das Entfernen einer Position: `CUSTOMER_CANCELLATION`, `DEFECT_BEFORE_PRODUCTION`, `WRONG_DESIGN_UPLOADED`, `DUPLICATE_ITEM`, `INTERNAL_ERROR`, `REPLACEMENT_BY_ADD_ITEM`, `SUPPORT_OVERRIDE`. / Reason for removing an item: `CUSTOMER_CANCELLATION`, `DEFECT_BEFORE_PRODUCTION`, `WRONG_DESIGN_UPLOADED`, `DUPLICATE_ITEM`, `INTERNAL_ERROR`, `REPLACEMENT_BY_ADD_ITEM`, `SUPPORT_OVERRIDE`."},"OrderItemDeleteRequest":{"properties":{"reason":{"$ref":"#/components/schemas/OrderItemDeleteReason","description":"Grund für das Entfernen, siehe `OrderItemDeleteReason` / Reason for the removal, see `OrderItemDeleteReason`."},"note":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":1000,"example":"Endkunde hat die Position abbestellt","description":"Freitext für das Protokoll, max. 1000 Zeichen ohne `<`, `>`, `&`, `\"`, `'` und Steuerzeichen; `null` = keine / Free text for the audit trail, max. 1000 characters without `<`, `>`, `&`, `\"`, `'` and control characters; `null` = none."},"apply_wallet_correction":{"oneOf":[{"type":"boolean"},{"type":"null"}],"description":"Steuert die Guthabenkorrektur; für Händlerschlüssel nicht erlaubt (403), es gilt die Vorgabe des Grundes / Controls the wallet correction; not allowed for merchant keys (403), the default of the reason applies."}},"type":"object","required":["reason"],"title":"OrderItemDeleteRequest"},"OrderItemReplaceVariantRequest":{"properties":{"product_variant_id":{"type":"integer","exclusiveMinimum":0.0,"example":503,"description":"ID der Zielvariante (größer 0); sie muss aktiv sein, zum selben Produkt gehören und sich von der aktuellen unterscheiden / ID of the target variant (greater than 0); it must be active, belong to the same product and differ from the current one."},"reason":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":500,"minLength":10,"description":"Begründung für das Protokoll, 10 bis 500 Zeichen ohne `<`, `>`, `&`, `\"`, `'` und Steuerzeichen; `null` = keine / Reason for the audit trail, 10 to 500 characters without `<`, `>`, `&`, `\"`, `'` and control characters; `null` = none.","example":"Kunde wünscht Größe L"}},"type":"object","required":["product_variant_id"],"title":"OrderItemReplaceVariantRequest"},"OrderItemVariantSwapInput":{"properties":{"item_id":{"type":"integer","exclusiveMinimum":0.0,"example":9001,"description":"ID der Position, deren Variante getauscht wird (größer 0); jede Position höchstens einmal je Aufruf / ID of the item whose variant is swapped (greater than 0); each item at most once per call."},"product_variant_id":{"type":"integer","exclusiveMinimum":0.0,"example":503,"description":"ID der Zielvariante (größer 0), aktiv und aus demselben Produkt / ID of the target variant (greater than 0), active and of the same product."}},"type":"object","required":["item_id","product_variant_id"],"title":"OrderItemVariantSwapInput"},"OrderItemVariantSwapPreviewPosition":{"properties":{"item_id":{"type":"integer","example":9001,"description":"ID der Position / ID of the item."},"current_product_variant_id":{"type":"integer","example":502,"description":"ID der aktuellen Variante / ID of the current variant."},"current_sku":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"TSHIRT-BLK-M","description":"SKU der aktuellen Variante; `null`, wenn sie nicht mehr im Katalog ist / SKU of the current variant; `null` if it is no longer in the catalog."},"new_product_variant_id":{"type":"integer","example":503,"description":"ID der Zielvariante / ID of the target variant."},"new_sku":{"type":"string","example":"TSHIRT-BLK-L","description":"SKU der Zielvariante / SKU of the target variant."},"product_price":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":1290,"description":"Aktueller Produktpreis der Position in Cent; der Tausch ändert ihn nicht; `null` = kein Preis hinterlegt / Current product price of the item in cents; the swap does not change it; `null` = no price stored."}},"type":"object","required":["current_product_variant_id","current_sku","item_id","new_product_variant_id","new_sku","product_price"],"title":"OrderItemVariantSwapPreviewPosition"},"OrderItemsVariantSwapPreviewResponse":{"properties":{"order_id":{"type":"integer","example":123456,"description":"ID der Bestellung / ID of the order."},"external_reference":{"type":"string","example":"SHOP-10042","description":"Ihre Bestellreferenz, wie beim Anlegen vergeben / Your order reference as given at creation."},"order_status":{"$ref":"#/components/schemas/OrderStatus","description":"Aktueller Bestellstatus / Current order status."},"is_editable":{"type":"boolean","example":true,"description":"`true`, wenn die Bestellung jetzt änderbar ist / `true` if the order is changeable now."},"blockers":{"items":{"$ref":"#/components/schemas/EditabilityBlocker"},"type":"array","description":"Gründe, warum sie nicht änderbar ist, siehe `EditabilityBlocker`; leer, wenn änderbar / Reasons why it is not changeable, see `EditabilityBlocker`; empty if changeable."},"positions":{"items":{"$ref":"#/components/schemas/OrderItemVariantSwapPreviewPosition"},"type":"array","description":"Die geprüften Positionen mit alter und neuer Variante, in Anfragereihenfolge / The validated positions with old and new variant, in request order."},"restart_follows":{"type":"boolean","default":true,"example":true,"description":"Immer `true`: nach dem Tausch wird die Bestellung neu angestoßen / Always `true`: the order is restarted after the swap."},"further_changes_blocked_after_restart":{"type":"boolean","default":true,"example":true,"description":"Immer `true`: nach dem Neustart sind keine weiteren Änderungen mehr möglich, sobald die Bestellung wieder zugeteilt ist / Always `true`: after the restart no further changes are possible once the order is routed again."},"fingerprint":{"type":"string","example":"a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90","description":"SHA-256-Hexwert (64 Zeichen) über die entscheidenden Werte der Vorschau; ändert sich, wenn sich Status, Editierbarkeit oder Positionen ändern / SHA-256 hex value (64 characters) over the deciding values of the preview; changes when status, editability or positions change."},"confirmed_summary":{"type":"string","example":"Variantentausch Bestellung SHOP-10042: 2 Position(en)","description":"Kurztext zur Bestätigung, Format `Variantentausch Bestellung <Referenz>: <n> Position(en)` / Short confirmation text, format `Variantentausch Bestellung <reference>: <n> Position(en)`."}},"type":"object","required":["confirmed_summary","external_reference","fingerprint","is_editable","order_id","order_status","positions"],"title":"OrderItemsVariantSwapPreviewResponse"},"OrderItemsVariantSwapRequest":{"properties":{"items":{"items":{"$ref":"#/components/schemas/OrderItemVariantSwapInput"},"type":"array","maxItems":100,"minItems":1,"description":"1 bis 100 Positionen mit Zielvariante; jede Position höchstens einmal / 1 to 100 items with target variant; each item at most once."},"reason":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":500,"minLength":10,"description":"Begründung für das Protokoll, 10 bis 500 Zeichen ohne `<`, `>`, `&`, `\"`, `'` und Steuerzeichen; `null` = keine / Reason for the audit trail, 10 to 500 characters without `<`, `>`, `&`, `\"`, `'` and control characters; `null` = none.","example":"Kunde wünscht Größe L"}},"type":"object","required":["items"],"title":"OrderItemsVariantSwapRequest"},"OrderMerchantPreviewResponse":{"properties":{"is_feasible":{"type":"boolean","example":true,"description":"`true`, wenn alle Positionen einem Produktionspartner zugewiesen werden könnten und die Preise vollständig sind; sonst `false`, siehe `unassignable_skus`. / `true` if all positions could be assigned to a production partner and prices are complete; otherwise `false`, see `unassignable_skus`."},"unassignable_skus":{"items":{"type":"string"},"type":"array","description":"SKUs der Positionen, die derzeit keinem Produktionspartner zugewiesen werden könnten; leer, wenn alle zuweisbar sind. / SKUs of the positions that currently could not be assigned to a production partner; empty if all can be assigned."},"positions":{"items":{"$ref":"#/components/schemas/MerchantPreviewPositionResponse"},"type":"array","description":"Die angefragten Positionen mit Stückzahl und Preisen. / The requested positions with quantity and prices."},"delivery_address":{"$ref":"#/components/schemas/MerchantPreviewAddressResponse","description":"Die Lieferadresse, wie sie bei der Anlage verwendet würde (Echo der gesendeten Adresse). / The delivery address as it would be used at creation (echo of the address sent)."},"billing_address":{"$ref":"#/components/schemas/MerchantPreviewAddressResponse","description":"Die Rechnungsadresse, wie sie bei der Anlage verwendet würde (Echo der gesendeten Adresse). / The billing address as it would be used at creation (echo of the address sent)."},"net_amount":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":2980,"description":"Nettobetrag der Bestellung in Cent; `null`, wenn für mindestens einen Artikel kein Katalogpreis vorliegt. / Net amount of the order in cents; `null` if at least one article has no catalog price."},"gross_amount":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":3546,"description":"Bruttobetrag der Bestellung in Cent, berechnet wie bei der Rechnung (inklusive Umsatzsteuer, soweit anfallend); `null`, wenn für mindestens einen Artikel kein Katalogpreis vorliegt. / Gross amount of the order in cents, calculated as for the invoice (including VAT where applicable); `null` if at least one article has no catalog price."},"currency":{"type":"string","default":"EUR","example":"EUR","description":"Währung der Beträge als ISO-4217-Code, derzeit immer `EUR`. / Currency of the amounts as ISO 4217 code, currently always `EUR`."},"payment_gateway":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"collective_invoice","description":"Kennung des Zahlungswegs, der bei der Anlage hinterlegt würde (derzeit `collective_invoice`). / Identifier of the payment route that would be stored at creation (currently `collective_invoice`)."},"wallet_coverage_checked":{"type":"boolean","default":false,"example":false,"description":"Immer `false`: Das Guthaben des Händlers wird in der Vorschau nicht geprüft, eine Deckung wird nicht zugesagt. / Always `false`: the merchant balance is not checked in the preview, coverage is not promised."},"fingerprint":{"type":"string","example":"9b74c9897bac770ffc029102a200c5de1c6a9a3d4f6b7e5d3c2b1a0f9e8d7c6b","description":"SHA-256 (Hex) über die entscheidenden Werte der Vorschau; gleicher Entwurf bei unverändertem Stand ergibt denselben Wert, eine Änderung an Preis oder Machbarkeit einen anderen. / SHA-256 (hex) over the deciding values of the preview; the same draft in an unchanged state yields the same value, a change in price or feasibility another."},"confirmed_summary":{"type":"string","example":"35.46 EUR","description":"Kurztext des Bruttobetrags zur Bestätigung, z. B. `35.46 EUR`; `amount unknown`, wenn der Betrag nicht bestimmbar ist. / Short text of the gross amount for confirmation, e.g. `35.46 EUR`; `amount unknown` if the amount cannot be determined."}},"type":"object","required":["billing_address","confirmed_summary","delivery_address","fingerprint","gross_amount","is_feasible","net_amount","positions"],"title":"OrderMerchantPreviewResponse","description":"Ergebnis der Bestellvorschau: Positionen, Beträge und Machbarkeit, ohne dass etwas gespeichert wurde. / Result of the order preview: positions, amounts and feasibility, nothing was saved."},"OrderReorderRequest":{"properties":{"item_ids":{"oneOf":[{"items":{"type":"integer","example":900101},"type":"array"},{"type":"null"}],"minLength":1,"description":"IDs der Positionen der Quellbestellung (`items[].id` aus `GET /api/orders/{order_id}`), die nachbestellt werden; mindestens ein Eintrag. Eine ID entspricht einem Stück. `null` oder weggelassen = die ganze Bestellung; eine ID, die keine aktive Position der Quelle ist, ergibt 400. / IDs of the items of the source order (`items[].id` from `GET /api/orders/{order_id}`) to re-order; at least one entry. One ID is one piece. `null` or omitted = the whole order; an ID that is not an active item of the source returns 400."},"variant_overrides":{"oneOf":[{"additionalProperties":{"type":"integer"},"type":"object"},{"type":"null"}],"minLength":1,"description":"Für Händler nicht erlaubt: jeder gesetzte Wert ergibt 403. / Not allowed for merchants: any value set returns 403."},"delivery_address":{"oneOf":[{"$ref":"#/components/schemas/AddressInput"},{"type":"null"}],"description":"Für Händler nicht erlaubt: jeder gesetzte Wert ergibt 403; die Lieferadresse der Quelle wird übernommen. / Not allowed for merchants: any value set returns 403; the delivery address of the source is taken over."},"allow_open_source":{"type":"boolean","default":false,"description":"Für Händler nicht erlaubt: `true` ergibt 403; `false` ist der Standard. / Not allowed for merchants: `true` returns 403; `false` is the default."},"open_source_override_reason":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":500,"minLength":10,"description":"Begründung zu `allow_open_source`, 10 bis 500 Zeichen; für Händler nicht nutzbar, da `allow_open_source` nicht erlaubt ist. / Reason for `allow_open_source`, 10 to 500 characters; not usable for merchants because `allow_open_source` is not allowed."}},"type":"object","required":[],"title":"OrderReorderRequest","description":"Optionaler Body der Nachbestellung. Für Händler ist nur `item_ids` erlaubt. / Optional body of the re-order. For merchants only `item_ids` is allowed."},"OrderStatus":{"type":"string","enum":["PENDING","READY","CHECK","ERROR","TRANSFERRED","PARTIALLY_TRANSFERRED","SHIPPED","CANCELED","PARTIALLY_CANCELED","CANCELLATION_PENDING","PAUSE"],"title":"OrderStatus","description":"Status einer Bestellung. Eine neue Bestellung entsteht als `PENDING`; je nach Bestellung wird sie danach für ein Korrekturfenster von 4 Stunden in `PAUSE` gehalten und anschließend wieder auf `PENDING` freigegeben. Typischer Verlauf: `PENDING` > `READY` > `TRANSFERRED` > `SHIPPED`. Angehaltene oder fehlgeschlagene Bestellungen stehen auf `CHECK` oder `ERROR`; der Rückhaltegrund steht im Feld `retention` der Bestellung.\n\nWerte:\n\n- `PENDING`: Bestellung angelegt, die Aufbereitung läuft (Druckdaten laden und rendern, Adresse prüfen) oder startet gerade.\n- `PAUSE`: Korrekturfenster vor der Produktion (4 Stunden ab Beginn der Pause). Adresse und Positionen sind in dieser Zeit noch änderbar; die Bestellung wird danach automatisch freigegeben, oder vorzeitig über den Neustart.\n- `READY`: Aufbereitung abgeschlossen, die Bestellung wartet auf die Übergabe an die Produktion.\n- `CHECK`: Bestellung angehalten, sie wartet auf eine Klärung oder Freigabe (zum Beispiel ungültige Adresse, fehlende Zuordnung zu einer Produktion, Rückfrage der Produktion oder eine Stornierung durch die Produktion). Der Grund steht in `retention`.\n- `ERROR`: technischer oder datenseitiger Fehler (zum Beispiel fehlende Preisdaten, Druckdatei nicht ladbar oder nicht renderbar, Übergabe an die Produktion komplett fehlgeschlagen).\n- `TRANSFERRED`: alle Fertigungsaufträge der Bestellung sind an die Produktion übergeben.\n- `PARTIALLY_TRANSFERRED`: ein Teil der Fertigungsaufträge ist übergeben, ein Teil nicht.\n- `SHIPPED`: versendet. Der Status wird gesetzt, sobald alle nicht stornierten Fertigungsaufträge versendet sind und keine Position ohne Fertigungsauftrag übrig ist.\n- `CANCELLATION_PENDING`: Stornierung bei der Produktion angefragt, aber noch nicht bestätigt. Die Bestellung kann danach `CANCELED` werden oder auf `CHECK` zurückfallen.\n- `CANCELED`: storniert.\n- `PARTIALLY_CANCELED`: ein Teil der Bestellung ist storniert, der Rest nicht.\n\nWelche Aktionen (Stornieren, Neustart, Positionen ändern, Nachbestellen) in welchem Status angenommen werden, liefert `GET /api/orders/status-gates`. Das Ändern von Positionen und Adressen ist nur in `PENDING`, `PAUSE`, `READY`, `CHECK` und `ERROR` möglich, und auch dort nur, solange die Produktion die Bestellung noch nicht angenommen hat. `SHIPPED`, `CANCELED` und `PARTIALLY_CANCELED` gelten als abgeschlossen; `TRANSFERRED` und `PARTIALLY_TRANSFERRED` nicht.\n\nStatus of an order. A new order is created as `PENDING`; depending on the order it is then held in `PAUSE` for a 4-hour correction window and released back to `PENDING`. Typical flow: `PENDING` > `READY` > `TRANSFERRED` > `SHIPPED`. Held or failed orders are in `CHECK` or `ERROR`; the reason is in the order field `retention`.\n\nValues:\n\n- `PENDING`: order created, preparation is running or about to start (loading and rendering print files, checking the address).\n- `PAUSE`: correction window before production (4 hours from the start of the pause). Address and items can still be changed; the order is released automatically afterwards, or early via restart.\n- `READY`: preparation finished, the order is waiting to be handed over to production.\n- `CHECK`: order on hold, waiting for clarification or release (for example invalid address, no production assignable, a query from production, or a cancellation by production). The reason is in `retention`.\n- `ERROR`: technical or data error (for example missing price data, print file cannot be loaded or rendered, handover to production failed completely).\n- `TRANSFERRED`: all manufacturing orders of the order are handed over to production.\n- `PARTIALLY_TRANSFERRED`: some manufacturing orders are handed over, some are not.\n- `SHIPPED`: shipped. Set once all non-canceled manufacturing orders are shipped and no item is left without a manufacturing order.\n- `CANCELLATION_PENDING`: cancellation requested at production but not yet confirmed. The order can then become `CANCELED` or fall back to `CHECK`.\n- `CANCELED`: canceled.\n- `PARTIALLY_CANCELED`: part of the order is canceled, the rest is not.\n\n`GET /api/orders/status-gates` returns the statuses in which each action (cancel, restart, change items, reorder) is accepted. Changing items and addresses is only possible in `PENDING`, `PAUSE`, `READY`, `CHECK` and `ERROR`, and even there only while production has not accepted the order. `SHIPPED`, `CANCELED` and `PARTIALLY_CANCELED` count as finished; `TRANSFERRED` and `PARTIALLY_TRANSFERRED` do not."},"OrderUserCancelResponse":{"properties":{"order_id":{"type":"integer","example":123456,"description":"ID der Bestellung / ID of the order."},"overall_outcome":{"$ref":"#/components/schemas/OrderCancelOverallOutcome","description":"Gesamtergebnis, siehe `OrderCancelOverallOutcome` / Overall result, see `OrderCancelOverallOutcome`."},"paid_cancel_available":{"type":"boolean","default":false,"example":false,"description":"`true`, wenn die Stornierung nur kostenpflichtig möglich ist; erneut mit `accept_cost: true` aufrufen / `true` if cancelling is only possible against cost; call again with `accept_cost: true`."},"phoenix_order_status_before":{"$ref":"#/components/schemas/OrderStatus","description":"Bestellstatus vor der Stornierung / Order status before the cancellation."},"phoenix_order_status_after":{"$ref":"#/components/schemas/OrderStatus","description":"Bestellstatus danach (z. B. `CANCELED`, `CANCELLATION_PENDING`, `PARTIALLY_CANCELED`; unverändert, wenn nichts storniert wurde) / Order status afterwards (e.g. `CANCELED`, `CANCELLATION_PENDING`, `PARTIALLY_CANCELED`; unchanged if nothing was canceled)."}},"type":"object","required":["order_id","overall_outcome","phoenix_order_status_after","phoenix_order_status_before"],"title":"OrderUserCancelResponse"},"OrderUserCreateRequest":{"properties":{"external_reference":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":100,"example":"SHOP-10045","description":"Eigene Bestellreferenz des Händlers, höchstens 100 Zeichen, zum späteren Wiederfinden über `GET /api/orders/by-external-reference/{external_reference}`. `null` oder weggelassen = das System vergibt eine. / Own order reference of the merchant, at most 100 characters, to find the order again via `GET /api/orders/by-external-reference/{external_reference}`. `null` or omitted = the system assigns one."},"delivery_address":{"$ref":"#/components/schemas/AddressInput","description":"Lieferadresse, an die versendet wird. / Delivery address the goods are shipped to."},"billing_address":{"$ref":"#/components/schemas/AddressInput","description":"Rechnungsadresse der Bestellung. / Billing address of the order."},"items":{"items":{"$ref":"#/components/schemas/OrderUserItemCreateRequest"},"type":"array","minItems":1,"description":"Bestellpositionen, mindestens eine. / Order items, at least one."},"additional_products":{"oneOf":[{"items":{"$ref":"#/components/schemas/AdditionalProductInput"},"type":"array"},{"type":"null"}],"description":"Optionale Zusatzprodukte ohne Veredelung, die mitbestellt werden; `null` oder weggelassen = keine. / Optional additional products without finishing that are ordered along; `null` or omitted = none."}},"type":"object","required":["billing_address","delivery_address","items"],"title":"OrderUserCreateRequest","description":"Body zum Anlegen einer Bestellung (und der Vorschau). Nur die hier genannten Felder sind erlaubt, jedes weitere ergibt 403 mit dem Feldpfad. / Body for creating an order (and the preview). Only the fields named here are allowed; any other field returns 403 with the field path."},"OrderUserDetailResponse":{"properties":{"id":{"type":"integer","example":900001,"description":"Numerische Bestell-ID; Schlüssel für die Pfade `/api/orders/{order_id}/…`. / Numeric order ID; key for the paths `/api/orders/{order_id}/…`."},"slug":{"type":"string","example":"CL-7K3M9QX","description":"Bestellnummer im Format `CL-…`; auch über die Suche auffindbar. / Order number in the format `CL-…`; also findable via search."},"internal_reference":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Optionale interne Referenz; bei über `POST /api/orders` angelegten Bestellungen nicht gesetzt (`null`). / Optional internal reference; not set (`null`) for orders created via `POST /api/orders`."},"external_reference":{"type":"string","example":"SHOP-10045","description":"Eigene Bestellreferenz des Händlers; hat der Händler keine gesendet, die vom System vergebene. / Own order reference of the merchant; the one assigned by the system if the merchant sent none."},"reordered_from_order_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"ID der Quellbestellung, wenn diese Bestellung eine Nachbestellung ist; sonst `null`. / ID of the source order if this order is a re-order; otherwise `null`."},"designer_id":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"4711","description":"Kennung des Händlers, dem die Bestellung gehört (die Kunden-ID als Text). / Identifier of the merchant owning the order (the customer ID as text)."},"status":{"$ref":"#/components/schemas/OrderStatus","description":"Aktueller Bestellstatus (`OrderStatus`). / Current order status (`OrderStatus`)."},"settlement_method":{"oneOf":[{"$ref":"#/components/schemas/SettlementMethod"},{"type":"null"}],"description":"Wie die Bestellung abgerechnet wird: `WALLET` (über das Guthaben des Händlers), `EXTERNAL_PAYMENT` (Zahlungsdienstleister oder Sammelrechnung), `NONE` (nichts abzurechnen); `null` bei Bestellungen aus der Zeit vor Einführung dieses Feldes. / How the order is settled: `WALLET` (via the merchant balance), `EXTERNAL_PAYMENT` (payment provider or collective invoice), `NONE` (nothing to settle); `null` for orders from before this field existed."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der Anlage, ISO 8601 mit Zeitzone. / Time of creation, ISO 8601 with time zone."},"updated_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:05Z","description":"Zeitpunkt der letzten Änderung, ISO 8601 mit Zeitzone. / Time of the last change, ISO 8601 with time zone."},"delivery_address":{"oneOf":[{"$ref":"#/components/schemas/OrderAddressResponse"},{"type":"null"}],"description":"Lieferadresse der Bestellung; fehlt im JSON, wenn keine vorhanden ist. / Delivery address of the order; missing from the JSON when none exists."},"billing_address":{"oneOf":[{"$ref":"#/components/schemas/OrderAddressResponse"},{"type":"null"}],"description":"Rechnungsadresse der Bestellung; fehlt im JSON, wenn keine vorhanden ist. / Billing address of the order; missing from the JSON when none exists."},"sender_address":{"oneOf":[{"$ref":"#/components/schemas/OrderAddressResponse"},{"type":"null"}],"description":"Absenderadresse, falls abweichend hinterlegt; fehlt im JSON, wenn keine vorhanden ist. / Sender address if stored differently; missing from the JSON when none exists."},"is_billing_address_editable":{"oneOf":[{"type":"boolean"},{"type":"null"}],"example":true,"description":"`true`, solange zur Bestellung noch keine aktive Rechnung existiert und die Rechnungsadresse daher noch geändert werden kann; `false` danach. / `true` while the order has no active invoice yet and the billing address can therefore still be changed; `false` afterwards."},"retention":{"oneOf":[{"$ref":"#/components/schemas/OrderUserRetentionResponse"},{"type":"null"}],"description":"Rückhaltegrund, wenn die Bestellung angehalten ist; sonst `null`. / Retention reason if the order is held; otherwise `null`."},"items":{"items":{"$ref":"#/components/schemas/OrderUserItemResponse"},"type":"array","description":"Die Positionen der Bestellung, ein Eintrag je Stück. / The items of the order, one entry per piece."},"manufacturing_orders":{"items":{"$ref":"#/components/schemas/OrderUserManufacturingOrderResponse"},"type":"array","description":"Fertigungsaufträge (Teilaufträge) mit ihren Sendungen. Nur mit `tracking=true` befüllt, sonst leer. / Manufacturing orders (partial orders) with their shipments. Only filled with `tracking=true`, otherwise empty."},"payment":{"oneOf":[{"$ref":"#/components/schemas/OrderUserPaymentResponse"},{"type":"null"}],"description":"Zahlungsangaben der Bestellung; fehlt im JSON, wenn keine vorhanden sind. / Payment data of the order; missing from the JSON when none exists."},"linked_support_tickets":{"items":{"$ref":"#/components/schemas/LinkedSupportTicket"},"type":"array","description":"Support-Tickets, die mit der Bestellung verknüpft und an den Händler gerichtet waren; leere Liste, wenn keine existieren. / Support tickets linked to the order that were addressed to the merchant; empty list if none exist."},"hold_until":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Zeitpunkt, bis zu dem die Bestellung vor der Verarbeitung zurückgehalten wird; `null` = es besteht kein aktiver Halt. Grund und Regel werden nicht genannt. / Time until which the order is held back before processing; `null` = no active hold. Reason and rule are not disclosed."}},"type":"object","required":["created_at","external_reference","id","internal_reference","slug","status","updated_at"],"title":"OrderUserDetailResponse","description":"Eine Bestellung des Händlers mit Adressen, Positionen, Zahlungsangaben und Sendungen. Adressen und `payment` fehlen im JSON, wenn sie nicht vorhanden sind. / An order of the merchant with addresses, items, payment data and shipments. Addresses and `payment` are missing from the JSON when not present."},"OrderUserItemArticleResponse":{"properties":{"sku":{"type":"string","example":"TSHIRT-SCHWARZ-M","description":"Artikelnummer (SKU) der Variante / Article number (SKU) of the variant."},"product_name":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Basic T-Shirt","description":"Name des Produkts; `null`, wenn nicht verfügbar / Name of the product; `null` if not available."},"description":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Beschreibung des Produkts; `null`, wenn keine vorliegt / Description of the product; `null` if there is none."},"color":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Farbbezeichnung der Variante; `null`, wenn nicht verfügbar / Color name of the variant; `null` if not available."},"color_hex":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Farbwert der Variante als Hex-Code; `null`, wenn nicht verfügbar / Color value of the variant as a hex code; `null` if not available."},"size":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Größe der Variante; `null`, wenn nicht verfügbar / Size of the variant; `null` if not available."},"product_image_url":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"URL des Produktfotos des unbedruckten Artikels bei Lagerware; bei Auftragsware (Druck auf Bestellung) `null`, dann ist das Vorschaubild unter `processings[].preview_url` das Bild / URL of the photo of the blank article for warehouse goods; `null` for made-to-order goods, where the preview image in `processings[].preview_url` is the image."},"stock_display":{"oneOf":[{"$ref":"#/components/schemas/ItemStockDisplayResponse"},{"type":"null"}],"description":"Bestandsanzeige der Position; fehlt, wenn keine Anzeige berechnet werden kann / Stock display of the item; omitted if no display can be computed."}},"type":"object","required":["sku"],"title":"OrderUserItemArticleResponse","description":"Artikelangaben zu einer Bestellposition: Artikelnummer, Name, Farbe, Größe und Bild sowie die Bestandsanzeige. Die Antwort enthält keine internen Preise und keine Aufschlüsselung nach Produktionsstätten.\n\nArticle details of an order item: article number, name, color, size and image, plus the stock display. The response contains no internal prices and no breakdown by production site."},"OrderUserItemCreateRequest":{"properties":{"sku":{"type":"string","maxLength":100,"example":"TSHIRT-SCHWARZ-M","description":"SKU der Artikelvariante, höchstens 100 Zeichen; muss im Katalog existieren und aktiv sein. / SKU of the article variant, at most 100 characters; must exist in the catalog and be active."},"external_id":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":64,"example":"LINE-1","description":"Eigene Positionskennung des Händlers, höchstens 64 Zeichen; wird unverändert an der Position gespeichert und zurückgegeben. `null` = keine. / Own item identifier of the merchant, at most 64 characters; stored unchanged on the item and returned. `null` = none."},"item_id":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":255,"description":"Weitere eigene Positionskennung (z. B. Zeilen-ID im Shop), höchstens 255 Zeichen; wird unverändert gespeichert und zurückgegeben. `null` = keine. / Further own item identifier (e.g. line ID in the shop), at most 255 characters; stored unchanged and returned. `null` = none."},"amount":{"type":"integer","minimum":1.0,"default":1,"example":2,"description":"Stückzahl, mindestens 1, Standard 1; jedes Stück wird als eigene Position angelegt. / Quantity, at least 1, default 1; each piece is created as its own item."},"processings":{"oneOf":[{"items":{"$ref":"#/components/schemas/OrderUserItemProcessingCreateRequest"},"type":"array"},{"type":"null"}],"description":"Veredelungen (Druck, Stick …) mit Motiv und Position. `null` oder leer bei Artikeln ohne Veredelung; bei nicht veredelbaren Artikeln werden Angaben nicht übernommen. / Processings (print, embroidery …) with motif and position. `null` or empty for articles without processing; for articles that cannot be finished, entries are not taken over."}},"type":"object","required":["sku"],"title":"OrderUserItemCreateRequest","description":"Eine Bestellposition mit Artikel, Stückzahl und Veredelungen. / One order item with article, quantity and processings."},"OrderUserItemProcessingCreateRequest":{"properties":{"design_url":{"oneOf":[{"type":"string","format":"url"},{"type":"null"}],"example":"https://example.com/designs/motiv-001.png","description":"URL der Motivdatei, die das System abruft; muss eine gültige URL sein. Es muss `design_url` oder `design_reference` gesetzt sein. `null` = nicht gesetzt. / URL of the motif file that the system fetches; must be a valid URL. Either `design_url` or `design_reference` must be set. `null` = not set."},"design_reference":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Referenz auf ein bereits im System vorhandenes Motiv anstelle einer URL. Es muss `design_url` oder `design_reference` gesetzt sein. `null` = nicht gesetzt. / Reference to a motif that already exists in the system instead of a URL. Either `design_url` or `design_reference` must be set. `null` = not set."},"preview_url":{"oneOf":[{"type":"string","format":"url"},{"type":"null"}],"description":"URL eines Vorschaubilds des veredelten Artikels; muss eine gültige URL sein. `null` = keines. / URL of a preview image of the finished article; must be a valid URL. `null` = none."},"processing_type":{"$ref":"#/components/schemas/ProcessingTypeEnum","description":"Veredelungsverfahren (`ProcessingTypeEnum`), z. B. `DTG`, `DTF` oder `EMBROIDERY`. Ist für den Artikel genau ein Verfahren hinterlegt und weicht die Angabe ab, wird das hinterlegte verwendet; ein nicht konfiguriertes Verfahren ergibt 400. / Processing method (`ProcessingTypeEnum`), e.g. `DTG`, `DTF` or `EMBROIDERY`. If exactly one method is stored for the article and the value differs, the stored one is used; an unconfigured method returns 400."},"position":{"$ref":"#/components/schemas/PrintPosition","description":"Platzierung der Veredelung auf dem Artikel (`PrintPosition`), z. B. `FRONT` oder `BACK`. / Placement of the processing on the article (`PrintPosition`), e.g. `FRONT` or `BACK`."}},"type":"object","required":["position","processing_type"],"title":"OrderUserItemProcessingCreateRequest","description":"Eine Veredelung einer Position: Verfahren, Platzierung und Motiv. `design_url` oder `design_reference` ist Pflicht. / One processing of an item: method, placement and motif. `design_url` or `design_reference` is required."},"OrderUserItemProcessingResponse":{"properties":{"id":{"type":"integer","example":910001,"description":"Kennung der Veredelung / Identifier of the finishing."},"processing_type_id":{"type":"integer","example":1,"description":"Kennung des Veredelungsverfahrens im Katalog; den Klartext liefert `processing_type` / Catalog identifier of the finishing method; `processing_type` gives the readable value."},"processing_type":{"oneOf":[{"$ref":"#/components/schemas/ProcessingTypeEnum"},{"type":"null"}],"example":"DTG","description":"Veredelungsverfahren (zum Beispiel `DTG`, `DTF`, `EMBROIDERY`); `null`, wenn es keinem Wert der Liste zugeordnet ist / Finishing method (for example `DTG`, `DTF`, `EMBROIDERY`); `null` if it maps to none of the listed values."},"position":{"$ref":"#/components/schemas/PrintPosition","description":"Druckposition auf dem Artikel, zum Beispiel `FRONT` / Print position on the article, for example `FRONT`."},"preview_url":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"URL des Vorschaubildes (Mockup) des Motivs auf dem Artikel; `null`, wenn keines vorliegt / URL of the preview image (mockup) of the design on the article; `null` if there is none."},"status":{"$ref":"#/components/schemas/ItemProcessingStatus","description":"Aufbereitungsstand der Druckdatei: `PENDING`, `DOWNLOADED`, `RENDERED` oder `ERROR` / Preparation state of the print file: `PENDING`, `DOWNLOADED`, `RENDERED` or `ERROR`."}},"type":"object","required":["id","position","processing_type_id","status"],"title":"OrderUserItemProcessingResponse","description":"Veredelung einer Bestellposition: Verfahren, Druckposition, Aufbereitungsstand und Vorschaubild. Eine Position kann mehrere Veredelungen haben, zum Beispiel Vorder- und Rückseite.\n\nFinishing of an order item: method, print position, preparation state and preview image. An item can have several finishings, for example front and back."},"OrderUserItemResponse":{"properties":{"id":{"type":"integer","example":900101,"description":"Kennung der Position / Identifier of the item."},"order_id":{"type":"integer","example":900001,"description":"Kennung der Bestellung, zu der die Position gehört / Identifier of the order the item belongs to."},"product_variant_id":{"type":"integer","example":3001,"description":"Kennung der bestellten Produktvariante im Katalog; die Artikelnummer steht in `article.sku` / Catalog identifier of the ordered product variant; the article number is in `article.sku`."},"item_group":{"type":"string","format":"uuid","example":"0f8fad5b-d9cb-469f-a165-70867728950e","description":"UUID, die die Stücke einer Bestellzeile zusammenfasst (Menge größer 1 ergibt mehrere Positionen mit derselben UUID) / UUID that groups the pieces of one order line (a quantity above 1 yields several items with the same UUID)."},"external_id":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"LINE-1","description":"Eigene Kennung des Händlers für die Position (bis 64 Zeichen), unverändert aus der Bestellung übernommen; `null`, wenn nicht angegeben / Merchant own identifier for the item (up to 64 characters), taken over unchanged from the order; `null` if not given."},"item_id":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Weitere eigene Kennung des Händlers (bis 255 Zeichen), unverändert aus der Bestellung übernommen, zum Beispiel eine Positionskennung des Shops; `null`, wenn nicht angegeben / Further merchant own identifier (up to 255 characters), taken over unchanged from the order, for example a line item identifier of the shop; `null` if not given."},"sales_price":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Verkaufspreis der Position als ganze Zahl; bei über die Händler-API angelegten Bestellungen nicht gesetzt (`null`) / Selling price of the item as an integer; not set (`null`) for orders created through the merchant API."},"product_price":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":1290,"description":"Preis der Position (Artikel ohne Veredelung) in Cent, netto; `null`, wenn kein Preis vorliegt / Price of the item (article without finishing) in cents, net; `null` if no price is available."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt, zu dem die Position angelegt wurde (ISO 8601, mit Zeitzone) / Time the item was created (ISO 8601, with time zone)."},"processings":{"oneOf":[{"items":{"$ref":"#/components/schemas/OrderUserItemProcessingResponse"},"type":"array"},{"type":"null"}],"description":"Veredelungen der Position; `null`, wenn sie nicht geladen wurden, leer bei Lagerware ohne Veredelung / Finishings of the item; `null` if not loaded, empty for warehouse goods without finishing."},"article":{"oneOf":[{"$ref":"#/components/schemas/OrderUserItemArticleResponse"},{"type":"null"}],"description":"Artikelangaben zur Position; fehlt, wenn nicht geladen / Article details of the item; omitted if not loaded."}},"type":"object","required":["created_at","external_id","id","item_group","item_id","order_id","product_variant_id"],"title":"OrderUserItemResponse","description":"Eine Position einer Bestellung. Wird ein Artikel mit Menge größer 1 bestellt, entsteht je Stück eine Position; alle Stücke dieser Bestellzeile teilen dieselbe `item_group`.\n\nOne item of an order. If an article is ordered with a quantity above 1, one item is created per piece; all pieces of that order line share the same `item_group`."},"OrderUserItemsVariantSwapResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/OrderUserItemResponse"},"type":"array","description":"Die getauschten Positionen / The swapped items."},"restart_triggered":{"type":"boolean","example":true,"description":"`true`, wenn der Neustart im selben Aufruf gelaufen ist / `true` if the restart ran within the same call."},"restart_required":{"type":"boolean","example":false,"description":"`true`, wenn der Neustart verweigert wurde und noch aussteht; der Tausch bleibt bestehen / `true` if the restart was refused and is still outstanding; the swap stands."},"restart_error":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Code, warum der Neustart nicht lief; `null`, wenn er lief / Code why the restart did not run; `null` if it ran."},"restart_detail":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Erklärender Text zu `restart_error`; `null`, wenn der Neustart lief / Explanatory text for `restart_error`; `null` if the restart ran."}},"type":"object","required":["items","restart_required","restart_triggered"],"title":"OrderUserItemsVariantSwapResponse"},"OrderUserManufacturingOrderResponse":{"properties":{"id":{"type":"integer","example":920001,"description":"ID des Fertigungsauftrags; stabiler Schlüssel zur Zuordnung. / ID of the manufacturing order; stable key for matching."},"manufacturer_name":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Musterproduktion GmbH","description":"Anzeigename des Produktionspartners; `null`, wenn er nicht aufgelöst werden kann. / Display name of the production partner; `null` if it cannot be resolved."},"shipments":{"items":{"$ref":"#/components/schemas/ShipmentSummary"},"type":"array","description":"Sendungen des Fertigungsauftrags mit Tracking; nur mit `tracking=true` befüllt, leer = noch keine Sendung. / Shipments of the manufacturing order with tracking; only filled with `tracking=true`, empty = no shipment yet."}},"type":"object","required":["id"],"title":"OrderUserManufacturingOrderResponse","description":"Ein Fertigungsauftrag (Teilauftrag) der Bestellung, reduziert auf Name des Produktionspartners und Sendungen. / One manufacturing order (partial order) of the order, reduced to the production partner name and shipments."},"OrderUserPageResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/OrderUserResponse"},"type":"array","description":"Die Bestellungen dieser Seite (Kopfdaten ohne Positionen). / The orders of this page (header without line items)."},"limit":{"type":"integer","example":50,"description":"Angewendete Seitengröße (nach Begrenzung auf 1 bis 200). / Applied page size (after clamping to 1 to 200)."},"offset":{"type":"integer","example":0,"description":"Angewendeter Offset (nach Begrenzung auf mindestens 0). / Applied offset (after clamping to at least 0)."},"total_count":{"type":"integer","example":2,"description":"Gesamtzahl der Treffer über alle Seiten, unabhängig von `limit` und `offset`. / Total number of matches across all pages, independent of `limit` and `offset`."}},"type":"object","required":["items","limit","offset","total_count"],"title":"OrderUserPageResponse","description":"Eine Seite von Bestellungen mit Angaben zur Seitenbildung. / One page of orders with pagination details."},"OrderUserPaymentResponse":{"properties":{"integration_payment_id":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"0192f3a4-5b6c-7d8e-9f01-23456789abcd","description":"Zahlungskennung der Bestellung; bei per API angelegten Bestellungen vom System vergeben. `null` = nicht vorhanden. / Payment identifier of the order; assigned by the system for orders created via the API. `null` = not present."},"integration_payment_reference":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"SHOP-10045","description":"Zahlungsreferenz; bei per API angelegten Bestellungen die `external_reference`, sonst die Zahlungskennung. `null` = nicht vorhanden. / Payment reference; for orders created via the API the `external_reference`, otherwise the payment identifier. `null` = not present."},"integration_payment_timestamp":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der Zahlungsangabe, ISO 8601 mit Zeitzone; bei per API angelegten Bestellungen der Zeitpunkt der Anlage. `null` = nicht vorhanden. / Time of the payment entry, ISO 8601 with time zone; for orders created via the API the time of creation. `null` = not present."},"integration_payment_gateway":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"collective_invoice","description":"Kennung des Zahlungswegs, z. B. `collective_invoice` oder `wallet`. `null` = nicht vorhanden. / Identifier of the payment route, e.g. `collective_invoice` or `wallet`. `null` = not present."}},"type":"object","required":[],"title":"OrderUserPaymentResponse","description":"Zahlungsangaben, die an der Bestellung hinterlegt sind. / Payment data stored on the order."},"OrderUserResponse":{"properties":{"id":{"type":"integer","example":900002,"description":"Kennung der Bestellung; sie steht in den Pfaden `/api/orders/{order_id}` / Identifier of the order; used in the paths `/api/orders/{order_id}`."},"slug":{"type":"string","example":"CL-8M2QX4A","description":"Kurzkennung der Bestellung zum Nennen im Gespräch, Präfix `CL-` und 7 Zeichen (ältere Bestellungen können das Präfix `CO-` tragen) / Short identifier of the order for use in conversation, prefix `CL-` and 7 characters (older orders can carry the prefix `CO-`)."},"internal_reference":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Zusätzliche Referenz der Bestellung, bis 100 Zeichen; über die Händler-API nicht setzbar, daher meist `null` / Additional reference of the order, up to 100 characters; cannot be set through the merchant API, so usually `null`."},"external_reference":{"type":"string","example":"SHOP-10046","description":"Eigene Bestellnummer des Händlers (bis 100 Zeichen), wie beim Anlegen angegeben. Wurde keine angegeben, vergibt das System eine UUID / Own order number of the merchant (up to 100 characters), as given when the order was created. If none was given, the system assigns a UUID."},"reordered_from_order_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":900001,"description":"Kennung der Ursprungsbestellung, wenn diese Bestellung eine Nachbestellung ist (`POST /api/orders/{order_id}/reorder`); sonst `null` / Identifier of the source order if this order is a reorder (`POST /api/orders/{order_id}/reorder`); otherwise `null`."},"designer_id":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"4711","description":"Kundennummer des Händlers (`customer_id`) als Zeichenkette; sie stammt aus dem Token / Customer number of the merchant (`customer_id`) as a string; it is taken from the token."},"status":{"$ref":"#/components/schemas/OrderStatus","description":"Bestellstatus, siehe Schema `OrderStatus` / Order status, see schema `OrderStatus`."},"settlement_method":{"oneOf":[{"$ref":"#/components/schemas/SettlementMethod"},{"type":"null"}],"description":"Abrechnungsart der Bestellung (`WALLET`, `EXTERNAL_PAYMENT`, `NONE`); `null` bei Bestellungen, die vor Einführung des Feldes angelegt wurden / Settlement method of the order (`WALLET`, `EXTERNAL_PAYMENT`, `NONE`); `null` for orders created before the field existed."},"created_at":{"type":"string","format":"date-time","example":"2026-01-16T09:12:00Z","description":"Zeitpunkt der Anlage (ISO 8601, mit Zeitzone) / Time the order was created (ISO 8601, with time zone)."},"updated_at":{"type":"string","format":"date-time","example":"2026-01-16T09:12:30Z","description":"Zeitpunkt der letzten Änderung an der Bestellung (ISO 8601, mit Zeitzone) / Time of the last change to the order (ISO 8601, with time zone)."},"delivery_address":{"oneOf":[{"$ref":"#/components/schemas/OrderAddressResponse"},{"type":"null"}],"description":"Lieferadresse (Empfänger der Sendung); fehlt, wenn nicht geladen / Delivery address (recipient of the shipment); omitted if not loaded."},"billing_address":{"oneOf":[{"$ref":"#/components/schemas/OrderAddressResponse"},{"type":"null"}],"description":"Rechnungsadresse; fehlt, wenn nicht geladen / Billing address; omitted if not loaded."},"sender_address":{"oneOf":[{"$ref":"#/components/schemas/OrderAddressResponse"},{"type":"null"}],"description":"Absenderadresse der Sendung; über die Händler-Bestellanlage nicht setzbar und daher meist nicht vorhanden / Sender address of the shipment; cannot be set through merchant order creation and is therefore usually not present."},"is_billing_address_editable":{"oneOf":[{"type":"boolean"},{"type":"null"}],"description":"`true`, solange die Rechnungsadresse noch geändert werden kann, also noch keine aktive Rechnung zur Bestellung existiert; das Land lässt sich nach dem ersten Setzen nicht mehr ändern. `null` in Listen und Suchergebnissen, berechnet wird der Wert nur in der Detailantwort / `true` while the billing address can still be changed, that is, no active invoice exists for the order yet; the country cannot be changed once set. `null` in lists and search results; the value is only computed in the detail response."},"retention":{"oneOf":[{"$ref":"#/components/schemas/OrderUserRetentionResponse"},{"type":"null"}],"description":"Rückhaltegrund, wenn die Bestellung angehalten ist; sonst `null` / Retention reason if the order is held; otherwise `null`."}},"type":"object","required":["created_at","external_reference","id","internal_reference","slug","status","updated_at"],"title":"OrderUserResponse","description":"Bestellung in der Händlersicht (ohne Positionen). Das Feld `status` zeigt den Stand, siehe `OrderStatus`; bei einer angehaltenen Bestellung nennt `retention` den Grund. Die Adressen (`delivery_address`, `billing_address`, `sender_address`) fehlen in der Antwort, wenn sie nicht geladen wurden oder nicht vorhanden sind, statt `null` zu sein.\n\nOrder in the merchant view (without items). The field `status` shows the state, see `OrderStatus`; for a held order `retention` names the reason. The addresses (`delivery_address`, `billing_address`, `sender_address`) are omitted from the response when they are not loaded or do not exist, instead of being `null`."},"OrderUserRetentionReasonResponse":{"properties":{"id":{"type":"integer","example":12,"description":"Stabiler Schlüssel des Grundes; passt zu `retention.reason_id` an Bestellungen und zu den Listenfiltern. / Stable key of the reason; matches `retention.reason_id` on orders and the list filters."},"name":{"type":"string","example":"Fehler - Produkt","description":"Anzeigename des Grundes; kann sich ändern und eignet sich nicht für Programmlogik. / Display name of the reason; may change and is not suitable for program logic."}},"type":"object","required":["id","name"],"title":"OrderUserRetentionReasonResponse","description":"Ein aktiver Rückhaltegrund. / One active retention reason."},"OrderUserRetentionResponse":{"properties":{"reason_id":{"type":"integer","example":7,"description":"Kennung des Rückhaltegrundes; stabiler Schlüssel zum Verzweigen. Die Liste liefert `GET /api/orders/retention-reasons` / Identifier of the retention reason; the stable key to branch on. The list is returned by `GET /api/orders/retention-reasons`."},"reason_name":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Fehler - Adresse","description":"Anzeigename des Grundes; kann sich ändern, nicht zum Verzweigen verwenden. `null`, wenn der Name in dieser Antwort nicht aufgelöst wurde / Display name of the reason; can change, do not branch on it. `null` if the name was not resolved in this response."}},"type":"object","required":["reason_id"],"title":"OrderUserRetentionResponse","description":"Rückhaltegrund einer angehaltenen Bestellung. Der Block steht an der Bestellung, solange ein Grund vermerkt ist (üblicherweise bei Status `CHECK`), und ist sonst `null`.\n\nRetention reason of a held order. The block is present on the order as long as a reason is recorded (usually with status `CHECK`) and is `null` otherwise."},"PrintPosition":{"type":"string","enum":["FRONT","BACK","SLEEVE_LEFT","SLEEVE_RIGHT","BACK_INSIDE","COMBINED","FRONT_SEGMENT","BACK_SEGMENT","FRONT_SEGMENT_PART","BACK_SEGMENT_PART","FRONT_HEM","BACK_HEM","SLEEVE","SLEEVE_HEM","NECK_OUTSIDE","NECK_INSIDE"],"title":"PrintPosition","description":"Position der Veredelung auf dem Artikel.\n\n- `FRONT`: Vorderseite.\n- `BACK`: Rückseite.\n- `SLEEVE_LEFT`: linker Ärmel.\n- `SLEEVE_RIGHT`: rechter Ärmel.\n- `BACK_INSIDE`: Innenseite Rücken.\n- `COMBINED`: kombiniert.\n- `FRONT_SEGMENT`: Vorderseite, Segment.\n- `BACK_SEGMENT`: Rückseite, Segment.\n- `FRONT_SEGMENT_PART`: Vorderseite, Segment-Teil.\n- `BACK_SEGMENT_PART`: Rückseite, Segment-Teil.\n- `FRONT_HEM`: Vorderseite, Saum.\n- `BACK_HEM`: Rückseite, Saum.\n- `SLEEVE`: Ärmel.\n- `SLEEVE_HEM`: Ärmel, Saum.\n- `NECK_OUTSIDE`: Kragen, Außenseite.\n- `NECK_INSIDE`: Kragen, Innenseite.\n\nWelche Positionen ein Artikel bietet und wie groß die Druckfläche je Position ist, hängt vom Artikel und vom Verfahren ab.\n\nPosition of the finishing on the article.\n\n- `FRONT`: front.\n- `BACK`: back.\n- `SLEEVE_LEFT`: left sleeve.\n- `SLEEVE_RIGHT`: right sleeve.\n- `BACK_INSIDE`: inside of the back.\n- `COMBINED`: combined.\n- `FRONT_SEGMENT`: front, segment.\n- `BACK_SEGMENT`: back, segment.\n- `FRONT_SEGMENT_PART`: front, segment part.\n- `BACK_SEGMENT_PART`: back, segment part.\n- `FRONT_HEM`: front, hem.\n- `BACK_HEM`: back, hem.\n- `SLEEVE`: sleeve.\n- `SLEEVE_HEM`: sleeve, hem.\n- `NECK_OUTSIDE`: collar, outside.\n- `NECK_INSIDE`: collar, inside.\n\nWhich positions an article offers and the print area per position depend on the article and the method."},"ProcessingTypeEnum":{"type":"string","enum":["DTG","DTF","EMBROIDERY","SEWING","SUBLIMATION","DIGITAL"],"title":"ProcessingTypeEnum","description":"Veredelungsverfahren einer Position.\n\n- `DTG`: Direct-to-Garment, Direktdruck auf Textil.\n- `DTF`: Direct-to-Film, Druck über Transferfolie.\n- `EMBROIDERY`: Stickerei.\n- `SEWING`: Nähen.\n- `SUBLIMATION`: Sublimationsdruck.\n- `DIGITAL`: Digitaldruck.\n\nWelche Verfahren und Positionen ein Artikel unterstützt, hängt vom Artikel ab: nicht jede Kombination aus Verfahren und Druckposition ist für jeden Artikel verfügbar.\n\nFinishing method of an item.\n\n- `DTG`: direct-to-garment printing.\n- `DTF`: direct-to-film printing via transfer film.\n- `EMBROIDERY`: embroidery.\n- `SEWING`: sewing.\n- `SUBLIMATION`: sublimation printing.\n- `DIGITAL`: digital printing.\n\nWhich methods and positions an article supports depends on the article: not every combination of method and print position is available for every article."},"ProductBestsellerResponse":{"properties":{"id":{"type":"integer","example":1001,"description":"Eindeutige ID des Produkts, Parameter `product_id` der Produkt- und Variantenabfragen / Unique product ID."},"name":{"type":"string","example":"Muster Basic T-Shirt","description":"Produktname, wie er im Katalog angezeigt wird / Product name as shown in the catalog."},"description":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Unisex T-Shirt aus Baumwolle","description":"Beschreibungstext des Produkts, `null` wenn keiner hinterlegt ist / Product description text, `null` if none is stored."},"type_id":{"type":"integer","example":12,"description":"ID der Warengruppe (Produkttyp), der das Produkt zugeordnet ist / ID of the product type (category) the product belongs to."},"fulfillment_type":{"$ref":"#/components/schemas/FulfillmentType","description":"Fertigungsart des Produkts: `ON_DEMAND` (je Bestellung bedruckt), `WAREHOUSE` (Lagerartikel) oder `ADDITIONAL_PRODUCT` (Beistellartikel) / Fulfillment type of the product, see enum values."},"production_type":{"$ref":"#/components/schemas/ProductionType","description":"Produktionsart: `PRODUCEABLE` (regulär) oder `INVOICE` (Rechnungsposition, nur bei Lagerartikeln) / Production type: `PRODUCEABLE` (regular) or `INVOICE` (invoice line, warehouse articles only)."},"status":{"$ref":"#/components/schemas/ProductStatus","description":"Zustand des Produkts: `ACTIVE` oder `INACTIVE`; die Listen enthalten beide Zustände / Product state: `ACTIVE` or `INACTIVE`; the lists contain both states."},"is_organic":{"type":"boolean","example":true,"description":"Kennzeichen, ob das Produkt als Bio-Ware geführt wird / Flag whether the product is listed as organic."},"material":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"100 % Baumwolle","description":"Materialangabe, z. B. `100 % Baumwolle`; `null` wenn keine hinterlegt ist / Material information, for example `100 % cotton`; `null` if none is stored."},"sku":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"MUSTER-TS-01","description":"Artikelnummer des Produkts (Produkt-SKU, nicht die Varianten-SKU); `null` wenn keine vergeben ist / Product-level article number (not the variant SKU); `null` if none is assigned."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der Anlage im Format ISO 8601 mit Zeitzone (UTC) / Creation time, ISO 8601 with time zone (UTC)."},"updated_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der letzten Änderung im Format ISO 8601 mit Zeitzone (UTC) / Time of the last change, ISO 8601 with time zone (UTC)."},"image_url":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"https://example.com/bilder/muster-shirt-front.jpg","description":"URL des repräsentativen Katalogbilds, abgeleitet vom Bild einer Variante; `null` wenn keine Variante ein Bild hat / URL of the representative catalog image derived from a variant image; `null` if no variant has an image."},"images":{"items":{"$ref":"#/components/schemas/ProductImageUserResponse"},"type":"array","description":"Bilder des Produkts in Anzeigereihenfolge; leer, wenn keine hinterlegt sind / Images of the product in display order; empty if none are stored."},"rank":{"type":"integer","example":1,"description":"Rang des Produkts, 1 = am häufigsten bestellt (gezählt nach Händlern der letzten 30 Tage); keine Mengenangabe / Rank of the product, 1 = ordered most often (counted by merchants in the last 30 days); no quantity."}},"type":"object","required":["created_at","description","fulfillment_type","id","is_organic","material","name","production_type","rank","sku","status","type_id","updated_at"],"title":"ProductBestsellerResponse","description":"Ein meistbestelltes Produkt: die Produktfelder plus Rang / A best-selling product: the product fields plus its rank."},"ProductColorResponse":{"properties":{"id":{"type":"integer","example":21,"description":"ID der Farbe; entspricht dem Feld `color_id` der Varianten / Color ID; matches the `color_id` field of variants."},"primary_color":{"type":"string","example":"Navy","description":"Bezeichnung der Hauptfarbe, z. B. `Navy` / Name of the primary color, for example `Navy`."},"primary_hex":{"type":"string","example":"#1f2a44","description":"Hex-Farbwert der Hauptfarbe zur Darstellung, z. B. `#1f2a44` / Hex value of the primary color for display, for example `#1f2a44`."},"secondary_color":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Bezeichnung der zweiten Farbe bei zweifarbigen Artikeln; `null` bei einfarbigen / Name of the secondary color for two-tone articles; `null` for single-color articles."},"secondary_hex":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Hex-Farbwert der zweiten Farbe; `null` bei einfarbigen Artikeln / Hex value of the secondary color; `null` for single-color articles."}},"type":"object","required":["id","primary_color","primary_hex","secondary_color","secondary_hex"],"title":"ProductColorResponse","description":"Eine Farbe des Katalogs, auf die Varianten über `color_id` verweisen / A catalog color that variants reference through `color_id`."},"ProductHighlightsResponse":{"properties":{"newest":{"items":{"$ref":"#/components/schemas/ProductUserResponse"},"type":"array","description":"Bis zu vier zuletzt angelegte Produkte, neueste zuerst / Up to four most recently created products, newest first."},"bestsellers":{"items":{"$ref":"#/components/schemas/ProductBestsellerResponse"},"type":"array","description":"Bis zu vier meistbestellte Produkte nach Rang aufsteigend; kann weniger Einträge oder keine enthalten / Up to four best-selling products by ascending rank; may hold fewer entries or none."}},"type":"object","required":["bestsellers","newest"],"title":"ProductHighlightsResponse","description":"Kacheln für die Händler-Startseite aus dem gemeinsamen Katalog / Home page tiles from the shared catalog."},"ProductImageUserResponse":{"properties":{"id":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":4711,"description":"Kennung des Bildeintrags; `null`, wenn keine vergeben ist / Identifier of the image entry; `null` if none is assigned."},"source_url":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"https://example.com/bilder/muster-shirt-front.jpg","description":"URL des Bilds; `null`, wenn der Eintrag keine Bild-URL trägt / Image URL; `null` if the entry carries no image URL."},"is_production":{"type":"boolean","example":false,"description":"`true`, wenn dies das Produktionsbild ist (die Druckvorlage), `false` für Anzeigebilder / `true` if this is the production image (the print master), `false` for display images."},"sort_order":{"type":"integer","example":0,"description":"Position in der Anzeigereihenfolge, aufsteigend sortiert / Position in the display order, ascending."}},"type":"object","required":["is_production","sort_order"],"title":"ProductImageUserResponse","description":"Ein Bildeintrag eines Produkts oder einer Variante / One image entry of a product or variant."},"ProductSafetyStockOverrideResponse":{"properties":{"mode":{"$ref":"#/components/schemas/SafetyStockOverrideMode","description":"`NONE` = kein Puffer trotz Standard, `CUSTOM` = eigene Staffel in `rule` / `NONE` = no buffer despite the default, `CUSTOM` = own tiers in `rule`."},"rule":{"oneOf":[{"$ref":"#/components/schemas/SafetyStockRuleResponse"},{"type":"null"}],"description":"Eigene Staffel bei `CUSTOM`; `null` bei `NONE` / Own tiers for `CUSTOM`; `null` for `NONE`."},"updated_at":{"type":"string","format":"date-time","description":"Zeitpunkt der letzten Änderung (UTC, ISO 8601) / Time of the last change (UTC, ISO 8601)."},"updated_by":{"type":"string","description":"Kennung des letzten Änderers, z. B. `user:4711` oder `customer-key:<ID>` / Identifier of the last editor, e.g. `user:4711` or `customer-key:<ID>`."}},"type":"object","required":["mode","rule","updated_at","updated_by"],"title":"ProductSafetyStockOverrideResponse","description":"Die Ausnahme vom Standard an einem Artikel.\n\nThe override of the default on one product."},"ProductSafetyStockResponse":{"properties":{"product_id":{"type":"integer","example":120045,"description":"ID des Lagerartikels / ID of the warehouse product."},"customer_id":{"type":"integer","example":100123,"description":"Kunden-ID des Besitzers / Customer ID of the owner."},"override":{"oneOf":[{"$ref":"#/components/schemas/ProductSafetyStockOverrideResponse"},{"type":"null"}],"description":"Ausnahme am Artikel; `null` = keine, der Standard gilt / Override on the product; `null` = none, the default applies."},"default":{"$ref":"#/components/schemas/CustomerSafetyStockResponse","description":"Standard des Händlers, auch wenn er ausgeschaltet ist / The merchant default, also if switched off."},"effective":{"oneOf":[{"$ref":"#/components/schemas/SafetyStockRuleResponse"},{"type":"null"}],"description":"Wirksame Staffel; `null` = kein Puffer (`source` `NONE`) / Tiers that apply; `null` = no buffer (`source` `NONE`)."},"source":{"type":"string","enum":["OVERRIDE","DEFAULT","NONE"],"example":"DEFAULT","description":"Herkunft der wirksamen Staffel: `OVERRIDE` (eigene Staffel am Artikel), `DEFAULT` (Standard) oder `NONE` (kein Puffer: Ausnahme `NONE` oder kein eingeschalteter Standard) / Origin of the tiers that apply: `OVERRIDE`, `DEFAULT` or `NONE` (no buffer: override `NONE` or no default switched on)."}},"type":"object","required":["customer_id","default","effective","override","product_id","source"],"title":"ProductSafetyStockResponse","description":"Sicherheitsbestand eines Artikels: Ausnahme, Standard des Besitzers und die daraus wirksame Staffel.\n\nSafety stock of one product: override, the owner's default and the tiers that apply as a result."},"ProductSizeResponse":{"properties":{"id":{"type":"integer","example":3,"description":"ID der Größe; entspricht dem Feld `size_id` der Varianten / Size ID; matches the `size_id` field of variants."},"name":{"type":"string","example":"M","description":"Bezeichnung der Größe, z. B. `M` oder `XL` / Name of the size, for example `M` or `XL`."}},"type":"object","required":["id","name"],"title":"ProductSizeResponse","description":"Eine Größe des Katalogs, auf die Varianten über `size_id` verweisen / A catalog size that variants reference through `size_id`."},"ProductStatus":{"type":"string","enum":["ACTIVE","INACTIVE"],"title":"ProductStatus","description":"Status eines Produkts oder einer Variante im Katalog.\n\n- `ACTIVE`: bestellbar.\n- `INACTIVE`: nicht bestellbar. Eine inaktive Variante lässt sich nicht als neue Position hinzufügen, nicht als Ziel eines Variantentauschs verwenden und nicht nachbestellen. Neu angelegte Lagerartikel sind zunächst `INACTIVE` und werden mit der Freigabe nach der Prüfung `ACTIVE`.\n\nStatus of a product or variant in the catalog.\n\n- `ACTIVE`: can be ordered.\n- `INACTIVE`: cannot be ordered. An inactive variant cannot be added as a new item, used as the target of a variant swap or reordered. Newly created warehouse articles start as `INACTIVE` and become `ACTIVE` once approved after review."},"ProductUserResponse":{"properties":{"id":{"type":"integer","example":1001,"description":"Eindeutige ID des Produkts, Parameter `product_id` der Produkt- und Variantenabfragen / Unique product ID."},"name":{"type":"string","example":"Muster Basic T-Shirt","description":"Produktname, wie er im Katalog angezeigt wird / Product name as shown in the catalog."},"description":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Unisex T-Shirt aus Baumwolle","description":"Beschreibungstext des Produkts, `null` wenn keiner hinterlegt ist / Product description text, `null` if none is stored."},"type_id":{"type":"integer","example":12,"description":"ID der Warengruppe (Produkttyp), der das Produkt zugeordnet ist / ID of the product type (category) the product belongs to."},"fulfillment_type":{"$ref":"#/components/schemas/FulfillmentType","description":"Fertigungsart des Produkts: `ON_DEMAND` (je Bestellung bedruckt), `WAREHOUSE` (Lagerartikel) oder `ADDITIONAL_PRODUCT` (Beistellartikel) / Fulfillment type of the product, see enum values."},"production_type":{"$ref":"#/components/schemas/ProductionType","description":"Produktionsart: `PRODUCEABLE` (regulär) oder `INVOICE` (Rechnungsposition, nur bei Lagerartikeln) / Production type: `PRODUCEABLE` (regular) or `INVOICE` (invoice line, warehouse articles only)."},"status":{"$ref":"#/components/schemas/ProductStatus","description":"Zustand des Produkts: `ACTIVE` oder `INACTIVE`; die Listen enthalten beide Zustände / Product state: `ACTIVE` or `INACTIVE`; the lists contain both states."},"is_organic":{"type":"boolean","example":true,"description":"Kennzeichen, ob das Produkt als Bio-Ware geführt wird / Flag whether the product is listed as organic."},"material":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"100 % Baumwolle","description":"Materialangabe, z. B. `100 % Baumwolle`; `null` wenn keine hinterlegt ist / Material information, for example `100 % cotton`; `null` if none is stored."},"sku":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"MUSTER-TS-01","description":"Artikelnummer des Produkts (Produkt-SKU, nicht die Varianten-SKU); `null` wenn keine vergeben ist / Product-level article number (not the variant SKU); `null` if none is assigned."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der Anlage im Format ISO 8601 mit Zeitzone (UTC) / Creation time, ISO 8601 with time zone (UTC)."},"updated_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der letzten Änderung im Format ISO 8601 mit Zeitzone (UTC) / Time of the last change, ISO 8601 with time zone (UTC)."},"image_url":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"https://example.com/bilder/muster-shirt-front.jpg","description":"URL des repräsentativen Katalogbilds, abgeleitet vom Bild einer Variante; `null` wenn keine Variante ein Bild hat / URL of the representative catalog image derived from a variant image; `null` if no variant has an image."},"images":{"items":{"$ref":"#/components/schemas/ProductImageUserResponse"},"type":"array","description":"Bilder des Produkts in Anzeigereihenfolge; leer, wenn keine hinterlegt sind / Images of the product in display order; empty if none are stored."}},"type":"object","required":["created_at","description","fulfillment_type","id","is_organic","material","name","production_type","sku","status","type_id","updated_at"],"title":"ProductUserResponse","description":"Ein Produkt des Katalogs (Hülle über Varianten) / A catalog product (container of variants)."},"ProductVariantUserPageResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ProductVariantUserResponse"},"type":"array","description":"Varianten dieser Seite in der Sortierung der Anfrage / Variants of this page in the order of the request."},"limit":{"type":"integer","example":20,"description":"Verwendete Seitengröße; die auf 1 bis 100 begrenzte Angabe, nicht der Rohwert der Anfrage / Page size used; the value clamped to 1 to 100, not the raw request value."},"offset":{"type":"integer","example":0,"description":"Verwendete Startposition (mindestens 0) / Start position used (at least 0)."},"total_count":{"type":"integer","example":1,"description":"Anzahl aller Treffer der Filter über alle Seiten; die nächste Seite beginnt bei `offset + limit`, solange das kleiner ist / Number of all matches of the filters across all pages; the next page starts at `offset + limit` while that is smaller."}},"type":"object","required":["items","limit","offset","total_count"],"title":"ProductVariantUserPageResponse","description":"Eine Seite der Variantenliste mit Paginierungsangaben / One page of the variant list with pagination data."},"ProductVariantUserResponse":{"properties":{"id":{"type":"integer","example":5001,"description":"Eindeutige ID der Variante, Parameter `variant_id` / Unique variant ID."},"product_id":{"type":"integer","example":1001,"description":"ID des zugehörigen Produkts (siehe `GET /api/products/{product_id}`) / ID of the parent product."},"color_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":21,"description":"ID der Farbe (siehe `GET /api/product-colors/{color_id}`); `null` bei Varianten ohne Farbe / Color ID; `null` for variants without a color."},"size_id":{"type":"integer","example":3,"description":"ID der Größe (siehe `GET /api/product-sizes/{size_id}`) / Size ID."},"sku":{"type":"string","example":"MUSTER-TS-01_Navy_M","description":"Eindeutige Artikelnummer der Variante (Farbe und Größe), Schlüssel für `GET /api/product-variants/by-sku/{sku}` und für Bestellungen / Unique article number of the variant (color and size); key for the by-SKU lookup and for orders."},"description":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Beschreibungstext der Variante; `null` wenn keiner hinterlegt ist / Variant description text; `null` if none is stored."},"product_image_url":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"https://example.com/bilder/muster-shirt-navy.jpg","description":"URL des Bilds dieser Variante; `null` wenn keines hinterlegt ist / URL of this variant's image; `null` if none is stored."},"status":{"$ref":"#/components/schemas/ProductStatus","description":"Zustand der Variante: `ACTIVE` oder `INACTIVE`; die Listen enthalten beide / Variant state: `ACTIVE` or `INACTIVE`; the lists contain both."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der Anlage im Format ISO 8601 mit Zeitzone (UTC) / Creation time, ISO 8601 with time zone (UTC)."},"updated_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der letzten Änderung im Format ISO 8601 mit Zeitzone (UTC) / Time of the last change, ISO 8601 with time zone (UTC)."},"stock_total":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":120,"description":"Summe der Bestände der Variante bei Bestandsführung (Stück); nur in den Listen mit `stock=true` gesetzt, dort 0 ohne Bestand, sonst `null`. Für die freie Menge `available` verwenden / Sum of the variant's tracked stocks (pieces); set only in the lists with `stock=true` (0 without stock), otherwise `null`. Use `available` for the free quantity."},"gross_stock":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":120,"description":"Gesamtbestand der Variante in Stück vor Abzug der Reservierung; `null` ohne `stock=true` (Liste) bzw. ohne Bestandsdaten. Bei Auftragsware ohne Bestandsführung kann der Wert 0 sein, dann gilt `stock_display` / Total stock of the variant in pieces before reservations; `null` without `stock=true` (lists) or without stock data. For made-to-order articles without tracked stock it can be 0; then `stock_display` applies."},"reserved":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":20,"description":"Für offene Bestellungen reservierte Menge in Stück; `null` ohne `stock=true` (Liste) bzw. ohne Bestandsdaten / Quantity reserved for open orders in pieces; `null` without `stock=true` (lists) or without stock data."},"available":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":100,"description":"Verfügbare Menge in Stück: `gross_stock` minus `reserved`, nie negativ; bei einem angewendeten Sicherheitsbestand zusätzlich um diesen verringert. `null` ohne `stock=true` (Liste) bzw. ohne Bestandsdaten / Available quantity in pieces: `gross_stock` minus `reserved`, never negative; reduced by a safety stock where one applies. `null` without `stock=true` (lists) or without stock data."},"available_unbuffered":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Verfügbare Menge vor Abzug des Sicherheitsbestands; nur vorhanden, wenn ein Sicherheitsbestand angewendet wird, sonst fehlt das Feld / Available quantity before the safety stock; present only when a safety stock applies, otherwise the field is omitted."},"safety_stock":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Abgezogener Sicherheitsbestand in Stück; nur vorhanden, wenn ein Sicherheitsbestand angewendet wird, sonst fehlt das Feld / Deducted safety stock in pieces; present only when a safety stock applies, otherwise the field is omitted."},"warehouse_color":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Eigene Farbbezeichnung eines Lagerartikels; `null`, wenn nicht hinterlegt (dann gilt die Katalogfarbe über `color_id`) / Own color label of a warehouse article; `null` if not stored (the catalog color via `color_id` applies)."},"warehouse_size":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Eigene Größenbezeichnung eines Lagerartikels; `null`, wenn nicht hinterlegt (dann gilt die Katalogröße über `size_id`) / Own size label of a warehouse article; `null` if not stored (the catalog size via `size_id` applies)."},"size_label":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"M","description":"Anzeigebezeichnung der Größe: `warehouse_size`, sonst der Name der Katalogröße / Display label of the size: `warehouse_size`, otherwise the catalog size name."},"color_label":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Navy","description":"Anzeigebezeichnung der Farbe: `warehouse_color`, sonst die Hauptfarbe der Katalogfarbe; `null` ohne Farbe / Display label of the color: `warehouse_color`, otherwise the primary color of the catalog color; `null` without a color."},"stock_display":{"oneOf":[{"$ref":"#/components/schemas/ItemStockDisplayResponse"},{"type":"null"}],"description":"Lieferbarkeit für die Anzeige: `kind` `IN_STOCK` mit `available_balance` oder `JIT` (Auftragsware); nur in den Listen mit `stock=true`, `null` für Rechnungspositionen oder ohne Bestandszeile / Deliverability for display: `kind` `IN_STOCK` with `available_balance` or `JIT` (made to order); only in the lists with `stock=true`, `null` for invoice lines or without a stock row."},"product_name":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Muster Basic T-Shirt","description":"Name des zugehörigen Produkts; nur in `GET /api/product-variants/paged` gesetzt, sonst fehlt das Feld / Name of the parent product; set only in `GET /api/product-variants/paged`, otherwise the field is omitted."},"brand_sku":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Herstellerartikelnummer der Variante; nur in `GET /api/product-variants/paged` und nur bei eigenen Produkten, sonst fehlt das Feld / Brand article number of the variant; only in `GET /api/product-variants/paged` and only for own products, otherwise the field is omitted."},"ean":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"EAN (GTIN) der Variante; nur in `GET /api/product-variants/paged` und nur bei eigenen Produkten, sonst fehlt das Feld / EAN (GTIN) of the variant; only in `GET /api/product-variants/paged` and only for own products, otherwise the field is omitted."},"images":{"items":{"$ref":"#/components/schemas/ProductImageUserResponse"},"type":"array","description":"Bilder der Variante in Anzeigereihenfolge; leer, wenn keine hinterlegt sind / Images of the variant in display order; empty if none are stored."}},"type":"object","required":["color_id","created_at","description","id","product_id","product_image_url","size_id","sku","status","updated_at"],"title":"ProductVariantUserResponse","description":"Eine Produktvariante: die bestellbare Einheit eines Produkts, eindeutig durch ihre `sku` bestimmt, mit Farbe, Größe und Bestand / A product variant: the orderable unit of a product, uniquely identified by its `sku`, with color, size and stock."},"ProductionType":{"type":"string","enum":["INVOICE","PRODUCEABLE"],"title":"ProductionType","description":"Produktionsart eines Produkts / Production type of a product. `PRODUCEABLE`: reguläres Produkt. `INVOICE`: Rechnungsposition; nur bei Lagerartikeln (`WAREHOUSE`) möglich. Für Rechnungspositionen liefern die Listen kein `stock_display`."},"ReorderPricingMode":{"type":"string","enum":["original","free"],"title":"ReorderPricingMode","default":"original","description":"Preismodus einer Nachbestellung. `original`: Preise der Quellbestellung werden übernommen. `free`: alle Preise werden auf 0 gesetzt; für Händler nicht verfügbar, es gilt immer `original`. / Pricing mode of a re-order. `original`: prices of the source order are taken over. `free`: all prices are set to 0; not available to merchants, `original` always applies."},"RetentionReasonCountResponse":{"properties":{"retention_reason_id":{"type":"integer","example":7,"description":"ID des Rückhaltegrundes (aus `GET /api/orders/retention-reasons`). / ID of the retention reason (from `GET /api/orders/retention-reasons`)."},"count":{"type":"integer","example":3,"description":"Anzahl der Bestellungen des Händlers, die aus diesem Grund angehalten sind (im gewählten Statusfilter). / Number of the merchant orders held for this reason (within the chosen status filter)."}},"type":"object","required":["count","retention_reason_id"],"title":"RetentionReasonCountResponse","description":"Anzahl angehaltener Bestellungen zu einem Rückhaltegrund. / Number of held orders for one retention reason."},"RetentionSummaryResponse":{"properties":{"counts":{"items":{"$ref":"#/components/schemas/RetentionReasonCountResponse"},"type":"array","description":"Zählung je aktivem Grund, aufsteigend nach Grund-ID; Gründe ohne Bestellung fehlen. / Count per active reason, ascending by reason ID; reasons without an order are missing."},"total_count":{"type":"integer","example":4,"description":"Summe aller `count`-Werte; eine Bestellung zählt nur unter ihrem einen Grund. / Sum of all `count` values; an order counts only under its one reason."}},"type":"object","required":["counts","total_count"],"title":"RetentionSummaryResponse","description":"Zahl angehaltener Bestellungen je Rückhaltegrund. / Number of held orders per retention reason."},"RoutingCause":{"type":"string","enum":["no_manufacturing_variant","no_eligible_manufacturer","missing_manufacturer_mapping","no_processing_support","no_stock","no_capacity","no_price","valadio_no_price","valadio_no_stock","valadio_no_processing_support","valadio_no_capacity","valadio_no_wrap_master_data","valadio_probe_missing_article_identifier","valadio_probe_unknown_reference_area","valadio_probe_missing_flier_article","valadio_probe_unconfirmed_label_placement","valadio_probe_brand_identity_mismatch","valadio_probe_unresolvable_carrier","valadio_probe_processing_without_technology","valadio_probe_unresolvable_geometry","valadio_probe_embroidery_ddf_disabled","valadio_probe_embroidery_campaign_missing","valadio_probe_embroidery_preview_unresolvable","valadio_probe_embroidery_anchor_unresolvable","valadio_probe_embroidery_size_mismatch","valadio_probe_embroidery_size_unverifiable","valadio_probe_embroidery_out_of_area"],"title":"RoutingCause","description":"Ursache, aus der einer Bestellposition noch kein Produktionspartner zugewiesen werden konnte, etwa `no_stock` (kein Bestand), `no_capacity` (keine Kapazität), `no_price` (kein Preis), `no_processing_support` (Veredelung nicht unterstützt) oder `no_eligible_manufacturer` (kein wählbarer Partner). Werte mit Präfix `valadio_` benennen Ursachen bei einem bestimmten Produktionspartner genauer. / Cause why an order item could not yet be assigned to a production partner, for example `no_stock`, `no_capacity`, `no_price`, `no_processing_support` or `no_eligible_manufacturer`. Values with the prefix `valadio_` describe causes at one specific production partner in more detail."},"SafetyStockErrorResponse":{"properties":{"detail":{"type":"string","description":"Kurze englische Fehlermeldung / Short English error message."},"error":{"type":"string","description":"Fehlerkennung, z. B. `INVALID_RULE` bei einer ungültigen Staffel / Error code, e.g. `INVALID_RULE` for invalid tiers."},"field":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Name des verletzenden Staffelfelds (`buffer`, `threshold`, `low_buffer`); `null` = keines / Name of the offending tier field (`buffer`, `threshold`, `low_buffer`); `null` = none."}},"type":"object","required":["detail","error"],"title":"SafetyStockErrorResponse","description":"Fehlerkörper der Sicherheitsbestand-Aufrufe in der Spec-Form. Die tatsächliche Antwort trägt die Felder `status_code`, `detail` und `extra`; Kennung und Feld stehen dort in `extra.error` und `extra.field`.\n\nError body of the safety stock calls in the spec form. The actual response carries the fields `status_code`, `detail` and `extra`; code and field are in `extra.error` and `extra.field` there."},"SafetyStockOverrideMode":{"type":"string","enum":["NONE","CUSTOM"],"title":"SafetyStockOverrideMode","description":"Art der Ausnahme am Artikel: `NONE` = kein Puffer trotz Standard, `CUSTOM` = eigene Staffel.\n\nKind of override on a product: `NONE` = no buffer despite the default, `CUSTOM` = own tiers."},"SafetyStockPreviewPointResponse":{"properties":{"free":{"type":"integer","example":0,"description":"Freier Bestand in Stück an diesem Stützpunkt / Free stock in pieces at this sample point."},"reported":{"type":"integer","example":0,"description":"Bei diesem freien Bestand gemeldete Menge in Stück (nach Abzug des Puffers) / Quantity reported at this free stock, in pieces (after the buffer)."}},"type":"object","required":["free","reported"],"title":"SafetyStockPreviewPointResponse","description":"Ein Stützpunkt der Vorschau: bei `free` freien Stück werden `reported` gemeldet.\n\nOne sample point of the preview: with `free` free pieces, `reported` pieces are reported."},"SafetyStockRuleResponse":{"properties":{"buffer":{"type":"integer","example":2,"description":"Puffer in Stück bei freiem Bestand ab `threshold` / Buffer in pieces for a free stock of `threshold` or more."},"threshold":{"type":"integer","example":10,"description":"Schwelle in freien Stück, ab der `buffer` statt `low_buffer` gilt / Threshold in free pieces from which `buffer` applies instead of `low_buffer`."},"low_buffer":{"type":"integer","example":1,"description":"Puffer in Stück bei freiem Bestand unterhalb von `threshold` / Buffer in pieces for a free stock below `threshold`."},"preview":{"items":{"$ref":"#/components/schemas/SafetyStockPreviewPointResponse"},"type":"array","description":"Stützpunkte der Staffel (frei 0, 1, `threshold` - 1, `threshold`, `threshold` + `buffer`), aufsteigend und ohne Doppelte; zeigt den Sprung an der Schwelle / Sample points of the tiers (free 0, 1, `threshold` - 1, `threshold`, `threshold` + `buffer`), ascending and deduplicated; shows the step at the threshold."}},"type":"object","required":["buffer","low_buffer","preview","threshold"],"title":"SafetyStockRuleResponse","description":"Eine Sicherheitsbestand-Staffel: ab `threshold` freien Stück hält der Puffer `buffer` zurück, darunter `low_buffer`. Gemeldet wird `max(0, frei - Puffer)`. Gültig sind `buffer` >= `low_buffer` >= 0, `threshold` >= 1, `threshold` > `buffer` und alle Werte <= 10.000.\n\nA safety stock tier: from `threshold` free pieces upwards the buffer held back is `buffer`, below it `low_buffer`. The reported quantity is `max(0, free - buffer)`. Valid are `buffer` >= `low_buffer` >= 0, `threshold` >= 1, `threshold` > `buffer` and all values <= 10,000."},"SettlementMethod":{"type":"string","enum":["WALLET","EXTERNAL_PAYMENT","NONE"],"title":"SettlementMethod","description":"Art der Abrechnung einer Bestellung mit dem Händler. Sie wird einmal beim Anlegen der Bestellung festgelegt.\n\n- `WALLET`: das Guthabenkonto (Wallet) des Händlers trägt die Bestellung; Reservierung, Abbuchung und Gutschrift laufen über dieses Konto.\n- `EXTERNAL_PAYMENT`: ein Zahlungsdienst oder eine Sammelrechnung begleicht die Bestellung. Das Guthabenkonto bucht sie nie; Erstattungen gehen über den Zahlungsweg zurück.\n- `NONE`: es ist nichts abzurechnen (Händler ohne Abrechnung oder kostenlose Nachbestellung).\n\nBei Bestellungen, die vor Einführung der Abrechnungsart angelegt wurden, kann der Wert fehlen (`null`).\n\nHow an order is settled with the merchant. It is set once when the order is created.\n\n- `WALLET`: the merchant wallet pays the order; reservation, charge and credit go through this account.\n- `EXTERNAL_PAYMENT`: a payment provider or a collective invoice settles the order. The wallet never books it; refunds go back through the payment channel.\n- `NONE`: nothing to settle (merchant without billing, or a free reorder).\n\nFor orders created before the settlement method existed, the value can be missing (`null`)."},"ShipmentSummary":{"properties":{"id":{"type":"integer","example":930001,"description":"ID der Sendung. / ID of the shipment."},"tracking_number":{"type":"string","example":"00340434161094042557","description":"Sendungsnummer des Versanddienstleisters. / Tracking number of the carrier."},"tracking_link":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"https://tracking.example.com/00340434161094042557","description":"Link zur Sendungsverfolgung beim Versanddienstleister; `null` = kein Link bekannt. / Link to the carrier tracking page; `null` = no link known."},"status":{"type":"string","example":"SHIPPED","description":"Sendungsstatus als Text, z. B. `SHIPPED`; die Menge der Werte ist nicht fest zugesagt. / Shipment status as text, e.g. `SHIPPED`; the set of values is not guaranteed."},"carrier_name":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"DHL","description":"Name des Versanddienstleisters; `null` = nicht bekannt. / Name of the carrier; `null` = not known."}},"type":"object","required":["id","status","tracking_number"],"title":"ShipmentSummary","description":"Eine Sendung mit Tracking-Daten. / One shipment with tracking data."},"ShippingListAmbiguousResponse":{"properties":{"row":{"type":"integer","example":6,"description":"Excel-Zeilennummer (1-basiert) / Excel row number (1-based)."},"value":{"type":"string","example":"4012345678901","description":"Die Artikelkennung der Zeile, die mehrfach getroffen hat / The article identifier of the row that matched more than once."},"candidates":{"items":{"type":"integer","example":48214},"type":"array","description":"IDs der passenden Varianten; eine davon als `product_variant_id` auswählen / IDs of the matching variants; choose one as `product_variant_id`."}},"type":"object","required":["candidates","row","value"],"title":"ShippingListAmbiguousResponse","description":"Zeile der Versandliste mit mehreren aktiven Treffern. / Shipping-list row with several active matches."},"ShippingListImportResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ShippingListItemResponse"},"type":"array","description":"Zugeordnete Positionen, je Variante eine / Matched items, one per variant."},"unmatched":{"items":{"$ref":"#/components/schemas/ShippingListUnmatchedResponse"},"type":"array","description":"Zeilen ohne Treffer / Rows without a match."},"ambiguous":{"items":{"$ref":"#/components/schemas/ShippingListAmbiguousResponse"},"type":"array","description":"Zeilen mit mehreren aktiven Treffern; der Händler muss auswählen / Rows with several active matches; the merchant has to choose."},"invalid":{"items":{"$ref":"#/components/schemas/ShippingListInvalidResponse"},"type":"array","description":"Unbrauchbare Zeilen mit Grund, nach Zeilennummer aufsteigend / Unusable rows with reason, ascending by row number."},"columns":{"additionalProperties":{"type":"string"},"type":"object","description":"Erkannte Spalten: Schlüssel `sku`, `ean`, `quantity`, `note` (nur die gefundenen), Wert ist die Überschrift in der Datei / Detected columns: keys `sku`, `ean`, `quantity`, `note` (only those found), value is the heading in the file."}},"type":"object","required":["ambiguous","columns","invalid","items","unmatched"],"title":"ShippingListImportResponse","description":"Vorschlag für eine Anlieferung aus einer Versandliste; legt nichts an. / Proposal for an inbound shipment from a shipping list; creates nothing."},"ShippingListInvalidResponse":{"properties":{"row":{"type":"integer","example":7,"description":"Excel-Zeilennummer (1-basiert) / Excel row number (1-based)."},"reason":{"$ref":"#/components/schemas/ShippingListRowIssue","description":"Grund, warum die Zeile nicht übernommen wurde, siehe `ShippingListRowIssue` / Reason the row was not taken over, see `ShippingListRowIssue`."}},"type":"object","required":["reason","row"],"title":"ShippingListInvalidResponse","description":"Unbrauchbare Zeile der Versandliste. / Unusable shipping-list row."},"ShippingListItemResponse":{"properties":{"product_variant_id":{"type":"integer","example":48213,"description":"ID der zugeordneten Lagerartikel-Variante; als `product_variant_id` beim Anlegen übernehmen / ID of the matched warehouse-article variant; take over as `product_variant_id` on create."},"sku":{"type":"string","example":"MUSTER-TS-BLK-M","description":"SKU der zugeordneten Variante; nur zur Anzeige, beim Anlegen nicht mitsenden / SKU of the matched variant; for display only, do not send on create."},"announced_quantity":{"type":"integer","example":120,"description":"Aufsummierte Stückzahl aller Zeilen dieser Variante; als `announced_quantity` übernehmen / Summed number of pieces of all rows of this variant; take over as `announced_quantity`."},"rows":{"items":{"type":"integer","example":2},"type":"array","description":"Excel-Zeilennummern (1-basiert), aus denen die Position summiert ist; beim Anlegen nicht mitsenden / Excel row numbers (1-based) the item is summed from; do not send on create."},"note":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Karton 1","description":"Verbundene, verschiedene Notizen der Zeilen (mit `; `), auf 512 Zeichen gekürzt; `null` ohne Notiz / Distinct notes of the rows joined with `; `, cut to 512 characters; `null` without a note."}},"type":"object","required":["announced_quantity","product_variant_id","rows","sku"],"title":"ShippingListItemResponse","description":"Vorgeschlagene Position aus der Versandliste. / Proposed item from the shipping list."},"ShippingListRowIssue":{"type":"string","enum":["NOT_FOUND","ARTICLE_MISSING","QUANTITY_MISSING","QUANTITY_INVALID","QUANTITY_TOO_LARGE","VARIANT_INACTIVE"],"title":"ShippingListRowIssue","description":"Grund, warum eine Zeile der Versandliste nicht in den Vorschlag kam. `NOT_FOUND`: kein eigener Lagerartikel mit der Kennung. `ARTICLE_MISSING`: keine Artikelkennung in der Zeile. `QUANTITY_MISSING`: Menge leer. `QUANTITY_INVALID`: Menge keine ganze Zahl größer 0. `QUANTITY_TOO_LARGE`: Summe der Variante über 100.000. `VARIANT_INACTIVE`: nur deaktivierte Treffer. / Reason a shipping-list row did not make it into the proposal. `NOT_FOUND`: no own warehouse article with the identifier. `ARTICLE_MISSING`: no article identifier in the row. `QUANTITY_MISSING`: quantity empty. `QUANTITY_INVALID`: quantity not a whole number greater than 0. `QUANTITY_TOO_LARGE`: variant sum above 100,000. `VARIANT_INACTIVE`: only deactivated matches."},"ShippingListUnmatchedResponse":{"properties":{"row":{"type":"integer","example":4,"description":"Excel-Zeilennummer (1-basiert) / Excel row number (1-based)."},"value":{"type":"string","example":"MUSTER-XX-1","description":"Die erste Artikelkennung der Zeile (SKU-Spalte vor EAN-Spalte), nach der gesucht wurde / The first article identifier of the row (SKU column before EAN column) that was searched for."},"reason":{"$ref":"#/components/schemas/ShippingListRowIssue","description":"Grund, derzeit `NOT_FOUND` (kein eigener Lagerartikel mit dieser Kennung) / Reason, currently `NOT_FOUND` (no own warehouse article with this identifier)."}},"type":"object","required":["reason","row","value"],"title":"ShippingListUnmatchedResponse","description":"Zeile der Versandliste ohne Treffer. / Shipping-list row without a match."},"StatusGatesResponse":{"properties":{"cancel":{"items":{"$ref":"#/components/schemas/OrderStatus"},"type":"array","description":"Status, in denen eine Stornierung angenommen wird: alle außer `CANCELED` und `CANCELLATION_PENDING`. Was sich tatsächlich stornieren lässt, entscheidet je Fertigungsauftrag. / Statuses in which a cancellation is accepted: all except `CANCELED` and `CANCELLATION_PENDING`. What can actually be canceled is decided per manufacturing order."},"restart":{"items":{"$ref":"#/components/schemas/OrderStatus"},"type":"array","description":"Status, in denen eine erneute Verarbeitung (Restart) der Bestellung angenommen wird. / Statuses in which a restart of the order processing is accepted."},"item_mod":{"items":{"$ref":"#/components/schemas/OrderStatus"},"type":"array","description":"Status, in denen Positionen geändert werden können; notwendige, nicht immer hinreichende Bedingung, da zusätzlich Fertigungsaufträge dagegen sprechen können. / Statuses in which items can be changed; a necessary but not always sufficient condition, as manufacturing orders can additionally speak against it."},"reorder":{"items":{"$ref":"#/components/schemas/OrderStatus"},"type":"array","description":"Status, in denen eine Nachbestellung angenommen wird: derzeit alle Status. / Statuses in which a re-order is accepted: currently all statuses."}},"type":"object","required":["cancel","item_mod","reorder","restart"],"title":"StatusGatesResponse","description":"Je Aktion die Bestellstatus, in denen sie angenommen wird. / For each action the order statuses in which it is accepted."},"SupplierStockIssue":{"type":"string","enum":["UNCOVERED","INBOUND_OVERDUE","COVERED"],"title":"SupplierStockIssue","description":"Lieferantenengpass einer Bestellung: `UNCOVERED` (Engpass ohne deckenden Zulauf), `INBOUND_OVERDUE` (Zulauf gedeckt, aber überfällig), `COVERED` (Zulauf gedeckt). Für Händler ohne Wirkung. / Supplier shortage of an order: `UNCOVERED` (shortage without covering inbound), `INBOUND_OVERDUE` (inbound covered but overdue), `COVERED` (inbound covered). Has no effect for merchants."},"UpdateBillingAddressRequest":{"properties":{"title":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":20,"description":"Anrede oder Titel, max. 20 Zeichen; `null` = keine Angabe / Salutation or title, max. 20 characters; `null` = not given."},"company":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":200,"example":"Mustermann GmbH","description":"Firmenname, max. 200 Zeichen; `null` = Privatadresse / Company name, max. 200 characters; `null` = private address."},"first_name":{"type":"string","maxLength":100,"example":"Max","description":"Vorname des Empfängers, max. 100 Zeichen / Recipient first name, max. 100 characters."},"last_name":{"type":"string","maxLength":100,"example":"Mustermann","description":"Nachname des Empfängers, max. 100 Zeichen / Recipient last name, max. 100 characters."},"care_of":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":200,"description":"Adresszusatz (z. B. c/o), max. 200 Zeichen; `null` = keiner / Address line addition (e.g. c/o), max. 200 characters; `null` = none."},"street":{"type":"string","maxLength":200,"example":"Musterstraße","description":"Straße ohne Hausnummer, max. 200 Zeichen / Street name without house number, max. 200 characters."},"house_number":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":20,"example":"1","description":"Hausnummer, max. 20 Zeichen; sie wird bei der Prüfung erwartet (Ausnahme: gültige Packstation) / House number, max. 20 characters; it is expected by the validation (exception: valid Packstation)."},"postcode":{"type":"string","maxLength":20,"example":"50667","description":"Postleitzahl, max. 20 Zeichen; das Format wird für das Land geprüft / Postal code, max. 20 characters; the format is checked for the country."},"city":{"type":"string","maxLength":100,"example":"Köln","description":"Ort, max. 100 Zeichen, darf nicht leer sein / City, max. 100 characters, must not be empty."},"country":{"type":"string","maxLength":2,"minLength":2,"example":"DE","description":"Zweibuchstabiger Ländercode (ISO 3166-1 alpha-2); muss dem hinterlegten Rechnungsland bzw. bei erster Anlage dem Lieferland entsprechen / Two-letter country code (ISO 3166-1 alpha-2); must equal the stored billing country, or the delivery country when first created."},"email":{"oneOf":[{"type":"string","format":"email"},{"type":"null"}],"example":"max.mustermann@example.com","description":"E-Mail-Adresse, an die die Rechnung geht; `null` = keine / Email address the invoice is sent to; `null` = none."}},"type":"object","required":["city","country","first_name","last_name","postcode","street"],"title":"UpdateBillingAddressRequest"},"UpdateDeliveryAddressRequest":{"properties":{"title":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":20,"description":"Anrede oder Titel, max. 20 Zeichen; `null` = keine Angabe / Salutation or title, max. 20 characters; `null` = not given."},"company":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":200,"description":"Firmenname, max. 200 Zeichen; `null` = Privatadresse / Company name, max. 200 characters; `null` = private address."},"first_name":{"type":"string","maxLength":100,"example":"Max","description":"Vorname des Empfängers, max. 100 Zeichen / Recipient first name, max. 100 characters."},"last_name":{"type":"string","maxLength":100,"example":"Mustermann","description":"Nachname des Empfängers, max. 100 Zeichen / Recipient last name, max. 100 characters."},"care_of":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":200,"description":"Adresszusatz (z. B. c/o), max. 200 Zeichen; `null` = keiner / Address line addition (e.g. c/o), max. 200 characters; `null` = none."},"street":{"type":"string","maxLength":200,"example":"Musterstraße","description":"Straße ohne Hausnummer, max. 200 Zeichen / Street name without house number, max. 200 characters."},"house_number":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":20,"example":"1","description":"Hausnummer, max. 20 Zeichen; sie wird bei der Prüfung erwartet (Ausnahme: gültige Packstation) / House number, max. 20 characters; it is expected by the validation (exception: valid Packstation)."},"postcode":{"type":"string","maxLength":20,"example":"50667","description":"Postleitzahl, max. 20 Zeichen; das Format wird für das Land geprüft / Postal code, max. 20 characters; the format is checked for the country."},"city":{"type":"string","maxLength":100,"example":"Köln","description":"Ort, max. 100 Zeichen, darf nicht leer sein / City, max. 100 characters, must not be empty."},"country":{"type":"string","maxLength":2,"minLength":2,"example":"DE","description":"Zweibuchstabiger Ländercode nach ISO 3166-1 alpha-2, z. B. `DE` / Two-letter country code per ISO 3166-1 alpha-2, e.g. `DE`."},"email":{"oneOf":[{"type":"string","format":"email"},{"type":"null"}],"example":"max.mustermann@example.com","description":"E-Mail-Adresse des Empfängers; `null` = keine / Recipient email address; `null` = none."}},"type":"object","required":["city","country","first_name","last_name","postcode","street"],"title":"UpdateDeliveryAddressRequest"},"UploadDeliveryReceiptResponse":{"properties":{"document_id":{"type":"integer","example":940001,"description":"ID des gespeicherten Lieferscheins; die Datei wird immer gespeichert. / ID of the stored delivery receipt; the file is always stored."},"overall":{"type":"string","example":"PARTIAL","description":"Gesamtergebnis: `OK` (alle Fertigungsaufträge nehmen ihn mit), `PARTIAL` (nur ein Teil) oder `STORED_ONLY` (keiner, oder noch kein Fertigungsauftrag). / Overall result: `OK` (all manufacturing orders take it along), `PARTIAL` (only some) or `STORED_ONLY` (none, or no manufacturing order yet)."},"per_mo":{"items":{"$ref":"#/components/schemas/DeliveryReceiptMoOutcomeResponse"},"type":"array","description":"Ergebnis je Fertigungsauftrag der Bestellung; leer, wenn noch keiner existiert. / Result per manufacturing order of the order; empty if none exists yet."}},"type":"object","required":["document_id","overall","per_mo"],"title":"UploadDeliveryReceiptResponse","description":"Ergebnis eines Lieferschein-Uploads. / Result of a delivery receipt upload."},"VariantAvailability":{"type":"string","enum":["AVAILABLE","SOLD_OUT"],"title":"VariantAvailability","description":"Filter nach Verfügbarkeit im Lagerbestand.\n\n- `AVAILABLE`: mehr als 0 Stück verfügbar. Bei Lagerartikeln gilt: mindestens eine Variante des Artikels ist verfügbar.\n- `SOLD_OUT`: keine Stück verfügbar (Bestand 0). Bei Lagerartikeln gilt: keine Variante ist verfügbar; Artikel ohne Varianten zählen als ausverkauft.\n\nMaßgeblich ist der Wert, den die Bestandsanzeige des Händlers zeigt.\n\nFilter by availability in stock.\n\n- `AVAILABLE`: more than 0 pieces available. For warehouse articles: at least one variant of the article is available.\n- `SOLD_OUT`: no pieces available (stock 0). For warehouse articles: no variant is available; articles without variants count as sold out.\n\nThe value shown in the merchant stock display is authoritative."},"VariantListSort":{"type":"string","enum":["name_asc","created_desc"],"title":"VariantListSort","description":"Sortierung der Produkte in `GET /api/product-variants/paged` / Product order. `name_asc` (Standard): nach Produktname aufsteigend. `created_desc`: zuletzt angelegtes Produkt zuerst. Innerhalb eines Produkts gilt immer: Farbbezeichnung, Größe in Tragereihenfolge, `sku`."},"WarehouseProductErrorResponse":{"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode der Antwort / HTTP status code of the response."},"detail":{"type":"string","description":"Kurze englische Fehlermeldung / Short English error message."},"extra":{"oneOf":[{"type":"object"},{"type":"array"},{"type":"null"}],"description":"Zusatzangaben: `error` (Fehlerkennung, z. B. `INVALID_VARIANTS`, `NOT_EDITABLE`, `REVIEW_STATE_CHANGED`) und bei 409 `review_status` (aktueller Wert); `null` = keine / Additional data: `error` (error code, e.g. `INVALID_VARIANTS`, `NOT_EDITABLE`, `REVIEW_STATE_CHANGED`) and on 409 `review_status` (current value); `null` = none."}},"type":"object","required":["detail","status_code"],"title":"WarehouseProductErrorResponse","description":"Fehlerkörper der Lagerartikel-Aufrufe. Eine maschinenlesbare Fehlerkennung steht in `extra.error`.\n\nError body of the warehouse product calls. A machine-readable error code is in `extra.error`."},"WarehouseProductListSort":{"type":"string","enum":["created_desc","updated_desc","submitted_asc","name_asc"],"title":"WarehouseProductListSort","default":"created_desc","description":"Sortierung der Artikelliste: `created_desc` (Standard), `updated_desc`, `submitted_asc`, `name_asc`.\n\nSort order of the product list: `created_desc` (default), `updated_desc`, `submitted_asc`, `name_asc`."},"WarehouseProductPageResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/WarehouseProductResponse"},"type":"array","description":"Artikel dieser Seite in der gewählten Sortierung / Products of this page in the chosen sort order."},"limit":{"type":"integer","example":20,"description":"Angewendete Seitengröße (Echo von `limit`) / Applied page size (echo of `limit`)."},"offset":{"type":"integer","example":0,"description":"Angewendeter Offset (Echo von `offset`) / Applied offset (echo of `offset`)."},"total_count":{"type":"integer","example":1,"description":"Anzahl aller Treffer nach Filtern, unabhängig von `limit` und `offset` / Number of all matches after filtering, independent of `limit` and `offset`."}},"type":"object","required":["items","limit","offset","total_count"],"title":"WarehouseProductPageResponse","description":"Eine Seite der Artikelliste.\n\nOne page of the product list."},"WarehouseProductResponse":{"properties":{"id":{"type":"integer","example":120045,"description":"ID des Artikels, für die Pfade `/api/warehouse/products/{product_id}` / ID of the product, used in the `/api/warehouse/products/{product_id}` paths."},"sku":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"SWP_EX4MPL01","description":"Artikel-SKU (`SWP_` plus 8 Zeichen), vom Server vergeben; bei Lagerartikeln ohne Prüfstatus nicht immer gesetzt (`null`) / Product SKU (`SWP_` plus 8 characters), assigned by the server; not always set (`null`) for products without a review status."},"name":{"type":"string","example":"Muster-T-Shirt Basic","description":"Artikelname / Product name."},"description":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Unisex-T-Shirt aus Bio-Baumwolle, Musterartikel.","description":"Beschreibung; `null` = keine / Description; `null` = none."},"customer_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":100123,"description":"Kunden-ID des Besitzers (der Händler selbst); `null` = Besitzer nicht mehr vorhanden / Customer ID of the owner (the merchant); `null` = owner no longer exists."},"status":{"$ref":"#/components/schemas/ProductStatus","description":"Aktivierungsstatus: `INACTIVE` bis zur Freigabe, danach `ACTIVE` / Activation status: `INACTIVE` until approval, `ACTIVE` afterwards."},"review_status":{"oneOf":[{"$ref":"#/components/schemas/WarehouseProductReviewStatus"},{"type":"null"}],"example":"IN_REVIEW","description":"Prüfstatus: `DRAFT`, `IN_REVIEW`, `APPROVED`, `DECLINED`. `null` = Lagerartikel, der nicht über die Händler-Anlage entstanden ist (nur mit `include_unreviewed` bzw. beim Einzelabruf) / Review status. `null` = warehouse product not created through the merchant flow (only with `include_unreviewed` or on single read)."},"review_note":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Begründung der letzten Ablehnung; bleibt nach der Korrektur stehen und wird mit der erneuten Einreichung geleert; `null` = keine / Reason of the last decline; stays after the correction and is cleared on resubmission; `null` = none."},"submitted_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"example":"2026-01-16T09:00:00Z","description":"Zeitpunkt der letzten Einreichung (UTC, ISO 8601); `null` = nie eingereicht / Time of the last submission (UTC, ISO 8601); `null` = never submitted."},"reviewed_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"example":"2026-01-17T08:00:00Z","description":"Zeitpunkt der letzten Entscheidung (Freigabe oder Ablehnung, UTC, ISO 8601); `null` = noch keine oder mit erneuter Einreichung geleert / Time of the last decision (approval or decline, UTC, ISO 8601); `null` = none yet or cleared by resubmission."},"supplier_number":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"LIEF-0001","description":"Eigene Lieferanten- oder Artikelnummer des Händlers; `null` = keine / Merchant's own supplier or article number; `null` = none."},"is_packaged":{"oneOf":[{"type":"boolean"},{"type":"null"}],"example":true,"description":"Kennzeichen, ob der Artikel verpackt geliefert wird; `null` = keine Angabe / Flag whether the product is delivered packaged; `null` = not specified."},"allow_return_restock":{"oneOf":[{"type":"boolean"},{"type":"null"}],"example":true,"description":"Kennzeichen, ob Retouren wieder eingelagert werden dürfen; `null` = keine Angabe / Flag whether returns may be restocked; `null` = not specified."},"recommended_price":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":1999,"description":"Preisempfehlung in Cent (1999 = 19,99); `null` = keine / Recommended price in cents (1999 = 19.99); `null` = none."},"image_url":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Hauptbild als dauerhafte öffentliche Adresse (ohne Ablaufzeit) oder Quell-URL; `null` = kein Bild / Main image as a permanent public URL (no expiry) or source URL; `null` = no image."},"customer_can_edit":{"type":"boolean","example":false,"description":"`true`, wenn der Händler den Artikel ändern darf (`DRAFT` oder `DECLINED`) / `true` if the merchant may change the product (`DRAFT` or `DECLINED`)."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der Anlage (UTC, ISO 8601) / Time of creation (UTC, ISO 8601)."},"updated_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der letzten Änderung (UTC, ISO 8601) / Time of the last change (UTC, ISO 8601)."},"variants":{"items":{"$ref":"#/components/schemas/WarehouseProductVariantResponse"},"type":"array","description":"Varianten des Artikels, aufsteigend nach ID / Variants of the product, ascending by ID."}},"type":"object","required":["created_at","customer_can_edit","id","name","review_status","sku","status","updated_at","variants"],"title":"WarehouseProductResponse","description":"Ein Lagerartikel des Händlers mit Prüfstatus und Varianten.\n\nA warehouse product of the merchant with review status and variants."},"WarehouseProductReviewStatus":{"type":"string","enum":["DRAFT","IN_REVIEW","APPROVED","DECLINED"],"title":"WarehouseProductReviewStatus","description":"Prüfstatus eines Lagerartikels: `DRAFT` (Entwurf, änderbar), `IN_REVIEW` (eingereicht, nicht änderbar), `APPROVED` (freigegeben, nicht änderbar), `DECLINED` (abgelehnt, änderbar).\n\nReview status of a warehouse product: `DRAFT` (editable), `IN_REVIEW` (submitted, not editable), `APPROVED` (not editable), `DECLINED` (editable)."},"WarehouseProductVariantRequest":{"properties":{"size":{"type":"string","maxLength":50,"example":"M","description":"Größenname, höchstens 50 Zeichen, nicht leer; Aliase wie `2XL`/`XXL` werden zusammengeführt / Size name, at most 50 characters, not blank; aliases such as `2XL`/`XXL` are merged."},"color":{"type":"string","maxLength":100,"example":"Schwarz","description":"Farbname, höchstens 100 Zeichen, nicht leer; unbekannte Farben legt der Server an / Color name, at most 100 characters, not blank; unknown colors are created by the server."},"ean":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":100,"example":"4006381333931","description":"EAN der Variante, höchstens 100 Zeichen; `null` = keine / EAN of the variant, at most 100 characters; `null` = none."},"weight_g":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":1000000,"example":180,"description":"Gewicht in Gramm, 0 bis 1.000.000; `null` = unbekannt / Weight in grams, 0 to 1,000,000; `null` = unknown."},"width_mm":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":100000,"example":300,"description":"Breite in Millimetern, 0 bis 100.000; `null` = unbekannt / Width in millimeters, 0 to 100,000; `null` = unknown."},"height_mm":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":100000,"example":400,"description":"Höhe in Millimetern, 0 bis 100.000; `null` = unbekannt / Height in millimeters, 0 to 100,000; `null` = unknown."},"depth_mm":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":100000,"example":20,"description":"Tiefe in Millimetern, 0 bis 100.000; `null` = unbekannt / Depth in millimeters, 0 to 100,000; `null` = unknown."}},"type":"object","required":["color","size"],"title":"WarehouseProductVariantRequest","description":"Eine Variante im Request. Größe und Farbe sind Namen; die Kombination aus Größe und Farbe identifiziert die Variante und darf je Artikel nur einmal vorkommen.\n\nOne variant in the request. Size and color are names; the combination of size and color identifies the variant and may appear only once per product."},"WarehouseProductVariantResponse":{"properties":{"id":{"type":"integer","example":880011,"description":"ID der Variante / ID of the variant."},"sku":{"type":"string","example":"SWP_EX4MPL01__Schwarz__M","description":"SKU der Variante, `<Artikel-SKU>__<Farbe>__<Größe>`; ändert sich nach der Anlage nie / SKU of the variant, `<product SKU>__<color>__<size>`; never changes after creation."},"status":{"$ref":"#/components/schemas/ProductStatus","description":"`ACTIVE` erst nach der Freigabe des Artikels, vorher `INACTIVE`; eine bei einem freigegebenen Artikel entfernte Variante wird `INACTIVE` / `ACTIVE` only after the product was approved, `INACTIVE` before; a variant removed from an approved product becomes `INACTIVE`."},"size_id":{"type":"integer","example":7,"description":"ID der Größe im Katalog / ID of the size in the catalog."},"color_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":31,"description":"ID der Farbe im Katalog; `null` = keine zugeordnet / ID of the color in the catalog; `null` = none assigned."},"size":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"M","description":"Größenname aus dem Katalog; `null` = keiner / Size name from the catalog; `null` = none."},"color":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Schwarz","description":"Farbname aus dem Katalog; `null` = keiner / Color name from the catalog; `null` = none."},"warehouse_size":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"M","description":"Größe, wie der Händler sie eingegeben hat; `null` = keine Eingabe gespeichert / Size as entered by the merchant; `null` = no input stored."},"warehouse_color":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Schwarz","description":"Farbe, wie der Händler sie eingegeben hat; `null` = keine Eingabe gespeichert / Color as entered by the merchant; `null` = no input stored."},"ean":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"4006381333931","description":"EAN der Variante; `null` = keine / EAN of the variant; `null` = none."},"weight_g":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":180,"description":"Gewicht in Gramm; `null` = unbekannt / Weight in grams; `null` = unknown."},"width_mm":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":300,"description":"Breite in Millimetern; `null` = unbekannt / Width in millimeters; `null` = unknown."},"height_mm":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":400,"description":"Höhe in Millimetern; `null` = unbekannt / Height in millimeters; `null` = unknown."},"depth_mm":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":20,"description":"Tiefe in Millimetern; `null` = unbekannt / Depth in millimeters; `null` = unknown."},"stock_number":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Lagernummer, die Shirtee der Variante zuweist. `null` = keine vergeben; der Bestand bleibt dann 0 / Stock number that Shirtee assigns to the variant. `null` = none assigned; stock then stays 0."},"gross_stock":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":14,"description":"Gesamtbestand in Stück, nie negativ. `null` = nicht gelesen (Antworten von Anlegen, Ändern, Einreichen) / Total stock in pieces, never negative. `null` = not read (responses of create, update, submit)."},"available":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":10,"description":"Verfügbarer Bestand in Stück: Gesamtbestand abzüglich Reservierungen, nie negativ; bei wirksamem Sicherheitsbestand zusätzlich um den Puffer vermindert. `null` = nicht gelesen / Available stock in pieces: total stock minus reservations, never negative; reduced by the buffer if a safety stock applies. `null` = not read."},"available_unbuffered":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":12,"description":"Verfügbarer Bestand vor Abzug des Sicherheitsbestands. Nur vorhanden, wenn ein Sicherheitsbestand geführt wird, sonst fehlt das Feld / Available stock before the safety stock is deducted. Present only if safety stock is maintained, otherwise the field is omitted."},"safety_stock":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":2,"description":"Menge, die der Sicherheitsbestand zurückhält; es gilt `available` + `safety_stock` = `available_unbuffered`. Nur vorhanden, wenn ein Sicherheitsbestand geführt wird, sonst fehlt das Feld / Quantity held back by the safety stock; `available` + `safety_stock` = `available_unbuffered`. Present only if safety stock is maintained, otherwise the field is omitted."}},"type":"object","required":["id","size_id","sku","status"],"title":"WarehouseProductVariantResponse","description":"Eine Variante eines Lagerartikels. Bestandsfelder sind nur beim Lesen (`GET`) gefüllt; in den Antworten von Anlegen, Ändern und Einreichen sind sie `null`.\n\nOne variant of a warehouse product. Stock fields are filled on reads (`GET`) only; in the responses of create, update and submit they are `null`."},"WarehouseProductWriteRequest":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"example":"Muster-T-Shirt Basic","description":"Artikelname, 1 bis 255 Zeichen / Product name, 1 to 255 characters."},"description":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":2048,"example":"Unisex-T-Shirt aus Bio-Baumwolle, Musterartikel.","description":"Beschreibung, höchstens 2048 Zeichen; `null` = keine / Description, at most 2048 characters; `null` = none."},"supplier_number":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":64,"example":"LIEF-0001","description":"Eigene Lieferanten- oder Artikelnummer des Händlers, höchstens 64 Zeichen; `null` = keine / Merchant's own supplier or article number, at most 64 characters; `null` = none."},"is_packaged":{"oneOf":[{"type":"boolean"},{"type":"null"}],"example":true,"description":"Kennzeichen, ob der Artikel verpackt geliefert wird; `null` = keine Angabe / Flag whether the product is delivered packaged; `null` = not specified."},"allow_return_restock":{"oneOf":[{"type":"boolean"},{"type":"null"}],"example":true,"description":"Kennzeichen, ob Retouren dieses Artikels wieder eingelagert werden dürfen; `null` = keine Angabe / Flag whether returns of this product may be restocked; `null` = not specified."},"recommended_price":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":10000000,"example":1999,"description":"Preisempfehlung in Cent (1999 = 19,99), 0 bis 10.000.000. Fehlt das Feld, bleibt beim `PUT` der gespeicherte Wert; `null` löscht ihn / Recommended price in cents (1999 = 19.99), 0 to 10,000,000. If the field is missing, `PUT` keeps the stored value; `null` clears it."},"variants":{"items":{"$ref":"#/components/schemas/WarehouseProductVariantRequest"},"type":"array","maxItems":500,"description":"Varianten des Artikels, 1 bis 500; jede Kombination aus Größe und Farbe höchstens einmal. Beim `PUT` ist die Liste der gewünschte Endstand / Variants of the product, 1 to 500; each size and color combination at most once. On `PUT` the list is the desired final state."}},"type":"object","required":["name","variants"],"title":"WarehouseProductWriteRequest","description":"Vollständiger Stand eines Lagerartikels für Anlegen (`POST`) und Ersetzen (`PUT`).\n\nComplete state of a warehouse product for create (`POST`) and replace (`PUT`)."},"WarehouseShipmentCreateRequest":{"properties":{"items":{"items":{"$ref":"#/components/schemas/WarehouseShipmentItemRequest"},"type":"array","maxItems":1000,"description":"Positionen der Anlieferung, mindestens 1, höchstens 1000; jede Variante höchstens einmal / Items of the shipment, at least 1, at most 1000; each variant at most once."},"notice":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":2048,"example":"Bitte vor 12 Uhr anliefern","description":"Freie Notiz zur Anlieferung für das Lager, höchstens 2048 Zeichen; `null` für keine / Free-text note on the shipment for the warehouse, at most 2048 characters; `null` for none."},"expected_on":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}],"example":"2026-02-10","description":"Vom Händler geplanter Anlieferungstag, Format `YYYY-MM-DD`; `null` für keinen. Ohne `planned_inbound_on` bestimmt er den Stichtag / Delivery day planned by the merchant, format `YYYY-MM-DD`; `null` for none. Without `planned_inbound_on` it determines the cut-off."},"planned_inbound_on":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Vom Lager gesetzter Eingangstermin; für Händler ohne Wirkung und wird ignoriert / Inbound date set by the warehouse; has no effect for merchants and is ignored."},"package_count":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":100000,"example":3,"description":"Anzahl Pakete, ganze Zahl von 0 bis 100000; `null` für keine Angabe / Number of packages, whole number from 0 to 100000; `null` for not specified."},"pallet_count":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":100000,"example":1,"description":"Anzahl Paletten, ganze Zahl von 0 bis 100000; `null` für keine Angabe / Number of pallets, whole number from 0 to 100000; `null` for not specified."},"carrier":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":64,"example":"Spedition Mustermann","description":"Name des Transporteurs, höchstens 64 Zeichen; `null` für keine Angabe / Name of the carrier, at most 64 characters; `null` for not specified."},"tracking_number":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":128,"example":"MUSTER-0001234","description":"Sendungsnummer des Transporteurs, höchstens 128 Zeichen; `null` für keine Angabe / Carrier tracking number, at most 128 characters; `null` for not specified."},"target_manufacturer_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":2147483647,"minimum":1,"description":"Ziellager-Zuweisung des Lagers; für Händler ohne Wirkung und wird ignoriert / Target-warehouse assignment by the warehouse; has no effect for merchants and is ignored."},"is_internal":{"oneOf":[{"type":"boolean"},{"type":"null"}],"description":"Kennzeichen interner Umlagerungen des Lagers; für Händler ohne Wirkung und wird ignoriert / Flag for internal transfers of the warehouse; has no effect for merchants and is ignored."},"expected_updated_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Beim Anlegen ohne Wirkung; wird nicht geprüft / Has no effect on create; not checked."},"customer_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":2147483647,"minimum":1,"description":"Für Händler ohne Wirkung: Der Kunde ergibt sich aus dem Zugang / Has no effect for merchants: the customer is derived from the credentials."}},"type":"object","required":["items"],"title":"WarehouseShipmentCreateRequest","description":"Daten zum Ankündigen einer Anlieferung. / Data for announcing an inbound shipment."},"WarehouseShipmentDocumentResponse":{"properties":{"id":{"type":"integer","example":7301,"description":"ID des Dokuments; wird für Download-URL und Entfernen verwendet / ID of the document; used for the download URL and for removal."},"filename":{"type":"string","example":"Packliste-2026-02.xlsx","description":"Dateiname wie hochgeladen, höchstens 255 Zeichen / File name as uploaded, at most 255 characters."},"content_type":{"type":"string","example":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","description":"Am Inhalt erkannter Medientyp, `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` (xlsx) oder `application/pdf` / Media type detected from the content, `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` (xlsx) or `application/pdf`."},"size_bytes":{"type":"integer","example":18432,"description":"Dateigröße in Bytes / File size in bytes."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:35:00Z","description":"Zeitpunkt des Hochladens, ISO 8601 mit Zeitzone / Upload time, ISO 8601 with time zone."}},"type":"object","required":["content_type","created_at","filename","id","size_bytes"],"title":"WarehouseShipmentDocumentResponse","description":"Ein an die Anlieferung gehängtes Dokument (Metadaten). / A document attached to the shipment (metadata)."},"WarehouseShipmentDocumentUrlResponse":{"properties":{"url":{"type":"string","example":"https://files.example.com/warehouse-shipments/90412/Packliste-2026-02.xlsx?signature=EXAMPLE","description":"Signierte Download-URL; ohne weitere Anmeldung nutzbar, daher vertraulich behandeln / Signed download URL; usable without further authentication, so treat as confidential."},"expires_in_seconds":{"type":"integer","example":900,"description":"Gültigkeit der URL in Sekunden ab Antwort, derzeit 900 (15 Minuten) / Validity of the URL in seconds from the response, currently 900 (15 minutes)."}},"type":"object","required":["expires_in_seconds","url"],"title":"WarehouseShipmentDocumentUrlResponse","description":"Signierte, befristete Download-URL für ein Dokument. / Signed, time-limited download URL for a document."},"WarehouseShipmentErrorResponse":{"properties":{"status_code":{"type":"integer","description":"HTTP-Statuscode der Antwort / HTTP status code of the response."},"detail":{"type":"string","description":"Menschenlesbare Fehlermeldung; nicht für Programmlogik verwenden, dafür `extra.error` / Human-readable error message; do not use for program logic, use `extra.error` instead."},"extra":{"oneOf":[{"type":"object"},{"type":"array"},{"type":"null"}],"description":"Zusatzangaben; bei fachlichen Fehlern ein Objekt mit `error` (Code, z. B. `SHIPMENT_LOCKED`) und je nach Fehler `status`, `reason`, `product_variant_ids`. Bei Validierungsfehlern ohne Code eine Liste der Verstöße; `null` ohne Zusatz / Additional data; for business errors an object with `error` (code, e.g. `SHIPMENT_LOCKED`) and, depending on the error, `status`, `reason`, `product_variant_ids`. For validation errors without a code a list of violations; `null` if none."}},"type":"object","required":["detail","status_code"],"title":"WarehouseShipmentErrorResponse","description":"Fehlerantwort der Anlieferungs-Aufrufe. `extra.error` trägt den maschinenlesbaren Code. / Error response of the inbound-shipment calls. `extra.error` carries the machine-readable code."},"WarehouseShipmentItemRequest":{"properties":{"product_variant_id":{"type":"integer","maximum":2147483647.0,"minimum":1.0,"example":48213,"description":"ID einer Lagerartikel-Variante des eigenen Händlerkontos, 1 bis 2147483647; jede Variante nur einmal je Anlieferung / ID of a warehouse-article variant of your own merchant account, 1 to 2147483647; each variant only once per shipment."},"announced_quantity":{"type":"integer","maximum":100000.0,"minimum":1.0,"example":120,"description":"Angekündigte Stückzahl dieser Variante, ganze Zahl von 1 bis 100000 / Announced number of pieces of this variant, whole number from 1 to 100000."},"note":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":512,"example":"Karton 1 bis 3","description":"Freie Notiz zur Position, höchstens 512 Zeichen; `null` für keine / Free-text note on the item, at most 512 characters; `null` for none."}},"type":"object","required":["announced_quantity","product_variant_id"],"title":"WarehouseShipmentItemRequest","description":"Eine angekündigte Position einer Anlieferung. / One announced item of an inbound shipment."},"WarehouseShipmentItemResponse":{"properties":{"id":{"type":"integer","example":551201,"description":"ID der Position / ID of the item."},"product_variant_id":{"type":"integer","example":48213,"description":"ID der angekündigten Lagerartikel-Variante / ID of the announced warehouse-article variant."},"announced_quantity":{"type":"integer","example":120,"description":"Vom Händler angekündigte Stückzahl / Number of pieces announced by the merchant."},"received_quantity":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Vom Lager gezählte Eingangsmenge; `null`, solange noch nichts gezählt ist / Quantity counted by the warehouse on receipt; `null` while nothing has been counted."},"damaged_quantity":{"type":"integer","example":0,"description":"Beim Wareneingang als beschädigt gemeldete Stückzahl, zusätzlich zu `received_quantity`; 0, solange nichts gezählt ist / Number of pieces reported damaged on receipt, in addition to `received_quantity`; 0 while nothing has been counted."},"note":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Karton 1 bis 3","description":"Notiz zur Position; `null` für keine / Note on the item; `null` for none."},"deviation_quantity":{"oneOf":[{"type":"integer"},{"type":"null"}],"readOnly":true,"description":"`received_quantity` minus `announced_quantity`: positiv bei Überlieferung, negativ bei Unterlieferung; `null`, solange nichts gezählt ist. `damaged_quantity` zählt nicht mit / `received_quantity` minus `announced_quantity`: positive for over-delivery, negative for under-delivery; `null` while nothing has been counted. `damaged_quantity` is not included."}},"type":"object","required":["announced_quantity","damaged_quantity","deviation_quantity","id","product_variant_id"],"title":"WarehouseShipmentItemResponse","description":"Eine Position einer Anlieferung mit Soll- und Ist-Menge. / One item of an inbound shipment with announced and received quantity."},"WarehouseShipmentPageResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/WarehouseShipmentResponse"},"type":"array","description":"Anlieferungen dieser Seite / Shipments on this page."},"limit":{"type":"integer","example":20,"description":"Angewandte Seitengröße der Anfrage / Page size applied for the request."},"offset":{"type":"integer","example":0,"description":"Angewandter Offset der Anfrage / Offset applied for the request."},"total_count":{"type":"integer","example":2,"description":"Anzahl aller Treffer über alle Seiten / Number of all matches across all pages."}},"type":"object","required":["items","limit","offset","total_count"],"title":"WarehouseShipmentPageResponse","description":"Eine Seite der Anlieferungsliste. / One page of the shipment list."},"WarehouseShipmentResponse":{"properties":{"id":{"type":"integer","example":90412,"description":"ID der Anlieferung; Pfadparameter `shipment_id` der übrigen Aufrufe / ID of the shipment; path parameter `shipment_id` of the other calls."},"reference":{"type":"string","example":"WHS_90412","description":"Anlieferungsnummer im Format `WHS_<id>` (z. B. `WHS_90412`), auch für Rückfragen beim Lager / Shipment number in the format `WHS_<id>` (e.g. `WHS_90412`), also for queries to the warehouse."},"customer_id":{"type":"integer","example":100234,"description":"Kunden-ID des Händlers, dem die Anlieferung gehört / Customer ID of the merchant who owns the shipment."},"status":{"$ref":"#/components/schemas/WarehouseShipmentStatus","description":"`ANNOUNCED` (angekündigt, noch änderbar), `RECEIVED` (Wareneingang gebucht) oder `CANCELED` (storniert) / `ANNOUNCED`, `RECEIVED` or `CANCELED`."},"notice":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Bitte vor 12 Uhr anliefern","description":"Freie Notiz des Händlers für das Lager; `null` für keine / Free-text note of the merchant for the warehouse; `null` for none."},"expected_on":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}],"example":"2026-02-10","description":"Vom Händler geplanter Anlieferungstag (`YYYY-MM-DD`); `null` für keinen / Delivery day planned by the merchant (`YYYY-MM-DD`); `null` for none."},"planned_inbound_on":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Vom Lager festgelegter Eingangstermin (`YYYY-MM-DD`); `null`, solange das Lager keinen gesetzt hat / Inbound date fixed by the warehouse (`YYYY-MM-DD`); `null` while the warehouse has not set one."},"package_count":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":3,"description":"Anzahl Pakete; `null` für keine Angabe / Number of packages; `null` for not specified."},"pallet_count":{"oneOf":[{"type":"integer"},{"type":"null"}],"example":1,"description":"Anzahl Paletten; `null` für keine Angabe / Number of pallets; `null` for not specified."},"carrier":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"Spedition Mustermann","description":"Name des Transporteurs; `null` für keine Angabe / Name of the carrier; `null` for not specified."},"tracking_number":{"oneOf":[{"type":"string"},{"type":"null"}],"example":"MUSTER-0001234","description":"Sendungsnummer des Transporteurs; `null` für keine Angabe / Carrier tracking number; `null` for not specified."},"received_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Zeitpunkt der Buchung des Wareneingangs, ISO 8601; `null`, solange nicht gebucht / Time the goods receipt was booked, ISO 8601; `null` until booked."},"canceled_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"example":"2026-01-17T09:00:00Z","description":"Zeitpunkt der Stornierung, ISO 8601; `null`, solange nicht storniert / Time of cancellation, ISO 8601; `null` unless canceled."},"created_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der Anlage, ISO 8601 mit Zeitzone / Creation time, ISO 8601 with time zone."},"updated_at":{"type":"string","format":"date-time","example":"2026-01-15T10:30:00Z","description":"Zeitpunkt der letzten Änderung, ISO 8601; als `expected_updated_at` beim Ändern verwendbar / Time of the last change, ISO 8601; usable as `expected_updated_at` on update."},"arrived_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Zeitpunkt, zu dem das Lager die Ware als angekommen markiert hat, ISO 8601; `null` ohne Markierung. Unabhängig von `received_at` / Time the warehouse marked the goods as arrived, ISO 8601; `null` if not marked. Independent of `received_at`."},"customer_edit_locked_from":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}],"example":"2026-02-07","description":"Stichtag (`YYYY-MM-DD`): ab diesem Tag darf der Händler nicht mehr ändern oder stornieren; `null`, solange kein Termin vorliegt. Maßgeblich ist `customer_can_edit` / Cut-off day (`YYYY-MM-DD`): from this day the merchant may no longer change or cancel; `null` while there is no date. `customer_can_edit` is authoritative."},"customer_can_edit":{"type":"boolean","example":true,"description":"`true`, wenn der Händler heute (Berlin) noch ändern, stornieren und Dokumente anhängen darf; `false` bei anderem Status als `ANNOUNCED`, nach dem Stichtag oder bei bereits angelegter Einkaufsbestellung / `true` if the merchant may still change, cancel and attach documents today (Berlin); `false` for a status other than `ANNOUNCED`, after the cut-off, or with an already created purchase order."},"target_manufacturer_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Nur für Umlagerungen des Lagers belegt; für Händler immer `null` / Only set for internal transfers of the warehouse; always `null` for merchants."},"target_sync_status":{"oneOf":[{"$ref":"#/components/schemas/WarehouseShipmentSyncStatus"},{"type":"null"}],"description":"Nur für Umlagerungen des Lagers belegt; für Händler immer `null` / Only set for internal transfers of the warehouse; always `null` for merchants."},"target_external_reference":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Nur für Umlagerungen des Lagers belegt; für Händler immer `null` / Only set for internal transfers of the warehouse; always `null` for merchants."},"target_sync_error_code":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Nur für Umlagerungen des Lagers belegt; für Händler immer `null` / Only set for internal transfers of the warehouse; always `null` for merchants."},"target_sync_error_message":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Nur für Umlagerungen des Lagers belegt; für Händler immer `null` / Only set for internal transfers of the warehouse; always `null` for merchants."},"is_internal":{"type":"boolean","default":false,"example":false,"description":"Kennzeichen interner Umlagerungen des Lagers; Händler sehen solche Anlieferungen nie, der Wert ist für sie immer `false` / Flag for internal transfers of the warehouse; merchants never see such shipments, so the value is always `false` for them."},"items":{"items":{"$ref":"#/components/schemas/WarehouseShipmentItemResponse"},"type":"array","description":"Positionen der Anlieferung / Items of the shipment."},"documents":{"items":{"$ref":"#/components/schemas/WarehouseShipmentDocumentResponse"},"type":"array","description":"Aktive (nicht entfernte) Dokumente der Anlieferung / Active (not removed) documents of the shipment."},"warnings":{"items":{"$ref":"#/components/schemas/WarehouseShipmentWarning"},"type":"array","description":"Hinweise zur Antwort, kein Fehler. `EDIT_WINDOW_CLOSED`: gespeichert, aber der Stichtag ist erreicht, ab jetzt ändert nur das Lager (nur beim Anlegen/Ändern). `RECEIVED_QUANTITY_FROM_ZOHO` betrifft nur den Wareneingang des Lagers. Sonst leer / Hints on the response, not an error. `EDIT_WINDOW_CLOSED`: saved, but the cut-off is reached, from now on only the warehouse can change it (only on create/update). `RECEIVED_QUANTITY_FROM_ZOHO` concerns only the warehouse's goods receipt. Otherwise empty."},"zoho_po_number":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Nummer der zugehörigen Einkaufsbestellung im Lagersystem; `null`, solange keine angelegt ist / Number of the associated purchase order in the warehouse system; `null` while none exists."},"zoho_po_state":{"$ref":"#/components/schemas/WarehouseZohoPoState","description":"Zustand der Einkaufsbestellung im Lagersystem: `NONE` (keine), `CREATING`, `UNKNOWN`, `ISSUED`, `RECEIVING`, `CLOSED`, `FAILED`. Jeder Wert außer `NONE` sperrt Änderungen durch den Händler / State of the purchase order in the warehouse system: `NONE`, `CREATING`, `UNKNOWN`, `ISSUED`, `RECEIVING`, `CLOSED`, `FAILED`. Every value except `NONE` locks changes by the merchant."},"zoho_receipt_synced_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Zeitpunkt des letzten erfolgreichen Abgleichs der Wareneingänge mit dem Lagersystem, ISO 8601; `null`, wenn noch nie / Time of the last successful sync of goods receipts with the warehouse system, ISO 8601; `null` if never."},"zoho_unmatched_lines":{"items":{"$ref":"#/components/schemas/WarehouseShipmentZohoUnmatchedLineResponse"},"type":"array","description":"Im Lagersystem gebuchte Zeilen ohne passende Position dieser Anlieferung; leer, wenn es keine gibt / Lines booked in the warehouse system without a matching item of this shipment; empty if there are none."},"zoho_po_last_error":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Interner Fehlertext des Lagers; wird für Händler nie ausgegeben (Feld fehlt) / Internal error text of the warehouse; never returned to merchants (field absent)."}},"type":"object","required":["created_at","customer_can_edit","customer_id","id","items","reference","status","updated_at"],"title":"WarehouseShipmentResponse","description":"Eine Anlieferung ans Lager mit Positionen und Dokumenten. / An inbound shipment to the warehouse with items and documents."},"WarehouseShipmentStatus":{"type":"string","enum":["ANNOUNCED","RECEIVED","CANCELED"],"title":"WarehouseShipmentStatus","description":"Status einer Anlieferung. `ANNOUNCED`: angekündigt, vor dem Stichtag änderbar und stornierbar. `RECEIVED`: Wareneingang gebucht, nicht mehr änderbar. `CANCELED`: storniert, nicht mehr änderbar. / Status of an inbound shipment. `ANNOUNCED`: announced, changeable and cancelable before the cut-off. `RECEIVED`: goods receipt booked, no longer changeable. `CANCELED`: canceled, no longer changeable."},"WarehouseShipmentSyncStatus":{"type":"string","enum":["PENDING","IN_PROGRESS","SENT","FAILED"],"title":"WarehouseShipmentSyncStatus","description":"Abgleichsstand einer Umlagerung des Lagers mit dem Ziellager (`PENDING`, `IN_PROGRESS`, `SENT`, `FAILED`); für Händler immer `null`. / Sync state of an internal warehouse transfer with the target warehouse (`PENDING`, `IN_PROGRESS`, `SENT`, `FAILED`); always `null` for merchants."},"WarehouseShipmentWarning":{"type":"string","enum":["EDIT_WINDOW_CLOSED","RECEIVED_QUANTITY_FROM_ZOHO"],"title":"WarehouseShipmentWarning","description":"Hinweis in `warnings`, kein Fehler. `EDIT_WINDOW_CLOSED`: gespeichert, der Stichtag ist aber erreicht; ab jetzt ändert nur das Lager. `RECEIVED_QUANTITY_FROM_ZOHO`: betrifft nur den Wareneingang des Lagers. / Hint in `warnings`, not an error. `EDIT_WINDOW_CLOSED`: saved, but the cut-off is reached; from now on only the warehouse can change it. `RECEIVED_QUANTITY_FROM_ZOHO`: concerns only the warehouse's goods receipt."},"WarehouseShipmentWriteRequest":{"properties":{"items":{"items":{"$ref":"#/components/schemas/WarehouseShipmentItemRequest"},"type":"array","maxItems":1000,"description":"Positionen der Anlieferung, mindestens 1, höchstens 1000; jede Variante höchstens einmal / Items of the shipment, at least 1, at most 1000; each variant at most once."},"notice":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":2048,"example":"Bitte vor 12 Uhr anliefern","description":"Freie Notiz zur Anlieferung für das Lager, höchstens 2048 Zeichen; `null` für keine / Free-text note on the shipment for the warehouse, at most 2048 characters; `null` for none."},"expected_on":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}],"example":"2026-02-12","description":"Vom Händler geplanter Anlieferungstag, Format `YYYY-MM-DD`; `null` für keinen. Ohne `planned_inbound_on` bestimmt er den Stichtag / Delivery day planned by the merchant, format `YYYY-MM-DD`; `null` for none. Without `planned_inbound_on` it determines the cut-off."},"planned_inbound_on":{"oneOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Vom Lager gesetzter Eingangstermin; für Händler ohne Wirkung und wird ignoriert / Inbound date set by the warehouse; has no effect for merchants and is ignored."},"package_count":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":100000,"example":4,"description":"Anzahl Pakete, ganze Zahl von 0 bis 100000; `null` für keine Angabe / Number of packages, whole number from 0 to 100000; `null` for not specified."},"pallet_count":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":100000,"example":1,"description":"Anzahl Paletten, ganze Zahl von 0 bis 100000; `null` für keine Angabe / Number of pallets, whole number from 0 to 100000; `null` for not specified."},"carrier":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":64,"example":"Spedition Mustermann","description":"Name des Transporteurs, höchstens 64 Zeichen; `null` für keine Angabe / Name of the carrier, at most 64 characters; `null` for not specified."},"tracking_number":{"oneOf":[{"type":"string"},{"type":"null"}],"maxLength":128,"example":"MUSTER-0001234","description":"Sendungsnummer des Transporteurs, höchstens 128 Zeichen; `null` für keine Angabe / Carrier tracking number, at most 128 characters; `null` for not specified."},"target_manufacturer_id":{"oneOf":[{"type":"integer"},{"type":"null"}],"maximum":2147483647,"minimum":1,"description":"Ziellager-Zuweisung des Lagers; für Händler ohne Wirkung und wird ignoriert / Target-warehouse assignment by the warehouse; has no effect for merchants and is ignored."},"is_internal":{"oneOf":[{"type":"boolean"},{"type":"null"}],"description":"Kennzeichen interner Umlagerungen des Lagers; für Händler ohne Wirkung und wird ignoriert / Flag for internal transfers of the warehouse; has no effect for merchants and is ignored."},"expected_updated_at":{"oneOf":[{"type":"string","format":"date-time"},{"type":"null"}],"example":"2026-01-15T10:30:00Z","description":"Optimistische Sperre: `updated_at` des Stands, den Sie bearbeitet haben (Vergleich auf Millisekunden, ohne Zeitzone gilt UTC). Weicht der gespeicherte Stand ab, antwortet der Aufruf mit 409 `SHIPMENT_STALE`; `null` prüft nicht. Beim Anlegen ohne Wirkung / Optimistic lock: `updated_at` of the state you edited (compared to the millisecond, UTC if no time zone). If the stored state differs, the call answers 409 `SHIPMENT_STALE`; `null` skips the check. Has no effect on create."}},"type":"object","required":["items"],"title":"WarehouseShipmentWriteRequest","description":"Vollständiger neuer Stand einer Anlieferung für `PUT`; fehlende Felder werden geleert. / Complete new state of an inbound shipment for `PUT`; missing fields are cleared."},"WarehouseShipmentZohoUnmatchedLineResponse":{"properties":{"sku":{"oneOf":[{"type":"string"},{"type":"null"}],"description":"Artikelnummer der gebuchten Zeile im Lagersystem; `null`, wenn sie fehlt / Article number of the booked line in the warehouse system; `null` if missing."},"quantity_received":{"type":"integer","description":"Auf dieser Zeile gebuchte Stückzahl / Number of pieces booked on this line."},"po_number":{"type":"string","description":"Nummer der Einkaufsbestellung, auf der gebucht wurde / Number of the purchase order the booking was made on."}},"type":"object","required":["po_number","quantity_received"],"title":"WarehouseShipmentZohoUnmatchedLineResponse","description":"Im Lagersystem gebuchte Zeile, die keiner Position der Anlieferung zugeordnet werden konnte. / Line booked in the warehouse system that could not be matched to an item of the shipment."},"WarehouseZohoPoState":{"type":"string","enum":["NONE","CREATING","UNKNOWN","ISSUED","RECEIVING","CLOSED","FAILED"],"title":"WarehouseZohoPoState","default":"NONE","description":"Zustand der Einkaufsbestellung zur Anlieferung im Lagersystem. `NONE`: keine. `CREATING`: wird angelegt. `UNKNOWN`: Ausgang der Anlage unklar. `ISSUED`: angelegt. `RECEIVING`: es ist bereits etwas gebucht. `CLOSED`: abgeschlossen. `FAILED`: Anlage fehlgeschlagen, wird vom Lager geklärt. Jeder Wert außer `NONE` sperrt Änderungen durch den Händler. / State of the purchase order for the shipment in the warehouse system. `NONE`: none. `CREATING`: being created. `UNKNOWN`: outcome of creation unclear. `ISSUED`: created. `RECEIVING`: something has already been booked. `CLOSED`: completed. `FAILED`: creation failed, handled by the warehouse. Every value except `NONE` locks changes by the merchant."}},"securitySchemes":{"BearerToken":{"type":"http","description":"Kunden-API-Schlüssel / customer API key","scheme":"bearer"}}},"security":[{"BearerToken":[]}],"externalDocs":{"url":"https://developers.shirtee.cloud","description":"Händler-API-Dokumentation / Merchant API documentation"},"tags":[{"name":"Complaints"},{"name":"Invoices"},{"name":"Orders"},{"name":"Product Colors"},{"name":"Product Sizes"},{"name":"Product Variants"},{"name":"Products"},{"name":"Warehouse Products"},{"name":"Warehouse Safety Stock"},{"name":"Warehouse Shipments"}]}