{
  "openapi": "3.1.0",
  "info": {
    "title": "Polygon One Compliance API",
    "description": "REST API for connecting ERP and other business systems to Polygon One. It covers both compliance modules: **EUDR** (EU Deforestation Regulation) — articles, suppliers, plots, evidence, orders and Due Diligence Statements — and **PPWR** (EU Packaging and Packaging Waste Regulation) — packaging components and units, documents, Declarations of Conformity, the SKU quantity feed and volume reports.\n\nAuthenticate every request with an API key created in Settings → API Keys, sent as `Authorization: Bearer <key>`. Each key carries scopes (e.g. `articles:read`, `packaging:write`) that limit what it may read and write.\n\nVersioning: `v1` changes only additively — new endpoints, new optional request fields and new response fields may appear, nothing documented is removed or changed in meaning. Ignore response fields you do not know.\n\nGuides and walkthroughs: https://help.polygon-one.com/api-reference/introduction",
    "version": "1.0.0",
    "contact": {
      "name": "Polygon One Support",
      "email": "help@polygon-one.eu"
    }
  },
  "tags": [
    {
      "name": "Articles",
      "description": "EUDR articles: your products and purchased goods, their HS code, EUDR relevance and supplier links."
    },
    {
      "name": "Suppliers",
      "description": "EUDR suppliers and their links to articles."
    },
    {
      "name": "Plots",
      "description": "EUDR plots of land (geolocations): create, validate, link to supplier articles, read the geo analysis and its report."
    },
    {
      "name": "Evidence",
      "description": "EUDR evidence documents attached to a supplier article (legal compliance documents, questionnaires)."
    },
    {
      "name": "Orders",
      "description": "Purchase and sale orders and their lines; the read-back of the DDS references linked to each order."
    },
    {
      "name": "Import Jobs",
      "description": "Status and result of an asynchronous batch import (articles, suppliers, orders, PPWR quantities)."
    },
    {
      "name": "Readiness",
      "description": "Action-scoped readiness snapshots for owned EUDR and PPWR resources."
    },
    {
      "name": "DDS Statements",
      "description": "EUDR Due Diligence Statements: create, read, update the TRACES numbers, delete."
    },
    {
      "name": "PPWR Packaging Data",
      "description": "PPWR master data: packaging components, packaging units, their sizes, bills of materials and article links."
    },
    {
      "name": "PPWR Documents",
      "description": "Upload supporting documents (test reports, declarations, technical documentation) to a packaging unit or component."
    },
    {
      "name": "PPWR Declarations of Conformity",
      "description": "Read Declarations of Conformity and download their files."
    },
    {
      "name": "PPWR Quantities & Volume Reports",
      "description": "The SKU quantity feed, aggregate material tonnage and the generated volume reports (Mengenmeldung)."
    }
  ],
  "servers": [
    {
      "url": "https://app.polygon-one.com",
      "description": "Production Server"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API Key",
        "description": "API key generated in Settings > API Keys. Include as `Authorization: Bearer <key>`."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request data",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "Validation failed",
              "details": [
                {
                  "origin": "string",
                  "code": "too_small",
                  "minimum": 1,
                  "inclusive": true,
                  "path": [
                    "address",
                    "street"
                  ],
                  "message": "Address is required."
                }
              ]
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Invalid or expired API key, or the key's user account is not active.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "Invalid or expired API key"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Insufficient permissions for this resource",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "Forbidden"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "Resource not found"
            }
          }
        }
      },
      "InternalError": {
        "description": "Internal server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "Internal server error"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded: currently 1000 requests per 60 seconds per client IP across all `/api` paths. Issued by the edge before the application runs, so the JSON body differs from every other error: `error` is an object. A `429` with an HTML body instead of JSON means the request carried no API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RateLimitedResponse"
            },
            "example": {
              "error": {
                "code": "rate_limited",
                "message": "…"
              }
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "Batch exceeds the row cap (`error: \"batchTooLarge\"`, plus `maxBatchSize`). Nothing staged — page the sync across multiple requests (orders: keep all lines of one order in the same request, see the Batch Import guide).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "error": "batchTooLarge",
              "maxBatchSize": 5000
            }
          }
        }
      },
      "BatchAccepted": {
        "description": "Batch accepted — async import job staged. Nothing imported yet; poll the job.",
        "headers": {
          "Location": {
            "description": "URL of the import job to poll",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ImportJobAccepted"
            },
            "example": {
              "jobId": "d2f7a4c9-8e15-4b63-9a2d-1c6e5f0b8d37",
              "status": "queued",
              "statusUrl": "/api/import-jobs/d2f7a4c9-8e15-4b63-9a2d-1c6e5f0b8d37"
            }
          }
        }
      },
      "PpwrOverwriteRequired": {
        "description": "Unconfirmed overwrite — nothing was written.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PpwrOverwriteRequired"
            },
            "example": {
              "error": "overwriteRequired",
              "confirmUpdateCount": 1
            }
          }
        }
      },
      "PpwrIntakeResult": {
        "description": "Intake result (partial accept — see the schema).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PpwrIntakeResult"
            },
            "example": {
              "imported": 1,
              "updated": [],
              "skipped": [],
              "failed": [],
              "invalid": []
            }
          }
        }
      }
    },
    "schemas": {
      "Address": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string",
            "minLength": 1,
            "description": "Street and house number (or the full address on one line). Required, not empty."
          },
          "postalCode": {
            "type": "string",
            "description": "Postal code; may be empty."
          },
          "city": {
            "type": "string",
            "description": "City; may be empty."
          },
          "additional": {
            "type": "string",
            "description": "Additional address line (e.g. building or floor)."
          },
          "validated": {
            "type": "boolean",
            "description": "`true` when the address was picked from the address search in the app. Informational."
          },
          "latitude": {
            "type": "number",
            "description": "Latitude of the address (WGS84), when known."
          },
          "longitude": {
            "type": "number",
            "description": "Longitude of the address (WGS84), when known."
          }
        },
        "required": [
          "street",
          "postalCode",
          "city"
        ],
        "description": "A postal address."
      },
      "Article": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the article."
          },
          "name": {
            "type": "string",
            "description": "Article name."
          },
          "shortDescription": {
            "type": "string",
            "description": "Short description of the article; empty string when none was given."
          },
          "internalArticleNr": {
            "type": "string",
            "description": "Internal article number (your ERP ID), unique per company. A per-order copy of an article carries `<internalArticleNr>#<orderNumber>`; the number to show to people is `externalArticleNr` when set, else `internalArticleNr`."
          },
          "externalArticleNr": {
            "type": [
              "string",
              "null"
            ],
            "description": "External article number, e.g. a supplier's or customer's number. On a per-order copy it holds the original article's `internalArticleNr`."
          },
          "ean": {
            "type": [
              "string",
              "null"
            ],
            "description": "EAN / GTIN barcode, or `null`."
          },
          "hsCode": {
            "type": "string",
            "description": "Harmonized System code"
          },
          "articleType": {
            "type": "string",
            "description": "`purchase` (bought from a supplier) or `sale` (sold by your company)."
          },
          "eudrRelevant": {
            "type": "boolean",
            "description": "Automatically determined from HS code"
          },
          "needsManualCheck": {
            "type": "boolean",
            "description": "`true` when the EUDR classification derived from the HS code should be checked by a person."
          },
          "sourceScope": {
            "type": "string",
            "description": "`standing`: the article's source is fixed. `perOrder`: the article is a template whose source varies per order; order import creates one copy per order from it."
          },
          "hsPlausibility": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "Stored result of an advisory check of the HS code against the article description, or `null` when not checked. Stored only: it never warns about or blocks a create or update. The object's shape is not part of the v1 contract and may change — do not depend on it."
          },
          "suppliers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Supplier"
            },
            "description": "The suppliers linked to the article. Embedded suppliers carry empty `articles` and `plots`."
          },
          "plots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Plot"
            },
            "description": "Order-line and DDS-line articles carry `plots: []` (DDS line plots live on `DdsStatementArticle.plots`). The article endpoints serve articles as `ArticleResponse` (distinct plots without geometry, capped at 1000); articles on the supplier endpoints (`SupplierResponseArticle`) carry no plot list — use GET /articles/{id}."
          },
          "complianceResults": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ComplianceResult"
            },
            "description": "The EUDR compliance result per supplier link of the article."
          },
          "geoComplianceResults": {
            "type": "array",
            "items": {},
            "description": "Geolocation compliance details. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "legalComplianceResults": {
            "type": "array",
            "items": {},
            "description": "Legal compliance details. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "legalDocuments": {
            "type": "array",
            "items": {},
            "description": "Legal documents on record. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "legalCategoryResults": {
            "type": "array",
            "items": {},
            "description": "Per-category legal compliance results. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "questionnaires": {
            "type": "array",
            "items": {},
            "description": "Supplier questionnaire responses. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "countryOfProduction": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Countries of production declared on one of the article's supplier links (which one is not specified), or `null`."
          },
          "commodityGroup": {
            "type": "string",
            "description": "EUDR commodity group, derived from the HS code unless set explicitly. One of the `CommodityGroup` values."
          },
          "weightPerPieceKg": {
            "type": [
              "number",
              "null"
            ],
            "description": "Weight of one piece in kg, used to derive net mass from a piece count; `null` when unknown."
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the article was moved to the trash (ISO 8601, UTC); `null` for a live article."
          },
          "certifications": {
            "type": "array",
            "items": {},
            "description": "Certifications (e.g. FSC, PEFC) on record for the article; absent when the article has no supplier link. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "ownSupplierArticleIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "UUIDs of the article's own supplier articles (one per linked supplier); absent when the article has no supplier link."
          },
          "supplierLinks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "supplierId": {
                  "type": "string",
                  "description": "UUID of the linked supplier."
                },
                "supplierArticleId": {
                  "type": "string",
                  "description": "UUID of the supplier article: this article as supplied by that supplier."
                }
              },
              "required": [
                "supplierId",
                "supplierArticleId"
              ]
            },
            "description": "The article's supplier links. `supplierArticleId` addresses this article for one supplier: pass it in `supplierArticleIds` of `POST /api/v1/plots`. Present on the article endpoints and on order-line articles; `[]` when the article has no supplier."
          },
          "inputArticles": {
            "type": "array",
            "items": {},
            "description": "Upstream input articles recorded for the article's supply chain; absent when there are none. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          }
        },
        "required": [
          "id",
          "name",
          "shortDescription",
          "internalArticleNr",
          "externalArticleNr",
          "ean",
          "hsCode",
          "articleType",
          "eudrRelevant",
          "needsManualCheck",
          "sourceScope",
          "hsPlausibility",
          "suppliers",
          "plots",
          "complianceResults",
          "geoComplianceResults",
          "legalComplianceResults",
          "legalDocuments",
          "legalCategoryResults",
          "questionnaires",
          "countryOfProduction",
          "commodityGroup",
          "weightPerPieceKg",
          "deletedAt"
        ]
      },
      "ArticleCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the article."
          },
          "name": {
            "type": "string",
            "description": "Article name."
          },
          "shortDescription": {
            "type": "string",
            "description": "Short description of the article; empty string when none was given."
          },
          "internalArticleNr": {
            "type": "string",
            "description": "Internal article number (your ERP ID), unique per company. A per-order copy of an article carries `<internalArticleNr>#<orderNumber>`; the number to show to people is `externalArticleNr` when set, else `internalArticleNr`."
          },
          "externalArticleNr": {
            "type": [
              "string",
              "null"
            ],
            "description": "External article number, e.g. a supplier's or customer's number. On a per-order copy it holds the original article's `internalArticleNr`."
          },
          "ean": {
            "type": [
              "string",
              "null"
            ],
            "description": "EAN / GTIN barcode, or `null`."
          },
          "hsCode": {
            "type": "string",
            "description": "Harmonized System code"
          },
          "articleType": {
            "type": "string",
            "description": "`purchase` (bought from a supplier) or `sale` (sold by your company)."
          },
          "sourceScope": {
            "type": "string",
            "description": "`standing`: the article's source is fixed. `perOrder`: the article is a template whose source varies per order; order import creates one copy per order from it."
          },
          "eudrRelevant": {
            "type": "boolean",
            "description": "Automatically determined from HS code"
          },
          "commodityGroup": {
            "type": "string",
            "description": "EUDR commodity group, derived from the HS code unless set explicitly. One of the `CommodityGroup` values."
          },
          "needsManualCheck": {
            "type": "boolean",
            "description": "`true` when the EUDR classification derived from the HS code should be checked by a person."
          },
          "hsPlausibility": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "Stored result of an advisory check of the HS code against the article description, or `null` when not checked. Stored only: it never warns about or blocks a create or update. The object's shape is not part of the v1 contract and may change — do not depend on it."
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the article was moved to the trash (ISO 8601, UTC); `null` for a live article."
          }
        },
        "required": [
          "id",
          "name",
          "shortDescription",
          "internalArticleNr",
          "externalArticleNr",
          "ean",
          "hsCode",
          "articleType",
          "sourceScope",
          "eudrRelevant",
          "commodityGroup",
          "needsManualCheck",
          "hsPlausibility",
          "deletedAt"
        ],
        "description": "The stored article fields. Further keys may be present and are not part of the contract; read the full article with `GET /api/v1/articles/{id}`."
      },
      "ArticleResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the article."
          },
          "name": {
            "type": "string",
            "description": "Article name."
          },
          "shortDescription": {
            "type": "string",
            "description": "Short description of the article; empty string when none was given."
          },
          "internalArticleNr": {
            "type": "string",
            "description": "Internal article number (your ERP ID), unique per company. A per-order copy of an article carries `<internalArticleNr>#<orderNumber>`; the number to show to people is `externalArticleNr` when set, else `internalArticleNr`."
          },
          "externalArticleNr": {
            "type": [
              "string",
              "null"
            ],
            "description": "External article number, e.g. a supplier's or customer's number. On a per-order copy it holds the original article's `internalArticleNr`."
          },
          "ean": {
            "type": [
              "string",
              "null"
            ],
            "description": "EAN / GTIN barcode, or `null`."
          },
          "hsCode": {
            "type": "string",
            "description": "Harmonized System code"
          },
          "articleType": {
            "type": "string",
            "description": "`purchase` (bought from a supplier) or `sale` (sold by your company)."
          },
          "eudrRelevant": {
            "type": "boolean",
            "description": "Automatically determined from HS code"
          },
          "needsManualCheck": {
            "type": "boolean",
            "description": "`true` when the EUDR classification derived from the HS code should be checked by a person."
          },
          "sourceScope": {
            "type": "string",
            "description": "`standing`: the article's source is fixed. `perOrder`: the article is a template whose source varies per order; order import creates one copy per order from it."
          },
          "hsPlausibility": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "Stored result of an advisory check of the HS code against the article description, or `null` when not checked. Stored only: it never warns about or blocks a create or update. The object's shape is not part of the v1 contract and may change — do not depend on it."
          },
          "suppliers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Supplier"
            },
            "description": "The suppliers linked to the article. Embedded suppliers carry empty `articles` and `plots`."
          },
          "plots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlotListItem"
            },
            "description": "Distinct plots of the article without geometry, at most 1000 (ordered by id); fetch geometry via GET /plots/{id}."
          },
          "complianceResults": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ComplianceResult"
            },
            "description": "The EUDR compliance result per supplier link of the article."
          },
          "geoComplianceResults": {
            "type": "array",
            "items": {},
            "description": "Geolocation compliance details. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "legalComplianceResults": {
            "type": "array",
            "items": {},
            "description": "Legal compliance details. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "legalDocuments": {
            "type": "array",
            "items": {},
            "description": "Legal documents on record. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "legalCategoryResults": {
            "type": "array",
            "items": {},
            "description": "Per-category legal compliance results. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "questionnaires": {
            "type": "array",
            "items": {},
            "description": "Supplier questionnaire responses. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "countryOfProduction": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Countries of production declared on one of the article's supplier links (which one is not specified), or `null`."
          },
          "commodityGroup": {
            "type": "string",
            "description": "EUDR commodity group, derived from the HS code unless set explicitly. One of the `CommodityGroup` values."
          },
          "weightPerPieceKg": {
            "type": [
              "number",
              "null"
            ],
            "description": "Weight of one piece in kg, used to derive net mass from a piece count; `null` when unknown."
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the article was moved to the trash (ISO 8601, UTC); `null` for a live article."
          },
          "certifications": {
            "type": "array",
            "items": {},
            "description": "Certifications (e.g. FSC, PEFC) on record for the article; absent when the article has no supplier link. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "ownSupplierArticleIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "UUIDs of the article's own supplier articles (one per linked supplier); absent when the article has no supplier link."
          },
          "supplierLinks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "supplierId": {
                  "type": "string",
                  "description": "UUID of the linked supplier."
                },
                "supplierArticleId": {
                  "type": "string",
                  "description": "UUID of the supplier article: this article as supplied by that supplier."
                }
              },
              "required": [
                "supplierId",
                "supplierArticleId"
              ]
            },
            "description": "The article's supplier links. `supplierArticleId` addresses this article for one supplier: pass it in `supplierArticleIds` of `POST /api/v1/plots`. Present on the article endpoints and on order-line articles; `[]` when the article has no supplier."
          },
          "inputArticles": {
            "type": "array",
            "items": {},
            "description": "Upstream input articles recorded for the article's supply chain; absent when there are none. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "plotsTruncated": {
            "type": "boolean",
            "description": "true when the article has more than 1000 distinct plots and `plots` holds only the first 1000 by id."
          }
        },
        "required": [
          "id",
          "name",
          "shortDescription",
          "internalArticleNr",
          "externalArticleNr",
          "ean",
          "hsCode",
          "articleType",
          "eudrRelevant",
          "needsManualCheck",
          "sourceScope",
          "hsPlausibility",
          "suppliers",
          "plots",
          "complianceResults",
          "geoComplianceResults",
          "legalComplianceResults",
          "legalDocuments",
          "legalCategoryResults",
          "questionnaires",
          "countryOfProduction",
          "commodityGroup",
          "weightPerPieceKg",
          "deletedAt",
          "plotsTruncated"
        ],
        "description": "An article as returned by GET /articles, GET /articles/{id} and PATCH /articles/{id}."
      },
      "ArticleType": {
        "type": "string",
        "enum": [
          "purchase",
          "sale"
        ],
        "description": "`purchase` = inbound article from a supplier, `sale` = outbound article you sell"
      },
      "BatchArticleInput": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Article name."
          },
          "shortDescription": {
            "type": [
              "string",
              "null"
            ],
            "description": "Short description of the article."
          },
          "articleType": {
            "type": "string",
            "description": "`purchase` (default) or `sale`."
          },
          "internalArticleNr": {
            "type": "string",
            "minLength": 1,
            "description": "Internal article number (your ERP ID) — the key the batch upserts on."
          },
          "externalArticleNr": {
            "type": [
              "string",
              "null"
            ],
            "description": "External article number, e.g. a supplier's or customer's number."
          },
          "hsCode": {
            "type": "string",
            "minLength": 1,
            "description": "HS code — EUDR relevance and commodity group are derived from it."
          },
          "ean": {
            "type": [
              "string",
              "null"
            ],
            "description": "EAN / GTIN barcode."
          },
          "weightPerPieceKg": {
            "type": [
              "number",
              "null"
            ],
            "exclusiveMinimum": 0,
            "description": "Weight of one piece in kg; must be greater than 0."
          },
          "sourceScope": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "standing",
              "perOrder",
              null
            ],
            "description": "`standing` (default): the source is fixed. `perOrder`: the source varies per order and order import creates one copy of the article per order."
          },
          "supplierId": {
            "type": "string",
            "description": "Purchase articles: UUID of an existing supplier of your company to link the article to."
          },
          "supplierName": {
            "type": "string",
            "description": "Purchase articles: supplier name, used to find a supplier or to create one when none matches."
          },
          "supplierEmail": {
            "type": "string",
            "description": "Contact email for a supplier the import creates."
          },
          "supplierCountry": {
            "type": "string",
            "description": "Country for a supplier the import creates."
          },
          "supplierAddress": {
            "type": "string",
            "description": "Address (one line) for a supplier the import creates."
          },
          "supplierExternalId": {
            "type": "string",
            "description": "Your ERP id of the supplier. Used to match an existing supplier and stored on a supplier the import creates."
          }
        },
        "required": [
          "name",
          "internalArticleNr",
          "hsCode"
        ],
        "description": "One article row of a batch import."
      },
      "BatchOrderInput": {
        "type": "object",
        "properties": {
          "orderNumber": {
            "type": "string",
            "minLength": 1,
            "description": "Your order number — rows with the same number form one order; the key the batch upserts on."
          },
          "orderDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Order date, ISO 8601."
          },
          "deliveryDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Optional ISO 8601 delivery date of this row's position. Rows of one order may carry different dates (split delivery): each line keeps its own, and the order's `deliveryDate` is the earliest of them."
          },
          "supplierName": {
            "type": "string",
            "description": "Resolved to a supplier ID by matching name"
          },
          "articleNumber": {
            "type": "string",
            "minLength": 1,
            "description": "Resolved to an existing article by internal article number. A number matching no article auto-creates a purchase article from `hsCode` and `articleDescription` (counted in `autoCreated.articles`); a number matching a deleted article fails the order with `articleDeleted`."
          },
          "positionId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 64,
            "description": "Position number of this line in your ERP (e.g. SAP item `00010`). Trimmed, max 64. Rows with a positionId are never merged (without one, rows of the same article are compared as one summed position); within one request every row of an order carries one or none (`positionIdMixed`), unique per order (`duplicatePositionId`). Transition and read-back rules: see the ERP batch guide."
          },
          "quantity": {
            "type": "number",
            "minimum": 0,
            "description": "Net mass in kilograms. Required unless `pieceCount` is provided."
          },
          "pieceCount": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "description": "Number of pieces. Used to derive net mass when `quantity` is omitted."
          },
          "volumeM3": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Volume in m³ — feeds the EUDR DDS supplementary unit (MTQ)."
          },
          "dryWeight90Kg": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Kilograms of 90 %-dry substance — feeds the EUDR DDS supplementary unit (KSD)."
          },
          "orderType": {
            "type": "string",
            "enum": [
              "purchase",
              "sale"
            ],
            "description": "`purchase` (inbound from a supplier) or `sale` (outbound to a customer)."
          },
          "hsCode": {
            "type": "string",
            "default": "",
            "description": "Required when the row auto-creates a new article (a blank or placeholder value such as `-` fails the whole order with `articleMissingHsCode`). **For an existing article it is ignored** — unless your workspace has per-order article copies enabled: then the order's copy of the article carries this HS code, and a changed HS code on a re-pushed order creates a new copy version without supplier data (EUDR relevance recomputed; with auto-invite enabled the supplier's invite is widened to it and they are emailed). An article carrying an external article number is never copied per order. Two rows of one order naming one article with different HS codes fail the order with `conflictingHsCodeForArticle`. To change an article's master HS code use `PATCH /api/v1/articles/{id}` or the articles batch import."
          },
          "articleDescription": {
            "type": "string",
            "description": "Name of the new article when the row auto-creates one. Ignored for an existing article."
          },
          "supplierExternalId": {
            "type": "string",
            "description": "External supplier ID from your ERP system"
          },
          "supplierEmail": {
            "type": "string",
            "description": "Used when creating a new supplier during resolution"
          },
          "supplierCountry": {
            "type": "string",
            "description": "Used when creating a new supplier during resolution"
          },
          "supplierAddress": {
            "type": "string",
            "description": "Used when creating a new supplier during resolution"
          },
          "ddsReferenceNumber": {
            "type": "string",
            "maxLength": 14,
            "description": "Existing TRACES reference number to link this order to a DDS statement"
          },
          "ddsVerificationNumber": {
            "type": "string",
            "maxLength": 35,
            "description": "Existing TRACES verification number to link this order to a DDS statement"
          }
        },
        "required": [
          "orderNumber",
          "articleNumber",
          "orderType"
        ],
        "description": "Flat structure for bulk order import. Supplier and article are resolved by name/number. Rows with the same `orderNumber` form one order. Each row must provide at least one of `quantity` or `pieceCount`."
      },
      "BatchSupplierInput": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Supplier company name. Rows upsert on `externalSupplierId`, else on the name."
          },
          "email": {
            "type": "string",
            "default": "",
            "description": "Contact email; may be omitted."
          },
          "contactName": {
            "type": "string",
            "description": "Contact person."
          },
          "country": {
            "type": "string",
            "description": "Country of the supplier. When omitted, the import tries to infer it from `address`."
          },
          "address": {
            "type": "string",
            "description": "Postal address on one line."
          },
          "externalSupplierId": {
            "type": "string",
            "description": "Your ERP id of the supplier."
          },
          "ccEmails": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 320,
              "format": "email"
            },
            "maxItems": 10,
            "description": "Additional contact emails (max 10), copied on every email to this supplier. Additive: addresses already on the supplier are kept, the main `email` is ignored here."
          }
        },
        "required": [
          "name"
        ],
        "description": "One supplier row of a batch import."
      },
      "CommodityGroup": {
        "type": "string",
        "enum": [
          "cattle",
          "cocoa",
          "coffee",
          "oil_palm",
          "rubber",
          "soya",
          "wood",
          "non_relevant"
        ],
        "description": "EUDR-regulated commodity groups. `non_relevant` = article is not covered by EUDR."
      },
      "ComplianceResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the compliance result."
          },
          "supplierArticleId": {
            "type": "string",
            "description": "UUID of the supplier article (one article from one supplier) this result belongs to."
          },
          "overallStatus": {
            "type": "string",
            "description": "One of: `compliant`, `non_compliant`, `invalid`, `unknown`, `not_eudr_relevant`, `pending_review`, `not_required_before_cutoff`, `covered_by_upstream_dds`."
          },
          "geoStatus": {
            "type": "string",
            "description": "One of: `compliant`, `non_compliant`, `invalid`, `unknown`, `not_eudr_relevant`, `pending_review`, `not_required_before_cutoff`, `covered_by_upstream_dds`."
          },
          "legalStatus": {
            "type": "string",
            "description": "One of: `compliant`, `non_compliant`, `invalid`, `unknown`, `not_eudr_relevant`, `pending_review`, `not_required_before_cutoff`, `covered_by_upstream_dds`."
          },
          "manuallyOverridden": {
            "type": "boolean",
            "description": "`true` when a user set this verdict by hand; it may then intentionally differ from what the evidence alone supports."
          },
          "evidenceOpen": {
            "type": "boolean",
            "description": "`true` when the result is `non_compliant` only because no document has been provided yet for the failing legal categories (shown as \"evidence open\" in the app). `false` otherwise."
          },
          "generatedReportUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reserved; not populated by the current platform — expect `null`."
          },
          "generatedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reserved; not populated by the current platform — expect `null`."
          },
          "updatedAt": {
            "type": "string",
            "description": "When the result was last recalculated (ISO 8601, UTC)."
          }
        },
        "required": [
          "id",
          "supplierArticleId",
          "overallStatus",
          "geoStatus",
          "legalStatus",
          "manuallyOverridden",
          "evidenceOpen",
          "generatedReportUrl",
          "generatedAt",
          "updatedAt"
        ]
      },
      "CreateArticleInput": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Article name"
          },
          "shortDescription": {
            "type": "string",
            "description": "Short description of the article."
          },
          "articleType": {
            "type": "string",
            "enum": [
              "purchase",
              "sale"
            ],
            "description": "Defaults to `purchase`. Sale articles are automatically linked to your company as supplier."
          },
          "internalArticleNr": {
            "type": "string",
            "minLength": 1,
            "description": "Internal article number (must be unique per company)"
          },
          "externalArticleNr": {
            "type": "string",
            "description": "External article number, e.g. a supplier's or customer's number."
          },
          "hsCode": {
            "type": "string",
            "minLength": 1,
            "description": "HS code — EUDR relevance and commodity group are determined automatically"
          },
          "ean": {
            "type": "string",
            "description": "EAN / GTIN barcode."
          },
          "weightPerPieceKg": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Weight of one piece in kg; must be greater than 0. Lets order lines be sent as a piece count."
          },
          "sourceScope": {
            "type": "string",
            "enum": [
              "standing",
              "perOrder"
            ],
            "description": "`standing` (default): the source is fixed. `perOrder`: the source varies per order and order import creates one copy of the article per order."
          },
          "supplierId": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "string",
                "enum": [
                  ""
                ]
              }
            ],
            "description": "Link to an existing supplier (recommended — fetch IDs via `GET /api/v1/suppliers`). Required for purchase articles if `supplierName` is not provided."
          },
          "supplierName": {
            "type": "string",
            "description": "Fallback when you have no `supplierId` (prefer `supplierId`). Matched against your existing suppliers ignoring case and surrounding/repeated whitespace; if none matches, a new supplier is created. Required for purchase articles if `supplierId` is not provided."
          },
          "supplierEmail": {
            "anyOf": [
              {
                "type": "string",
                "format": "email"
              },
              {
                "type": "string",
                "enum": [
                  ""
                ]
              }
            ],
            "description": "Optional supplier contact email. Used when creating a new supplier via `supplierName`."
          },
          "eudrRelevant": {
            "type": "boolean",
            "description": "Explicit EUDR classification; overrides the one derived from the HS code."
          },
          "commodityGroup": {
            "type": "string",
            "enum": [
              "cattle",
              "cocoa",
              "coffee",
              "oil_palm",
              "rubber",
              "soya",
              "wood",
              "non_relevant"
            ],
            "description": "Explicit EUDR commodity group; overrides the one derived from the HS code."
          },
          "acknowledgeWarnings": {
            "type": "boolean",
            "description": "Set to `true` to override soft duplicate warnings. If omitted/false and the article triggers a soft warning (duplicate name or duplicate EAN), the request returns `409` with a machine-readable `warnings` array instead of creating the article. A hard duplicate of `internalArticleNr` always returns `409` and cannot be overridden."
          }
        },
        "required": [
          "name",
          "internalArticleNr",
          "hsCode"
        ]
      },
      "CreateDdsInput": {
        "type": "object",
        "properties": {
          "supplierId": {
            "type": "string",
            "format": "uuid",
            "description": "The supplier for this DDS. All articles must be linked to this supplier."
          },
          "type": {
            "type": "string",
            "enum": [
              "import",
              "export",
              "domestic_production"
            ],
            "description": "Activity type: `import`, `export` or `domestic_production`."
          },
          "name": {
            "type": "string",
            "maxLength": 100,
            "description": "Name of the statement (at most 100 characters)."
          },
          "articles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "articleId": {
                  "type": "string",
                  "format": "uuid",
                  "description": "UUID of an article linked to `supplierId`."
                },
                "amount": {
                  "type": "string",
                  "description": "Quantity to declare: net mass in kilograms, as a numeric string ≥ 0 (e.g. `\"1250.5\"`)."
                },
                "supplementaryUnitValue": {
                  "type": "string",
                  "description": "Appendix-I supplementary-unit quantity. Accepted only on import/export lines whose HS code requires one (400 otherwise). Empty or absent = none."
                },
                "percentageEstimationOrDeviation": {
                  "type": "string",
                  "description": "domestic_production only: TRACES percentageEstimationOrDeviation, 0–100 with at most 3 decimals. Absent = submitted as 0; ignored for import/export."
                }
              },
              "required": [
                "articleId",
                "amount"
              ]
            },
            "minItems": 1,
            "maxItems": 500,
            "description": "The article lines to declare: 1–500 lines, each article at most once."
          }
        },
        "required": [
          "supplierId",
          "type",
          "articles"
        ]
      },
      "CreateOrderInput": {
        "type": "object",
        "properties": {
          "supplierId": {
            "type": "string",
            "minLength": 1,
            "description": "UUID of an existing supplier of your company."
          },
          "orderNumber": {
            "type": "string",
            "minLength": 1,
            "description": "Your order number, unique per company."
          },
          "orderDate": {
            "type": "string",
            "description": "ISO 8601 date string"
          },
          "deliveryDate": {
            "type": "string",
            "description": "Optional ISO 8601 delivery date. Often unknown at order time."
          },
          "orderType": {
            "type": "string",
            "enum": [
              "purchase",
              "sale"
            ],
            "description": "`purchase` (inbound from a supplier) or `sale` (outbound to a customer)."
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateOrderLineInput"
            },
            "minItems": 1,
            "description": "The order lines (at least one)."
          }
        },
        "required": [
          "supplierId",
          "orderNumber",
          "orderType",
          "lines"
        ]
      },
      "CreateOrderLineInput": {
        "type": "object",
        "properties": {
          "articleId": {
            "type": "string",
            "minLength": 1,
            "description": "UUID of an existing article of your company."
          },
          "positionId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 64,
            "description": "Optional ERP position id of the line (max 64, trimmed); unique per order. Carried unchanged by the UI editor."
          },
          "quantity": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Net mass in kilograms. Required unless `pieceCount` is provided."
          },
          "pieceCount": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "description": "Number of pieces. Used to derive net mass when `quantity` is omitted."
          },
          "volumeM3": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Volume in m³. Feeds the EUDR DDS supplementary unit (MTQ). Optional and independent of net mass."
          },
          "dryWeight90Kg": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Kilograms of 90 %-dry substance. Feeds the EUDR DDS supplementary unit (KSD) for wood-pulp HS codes."
          },
          "deliveryDate": {
            "type": "string",
            "description": "Optional ISO 8601 delivery date of this position. When any line has one, a line without one takes the order-level `deliveryDate` as its own, and the order's `deliveryDate` is the earliest line date."
          }
        },
        "required": [
          "articleId"
        ],
        "description": "Each line must provide `articleId` and at least one of `quantity` or `pieceCount`. When only `pieceCount` is given, net mass (kg) is derived as `pieceCount × weightPerPieceKg` from the article master data."
      },
      "CreatePlotInput": {
        "type": "object",
        "required": [
          "geojson"
        ],
        "description": "Fields read from the request body. Anything else — including server-owned fields such as `id`, `analysisStatus`, `analysisResult`, `deforestationRiskResult`, `forestPercentage`, `isDegraded`, `imageWidth`, `imageHeight`, `pixelCoords`, `createdAt` and `updatedAt` — is ignored.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Plot name. Part of the duplicate check (case and surrounding/multiple whitespace are ignored)."
          },
          "country": {
            "type": "string",
            "description": "Country of production. Send ISO 3166-1 alpha-2 (e.g. `BR`); the value is stored as sent, not validated. Part of the duplicate check."
          },
          "geojson": {
            "type": "object",
            "description": "Required. Plot geometry as GeoJSON: a Feature or a bare Geometry of type `Polygon`, `MultiPolygon`, `Point` or `MultiPoint`, in WGS84 longitude/latitude. A missing geometry is `400` with `code: plot_geometry_missing`; any other type (`FeatureCollection`, `GeometryCollection`, `LineString`, `MultiLineString`, …) is `400` with `code: plot_geometry_type_unsupported` — one request creates one plot, so send each feature of a collection as its own request. Coordinates outside longitude ±180 / latitude ±90 are rejected with `400`, as is a geometry above the intake limits. A point is only accepted up to 4 ha (20,000 ha when the commodity group is `cattle` — sent, or derived from the links (see Create Plot)) when `size` is given; above that EUDR requires a polygon. Part of the duplicate check."
          },
          "size": {
            "type": "number",
            "minimum": 0,
            "description": "Area in hectares. Must be a finite number ≥ 0, otherwise `400`."
          },
          "commodityGroup": {
            "$ref": "#/components/schemas/CommodityGroup"
          },
          "species": {
            "type": "array",
            "maxItems": 500,
            "items": {
              "$ref": "#/components/schemas/PlotSpecies"
            },
            "description": "Tree species. Each entry needs both a common and a scientific name, otherwise `400`. Required (at least one scientific name) when the plot's commodity group is `wood` — sent, or derived from the links (see Create Plot)."
          },
          "scientificName": {
            "type": "string",
            "description": "Legacy single-species shorthand, used only when `species` is empty. Prefer `species`."
          },
          "producerName": {
            "type": "string",
            "description": "Name of the producer."
          },
          "productionDateFrom": {
            "type": "string",
            "format": "date",
            "description": "Start of the production period (`YYYY-MM-DD`)."
          },
          "productionDateTo": {
            "type": "string",
            "format": "date",
            "description": "End of the production period (`YYYY-MM-DD`)."
          },
          "supplierArticleIds": {
            "type": "array",
            "maxItems": 5000,
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Supplier articles to link the plot to on creation (optional; duplicates are collapsed). Every id must belong to your company, otherwise `403`. Part of the duplicate check: the same plot with a different set of links is a new plot. Not an array (other than `null`, which counts as no links) is `400` with `code: plot_supplier_article_ids_invalid`. The commodity group is sent, or derived from the links (see Create Plot); a value outside the enum is `400` with `code: plot_commodity_group_invalid`."
          }
        }
      },
      "CreateSupplierInput": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Supplier company name"
          },
          "contactName": {
            "type": "string",
            "description": "Contact person name"
          },
          "email": {
            "type": "string",
            "minLength": 1,
            "format": "email",
            "description": "Supplier contact email"
          },
          "externalSupplierId": {
            "type": "string",
            "description": "External ID from your ERP system"
          },
          "country": {
            "type": "string",
            "enum": [
              "Afghanistan",
              "Albania",
              "Algeria",
              "Andorra",
              "Angola",
              "Antigua and Barbuda",
              "Argentina",
              "Armenia",
              "Aruba",
              "Australia",
              "Austria",
              "Azerbaijan",
              "Bahamas",
              "Bahrain",
              "Bangladesh",
              "Barbados",
              "Belarus",
              "Belgium",
              "Belize",
              "Benin",
              "Bermuda",
              "Bhutan",
              "Bolivia",
              "Bosnia and Herzegovina",
              "Botswana",
              "Brazil",
              "British Virgin Islands",
              "Brunei",
              "Bulgaria",
              "Burkina Faso",
              "Burundi",
              "Cabo Verde",
              "Cambodia",
              "Cameroon",
              "Canada",
              "Cayman Islands",
              "Central African Republic",
              "Chad",
              "Chile",
              "China",
              "Colombia",
              "Comoros",
              "Congo (Congo-Brazzaville)",
              "Costa Rica",
              "Côte d'Ivoire",
              "Croatia",
              "Cuba",
              "Curaçao",
              "Cyprus",
              "Czechia",
              "Democratic Republic of the Congo",
              "Denmark",
              "Djibouti",
              "Dominica",
              "Dominican Republic",
              "Ecuador",
              "Egypt",
              "El Salvador",
              "Equatorial Guinea",
              "Eritrea",
              "Estonia",
              "Eswatini",
              "Ethiopia",
              "Faroe Islands",
              "Fiji",
              "Finland",
              "France",
              "French Polynesia",
              "Gabon",
              "Gambia",
              "Georgia",
              "Germany",
              "Ghana",
              "Gibraltar",
              "Greece",
              "Greenland",
              "Grenada",
              "Guatemala",
              "Guernsey",
              "Guinea",
              "Guinea-Bissau",
              "Guyana",
              "Haiti",
              "Honduras",
              "Hong Kong",
              "Hungary",
              "Iceland",
              "India",
              "Indonesia",
              "Iran",
              "Iraq",
              "Ireland",
              "Isle of Man",
              "Israel",
              "Italy",
              "Jamaica",
              "Japan",
              "Jersey",
              "Jordan",
              "Kazakhstan",
              "Kenya",
              "Kiribati",
              "Kosovo",
              "Kuwait",
              "Kyrgyzstan",
              "Laos",
              "Latvia",
              "Lebanon",
              "Lesotho",
              "Liberia",
              "Libya",
              "Liechtenstein",
              "Lithuania",
              "Luxembourg",
              "Macau",
              "Madagascar",
              "Malawi",
              "Malaysia",
              "Maldives",
              "Mali",
              "Malta",
              "Marshall Islands",
              "Mauritania",
              "Mauritius",
              "Mexico",
              "Micronesia",
              "Moldova",
              "Monaco",
              "Mongolia",
              "Montenegro",
              "Morocco",
              "Mozambique",
              "Myanmar (Burma)",
              "Namibia",
              "Nauru",
              "Nepal",
              "Netherlands",
              "New Caledonia",
              "New Zealand",
              "Nicaragua",
              "Niger",
              "Nigeria",
              "North Korea",
              "North Macedonia",
              "Norway",
              "Oman",
              "Pakistan",
              "Palau",
              "Palestine State",
              "Panama",
              "Papua New Guinea",
              "Paraguay",
              "Peru",
              "Philippines",
              "Poland",
              "Portugal",
              "Puerto Rico",
              "Qatar",
              "Romania",
              "Russia",
              "Rwanda",
              "Saint Kitts and Nevis",
              "Saint Lucia",
              "Saint Vincent and the Grenadines",
              "Samoa",
              "San Marino",
              "Sao Tome and Principe",
              "Saudi Arabia",
              "Senegal",
              "Serbia",
              "Seychelles",
              "Sierra Leone",
              "Singapore",
              "Sint Maarten",
              "Slovakia",
              "Slovenia",
              "Solomon Islands",
              "Somalia",
              "South Africa",
              "South Korea",
              "South Sudan",
              "Spain",
              "Sri Lanka",
              "Sudan",
              "Suriname",
              "Sweden",
              "Switzerland",
              "Syria",
              "Taiwan",
              "Tajikistan",
              "Tanzania",
              "Thailand",
              "Timor-Leste",
              "Togo",
              "Tonga",
              "Trinidad and Tobago",
              "Tunisia",
              "Turkey",
              "Turkmenistan",
              "Turks and Caicos Islands",
              "Tuvalu",
              "U.S. Virgin Islands",
              "Uganda",
              "Ukraine",
              "United Arab Emirates",
              "United Kingdom",
              "United States",
              "Uruguay",
              "Uzbekistan",
              "Vanuatu",
              "Vatican City",
              "Venezuela",
              "Vietnam",
              "Yemen",
              "Zambia",
              "Zimbabwe"
            ],
            "description": "Country name (e.g. \"Germany\", \"Brazil\")"
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          },
          "associatedArticles": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of existing article IDs to link to this supplier"
          },
          "ccEmails": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 320,
              "format": "email"
            },
            "maxItems": 10,
            "description": "Additional contact emails (max 10), copied on every email to this supplier. An address equal to `email` is ignored; an invalid address rejects the request."
          }
        },
        "required": [
          "name",
          "email",
          "country",
          "address"
        ]
      },
      "DdsStatement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the DDS statement."
          },
          "companyId": {
            "type": "string",
            "description": "UUID of your company."
          },
          "createdByUserId": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the user who created the statement, or `null`."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Name of the statement, or `null`."
          },
          "country": {
            "type": [
              "string",
              "null"
            ],
            "description": "Country of your company as recorded on its address when the statement was created, or `null`."
          },
          "referenceNumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "TRACES reference number (assigned after submission)"
          },
          "verificationNumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "TRACES verification number (assigned after validation)"
          },
          "tracesUuid": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identifier TRACES assigned on submission; `null` before submission and for external statements."
          },
          "submittedOn": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the statement was submitted to TRACES (ISO 8601, UTC), or `null`."
          },
          "type": {
            "type": "string",
            "description": "Activity type: `import`, `export`, `domestic_production` or `trade` (see `DdsType`)."
          },
          "source": {
            "type": "string",
            "description": "One of: `internal`, `external`."
          },
          "articles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DdsStatementArticle"
            },
            "description": "The declared article lines."
          },
          "orders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Order"
            },
            "description": "Orders assigned to this DDS statement"
          },
          "status": {
            "type": "string",
            "description": "One of: `draft`, `processing`, `submitted`, `validated`, `rejected`, `under_control`, `correction_requested`, `deleted`, `failed`, `external`, `withdrawn`, `archived`, `grouped`."
          },
          "statusUpdatedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When `status` last changed (ISO 8601, UTC), or `null`."
          },
          "errorMessage": {
            "type": [
              "string",
              "null"
            ],
            "description": "Error message if submission failed"
          },
          "declaration": {
            "type": "boolean",
            "description": "Whether the due-diligence declaration has been confirmed for this statement."
          },
          "fullName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Name of the person who signed the declaration, or `null`."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Free-text notes, or `null`."
          },
          "totalVolume": {
            "type": [
              "number",
              "null"
            ],
            "description": "Sum of the lines' `volume`, in kilograms; `null` when any line has a `null` volume."
          },
          "totalAssignedVolume": {
            "type": "number",
            "description": "Sum of the lines' `assignedVolume`, in kilograms."
          },
          "totalRemainingVolume": {
            "type": [
              "number",
              "null"
            ],
            "description": "`totalVolume` minus `totalAssignedVolume`, in kilograms; `null` when `totalVolume` is `null`."
          },
          "verificationResult": {
            "type": [
              "string",
              "null"
            ],
            "description": "External statements only: the last TRACES check of the reference and verification number — `existing_usable`, `existing_non_usable` or `non_existent`; `null` when never checked. Only `existing_usable` means the statement may be relied on."
          },
          "verificationCheckedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When `verificationResult` was obtained (ISO 8601, UTC), or `null`."
          },
          "groupHeadId": {
            "type": [
              "string",
              "null"
            ],
            "description": "On a member of a TRACES statement group: UUID of the group head. `null` on every other statement."
          },
          "memberCount": {
            "type": "number",
            "description": "Number of member statements when this statement is a group head; `0` otherwise."
          },
          "members": {
            "type": "array",
            "items": {},
            "description": "By-id read of a group head only: its member statements. The item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "groupHeadReferenceNumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "By-id read of a group member only: the TRACES reference number of its group head, or `null`."
          }
        },
        "required": [
          "id",
          "companyId",
          "createdByUserId",
          "name",
          "country",
          "referenceNumber",
          "verificationNumber",
          "tracesUuid",
          "submittedOn",
          "type",
          "source",
          "articles",
          "orders",
          "status",
          "statusUpdatedAt",
          "errorMessage",
          "declaration",
          "fullName",
          "notes",
          "totalVolume",
          "totalAssignedVolume",
          "totalRemainingVolume",
          "verificationResult",
          "verificationCheckedAt",
          "groupHeadId",
          "memberCount"
        ]
      },
      "DdsStatementArticle": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the DDS line."
          },
          "ddsStatementId": {
            "type": "string",
            "description": "UUID of the DDS statement this line belongs to."
          },
          "supplierArticleId": {
            "type": "string",
            "description": "UUID of the supplier article (the article from one supplier) the line declares."
          },
          "volume": {
            "type": [
              "number",
              "null"
            ],
            "description": "Declared quantity of the line: net mass in kilograms. `null` only on an external (upstream) statement whose reference was declared without a quantity."
          },
          "supplementaryUnitValue": {
            "type": [
              "number",
              "null"
            ],
            "description": "Quantity in the TRACES supplementary unit the line's HS code requires (e.g. m³), or `null`."
          },
          "percentageEstimationOrDeviation": {
            "type": [
              "number",
              "null"
            ],
            "description": "TRACES percentageEstimationOrDeviation of a domestic_production line (0–100, ≤3 decimals); null = not entered, submitted as 0."
          },
          "article": {
            "$ref": "#/components/schemas/Article"
          },
          "supplier": {
            "$ref": "#/components/schemas/Supplier"
          },
          "plots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlotListItem"
            },
            "description": "The line's declared plots without geometry, at most 1000 (ordered by id); fetch geometry via GET /plots/{id}."
          },
          "plotsTruncated": {
            "type": "boolean",
            "description": "true when the line declares more than 1000 plots and `plots` holds only the first 1000 by id."
          },
          "assignedVolume": {
            "type": "number",
            "description": "Part of `volume` already assigned to linked orders, in kilograms."
          },
          "remainingVolume": {
            "type": [
              "number",
              "null"
            ],
            "description": "Part of `volume` not yet assigned to orders, in kilograms; `null` when `volume` is `null`."
          }
        },
        "required": [
          "id",
          "ddsStatementId",
          "supplierArticleId",
          "volume",
          "supplementaryUnitValue",
          "percentageEstimationOrDeviation",
          "article",
          "plots",
          "plotsTruncated",
          "assignedVolume",
          "remainingVolume"
        ]
      },
      "DdsType": {
        "type": "string",
        "enum": [
          "import",
          "export",
          "trade",
          "domestic_production"
        ],
        "description": "`import` = goods entering the EU, `export` = goods leaving the EU, `domestic_production` = produced within the EU (submitted to TRACES as DOMESTIC), `trade` = legacy intra-EU trade (read-only; TRACES V3 removed TRADE, never submitted)"
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable message, or a stable machine key (e.g. `batchTooLarge`, `overwriteRequired`, `duplicate`) on the batch, PPWR and upload endpoints."
          },
          "code": {
            "type": "string",
            "description": "Stable machine code on some `400` and `409` answers, e.g. `plot_geometry_invalid` or `FORK_HAS_ORDER`. Match on it rather than on `error`. Further flat keys may accompany it (e.g. `precisionDigits`, `field`)."
          },
          "details": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationIssue"
            },
            "description": "The validation issues on a `400` validation error."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "enum": [
                    "duplicateName",
                    "duplicateEan"
                  ],
                  "description": "`duplicateName`: a live article of your company already has this name. `duplicateEan`: a live article already has this EAN."
                },
                "existingInternalArticleNr": {
                  "type": "string",
                  "description": "`duplicateName` only: internal article number of the existing article."
                },
                "existingArticleName": {
                  "type": "string",
                  "description": "`duplicateEan` only: name of the existing article."
                }
              },
              "required": [
                "type"
              ]
            },
            "description": "`POST /articles` `409` only: soft duplicate warnings. Resend with `acknowledgeWarnings: true` to create the article anyway."
          }
        },
        "required": [
          "error"
        ],
        "additionalProperties": {},
        "description": "Error body of every endpoint except the `429` the edge answers. Some errors add flat machine-readable keys next to `error`, e.g. `maxBatchSize` on `413 batchTooLarge` or `confirmUpdateCount` on `409 overwriteRequired`."
      },
      "Evidence": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The new evidence document's id."
          },
          "s3Key": {
            "type": "string",
            "description": "Storage key of the stored file."
          },
          "fileName": {
            "type": "string",
            "description": "File name as stored."
          },
          "fileSize": {
            "type": "number",
            "description": "Size of the stored file in bytes."
          },
          "mimeType": {
            "type": "string",
            "description": "MIME type of the stored file."
          },
          "message": {
            "type": "string",
            "description": "Human-readable confirmation, e.g. that the analysis is in progress."
          }
        },
        "required": [
          "id",
          "s3Key",
          "fileName",
          "fileSize",
          "mimeType",
          "message"
        ]
      },
      "EvidenceDocument": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the evidence document."
          },
          "supplierArticleId": {
            "type": "string",
            "description": "UUID of the supplier article the document is attached to."
          },
          "supplierId": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the supplier, or `null`."
          },
          "fileName": {
            "type": "string",
            "description": "File name."
          },
          "fileSize": {
            "type": "number",
            "description": "File size in bytes."
          },
          "mimeType": {
            "type": "string",
            "description": "MIME type of the file."
          },
          "evidenceType": {
            "type": "string",
            "description": "`legal_compliance`, `geo_compliance` or `questionnaire`."
          },
          "sourceType": {
            "type": "string",
            "description": "How the document arrived: `user_upload`, `api` or `email_ingest`."
          },
          "verificationStatus": {
            "type": "string",
            "description": "`unverified`, `auto_verified`, `manually_verified` or `rejected`."
          },
          "supplierAuthored": {
            "type": "boolean",
            "description": "`true` when the supplier provided the document themselves (supplier portal or invitation link); `false` for documents your company uploaded."
          },
          "uploadedAt": {
            "type": "string",
            "description": "When the document was uploaded (ISO 8601, UTC)."
          },
          "validUntil": {
            "type": [
              "string",
              "null"
            ],
            "description": "Expiry date of the document when known (ISO 8601, UTC), or `null`."
          },
          "mappings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "UUID of the mapping."
                },
                "evidenceId": {
                  "type": "string",
                  "description": "UUID of the evidence document."
                },
                "supplierArticleId": {
                  "type": "string",
                  "description": "UUID of the supplier article the mapping applies to."
                },
                "category": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "EUDR legal category the document was mapped to (e.g. `land_use_rights`), or `null`."
                },
                "documentType": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Type of legal document recognised (e.g. `land_rights`, `environmental_permit`), or `null`."
                },
                "countryCode": {
                  "type": "string",
                  "description": "Country the mapping applies to, ISO 3166-1 alpha-2; empty string when not country-specific."
                },
                "status": {
                  "type": "string",
                  "description": "`proposed` (suggested by the analysis), `accepted` or `rejected`."
                },
                "confidence": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Confidence of the analysis in this mapping, or `null`."
                },
                "decidedAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "When the mapping was accepted or rejected (ISO 8601, UTC), or `null`."
                }
              },
              "required": [
                "id",
                "evidenceId",
                "supplierArticleId",
                "category",
                "documentType",
                "countryCode",
                "status",
                "confidence",
                "decidedAt"
              ]
            },
            "description": "How the document was mapped to legal categories for this supplier article."
          }
        },
        "required": [
          "id",
          "supplierArticleId",
          "supplierId",
          "fileName",
          "fileSize",
          "mimeType",
          "evidenceType",
          "sourceType",
          "verificationStatus",
          "supplierAuthored",
          "uploadedAt",
          "validUntil",
          "mappings"
        ]
      },
      "EvidenceDuplicate": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "duplicate"
            ],
            "description": "Always `duplicate`."
          },
          "existing": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "UUID of the existing evidence document with the same bytes."
              },
              "fileName": {
                "type": "string",
                "description": "File name of the existing document."
              }
            },
            "required": [
              "id",
              "fileName"
            ],
            "description": "The live document that already has these exact bytes."
          }
        },
        "required": [
          "error",
          "existing"
        ]
      },
      "EvidenceInput": {
        "type": "object",
        "properties": {
          "supplierId": {
            "type": "string",
            "format": "uuid",
            "description": "The supplier of the supplier link (`supplierLinks[].supplierId` of the article)."
          },
          "articleId": {
            "type": "string",
            "format": "uuid",
            "description": "The article — for per-order origin, the per-order fork's id."
          },
          "uploadedS3Key": {
            "type": "string",
            "description": "The `s3Key` from `POST /api/v1/evidence/upload-url`, after the `PUT`."
          },
          "uploadedFileName": {
            "type": "string",
            "description": "File name; required with `uploadedS3Key`."
          },
          "uploadedFileSize": {
            "type": "string",
            "description": "Size in bytes (a form field, so a string); required with `uploadedS3Key`."
          },
          "uploadedMimeType": {
            "type": "string",
            "description": "MIME type; required with `uploadedS3Key`."
          },
          "reuseS3Key": {
            "type": "string",
            "description": "The `s3Key` returned by an earlier successful `POST /api/v1/evidence`. Reuses that company-owned file for this target without another upload; do not send `file` or `uploaded*` fields with it."
          },
          "file": {
            "type": "string",
            "description": "The file itself, instead of the `uploaded*` fields — small files only (at most 4.5 MB, the platform request cap); use the upload URL for anything larger."
          },
          "evidenceType": {
            "type": "string",
            "enum": [
              "legal_compliance",
              "questionnaire"
            ],
            "description": "Default `legal_compliance`."
          },
          "note": {
            "type": "string",
            "description": "Free-text note for the document. It is passed to the document analysis as context."
          },
          "certificationScheme": {
            "type": "string",
            "description": "The certification scheme the document belongs to (e.g. `FSC`). It is passed to the document analysis as a hint, and the document is then analysed as a risk-mitigation certificate."
          },
          "allowDuplicate": {
            "type": "string",
            "enum": [
              "true"
            ],
            "description": "Send `true` to store a second copy of a file that a `409` reported as a duplicate."
          }
        },
        "required": [
          "supplierId",
          "articleId"
        ]
      },
      "EvidenceUploadUrl": {
        "type": "object",
        "properties": {
          "uploadUrl": {
            "type": "string",
            "description": "Presigned S3 PUT URL, valid for 10 minutes. Send the file bytes with the same `Content-Type`."
          },
          "s3Key": {
            "type": "string",
            "description": "The staging key — pass it as `uploadedS3Key` to `POST /api/v1/evidence`."
          }
        },
        "required": [
          "uploadUrl",
          "s3Key"
        ]
      },
      "EvidenceUploadUrlInput": {
        "type": "object",
        "properties": {
          "fileName": {
            "type": "string",
            "minLength": 1,
            "description": "Name of the file to upload, including its extension."
          },
          "contentType": {
            "type": "string",
            "minLength": 1,
            "description": "MIME type of the file (e.g. `application/pdf`). Send the same value as `Content-Type` when uploading to `uploadUrl`."
          },
          "fileSize": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "description": "Size of the file in bytes. It is signed into `uploadUrl`: the `PUT` must send exactly this many bytes."
          }
        },
        "required": [
          "fileName",
          "contentType",
          "fileSize"
        ],
        "description": "The file to upload: name, MIME type and size in bytes."
      },
      "GenerateMengenmeldungInput": {
        "type": "object",
        "properties": {
          "periodYear": {
            "type": "integer",
            "minimum": 2000,
            "maximum": 2100,
            "description": "Calendar year to report (2000–2100)."
          },
          "market": {
            "type": "string",
            "pattern": "^[A-Z]{2}$",
            "description": "ISO alpha-2 (case-insensitive)."
          },
          "format": {
            "type": "string",
            "enum": [
              "lucid_de",
              "verpact_nl",
              "ara_at",
              "bdo_pl",
              "miteco_es",
              "conai_it"
            ],
            "description": "The register: `lucid_de` (Germany, LUCID XML) or one of the worksheet registers (`verpact_nl`, `ara_at`, `bdo_pl`, `miteco_es`, `conai_it`). `market` must match the register."
          },
          "reportType": {
            "type": "string",
            "enum": [
              "HPM1",
              "HMM1",
              "HJM1",
              "HNM1",
              "HAM1"
            ],
            "description": "`lucid_de` only: the LUCID report type (`HPM1` plan, `HMM1` intra-year, `HJM1` year-end, `HNM1` supplementary, `HAM1` deduction). Worksheet registers always report `ANNUAL`."
          },
          "systemOperatorId": {
            "type": "string",
            "pattern": "^[A-Z]{2}[0-9]{13}$",
            "description": "Your dual system's LUCID number: two letters + 13 digits (lower case is accepted and upper-cased). For `lucid_de`, omit it to use the SystemOperatorID stored in your workspace; a value sent here wins. Without either, `lucid_de` answers `400`. Unused by the worksheet registers."
          }
        },
        "required": [
          "periodYear",
          "market",
          "format"
        ],
        "description": "Trigger a report generation. `reportType` is **required for `lucid_de`**; `systemOperatorId` is too, unless your workspace stores one (then it is the default). Both are unused by the worksheet registers, which always produce the annual report."
      },
      "ImportJob": {
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string",
            "description": "UUID of the import job."
          },
          "kind": {
            "type": "string",
            "description": "articles | suppliers | orders, or a PPWR kind (ppwr_units | ppwr_components | ppwr_article_links | ppwr_formats | ppwr_quantities), or `plots` (a large plot-file import committed in the app)."
          },
          "source": {
            "type": "string",
            "description": "`erp` = staged by this API; `ui` = a CSV import run in the app."
          },
          "runId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Null for `erp` jobs; set when a UI upload was recorded in accumulated form."
          },
          "status": {
            "type": "string",
            "description": "queued | running | completed | failed"
          },
          "progress": {
            "$ref": "#/components/schemas/ImportJobProgress"
          },
          "result": {
            "description": "The merged result, `null` until the job is `completed` (a failed `plots` job may carry the partial result). Its shape depends on `kind`:\n\n- `articles`: `{ imported: [{ internalArticleNr, id }], updated: [{ internalArticleNr }], failed: [{ internalArticleNr, error }], skipped, skippedRows: [{ key, reason }], consolidatedRows }`\n- `suppliers`: `{ imported: [{ id, name, country }], updated: [{ name, country }], failed: [{ name, error }], skipped, inferredCountryCount, contactsAdded: [{ id, supplierId, email }] }`\n- `orders`: `{ imported: [{ id, orderNumber }], updated: [{ id, orderNumber }], failed: [{ orderNumber, error }], skipped, skippedOrders: [{ id, orderNumber }], autoCreated: { suppliers, articles, supplierArticleLinks } }`\n- `ppwr_quantities`: `{ imported, updated, deleted, failed[], derived, cleared, conflicts[], multiLinkedArticleNrs[] }` — `derived`, `cleared` and `conflicts` count packaging units of the touched period/market scopes, read before and after the batch (feed figures are computed at read, never stored): units counting the feed after it, units that stopped counting it, and units using typed figures instead (one conflict per unit). `multiLinkedArticleNrs` lists the article numbers whose quantity feeds more than one packaging unit (an article can be linked to several units, e.g. sales plus transport packaging), so the same quantity counts on each linked unit. Informational, never blocking.\n\n`skipped` is a count. Each `failed[].error` is `{ key, params? }`: a stable machine key plus its parameters."
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Stable machine key when `status` is `failed` — e.g. `workerError`, `dispatchFailed`, or a JSON string for structured failures: `{\"key\":\"lineReplacementRequired\",\"orderNumbers\":[…]}` or `{\"key\":\"invalidPayload\",\"issues\":[{\"path\",\"code\"}]}`. Never contains payload values."
          },
          "createdAt": {
            "type": "string",
            "description": "When the job was staged (ISO 8601, UTC)."
          },
          "finishedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the job reached `completed` or `failed` (ISO 8601, UTC); `null` while it is still running."
          }
        },
        "required": [
          "jobId",
          "kind",
          "source",
          "runId",
          "status",
          "progress",
          "error",
          "createdAt",
          "finishedAt"
        ],
        "description": "Async batch import job. `completed` and `failed` are terminal — stop polling. The staged input payload is freed ~24 h after the job finishes and the job row itself is deleted ~30 days after creation; poll and persist the result within that window."
      },
      "ImportJobAccepted": {
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string",
            "description": "UUID of the staged import job — pass it to `GET /api/v1/import-jobs/{jobId}`."
          },
          "status": {
            "type": "string",
            "description": "Always `queued` — nothing is imported yet."
          },
          "statusUrl": {
            "type": "string",
            "description": "The poll URL, also sent as the `Location` header."
          }
        },
        "required": [
          "jobId",
          "status",
          "statusUrl"
        ],
        "description": "Batch import staged as an async job. Nothing is imported yet — poll `statusUrl` for progress and the final result."
      },
      "ImportJobProgress": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number",
            "description": "Rows accepted into the job"
          },
          "processed": {
            "type": "number",
            "description": "Rows processed so far (authoritative once the job is terminal)"
          },
          "failed": {
            "type": "number",
            "description": "Rows that failed with a per-row error"
          }
        },
        "required": [
          "total",
          "processed",
          "failed"
        ]
      },
      "MengenmeldungBlockingError": {
        "type": "object",
        "description": "One reason the data is not declarable yet. The element shape differs by register family — `familyLabelsDe` is LUCID only; `packagingSpecId`, `componentId` and `candidates` are worksheet-register only.",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "missing_mass",
              "ambiguous_material",
              "ambiguous_multi_material",
              "unmapped_material",
              "missing_channel",
              "placement_needs_format",
              "placement_both_levels"
            ],
            "description": "`missing_mass` — a component in a linked unit has no weight. `ambiguous_material` — a material whose register category cannot be derived (LUCID: the metal and composite families). `ambiguous_multi_material` — a multi-material component whose mass split is unknowable. `unmapped_material` and `missing_channel` — worksheet registers only. `placement_needs_format` — a unit-level figure cannot be converted to mass because its sizes weigh a component differently; enter the figure per size. `placement_both_levels` — a unit holds a unit-level figure and per-size figures; they are never added, put the unit's total on one level (component fields are empty). Clients must accept kinds added later."
          },
          "specRef": {
            "type": "string",
            "description": "`internalRef` of the packaging unit."
          },
          "packagingSpecId": {
            "type": "string",
            "format": "uuid",
            "description": "Worksheet registers only: UUID of the packaging unit concerned."
          },
          "componentId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "UUID of the component concerned, or `null` when the problem is not tied to one component."
          },
          "componentCode": {
            "type": [
              "string",
              "null"
            ],
            "description": "`code` of the component concerned, or `null`."
          },
          "componentName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Name of the component concerned, or `null`."
          },
          "material": {
            "type": [
              "string",
              "null"
            ],
            "description": "The material family concerned (e.g. `metal`), or `null`."
          },
          "familyLabelsDe": {
            "type": [
              "string",
              "null"
            ],
            "description": "LUCID only: the German labels of the category family that must be declared with figures."
          },
          "candidates": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "description": "Code of the register category."
                },
                "label": {
                  "type": "string",
                  "description": "Name of the register category."
                }
              }
            },
            "description": "Worksheet registers only: the register categories this component could be mapped to (mapped once in the app)."
          }
        }
      },
      "MengenmeldungNotDeclarable": {
        "type": "object",
        "description": "The data is not declarable yet — **nothing was written**.",
        "required": [
          "error",
          "blockingErrors"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "blocking_errors",
              "nothing_to_declare"
            ],
            "description": "`blocking_errors` — the listed data-quality problems must be fixed first. `nothing_to_declare` — no declarable figures exist for that period and market (`blockingErrors` is empty)."
          },
          "blockingErrors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MengenmeldungBlockingError"
            },
            "description": "What must be fixed before the report can be generated, item by item. Empty for `nothing_to_declare`."
          }
        }
      },
      "MengenmeldungReport": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the report — what `GET /api/v1/ppwr/mengenmeldung/{reportId}/xml` takes."
          },
          "periodYear": {
            "type": "number",
            "description": "Calendar year the report covers."
          },
          "market": {
            "type": "string",
            "description": "ISO alpha-2 market code."
          },
          "format": {
            "type": "string",
            "description": "One of: `lucid_de`, `austria_edm`, `verpact_nl`, `ara_at`, `bdo_pl`, `miteco_es`, `conai_it`."
          },
          "reportType": {
            "type": "string",
            "description": "The LUCID Meldungsart for `lucid_de`; worksheet registers always report `ANNUAL`. One of: `HPM1`, `HMM1`, `HJM1`, `HNM1`, `HAM1`, `ANNUAL`."
          },
          "systemOperatorId": {
            "type": "string",
            "description": "The dual system's LUCID number the volumes are reported under. Empty string for worksheet registers, which have no system operator."
          },
          "xsdVersion": {
            "type": "string",
            "description": "The LUCID XML interface version the file was built against; `worksheet-<n>` for worksheet registers, which have no XSD."
          },
          "status": {
            "type": "string",
            "description": "generated | superseded"
          },
          "version": {
            "type": "number",
            "description": "Version of the report within its (`periodYear`, `market`, `format`) scope; each regeneration increments it."
          },
          "supersedesId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The report this one replaced, or `null`."
          },
          "snapshotHash": {
            "type": "string",
            "description": "SHA-256 of the frozen snapshot."
          },
          "generatedAt": {
            "type": "string",
            "description": "When the report was generated (ISO 8601, UTC)."
          }
        },
        "required": [
          "id",
          "periodYear",
          "market",
          "format",
          "reportType",
          "systemOperatorId",
          "xsdVersion",
          "status",
          "version",
          "supersedesId",
          "snapshotHash",
          "generatedAt"
        ],
        "description": "Metadata of a generated report. The frozen computation snapshot is never returned — download the artifact from `GET /api/v1/ppwr/mengenmeldung/{reportId}/xml`."
      },
      "MengenmeldungStatus": {
        "type": "string",
        "enum": [
          "generated",
          "superseded"
        ],
        "description": "Exactly one report per (`periodYear`, `market`, `format`) is `generated` — that is the one to download."
      },
      "Order": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the order."
          },
          "supplier": {
            "$ref": "#/components/schemas/Supplier"
          },
          "orderNumber": {
            "type": "string",
            "description": "Your order number, unique per company — the key batch imports upsert on."
          },
          "orderDate": {
            "type": [
              "string",
              "null"
            ],
            "description": "Order date (ISO 8601, UTC), or `null`."
          },
          "deliveryDate": {
            "type": [
              "string",
              "null"
            ],
            "description": "Delivery date (ISO 8601, UTC), or `null` when not known. When the lines carry their own dates (`lines[].deliveryDate`), the earliest of them."
          },
          "orderType": {
            "type": "string",
            "description": "`purchase` (inbound from a supplier) or `sale` (outbound to a customer)."
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderLine"
            },
            "description": "The order lines."
          },
          "totalVolume": {
            "type": "number",
            "description": "Sum of all order line quantities"
          },
          "ddsReferences": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "UUID of the linked DDS statement."
                },
                "referenceNumber": {
                  "type": "string",
                  "description": "TRACES reference number of a linked DDS. Empty/absent until the DDS is submitted — linkage is not submission."
                },
                "verificationNumber": {
                  "type": "string",
                  "description": "TRACES verification number of the linked DDS. Empty or absent until TRACES has validated the DDS."
                }
              },
              "required": [
                "id"
              ]
            },
            "description": "The TRACES referenceNumber / verificationNumber pairs of the live DDS statements linked to this order. A withdrawn or rejected statement is not listed; an archived one stays."
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "done",
              "notRelevant"
            ],
            "description": "Derived EUDR status of the order, recomputed on every read (never stored). `notRelevant`: no line carries an EUDR-relevant article AND no line's article awaits the manual EUDR check (`lines[].article.needsManualCheck`) — such a line counts as EUDR-relevant below until a person resolves the check. `done`: every EUDR-relevant line is covered by a submitted, validated or grouped DDS linked to THIS order that declares the line's article FOR THE ORDER'S SUPPLIER with enough remaining volume (the article's quantity over all orders of that supplier linked to that DDS does not exceed its declared volume; an order of another supplier linked by hand stays open). `open`: otherwise — including after a quantity increase beyond the declared volume, an article change, or a withdrawn/rejected DDS."
          }
        },
        "required": [
          "id",
          "supplier",
          "orderNumber",
          "orderDate",
          "deliveryDate",
          "orderType",
          "lines",
          "totalVolume",
          "ddsReferences",
          "status"
        ]
      },
      "OrderLine": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the order line."
          },
          "article": {
            "$ref": "#/components/schemas/Article"
          },
          "quantity": {
            "type": "number",
            "description": "Net mass in kilograms. Derived from `pieceCount × weightPerPieceKg` when the line was created with `pieceCount` instead of `quantity`."
          },
          "pieceCount": {
            "type": [
              "number",
              "null"
            ],
            "description": "Number of pieces, when the line was quantified by piece count rather than net mass."
          },
          "volumeM3": {
            "type": [
              "number",
              "null"
            ],
            "description": "Volume in m³. Feeds the EUDR DDS supplementary unit (MTQ) for HS codes that require it."
          },
          "dryWeight90Kg": {
            "type": [
              "number",
              "null"
            ],
            "description": "Kilograms of 90 %-dry substance. Feeds the EUDR DDS supplementary unit (KSD) for wood-pulp HS codes."
          },
          "positionId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The ERP's position id of this line (SAP item number), when the line was imported with one."
          },
          "deliveryDate": {
            "type": [
              "string",
              "null"
            ],
            "description": "This position's own delivery date (ISO 8601, UTC), when imported with one; `null` = the order's `deliveryDate` applies."
          }
        },
        "required": [
          "id",
          "article",
          "quantity",
          "pieceCount",
          "volumeM3",
          "dryWeight90Kg"
        ]
      },
      "OrderType": {
        "type": "string",
        "enum": [
          "purchase",
          "sale"
        ],
        "description": "`purchase` = inbound order from a supplier, `sale` = outbound order to a customer"
      },
      "OriginConfirmationAccepted": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "queued"
            ],
            "description": "The confirmation request was accepted for asynchronous processing."
          },
          "orderId": {
            "type": "string",
            "format": "uuid",
            "description": "The exact order whose current origin data will be presented to the supplier."
          },
          "supplierArticleCount": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "description": "Number of distinct supplier-article targets queued."
          }
        },
        "required": [
          "status",
          "orderId",
          "supplierArticleCount"
        ]
      },
      "OriginConfirmationInput": {
        "type": "object",
        "properties": {
          "supplierArticleIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Live supplier-article links on this exact order whose current buyer-provided origin data is complete."
          }
        },
        "required": [
          "supplierArticleIds"
        ]
      },
      "Plot": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the plot."
          },
          "companyId": {
            "type": "string",
            "description": "UUID of your company (the plot's owner)."
          },
          "createdByUserId": {
            "type": "string",
            "description": "UUID of the user who created the plot (for an API key: the user the key acts as); absent when unknown."
          },
          "name": {
            "type": "string",
            "description": "Plot name; empty string when none was given."
          },
          "species": {
            "type": "array",
            "items": {},
            "description": "Tree species recorded for the plot (entries as sent on create, with `commonName` and `scientificName`). The item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "country": {
            "type": "string",
            "description": "Country as sent on create; ISO 3166-1 alpha-2 (e.g. `BR`) expected but not validated. Empty string when unknown."
          },
          "size": {
            "type": "number",
            "description": "Declared area in hectares; `0` when none was given."
          },
          "requiresAreaPlausibilityReview": {
            "type": "boolean",
            "description": "`true` when the declared or the measured area exceeds 10,000 ha, so the area should be checked by a person."
          },
          "commodityGroup": {
            "type": [
              "string",
              "null"
            ],
            "description": "EUDR commodity group of the plot (a `CommodityGroup` value), or `null`."
          },
          "deforestationRiskResult": {
            "type": [
              "number",
              "null"
            ],
            "description": "Stored deforestation risk as a number: `0` low, `2` moderate, `1` high; `null` when no result is stored or the analysis was invalid. `GET /api/v1/plots/{id}` carries the readable `analysis.riskLevel`."
          },
          "productionDateFrom": {
            "type": "string",
            "description": "Start of the production period (ISO 8601, midnight UTC of the stored day); absent when not set."
          },
          "productionDateTo": {
            "type": "string",
            "description": "End of the production period (ISO 8601, midnight UTC of the stored day); absent when not set."
          },
          "producerName": {
            "type": "string",
            "description": "Name of the producer; absent when not set."
          },
          "importSourceFormat": {
            "type": "string",
            "description": "File format the plot was imported from in the app: `geojson`, `wkt`, `point_csv`, `kml`, `kmz` or `document_extraction`; absent otherwise."
          },
          "importPrecisionClass": {
            "type": "string",
            "description": "Coordinate precision class measured at import: `ok` (6 or more decimals), `borderline` (5), `low` (4), `reject` (3 or fewer) or `mixed`; absent when not measured."
          },
          "importPrecisionDigits": {
            "type": "number",
            "description": "Fewest decimal places of any coordinate, as measured at import; absent when not measured."
          },
          "importPrecisionAcceptedAt": {
            "type": "string",
            "description": "When the plot's coordinate precision was accepted despite being below the EUDR format (ISO 8601, UTC); absent when no acceptance is recorded."
          },
          "importPrecisionAcceptedBy": {
            "type": "string",
            "description": "UUID of the user who accepted the coordinate precision; absent when no user is recorded."
          },
          "importPrecisionAcceptedByName": {
            "type": "string",
            "description": "Name of the user who accepted the coordinate precision; absent when not known."
          },
          "importOriginalCentroidLng": {
            "type": "number",
            "description": "Longitude of the centroid of the geometry as originally imported (e.g. before a point was turned into a circle); absent when not recorded."
          },
          "importOriginalCentroidLat": {
            "type": "number",
            "description": "Latitude of the centroid of the geometry as originally imported; absent when not recorded."
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the plot was created (ISO 8601, UTC), or `null`."
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the plot was last changed (ISO 8601, UTC), or `null`."
          },
          "analysisStatus": {
            "type": "string",
            "description": "State of the deforestation analysis: `pending`, `in_progress`, `completed`, `failed`, `exempt` or `skipped`."
          },
          "forestPercentage": {
            "type": "number",
            "description": "Share of the plot that is forest in the JRC Global Forest Cover 2020 map, in percent; absent until measured."
          },
          "isDegraded": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the plot carries an unresolved forest-degradation risk (wood only); `null` when not determined."
          },
          "geojson": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "The stored geometry as GeoJSON (RFC 7946): a Feature or a bare Geometry in WGS84 longitude/latitude; `null` when none is stored."
          },
          "supplierArticleIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "UUIDs of the supplier articles the plot is linked to."
          }
        },
        "required": [
          "id",
          "companyId",
          "name",
          "species",
          "country",
          "size",
          "requiresAreaPlausibilityReview",
          "commodityGroup",
          "deforestationRiskResult",
          "createdAt",
          "updatedAt",
          "analysisStatus",
          "isDegraded",
          "geojson",
          "supplierArticleIds"
        ]
      },
      "PlotAnalysis": {
        "type": "object",
        "properties": {
          "riskLevel": {
            "type": "string",
            "enum": [
              "LOW",
              "MODERATE",
              "HIGH",
              "INVALID"
            ],
            "description": "The stored risk level of the analysis. `LOW`, `MODERATE`, `HIGH`, or `INVALID` (the plot or data-quality checks failed; `analysisStatus` is then `failed`). New values may be added; treat a value you do not know as needing review."
          },
          "assessedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the stored result was produced (ISO 8601), or `null` when the record does not say. Not the plot's `updatedAt`."
          },
          "conclusion": {
            "type": "string",
            "description": "The report's conclusion sentence for this risk level. A geospatial risk assessment, not a standalone determination of EUDR compliance."
          },
          "limitations": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What the stored result does not establish, as the report prints it after \"Limitations:\". Empty when there is none."
          },
          "evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlotEvidenceRow"
            },
            "description": "The report's technical evidence register: one row per dataset, in report order."
          }
        },
        "required": [
          "riskLevel",
          "assessedAt",
          "conclusion",
          "limitations",
          "evidence"
        ],
        "description": "The stored geo analysis result of a plot. This is a geospatial risk assessment, not a standalone determination of EUDR compliance. English only; `conclusion`, `limitations` and `evidence` are the texts the plot report prints for the same stored result (the report prints the scope sentence above as its own line)."
      },
      "PlotDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the plot."
          },
          "companyId": {
            "type": "string",
            "description": "UUID of your company (the plot's owner)."
          },
          "createdByUserId": {
            "type": "string",
            "description": "UUID of the user who created the plot (for an API key: the user the key acts as); absent when unknown."
          },
          "name": {
            "type": "string",
            "description": "Plot name; empty string when none was given."
          },
          "species": {
            "type": "array",
            "items": {},
            "description": "Tree species recorded for the plot (entries as sent on create, with `commonName` and `scientificName`). The item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "country": {
            "type": "string",
            "description": "Country as sent on create; ISO 3166-1 alpha-2 (e.g. `BR`) expected but not validated. Empty string when unknown."
          },
          "size": {
            "type": "number",
            "description": "Declared area in hectares; `0` when none was given."
          },
          "requiresAreaPlausibilityReview": {
            "type": "boolean",
            "description": "`true` when the declared or the measured area exceeds 10,000 ha, so the area should be checked by a person."
          },
          "commodityGroup": {
            "type": [
              "string",
              "null"
            ],
            "description": "EUDR commodity group of the plot (a `CommodityGroup` value), or `null`."
          },
          "deforestationRiskResult": {
            "type": [
              "number",
              "null"
            ],
            "description": "Stored deforestation risk as a number: `0` low, `2` moderate, `1` high; `null` when no result is stored or the analysis was invalid. `GET /api/v1/plots/{id}` carries the readable `analysis.riskLevel`."
          },
          "productionDateFrom": {
            "type": "string",
            "description": "Start of the production period (ISO 8601, midnight UTC of the stored day); absent when not set."
          },
          "productionDateTo": {
            "type": "string",
            "description": "End of the production period (ISO 8601, midnight UTC of the stored day); absent when not set."
          },
          "producerName": {
            "type": "string",
            "description": "Name of the producer; absent when not set."
          },
          "importSourceFormat": {
            "type": "string",
            "description": "File format the plot was imported from in the app: `geojson`, `wkt`, `point_csv`, `kml`, `kmz` or `document_extraction`; absent otherwise."
          },
          "importPrecisionClass": {
            "type": "string",
            "description": "Coordinate precision class measured at import: `ok` (6 or more decimals), `borderline` (5), `low` (4), `reject` (3 or fewer) or `mixed`; absent when not measured."
          },
          "importPrecisionDigits": {
            "type": "number",
            "description": "Fewest decimal places of any coordinate, as measured at import; absent when not measured."
          },
          "importPrecisionAcceptedAt": {
            "type": "string",
            "description": "When the plot's coordinate precision was accepted despite being below the EUDR format (ISO 8601, UTC); absent when no acceptance is recorded."
          },
          "importPrecisionAcceptedBy": {
            "type": "string",
            "description": "UUID of the user who accepted the coordinate precision; absent when no user is recorded."
          },
          "importPrecisionAcceptedByName": {
            "type": "string",
            "description": "Name of the user who accepted the coordinate precision; absent when not known."
          },
          "importOriginalCentroidLng": {
            "type": "number",
            "description": "Longitude of the centroid of the geometry as originally imported (e.g. before a point was turned into a circle); absent when not recorded."
          },
          "importOriginalCentroidLat": {
            "type": "number",
            "description": "Latitude of the centroid of the geometry as originally imported; absent when not recorded."
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the plot was created (ISO 8601, UTC), or `null`."
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the plot was last changed (ISO 8601, UTC), or `null`."
          },
          "analysisStatus": {
            "type": "string",
            "description": "State of the deforestation analysis: `pending`, `in_progress`, `completed`, `failed`, `exempt` or `skipped`."
          },
          "forestPercentage": {
            "type": "number",
            "description": "Share of the plot that is forest in the JRC Global Forest Cover 2020 map, in percent; absent until measured."
          },
          "isDegraded": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the plot carries an unresolved forest-degradation risk (wood only); `null` when not determined."
          },
          "geojson": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "The stored geometry as GeoJSON (RFC 7946): a Feature or a bare Geometry in WGS84 longitude/latitude; `null` when none is stored."
          },
          "supplierArticleIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "UUIDs of the supplier articles the plot is linked to."
          },
          "analysis": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PlotAnalysis"
              },
              {
                "type": "null"
              }
            ],
            "description": "The stored geo analysis result, as the plot report prints it. `null` until a result is stored (see the endpoint description)."
          }
        },
        "required": [
          "id",
          "companyId",
          "name",
          "species",
          "country",
          "size",
          "requiresAreaPlausibilityReview",
          "commodityGroup",
          "deforestationRiskResult",
          "createdAt",
          "updatedAt",
          "analysisStatus",
          "isDegraded",
          "geojson",
          "supplierArticleIds",
          "analysis"
        ]
      },
      "PlotEvidenceRow": {
        "type": "object",
        "properties": {
          "dataset": {
            "type": "string",
            "description": "Dataset name. One of `JRC GFC 2020`, `Hansen GFC`, `GFW alerts`, `JRC TMF AnnualChange`, `JRC GFT 2020` (wood only); stable."
          },
          "measurementStatus": {
            "type": "string",
            "description": "Whether the dataset was measured for this plot, in words. Human-readable: the wording may change, do not match on it."
          },
          "observation": {
            "type": "string",
            "description": "What the stored record holds for this dataset, in words — e.g. alert counts with their years and the latest alert date. Human-readable: the wording may change, do not match on it."
          },
          "relevance": {
            "type": "string",
            "description": "What the dataset is evidence of. Human-readable: the wording may change, do not match on it."
          }
        },
        "required": [
          "dataset",
          "measurementStatus",
          "observation",
          "relevance"
        ]
      },
      "PlotGeometryWarning": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Stable machine code. `POLYGON_HOLES_REMOVED`: interior rings were removed, the excluded area is now part of the plot. `POLYGON_SELF_INTERSECTION_REPAIRED`: a self-intersecting ring was repaired (area change at most 2 %; may become a `MultiPolygon`). `COORDINATE_PRECISION_BORDERLINE`: 5 decimal places. `COORDINATE_PRECISION_LOW`: 4 decimal places. New codes may be added."
          }
        },
        "required": [
          "code"
        ],
        "description": "One change or note of the geometry quality checks."
      },
      "PlotListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the plot."
          },
          "companyId": {
            "type": "string",
            "description": "UUID of your company (the plot's owner)."
          },
          "createdByUserId": {
            "type": "string",
            "description": "UUID of the user who created the plot (for an API key: the user the key acts as); absent when unknown."
          },
          "name": {
            "type": "string",
            "description": "Plot name; empty string when none was given."
          },
          "species": {
            "type": "array",
            "items": {},
            "description": "Tree species recorded for the plot (entries as sent on create, with `commonName` and `scientificName`). The item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "country": {
            "type": "string",
            "description": "Country as sent on create; ISO 3166-1 alpha-2 (e.g. `BR`) expected but not validated. Empty string when unknown."
          },
          "size": {
            "type": "number",
            "description": "Declared area in hectares; `0` when none was given."
          },
          "requiresAreaPlausibilityReview": {
            "type": "boolean",
            "description": "`true` when the declared or the measured area exceeds 10,000 ha, so the area should be checked by a person."
          },
          "commodityGroup": {
            "type": [
              "string",
              "null"
            ],
            "description": "EUDR commodity group of the plot (a `CommodityGroup` value), or `null`."
          },
          "deforestationRiskResult": {
            "type": [
              "number",
              "null"
            ],
            "description": "Stored deforestation risk as a number: `0` low, `2` moderate, `1` high; `null` when no result is stored or the analysis was invalid. `GET /api/v1/plots/{id}` carries the readable `analysis.riskLevel`."
          },
          "productionDateFrom": {
            "type": "string",
            "description": "Start of the production period (ISO 8601, midnight UTC of the stored day); absent when not set."
          },
          "productionDateTo": {
            "type": "string",
            "description": "End of the production period (ISO 8601, midnight UTC of the stored day); absent when not set."
          },
          "producerName": {
            "type": "string",
            "description": "Name of the producer; absent when not set."
          },
          "importSourceFormat": {
            "type": "string",
            "description": "File format the plot was imported from in the app: `geojson`, `wkt`, `point_csv`, `kml`, `kmz` or `document_extraction`; absent otherwise."
          },
          "importPrecisionClass": {
            "type": "string",
            "description": "Coordinate precision class measured at import: `ok` (6 or more decimals), `borderline` (5), `low` (4), `reject` (3 or fewer) or `mixed`; absent when not measured."
          },
          "importPrecisionDigits": {
            "type": "number",
            "description": "Fewest decimal places of any coordinate, as measured at import; absent when not measured."
          },
          "importPrecisionAcceptedAt": {
            "type": "string",
            "description": "When the plot's coordinate precision was accepted despite being below the EUDR format (ISO 8601, UTC); absent when no acceptance is recorded."
          },
          "importPrecisionAcceptedBy": {
            "type": "string",
            "description": "UUID of the user who accepted the coordinate precision; absent when no user is recorded."
          },
          "importPrecisionAcceptedByName": {
            "type": "string",
            "description": "Name of the user who accepted the coordinate precision; absent when not known."
          },
          "importOriginalCentroidLng": {
            "type": "number",
            "description": "Longitude of the centroid of the geometry as originally imported (e.g. before a point was turned into a circle); absent when not recorded."
          },
          "importOriginalCentroidLat": {
            "type": "number",
            "description": "Latitude of the centroid of the geometry as originally imported; absent when not recorded."
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the plot was created (ISO 8601, UTC), or `null`."
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the plot was last changed (ISO 8601, UTC), or `null`."
          },
          "analysisStatus": {
            "type": "string",
            "description": "State of the deforestation analysis: `pending`, `in_progress`, `completed`, `failed`, `exempt` or `skipped`."
          },
          "forestPercentage": {
            "type": "number",
            "description": "Share of the plot that is forest in the JRC Global Forest Cover 2020 map, in percent; absent until measured."
          },
          "isDegraded": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the plot carries an unresolved forest-degradation risk (wood only); `null` when not determined."
          }
        },
        "required": [
          "id",
          "companyId",
          "name",
          "species",
          "country",
          "size",
          "requiresAreaPlausibilityReview",
          "commodityGroup",
          "deforestationRiskResult",
          "createdAt",
          "updatedAt",
          "analysisStatus",
          "isDegraded"
        ]
      },
      "PlotSpecies": {
        "type": "object",
        "properties": {
          "commonName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Common (trade) name, e.g. `Oak`."
          },
          "scientificName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Scientific (Latin) name, e.g. `Quercus robur`."
          }
        },
        "required": [
          "commonName",
          "scientificName"
        ]
      },
      "PlotValidation": {
        "type": "object",
        "properties": {
          "valid": {
            "type": "boolean",
            "description": "`true` when create would accept the plot; `false` when it would answer `400`."
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "description": "The `code` create would answer, e.g. `plot_geometry_invalid`."
                },
                "message": {
                  "type": "string",
                  "description": "Human-readable English explanation. The wording may change; match on `code`."
                }
              },
              "required": [
                "code",
                "message"
              ]
            },
            "description": "Why create would refuse: `code` (the `code` create answers, e.g. `plot_geometry_invalid`, `plot_geometry_self_intersection_unrepairable`, `plot_geometry_too_many_vertices`, `plot_precision_too_low`) and `message`. `[]` when `valid` is `true`."
          },
          "warnings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlotGeometryWarning"
            },
            "description": "What the geometry quality checks changed or noted, as on create."
          },
          "precision": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "digits": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Fewest decimal places of any longitude/latitude, counted as written; `null` when not measured."
              },
              "class": {
                "type": "string",
                "enum": [
                  "ok",
                  "borderline",
                  "low",
                  "reject"
                ],
                "description": "`ok` (6 or more decimals), `borderline` (5), `low` (4) or `reject` (3 or fewer)."
              }
            },
            "required": [
              "digits",
              "class"
            ],
            "description": "`digits`: the fewest decimal places of any longitude/latitude, counted as written; `class`: `ok` (6 or more), `borderline` (5), `low` (4) or `reject` (3 or fewer). `null` when a check refused the request before the precision was measured."
          },
          "geometry": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "The geometry create would store (rounded, cleaned and repaired). `null` when `valid` is `false`."
          },
          "measuredAreaHa": {
            "type": [
              "number",
              "null"
            ],
            "description": "Geodesic area of `geometry` in hectares, rounded to 2 decimals. `null` for a point or when `valid` is `false`."
          }
        },
        "required": [
          "valid",
          "errors",
          "warnings",
          "precision",
          "geometry",
          "measuredAreaHa"
        ],
        "description": "The verdict `POST /api/v1/plots` would give for the same request. Nothing is written."
      },
      "PpwrArticleLinkIntakeInput": {
        "type": "object",
        "properties": {
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrArticleLinkRow"
            },
            "maxItems": 1000,
            "description": "The rows, at most 1000 per request."
          }
        },
        "required": [
          "rows"
        ],
        "description": "Envelope form for the article-link intake. Links are create-only."
      },
      "PpwrArticleLinkRow": {
        "type": "object",
        "properties": {
          "specInternalRef": {
            "type": "string",
            "minLength": 1,
            "description": "`internalRef` of an existing packaging unit."
          },
          "articleNumber": {
            "type": "string",
            "minLength": 1,
            "description": "The article's internal article number (the number IS the SKU)."
          },
          "formatReference": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 120,
            "description": "Name a SIZE of this unit and the link records THAT size; omit it to link the whole unit. A reference naming no size of this unit is the row error `unknownFormatRef`."
          }
        },
        "required": [
          "specInternalRef",
          "articleNumber"
        ],
        "description": "One unit⇄article link for `POST /api/v1/ppwr/article-links`. Create-only and idempotent on (`specInternalRef`, `articleNumber`). **An unknown article number or unit reference is a row error here** — unlike the unit row's `articleNumbers` column, which skips unmatched numbers silently."
      },
      "PpwrArticleUnits": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Packaging unit UUID."
                },
                "internalRef": {
                  "type": "string",
                  "description": "Stable tenant reference used by PPWR intake and link operations."
                },
                "name": {
                  "type": "string",
                  "description": "Packaging unit name."
                },
                "packagingType": {
                  "type": "string",
                  "description": "Packaging category."
                },
                "role": {
                  "type": "string",
                  "description": "Economic-operator role for this unit."
                }
              },
              "required": [
                "id",
                "internalRef",
                "name",
                "packagingType",
                "role"
              ]
            },
            "description": "Live linked packaging units in stable reference/id order."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Opaque cursor for the next page, or null on the final page."
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another page exists."
          }
        },
        "required": [
          "items",
          "nextCursor",
          "hasMore"
        ]
      },
      "PpwrComponent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the component — what `GET /api/v1/ppwr/components/{id}` takes."
          },
          "code": {
            "type": "string",
            "description": "Component code. Unique among your live components per supplier (components without a supplier form their own group), not per company — the same code can exist once in your own catalogue and once per supplier. Together with the resolved supplier it is the upsert key of `POST /api/v1/ppwr/components`."
          },
          "name": {
            "type": "string",
            "description": "Component name."
          },
          "supplierId": {
            "type": [
              "string",
              "null"
            ],
            "description": "`null` for a component of your own catalogue."
          },
          "materials": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Material families of the component (a laminate has several): `plastic`, `paper_board`, `glass`, `metal`, `wood`, `composite`, `other`."
          },
          "polymer": {
            "type": [
              "string",
              "null"
            ],
            "description": "Main polymer of a plastic component: `pet`, `hdpe`, `ldpe`, `pp`, `ps`, `pvc` or `other`; `null` for non-plastic components or when unknown."
          },
          "massGrams": {
            "type": [
              "string",
              "null"
            ],
            "description": "Mass of one piece, in grams."
          },
          "recycledContentPct": {
            "type": [
              "string",
              "null"
            ],
            "description": "Recycled content in percent (0–100), as a decimal string; `null` when unknown."
          },
          "recycledContentSource": {
            "type": [
              "string",
              "null"
            ],
            "description": "Source of the recycled content: `pcr` (post-consumer) or `pir` (post-industrial); `null` when unknown."
          },
          "recycledContentMethod": {
            "type": [
              "string",
              "null"
            ],
            "description": "How the recycled content is attributed: `physical` or `mass_balance`; `null` when unknown."
          },
          "contactSensitive": {
            "type": "boolean",
            "description": "Contact-sensitive packaging (PPWR Art. 7 scope). Always `true` when `foodContact` is."
          },
          "foodContact": {
            "type": "boolean",
            "description": "Food-contact packaging. Makes the PPWR Art. 5 PFAS limits apply."
          },
          "heavyMetalsMgPerKg": {
            "type": [
              "string",
              "null"
            ],
            "description": "Sum of lead, cadmium, mercury and hexavalent chromium in mg/kg, as a decimal string; `null` when unknown — or when `heavyMetalsValueKind` is `below_detection` (not detected). The PPWR Art. 5(4) limit is 100 mg/kg."
          },
          "heavyMetalsValueKind": {
            "type": "string",
            "description": "What `heavyMetalsMgPerKg` is: a measurement (`measured`), a bound the supplier declared (`declared_within_limit`), an upper bound computed from a lab's own per-metal results (`measured_upper_bound` — a test result, not a supplier declaration), or `below_detection` — all four metals not detected (the number is `null`; counts as conforming)."
          },
          "heavyMetalsBasis": {
            "type": [
              "string",
              "null"
            ],
            "description": "What substantiates the heavy-metals value: `test_report`, `supplier_declaration` or `not_substantiated`; `null` when not captured."
          },
          "heavyMetalsMethod": {
            "type": [
              "string",
              "null"
            ],
            "description": "Measurement standard or method of the heavy-metals value (free text, e.g. `CEN/CR 13695-1`), or `null`."
          },
          "heavyMetalsRecycledGlassDerogation": {
            "type": "boolean",
            "description": "The recycled-glass attestation for the Art. 5(4) sum. Set in the app only; no import or API write touches it."
          },
          "heavyMetalsEvidenceId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The evidence document backing the heavy-metals value, when one is attached."
          },
          "pfasCompliant": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Tri-state: `null` = unknown."
          },
          "pfasBasis": {
            "type": [
              "string",
              "null"
            ],
            "description": "Food-contact components: what substantiates the PFAS claim — `test_report`, `supplier_declaration` or `not_substantiated`; `null` when not captured."
          },
          "pfasMethod": {
            "type": [
              "string",
              "null"
            ],
            "description": "Food-contact components: measurement method of the PFAS or total-fluorine value (free text), or `null`."
          },
          "pfasTotalFluorineMgPerKg": {
            "type": [
              "string",
              "null"
            ],
            "description": "Food-contact components: total fluorine in mg/kg, as a decimal string; `null` when unknown."
          },
          "pfasTotalFluorineValueKind": {
            "type": "string",
            "description": "Whether `pfasTotalFluorineMgPerKg` is a measurement (`measured`) or a bound the supplier declared (`declared_within_limit`)."
          },
          "pfasSumPpb": {
            "type": [
              "string",
              "null"
            ],
            "description": "Food-contact components: measured sum of PFAS in ppb, as a decimal string; `null` when unknown."
          },
          "pfasSumValueKind": {
            "type": "string",
            "description": "Whether `pfasSumPpb` is a measurement (`measured`) or a bound the supplier declared (`declared_within_limit`)."
          },
          "pfasEvidenceId": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the document backing the PFAS claim, when one is attached; `null` otherwise."
          },
          "lastProvidedBySupplierId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The supplier who last supplied this component's data through a data request."
          },
          "lastProvidedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When a supplier last provided this component's data through a data request (ISO 8601, UTC), or `null`."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Free-text notes, or `null`."
          },
          "createdAt": {
            "type": "string",
            "description": "When the component was created (ISO 8601, UTC)."
          },
          "updatedAt": {
            "type": "string",
            "description": "When the component was last changed (ISO 8601, UTC)."
          }
        },
        "required": [
          "id",
          "code",
          "name",
          "supplierId",
          "materials",
          "polymer",
          "massGrams",
          "recycledContentPct",
          "recycledContentSource",
          "recycledContentMethod",
          "contactSensitive",
          "foodContact",
          "heavyMetalsMgPerKg",
          "heavyMetalsValueKind",
          "heavyMetalsBasis",
          "heavyMetalsMethod",
          "heavyMetalsRecycledGlassDerogation",
          "heavyMetalsEvidenceId",
          "pfasCompliant",
          "pfasBasis",
          "pfasMethod",
          "pfasTotalFluorineMgPerKg",
          "pfasTotalFluorineValueKind",
          "pfasSumPpb",
          "pfasSumValueKind",
          "pfasEvidenceId",
          "lastProvidedBySupplierId",
          "lastProvidedAt",
          "notes",
          "createdAt",
          "updatedAt"
        ],
        "description": "One packaging component as stored — the shape both `GET /api/v1/ppwr/components` and `GET /api/v1/ppwr/components/{id}` return. Numeric values are decimal strings. Provenance and evidence fields are read-only: the intake API never writes them."
      },
      "PpwrComponentIntakeInput": {
        "type": "object",
        "properties": {
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrComponentRow"
            },
            "maxItems": 1000,
            "description": "The rows, at most 1000 per request."
          },
          "overwrite": {
            "type": "boolean",
            "default": false,
            "description": "Authorises overwriting values that are already filled (including supplier- and AI-attested ones). Without it a batch containing any such change is refused with `409 overwriteRequired` and **nothing** is written."
          }
        },
        "required": [
          "rows"
        ],
        "description": "Envelope form for the component intake."
      },
      "PpwrComponentRow": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "minLength": 1,
            "description": "Your component code — the upsert key, compared byte-exact after trimming (`KAR-01` ≠ `kar-01`)."
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Component name."
          },
          "supplierName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Resolved to one of your suppliers by fuzzy name match (case, umlauts, punctuation and legal-form tokens are ignored). A name that matches **two or more** distinct suppliers fails the row with `ambiguousSupplierName` — the import never guesses. A name that matches **none** creates a name-only supplier (no email, data incomplete) once per distinct name in the request and links the record to it; the created names are returned in `suppliersCreated`. A blank cell resolves to *no supplier* (your own bucket)."
          },
          "materials": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "plastic",
                "paper_board",
                "glass",
                "metal",
                "wood",
                "composite",
                "other"
              ]
            },
            "minItems": 1,
            "description": "At least one material. Also accepts a `;`- or `,`-delimited string."
          },
          "polymer": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "pet",
              "hdpe",
              "ldpe",
              "pp",
              "ps",
              "pvc",
              "other",
              null
            ],
            "description": "Polymer type (plastics only)."
          },
          "massGrams": {
            "type": [
              "string",
              "null"
            ],
            "description": "Mass of ONE piece of this component, in grams."
          },
          "recycledContentPct": {
            "type": [
              "string",
              "null"
            ],
            "description": "Recycled content, 0–100."
          },
          "recycledContentSource": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "pcr",
              "pir",
              null
            ],
            "description": "`pcr` = post-consumer, `pir` = post-industrial."
          },
          "recycledContentMethod": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "physical",
              "mass_balance",
              null
            ],
            "description": "How the recycled content is attributed: `physical` or `mass_balance`. Required together with `recycledContentSource` when `recycledContentPct` is above 0."
          },
          "contactSensitive": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Contact-sensitive packaging. Blank = `false` on a create and unchanged on an update; an explicit `false` switches a stored `true` off (an overwrite)."
          },
          "foodContact": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Food-contact packaging. Blank = `false` on a create and unchanged on an update; an explicit `false` switches a stored `true` off (an overwrite). Switching it off is refused with `foodContactOffWithPfasData` while PFAS data is stored for the component — the import never deletes it; switch food contact off in the app's component editor, which removes the PFAS data. Implies `contactSensitive`; when the row states a flag or a PFAS value, both rules are checked on the stored values merged with the row, so a blank flag on an update is judged by the stored one."
          },
          "heavyMetalsMgPerKg": {
            "type": [
              "string",
              "null"
            ],
            "description": "Sum of the four regulated heavy metals, mg/kg."
          },
          "heavyMetalsBasis": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "test_report",
              "supplier_declaration",
              "not_substantiated",
              null
            ],
            "description": "Provenance of the heavy-metals claim."
          },
          "heavyMetalsMethod": {
            "type": [
              "string",
              "null"
            ],
            "description": "Annex VII d) measurement standard (free text, e.g. `CEN/CR 13695-1`). Accepted on every component."
          },
          "pfasCompliant": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Tri-state: blank = unknown. Food-contact components only."
          },
          "pfasBasis": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "test_report",
              "supplier_declaration",
              "not_substantiated",
              null
            ],
            "description": "Provenance of the PFAS claim. Food-contact components only."
          },
          "pfasMethod": {
            "type": [
              "string",
              "null"
            ],
            "description": "PFAS measurement method (free text). Food-contact components only."
          },
          "pfasSumPpb": {
            "type": [
              "string",
              "null"
            ],
            "description": "Measured PFAS sum in ppb. Food-contact components only."
          },
          "pfasTotalFluorineMgPerKg": {
            "type": [
              "string",
              "null"
            ],
            "description": "Total fluorine in mg/kg — the screening route. Food-contact components only."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Free-text notes."
          }
        },
        "required": [
          "code",
          "name",
          "materials"
        ],
        "description": "One packaging-component row for `POST /api/v1/ppwr/components`. Upsert key: `code` + resolved supplier. Cells are coerced exactly as the in-app CSV/Excel importer coerces them, so a JSON-native value and its string spelling are equivalent (`12` = `\"12\"`, `[\"plastic\"]` = `\"plastic;paper_board\"`, `true` = `\"yes\"`/`\"ja\"`/`\"1\"`). An empty or omitted field is a no-op — it never clears a stored value. Cross-field rules (each rejects the row with the named key): a `recycledContentPct` above 0 requires `recycledContentSource` **and** `recycledContentMethod` (`recycledProvenanceRequired`); `foodContact` requires `contactSensitive` (`foodContactImpliesContactSensitive`); the five PFAS fields are only accepted on a food-contact component (`pfasOnlyFoodContact`); switching `foodContact` off while PFAS data is stored is refused (`foodContactOffWithPfasData`). On an update these rules read a blank flag as the stored value."
      },
      "PpwrDeclaration": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the declaration — what `GET /api/v1/ppwr/declarations/{id}` takes."
          },
          "version": {
            "type": "number",
            "description": "Version number; a successor that supersedes this declaration carries a higher one."
          },
          "status": {
            "type": "string",
            "description": "Status of the declaration: `draft`, `issued`, `superseded` or `withdrawn`. One of: `draft`, `issued`, `superseded`, `withdrawn`."
          },
          "origin": {
            "type": "string",
            "description": "`generated` (drawn up in the app) or `collected` (the manufacturer's uploaded DoC). One of: `generated`, `collected`."
          },
          "referenceNumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reference number printed on the declaration, or `null` (e.g. for a draft)."
          },
          "issuedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the declaration was issued (ISO 8601, UTC); `null` for a draft."
          },
          "withdrawnAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the declaration was withdrawn (ISO 8601, UTC); `null` unless withdrawn."
          },
          "supersededAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When a newer declaration replaced this one for its last unit (ISO 8601, UTC); `null` unless `status` is `superseded`, and can also be `null` for a declaration superseded before 2026-10 whose successors were since deleted. A family declaration that loses only some units to a newer one stays `issued` with `supersededAt: null` — those units leave its `activeSpecIds`."
          },
          "supersedesId": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the earlier declaration this one replaces, or `null`."
          },
          "verified": {
            "type": "boolean",
            "description": "A generated DoC always; a collected DoC once its verification passed and while its file is on record."
          },
          "isFallback": {
            "type": "boolean",
            "description": "An importer substitute DoC (Ersatz-Konformitätserklärung)."
          },
          "pdfUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "Path of the PDF download (`GET`, same API key); `null` for a draft, and for a collected declaration whose uploaded file is no longer on record (the download would answer `404`) — `verified` is then `false` too."
          },
          "specIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Every packaging unit the declaration covers (a family DoC covers several)."
          },
          "activeSpecIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The units it is currently the active DoC for."
          }
        },
        "required": [
          "id",
          "version",
          "status",
          "origin",
          "referenceNumber",
          "issuedAt",
          "withdrawnAt",
          "supersededAt",
          "supersedesId",
          "verified",
          "isFallback",
          "pdfUrl",
          "specIds",
          "activeSpecIds"
        ]
      },
      "PpwrDeclarationSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the declaration — what `GET /api/v1/ppwr/declarations/{id}` takes."
          },
          "version": {
            "type": "number",
            "description": "Version number; a successor that supersedes this declaration carries a higher one."
          },
          "status": {
            "type": "string",
            "description": "Status of the declaration: `draft`, `issued`, `superseded` or `withdrawn`. One of: `draft`, `issued`, `superseded`, `withdrawn`."
          },
          "origin": {
            "type": "string",
            "description": "`generated` (drawn up in the app) or `collected` (the manufacturer's uploaded DoC). One of: `generated`, `collected`."
          },
          "referenceNumber": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reference number printed on the declaration, or `null` (e.g. for a draft)."
          },
          "issuedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the declaration was issued (ISO 8601, UTC); `null` for a draft."
          },
          "withdrawnAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the declaration was withdrawn (ISO 8601, UTC); `null` unless withdrawn."
          },
          "supersededAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When a newer declaration replaced this one for its last unit (ISO 8601, UTC); `null` unless `status` is `superseded`, and can also be `null` for a declaration superseded before 2026-10 whose successors were since deleted. A family declaration that loses only some units to a newer one stays `issued` with `supersededAt: null` — those units leave its `activeSpecIds`."
          },
          "supersedesId": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the earlier declaration this one replaces, or `null`."
          },
          "verified": {
            "type": "boolean",
            "description": "A generated DoC always; a collected DoC once its verification passed and while its file is on record."
          },
          "isFallback": {
            "type": "boolean",
            "description": "An importer substitute DoC (Ersatz-Konformitätserklärung)."
          },
          "pdfUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "Path of the PDF download (`GET`, same API key); `null` for a draft, and for a collected declaration whose uploaded file is no longer on record (the download would answer `404`) — `verified` is then `false` too."
          }
        },
        "required": [
          "id",
          "version",
          "status",
          "origin",
          "referenceNumber",
          "issuedAt",
          "withdrawnAt",
          "supersededAt",
          "supersedesId",
          "verified",
          "isFallback",
          "pdfUrl"
        ]
      },
      "PpwrDocument": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The new document's id."
          },
          "extractionQueued": {
            "type": "boolean",
            "description": "True when AI extraction was queued for this document."
          },
          "aiSkippedReason": {
            "type": "string",
            "enum": [
              "no_unit",
              "quota",
              "spend",
              "enqueue",
              "disabled"
            ],
            "description": "Why an extractable document did NOT queue extraction; absent when it did, or when the type is not analysed."
          }
        },
        "required": [
          "id",
          "extractionQueued"
        ]
      },
      "PpwrDocumentDuplicate": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "duplicate"
            ],
            "description": "Always `duplicate`."
          },
          "existing": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "UUID of the existing document with the same bytes."
              },
              "fileName": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "File name of the existing document, or `null`."
              },
              "anchor": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "unit",
                      "component"
                    ],
                    "description": "Whether the existing copy is attached to a packaging unit or a component."
                  },
                  "ref": {
                    "type": "string",
                    "description": "Your reference of that unit (`internalRef`) or component (`code`)."
                  },
                  "name": {
                    "type": "string",
                    "description": "Name of that unit or component."
                  }
                },
                "required": [
                  "kind",
                  "ref",
                  "name"
                ],
                "description": "The packaging unit or component the existing copy is attached to; null when it is on neither."
              }
            },
            "required": [
              "id",
              "fileName",
              "anchor"
            ],
            "description": "The live document of your company that already has these exact bytes."
          }
        },
        "required": [
          "error",
          "existing"
        ]
      },
      "PpwrDocumentInput": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "heavy_metals",
              "pfas",
              "recycled_content",
              "technical_doc",
              "declaration_of_conformity",
              "other",
              "technical_drawing",
              "marking",
              "supplier_statement"
            ],
            "description": "Document type. `technical_doc`, `declaration_of_conformity` and `marking` can be attached to a packaging unit only."
          },
          "storageKey": {
            "type": "string",
            "minLength": 1,
            "description": "The `s3Key` from `POST /api/v1/ppwr/documents/upload-url`, after the file was uploaded. Usable for one attach."
          },
          "fileName": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "description": "File name to record for the document, or `null`."
          },
          "target": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "packagingSpecId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "UUID of the packaging unit (`id` of `GET /api/v1/ppwr/units`)."
                  }
                },
                "required": [
                  "packagingSpecId"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "componentId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "UUID of the packaging component (`id` of `GET /api/v1/ppwr/components`)."
                  }
                },
                "required": [
                  "componentId"
                ]
              }
            ],
            "description": "Where to attach the document: exactly one of `packagingSpecId` or `componentId`."
          },
          "allowDuplicate": {
            "type": "boolean",
            "description": "Send `true` to attach a second copy of a file that a `409` reported as a duplicate."
          }
        },
        "required": [
          "type",
          "storageKey",
          "fileName",
          "target"
        ],
        "description": "Attach an uploaded file as a document of a packaging unit or component."
      },
      "PpwrDocumentUploadUrl": {
        "type": "object",
        "properties": {
          "uploadUrl": {
            "type": "string",
            "description": "Presigned S3 PUT URL, valid for 10 minutes. Send the file bytes with the same `Content-Type`."
          },
          "s3Key": {
            "type": "string",
            "description": "The staging key — pass it as `storageKey` to `POST /api/v1/ppwr/documents`."
          }
        },
        "required": [
          "uploadUrl",
          "s3Key"
        ]
      },
      "PpwrDocumentUploadUrlInput": {
        "type": "object",
        "properties": {
          "fileName": {
            "type": "string",
            "minLength": 1,
            "description": "Name of the file to upload, including its extension."
          },
          "contentType": {
            "type": "string",
            "minLength": 1,
            "description": "MIME type of the file (e.g. `application/pdf`). Send the same value as `Content-Type` when uploading to `uploadUrl`."
          },
          "fileSize": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "description": "Size of the file in bytes. It is signed into `uploadUrl`: the `PUT` must send exactly this many bytes."
          }
        },
        "required": [
          "fileName",
          "contentType",
          "fileSize"
        ]
      },
      "PpwrFormatIntakeInput": {
        "type": "object",
        "properties": {
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrFormatRow"
            },
            "maxItems": 1000,
            "description": "The rows, at most 1000 per request."
          },
          "overwrite": {
            "type": "boolean",
            "default": false,
            "description": "Authorises overwriting values that are already filled (including supplier- and AI-attested ones). Without it a batch containing any such change is refused with `409 overwriteRequired` and **nothing** is written."
          }
        },
        "required": [
          "rows"
        ],
        "description": "Envelope form for the size intake. Blank-is-keep; changing a stored value needs `overwrite: true`."
      },
      "PpwrFormatRow": {
        "type": "object",
        "properties": {
          "specInternalRef": {
            "type": "string",
            "minLength": 1,
            "description": "`internalRef` of an existing packaging unit in YOUR company. An unknown reference is the row error `unknownUnitRef` — the unit is never auto-created."
          },
          "reference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "description": "The size's identifier, unique within your company."
          },
          "gtin": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(\\d{8}|\\d{12}|\\d{13}|\\d{14})$",
            "description": "GTIN of the size: 8, 12, 13 or 14 digits."
          },
          "supplierReference": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 120,
            "description": "The supplier's own reference for the size (at most 120 characters)."
          },
          "label": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 120,
            "description": "Human-readable name of the size (at most 120 characters)."
          },
          "widthMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Width in mm."
          },
          "heightMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Height in mm."
          },
          "depthMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Depth in mm."
          }
        },
        "required": [
          "specInternalRef",
          "reference"
        ],
        "description": "One size of an existing packaging unit, for `POST /api/v1/ppwr/formats`. Upsert key: (`specInternalRef`, `reference`). Blank-is-keep: an omitted or blank field keeps the stored value, so this endpoint can add and change size data but never clear it. Filling an empty field is automatic; changing a stored value needs `overwrite: true` (`409 overwriteRequired` otherwise, nothing written). Naming the unit's own `internalRef` addresses its PRIMARY size (its reference always follows the unit and is never renamed here)."
      },
      "PpwrIndexedRowError": {
        "type": "object",
        "description": "A row rejected before the upsert engine ran, reported by its position in the request.",
        "properties": {
          "index": {
            "type": "integer",
            "description": "0-based position of the row in the request."
          },
          "identifier": {
            "type": "string",
            "description": "The row's key as sent (`code`, `internalRef`, `specInternalRef` or `zsvrCategory`, depending on the endpoint); empty string when the row carried none."
          },
          "error": {
            "type": "string",
            "description": "Usually a stable machine key; a field with no custom message falls back to the validator's own English text."
          }
        }
      },
      "PpwrIntakeResult": {
        "type": "object",
        "description": "Result of a synchronous PPWR intake. **Partial accept:** valid rows commit even when other rows are `invalid` or `failed` — the one exception is the `409` overwrite confirmation, which is all-or-nothing. **Idempotent:** replaying an identical request changes nothing (matched rows return as `skipped`), except unit rows without `internalRef`, which are always creates.",
        "required": [
          "imported",
          "updated",
          "skipped",
          "failed",
          "invalid"
        ],
        "properties": {
          "imported": {
            "type": "integer",
            "description": "ENTITIES created (units, components, links) — never sizes."
          },
          "updated": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Identifiers of rows whose existing match changed. A size created on an existing unit appears as `<unit ref> / <size ref>`."
          },
          "skipped": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Identifiers of rows that matched with nothing to change."
          },
          "failed": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrRowError"
            },
            "description": "Rows the upsert engine rejected (unknown reference, ambiguous match, a new unit over the plan's unit quota → `packagingUnitQuotaReached`, …). A row refused before its write (these, and a new unit over the quota) writes nothing — not even the supplier it names; a unit written whose component or article link then failed is reported here with that link's key. Its `error` values are stable machine keys."
          },
          "invalid": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrIndexedRowError"
            },
            "description": "Rows rejected by schema validation before the engine ran. Most `error` values are stable machine keys, but a field with no custom message falls back to the validator's own English text — match on the key, fall back to displaying the string."
          },
          "sizesCreated": {
            "type": "integer",
            "description": "Unit intake only: sizes created for the rows' units."
          },
          "articleNumbersUnmatched": {
            "type": "integer",
            "description": "Unit intake only: distinct `articleNumbers` no live article matched. Skipped, never a row error."
          },
          "articleLinksCreated": {
            "type": "integer",
            "description": "Unit intake only: unit⇄article links created from `articleNumbers`."
          },
          "componentLinksCreated": {
            "type": "integer",
            "description": "Unit intake only: unit⇄component links created from `componentCodes`."
          },
          "componentStubsCreated": {
            "type": "integer",
            "description": "Unit intake only: minimal placeholder components created for unknown `componentCodes`."
          },
          "suppliersCreated": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Unit + component intake: names of the name-only suppliers created for `supplierName`s that matched no existing supplier."
          },
          "unitsWithoutComponents": {
            "type": "integer",
            "description": "Unit intake only: units created with neither `componentCodes` nor a `material`. They hold no component yet, so no regulated value can be recorded on them — send `componentCodes`, or `material` for single-part packaging."
          },
          "mainPartsCreated": {
            "type": "integer",
            "description": "Unit intake only: main-part components created from rows' `material` (one per unit that had no component yet)."
          }
        }
      },
      "PpwrLinkIntakeInput": {
        "type": "object",
        "properties": {
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrLinkRow"
            },
            "maxItems": 1000,
            "description": "The rows, at most 1000 per request."
          }
        },
        "required": [
          "rows"
        ],
        "description": "Envelope form for the bill-of-materials intake. Links are create-only."
      },
      "PpwrLinkRow": {
        "type": "object",
        "properties": {
          "specInternalRef": {
            "type": "string",
            "minLength": 1,
            "description": "`internalRef` of an existing packaging unit."
          },
          "componentCode": {
            "type": "string",
            "minLength": 1,
            "description": "`code` of an existing component. An ambiguous code is the row error `ambiguousComponentMatch`."
          },
          "quantity": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "description": "Pieces of this component in the unit. Blank = 1."
          },
          "massGrams": {
            "type": [
              "string",
              "null"
            ],
            "description": "This unit's own mass for ONE piece of the component, in grams. Blank/omitted = the component's own mass applies; on a replayed row a blank never clears a mass already stored."
          },
          "formatReference": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 120,
            "description": "Name a SIZE of this unit and `massGrams` is stored for THAT size only, leaving the unit's own mass untouched. A reference naming no size of this unit is the row error `unknownFormatRef` and the link is NOT created."
          }
        },
        "required": [
          "specInternalRef",
          "componentCode"
        ],
        "description": "One bill-of-materials link for `POST /api/v1/ppwr/links`. Create-only and idempotent on (`specInternalRef`, `componentCode`) — a replayed row comes back as `skipped`. Unknown unit references and component codes are row errors, never auto-created."
      },
      "PpwrOverwriteRequired": {
        "type": "object",
        "description": "The batch contains at least one change that would overwrite an already-filled value. Nothing was written — resubmit with `overwrite: true`, or drop those rows.",
        "required": [
          "error",
          "confirmUpdateCount"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "overwriteRequired"
            ],
            "description": "Always `overwriteRequired`."
          },
          "confirmUpdateCount": {
            "type": "integer",
            "description": "How many rows in the batch need confirmation."
          }
        }
      },
      "PpwrQuantityIntakeInput": {
        "type": "object",
        "properties": {
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrQuantityRow"
            },
            "minItems": 1,
            "maxItems": 5000,
            "description": "The rows: at least 1, at most 5000 per request."
          },
          "replaceScope": {
            "type": "string",
            "enum": [
              "period-market"
            ],
            "description": "Declares the batch the authoritative snapshot of every `(periodYear, market)` pair it mentions: stored rows in exactly those scopes that the batch omits are deleted. Other scopes are never touched. Omit it for a delta feed. Any other value is a `400`."
          }
        },
        "required": [
          "rows"
        ],
        "description": "Envelope form for the quantity feed. At least one row is required."
      },
      "PpwrQuantityRow": {
        "type": "object",
        "properties": {
          "articleNumber": {
            "type": "string",
            "minLength": 1,
            "description": "Internal article number of an existing article. An unknown number is the row error `unknownArticleNumber`; a key repeated inside one batch is first-seen-wins plus `duplicateInFile` on the later rows."
          },
          "periodYear": {
            "type": "integer",
            "minimum": 2000,
            "maximum": 2100,
            "description": "Calendar reporting year."
          },
          "market": {
            "type": "string",
            "pattern": "^[A-Z]{2}$",
            "description": "ISO alpha-2 market code (case-insensitive, stored upper-case)."
          },
          "quantity": {
            "type": "string",
            "minLength": 1,
            "description": "Pieces placed on that market in that year. Required and non-negative — a blank quantity is a broken feed row, not zero."
          }
        },
        "required": [
          "articleNumber",
          "periodYear",
          "market",
          "quantity"
        ],
        "description": "One placed-quantity row for `POST /api/v1/ppwr/quantities`. Upsert key: (`articleNumber`, `periodYear`, `market`) — re-pushing a period with corrected numbers is the normal flow."
      },
      "PpwrRowError": {
        "type": "object",
        "description": "A row the upsert engine rejected. Carries no `index` — the engine reports by identifier.",
        "properties": {
          "identifier": {
            "type": "string",
            "description": "Identifies the rejected row, e.g. its `code` (components) or `internalRef` (units)."
          },
          "error": {
            "type": "string",
            "description": "Stable machine key (clamped: anything unexpected becomes `dbError`)."
          }
        }
      },
      "PpwrTonnageIntakeInput": {
        "type": "object",
        "properties": {
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrTonnageRow"
            },
            "maxItems": 1000,
            "description": "The rows, at most 1000 per request."
          }
        },
        "required": [
          "rows"
        ],
        "description": "Envelope form for the tonnage intake."
      },
      "PpwrTonnageResult": {
        "type": "object",
        "description": "Result of the synchronous tonnage intake. A category a human entered in the app is reported in `skipped`, never overwritten; delete the override in the app and the next push recreates it as ERP-owned.",
        "required": [
          "written",
          "skipped",
          "failed",
          "invalid"
        ],
        "properties": {
          "written": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "periodYear": {
                  "type": "integer",
                  "description": "Reporting year of the written row."
                },
                "market": {
                  "type": "string",
                  "description": "Market of the written row, ISO 3166-1 alpha-2."
                },
                "zsvrCategory": {
                  "$ref": "#/components/schemas/ZsvrCategory"
                }
              }
            },
            "description": "The categories written (created or updated) by this request."
          },
          "skipped": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "periodYear": {
                  "type": "integer",
                  "description": "Reporting year of the skipped row."
                },
                "market": {
                  "type": "string",
                  "description": "Market of the skipped row, ISO 3166-1 alpha-2."
                },
                "zsvrCategory": {
                  "$ref": "#/components/schemas/ZsvrCategory"
                },
                "reason": {
                  "type": "string",
                  "enum": [
                    "manualOverridePresent"
                  ],
                  "description": "Always `manualOverridePresent`: a figure entered in the app exists for this category."
                }
              }
            },
            "description": "The categories not written because a figure entered in the app takes precedence."
          },
          "failed": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrIndexedRowError"
            },
            "description": "Rows that hit an unexpected database error (`dbError`). Reported per row — the categories that committed are kept."
          },
          "invalid": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrIndexedRowError"
            },
            "description": "Rows rejected by schema validation."
          }
        }
      },
      "PpwrTonnageRow": {
        "type": "object",
        "properties": {
          "periodYear": {
            "type": "integer",
            "minimum": 2000,
            "maximum": 2100,
            "description": "Calendar reporting year (2000–2100)."
          },
          "market": {
            "type": "string",
            "pattern": "^[A-Z]{2}$",
            "description": "ISO alpha-2 market code."
          },
          "zsvrCategory": {
            "type": "string",
            "enum": [
              "10000",
              "20000",
              "30000",
              "40000",
              "50000",
              "60000",
              "70000",
              "80000"
            ],
            "description": "The VerpackG material category (see `ZsvrCategory`)."
          },
          "tonnageKg": {
            "type": "number",
            "minimum": 0,
            "description": "Kilograms placed. A JSON **number** — unlike the intake row schemas, this field is not string-coerced."
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 500,
            "description": "Optional note (at most 500 characters)."
          }
        },
        "required": [
          "periodYear",
          "market",
          "zsvrCategory",
          "tonnageKg"
        ],
        "description": "One aggregate-tonnage row for `POST /api/v1/ppwr/tonnage`. Upsert key: (`zsvrCategory`, `periodYear`, `market`). LUCID (Germany) only."
      },
      "PpwrUnitComponentLink": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Component code. Unique among your live components per supplier (components without a supplier form their own group), not per company — the same code can exist once in your own catalogue and once per supplier. Together with the resolved supplier it is the upsert key of `POST /api/v1/ppwr/components`."
          },
          "name": {
            "type": "string",
            "description": "Component name."
          },
          "supplierId": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the component's supplier; `null` for a component of your own catalogue."
          },
          "polymer": {
            "type": [
              "string",
              "null"
            ],
            "description": "Main polymer of a plastic component: `pet`, `hdpe`, `ldpe`, `pp`, `ps`, `pvc` or `other`; `null` for non-plastic components or when unknown."
          },
          "materials": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Material families of the component (a laminate has several): `plastic`, `paper_board`, `glass`, `metal`, `wood`, `composite`, `other`."
          },
          "massGrams": {
            "type": [
              "string",
              "null"
            ],
            "description": "Mass of one piece, in grams, as a decimal string."
          },
          "recycledContentPct": {
            "type": [
              "string",
              "null"
            ],
            "description": "Recycled content in percent (0–100), as a decimal string; `null` when unknown."
          },
          "foodContact": {
            "type": "boolean",
            "description": "Food-contact packaging. Makes the PPWR Art. 5 PFAS limits apply."
          },
          "heavyMetalsMgPerKg": {
            "type": [
              "string",
              "null"
            ],
            "description": "Sum of lead, cadmium, mercury and hexavalent chromium in mg/kg, as a decimal string; `null` when unknown — or when `heavyMetalsValueKind` is `below_detection` (not detected). The PPWR Art. 5(4) limit is 100 mg/kg."
          },
          "heavyMetalsValueKind": {
            "type": "string",
            "description": "What `heavyMetalsMgPerKg` is: a measurement (`measured`), a bound the supplier declared (`declared_within_limit`), an upper bound computed from a lab's own per-metal results (`measured_upper_bound` — a test result, not a supplier declaration), or `below_detection` — all four metals not detected (the number is `null`; counts as conforming)."
          },
          "pfasCompliant": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Tri-state: `null` = unknown."
          },
          "recycledContentSource": {
            "type": [
              "string",
              "null"
            ],
            "description": "Source of the recycled content: `pcr` (post-consumer) or `pir` (post-industrial); `null` when unknown."
          },
          "recycledContentMethod": {
            "type": [
              "string",
              "null"
            ],
            "description": "How the recycled content is attributed: `physical` or `mass_balance`; `null` when unknown."
          },
          "contactSensitive": {
            "type": "boolean",
            "description": "Contact-sensitive packaging (PPWR Art. 7 scope). Always `true` when `foodContact` is."
          },
          "heavyMetalsBasis": {
            "type": [
              "string",
              "null"
            ],
            "description": "What substantiates the heavy-metals value: `test_report`, `supplier_declaration` or `not_substantiated`; `null` when not captured."
          },
          "heavyMetalsRecycledGlassDerogation": {
            "type": "boolean",
            "description": "The recycled-glass attestation for the Art. 5(4) sum. Set in the app only; no import or API write touches it."
          },
          "pfasBasis": {
            "type": [
              "string",
              "null"
            ],
            "description": "Food-contact components: what substantiates the PFAS claim — `test_report`, `supplier_declaration` or `not_substantiated`; `null` when not captured."
          },
          "pfasTotalFluorineMgPerKg": {
            "type": [
              "string",
              "null"
            ],
            "description": "Food-contact components: total fluorine in mg/kg, as a decimal string; `null` when unknown."
          },
          "pfasSumPpb": {
            "type": [
              "string",
              "null"
            ],
            "description": "Food-contact components: measured sum of PFAS in ppb, as a decimal string; `null` when unknown."
          },
          "linkId": {
            "type": "string",
            "description": "Id of the unit⇄component link itself."
          },
          "componentId": {
            "type": "string",
            "description": "The component's id — what `GET /api/v1/ppwr/components/{id}` takes."
          },
          "quantity": {
            "type": "number",
            "description": "How many pieces of this component the unit contains."
          },
          "completeness": {
            "type": "string",
            "description": "Data completeness of this component."
          },
          "missingFields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Required PPWR Annex VII fields of this component that are still missing. Empty when complete."
          }
        },
        "required": [
          "code",
          "name",
          "supplierId",
          "polymer",
          "materials",
          "massGrams",
          "recycledContentPct",
          "foodContact",
          "heavyMetalsMgPerKg",
          "heavyMetalsValueKind",
          "pfasCompliant",
          "recycledContentSource",
          "recycledContentMethod",
          "contactSensitive",
          "heavyMetalsBasis",
          "heavyMetalsRecycledGlassDerogation",
          "pfasBasis",
          "pfasTotalFluorineMgPerKg",
          "pfasSumPpb",
          "linkId",
          "componentId",
          "quantity",
          "completeness",
          "missingFields"
        ],
        "description": "One line of a packaging unit's bill of materials: the linked component's identifying and substance data, plus the quantity of that component in the unit."
      },
      "PpwrUnitDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unit's UUID — what every other `/api/v1/ppwr` endpoint takes."
          },
          "name": {
            "type": "string",
            "description": "Name of the packaging unit."
          },
          "internalRef": {
            "type": "string",
            "description": "Your reference for the unit, or the `PU-<n>` the server generated for a row that sent none. The upsert key of `POST /api/v1/ppwr/units` and the `specInternalRef` of the link endpoints."
          },
          "packagingType": {
            "type": "string",
            "description": "Packaging category: `sales`, `grouped`, `transport`, `ecommerce` or `service`."
          },
          "format": {
            "type": [
              "string",
              "null"
            ],
            "description": "Packaging form (free text)."
          },
          "role": {
            "type": "string",
            "description": "Your economic-operator role for this unit: `manufacturer`, `importer`, `distributor`, `authorised_representative`, `supplier` or `fulfilment_service_provider`."
          },
          "recyclabilityGrade": {
            "type": [
              "string",
              "null"
            ],
            "description": "Design-for-recycling grade: `A`, `B`, `C` or `non_recyclable`; `null` when not assessed."
          },
          "gradeSource": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where the grade came from. An imported grade is stored as `declared`."
          },
          "placedUnderOwnBrand": {
            "type": "boolean",
            "description": "`true` when you place the unit on the market under your own brand — you are then treated as its manufacturer (PPWR Art. 21)."
          },
          "modifiesConformity": {
            "type": "boolean",
            "description": "`true` when you modify the unit in a way that affects its conformity — you are then treated as its manufacturer (PPWR Art. 21)."
          },
          "isProducer": {
            "type": "boolean",
            "description": "`true` when you are the producer for extended producer responsibility, i.e. you first make the unit available on a member-state market. Applies on top of `role`."
          },
          "reusable": {
            "type": "boolean",
            "description": "Art. 11 reusable packaging."
          },
          "targetRotations": {
            "type": [
              "number",
              "null"
            ],
            "description": "Reusable packaging: the number of rotations the unit is designed for, or `null`."
          },
          "averageRotations": {
            "type": [
              "string",
              "null"
            ],
            "description": "Decimal string."
          },
          "averageRotationMethod": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reusable packaging: how `averageRotations` was obtained — `measured` or `estimated`; `null` when unknown."
          },
          "reconditioningProcess": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reusable packaging: description of the reconditioning process between rotations, or `null`."
          },
          "recyclabilityReference": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reference supporting the recyclability assessment (free text), or `null`."
          },
          "marketMemberStates": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "ISO alpha-2 codes of the member states the unit is placed on the market in."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description and intended use of the packaging."
          },
          "supplierId": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the upstream supplier that supplies the whole unit and its Declaration of Conformity (importer and distributor units), or `null`."
          },
          "supplierRoleOverride": {
            "type": [
              "string",
              "null"
            ],
            "description": "A manual correction of how that supplier relates to the unit: `component_supplier`, `external_manufacturer` or `upstream_operator`; `null` when the relationship is derived from `role`."
          },
          "reuseSystemMemberId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set when the unit is managed inside a re-use system pool."
          },
          "gtin": {
            "type": [
              "string",
              "null"
            ],
            "description": "The PRIMARY size's GTIN."
          },
          "widthMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Width of the primary size in mm, as a decimal string."
          },
          "heightMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Height of the primary size in mm, as a decimal string."
          },
          "depthMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Depth of the primary size in mm, as a decimal string."
          },
          "supplierCountry": {
            "type": [
              "string",
              "null"
            ],
            "description": "Country of the unit's supplier, `null` when it has none."
          },
          "formats": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrUnitFormat"
            },
            "description": "Every size, primary first."
          },
          "components": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrUnitComponentLink"
            },
            "description": "The bill of materials, ordered by component code: each link with its quantity and the component's own fields."
          }
        },
        "required": [
          "id",
          "name",
          "internalRef",
          "packagingType",
          "format",
          "role",
          "recyclabilityGrade",
          "gradeSource",
          "placedUnderOwnBrand",
          "modifiesConformity",
          "isProducer",
          "reusable",
          "targetRotations",
          "averageRotations",
          "averageRotationMethod",
          "reconditioningProcess",
          "recyclabilityReference",
          "marketMemberStates",
          "notes",
          "supplierId",
          "supplierRoleOverride",
          "reuseSystemMemberId",
          "gtin",
          "widthMm",
          "heightMm",
          "depthMm",
          "supplierCountry",
          "formats",
          "components"
        ],
        "description": "One packaging unit as `GET /api/v1/ppwr/units/{id}` returns it: the stored unit fields, the identity of its PRIMARY size folded in (`gtin` and the three dimensions), its supplier's country, all of its sizes and its bill of materials."
      },
      "PpwrUnitFormat": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the size."
          },
          "packagingSpecId": {
            "type": "string",
            "description": "The unit this size belongs to."
          },
          "reference": {
            "type": "string",
            "description": "The size's own identifier — the `reference` of `POST /api/v1/ppwr/formats` and of a unit row's `sizes[]`."
          },
          "gtin": {
            "type": [
              "string",
              "null"
            ],
            "description": "GTIN (barcode) of the size, or `null`."
          },
          "supplierReference": {
            "type": [
              "string",
              "null"
            ],
            "description": "The supplier's own reference for the size, or `null`."
          },
          "label": {
            "type": [
              "string",
              "null"
            ],
            "description": "Human-readable name of the size, or `null`."
          },
          "widthMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Width in mm, as a decimal string."
          },
          "heightMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Height in mm, as a decimal string."
          },
          "depthMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Depth in mm, as a decimal string."
          },
          "isPrimary": {
            "type": "boolean",
            "description": "`true` for the unit's primary size — the one whose GTIN and dimensions the unit itself reports."
          },
          "sortOrder": {
            "type": "number",
            "description": "Display position of the size within the unit (ascending)."
          }
        },
        "required": [
          "id",
          "packagingSpecId",
          "reference",
          "gtin",
          "supplierReference",
          "label",
          "widthMm",
          "heightMm",
          "depthMm",
          "isPrimary",
          "sortOrder"
        ],
        "description": "One size of a packaging unit. The unit's primary size carries its GTIN and dimensions; `GET /api/v1/ppwr/units/{id}` returns the primary size first."
      },
      "PpwrUnitIntakeInput": {
        "type": "object",
        "properties": {
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PpwrUnitRow"
            },
            "maxItems": 1000,
            "description": "The rows, at most 1000 per request."
          },
          "overwrite": {
            "type": "boolean",
            "default": false,
            "description": "Authorises overwriting values that are already filled (including supplier- and AI-attested ones). Without it a batch containing any such change is refused with `409 overwriteRequired` and **nothing** is written."
          }
        },
        "required": [
          "rows"
        ],
        "description": "Envelope form for the unit intake. At most 1000 `sizes` entries across all rows."
      },
      "PpwrUnitListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unit's UUID — what every other `/api/v1/ppwr` endpoint takes."
          },
          "name": {
            "type": "string",
            "description": "Name of the packaging unit."
          },
          "internalRef": {
            "type": "string",
            "description": "Your reference for the unit, or the `PU-<n>` the server generated for a row that sent none. The upsert key of `POST /api/v1/ppwr/units` and the `specInternalRef` of the link endpoints."
          },
          "packagingType": {
            "type": "string",
            "description": "Packaging category: `sales`, `grouped`, `transport`, `ecommerce` or `service`."
          },
          "role": {
            "type": "string",
            "description": "Your economic-operator role for this unit: `manufacturer`, `importer`, `distributor`, `authorised_representative`, `supplier` or `fulfilment_service_provider`."
          },
          "recyclabilityGrade": {
            "type": [
              "string",
              "null"
            ],
            "description": "Design-for-recycling grade: `A`, `B`, `C` or `non_recyclable`; `null` when not assessed."
          },
          "reusable": {
            "type": "boolean",
            "description": "Art. 11 reusable packaging."
          },
          "componentCount": {
            "type": "number",
            "description": "Number of components linked to the unit."
          },
          "completeness": {
            "type": "string",
            "description": "Data completeness, derived from the unit's components: `complete` when every component is complete, `incomplete` when the unit has no components, else `in_progress`."
          },
          "missingFields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The required Annex VII fields still missing across the unit's components. Empty when complete."
          },
          "obligationStatus": {
            "type": "string",
            "description": "Rollup of the unit's applicable PPWR obligations."
          },
          "reuseStatus": {
            "type": "string",
            "description": "State of the Art. 11 / Art. 26 re-use documentation for this unit."
          },
          "docState": {
            "type": "string",
            "description": "Only with `?include=doc` (or when named in `?fields=`). The unit's Declaration-of-Conformity state, the same value the app's units table shows. One of: `issued`, `in_review`, `outdated`, `ready`, `blocked`, `collect`, `not_applicable`."
          },
          "activeDeclaration": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "UUID of the declaration — what `GET /api/v1/ppwr/declarations/{id}` takes."
              },
              "version": {
                "type": "number",
                "description": "Version number; a successor that supersedes this declaration carries a higher one."
              },
              "status": {
                "type": "string",
                "description": "Status of the declaration: `draft`, `issued`, `superseded` or `withdrawn`."
              },
              "origin": {
                "type": "string",
                "description": "`generated` (drawn up in the app) or `collected` (the manufacturer's uploaded DoC)."
              },
              "referenceNumber": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Reference number printed on the declaration, or `null` (e.g. for a draft)."
              },
              "issuedAt": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "When the declaration was issued (ISO 8601, UTC); `null` for a draft."
              },
              "withdrawnAt": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "When the declaration was withdrawn (ISO 8601, UTC); `null` unless withdrawn."
              },
              "supersededAt": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "When a newer declaration replaced this one for its last unit (ISO 8601, UTC); `null` unless `status` is `superseded`, and can also be `null` for a declaration superseded before 2026-10 whose successors were since deleted. A family declaration that loses only some units to a newer one stays `issued` with `supersededAt: null` — those units leave its `activeSpecIds`."
              },
              "supersedesId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "UUID of the earlier declaration this one replaces, or `null`."
              },
              "verified": {
                "type": "boolean",
                "description": "A generated DoC always; a collected DoC once its verification passed and while its file is on record."
              },
              "isFallback": {
                "type": "boolean",
                "description": "An importer substitute DoC (Ersatz-Konformitätserklärung)."
              },
              "pdfUrl": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Path of the PDF download (`GET`, same API key); `null` for a draft, and for a collected declaration whose uploaded file is no longer on record (the download would answer `404`) — `verified` is then `false` too."
              }
            },
            "required": [
              "id",
              "version",
              "status",
              "origin",
              "referenceNumber",
              "issuedAt",
              "withdrawnAt",
              "supersededAt",
              "supersedesId",
              "verified",
              "isFallback",
              "pdfUrl"
            ],
            "description": "Only with `?include=doc` (or when named in `?fields=`). The unit's currently active (issued) declaration, or `null` when it has none."
          }
        },
        "required": [
          "id",
          "name",
          "internalRef",
          "packagingType",
          "role",
          "recyclabilityGrade",
          "reusable",
          "componentCount",
          "completeness",
          "missingFields",
          "obligationStatus",
          "reuseStatus"
        ],
        "description": "One packaging unit as `GET /api/v1/ppwr/units` returns it — the identifying fields plus the rolled-up compliance state the **Packaging units** cockpit shows for the same unit."
      },
      "PpwrUnitRow": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Name of the packaging unit."
          },
          "internalRef": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 120,
            "description": "Your reference for the unit — the upsert key, unique within your company. Omit it only for rows you never intend to replay (see the schema description)."
          },
          "packagingType": {
            "type": "string",
            "enum": [
              "sales",
              "grouped",
              "transport",
              "ecommerce",
              "service"
            ],
            "description": "Packaging category: `sales`, `grouped`, `transport`, `ecommerce` or `service`."
          },
          "role": {
            "type": "string",
            "enum": [
              "manufacturer",
              "importer",
              "distributor",
              "authorised_representative",
              "supplier",
              "fulfilment_service_provider"
            ],
            "description": "Your economic-operator role for this unit: `manufacturer`, `importer`, `distributor`, `authorised_representative`, `supplier` or `fulfilment_service_provider`."
          },
          "supplierName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Resolved to one of your suppliers by fuzzy name match (case, umlauts, punctuation and legal-form tokens are ignored). A name that matches **two or more** distinct suppliers fails the row with `ambiguousSupplierName` — the import never guesses. A name that matches **none** creates a name-only supplier (no email, data incomplete) once per distinct name in the request and links the record to it; the created names are returned in `suppliersCreated`. A blank cell resolves to *no supplier* (your own bucket)."
          },
          "format": {
            "type": [
              "string",
              "null"
            ],
            "description": "Packaging form (free text)."
          },
          "recyclabilityGrade": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "A",
              "B",
              "C",
              "non_recyclable",
              null
            ],
            "description": "A supplied grade is stored as supplier-declared."
          },
          "recyclabilityReference": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000,
            "description": "What the recyclability grade rests on — the supplier sheet or test report it was taken from (free text, at most 2000 characters)."
          },
          "gtin": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^(\\d{8}|\\d{12}|\\d{13}|\\d{14})$",
            "description": "GTIN of the unit's PRIMARY size."
          },
          "supplierReference": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 120,
            "description": "The supplier's own reference for the unit's primary size (on a size row: for that size), at most 120 characters."
          },
          "widthMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Width of the primary size, in mm."
          },
          "heightMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Height of the primary size, in mm."
          },
          "depthMm": {
            "type": [
              "string",
              "null"
            ],
            "description": "Depth of the primary size, in mm."
          },
          "sizeReference": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 120,
            "description": "The flat spelling of a size: several rows sharing one `internalRef`, each with its own `sizeReference`, fold into ONE unit with N sizes. Blank (or equal to `internalRef`) marks the UNIT row. Prefer `sizes[]`."
          },
          "sizeLabel": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 120,
            "description": "Human name of the size. Only a SIZE row may carry it — on a unit row it fails as `conflictingSizeRow`."
          },
          "marketMemberStates": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "pattern": "^[A-Z]{2}$"
            },
            "description": "ISO alpha-2 codes (case-insensitive, stored upper-case). A blank column imports as an empty list and is NOT back-filled from your PPWR default."
          },
          "notes": {
            "type": "string",
            "minLength": 1,
            "description": "**Required** — description and intended use of the packaging. A row without it fails as `descriptionRequired`, including fill-only updates."
          },
          "placedUnderOwnBrand": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Blank = `false` on a create; on an update a blank/absent value leaves the stored value unchanged and an explicit `false` switches a stored `true` off (an overwrite)."
          },
          "modifiesConformity": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Blank = `false` on a create; on an update a blank/absent value leaves the stored value unchanged and an explicit `false` switches a stored `true` off (an overwrite)."
          },
          "reusable": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Art. 11 reusable packaging. Blank = `false` on a create; on an update a blank/absent value leaves the stored value unchanged and an explicit `false` switches a stored `true` off (an overwrite)."
          },
          "articleNumbers": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Links the unit to existing articles by internal article number. On a SIZE row the link is to that size. **An unmatched number is skipped silently** (counted in `articleNumbersUnmatched`), never created and never a row error — unlike `POST /api/v1/ppwr/article-links`, which errors."
          },
          "componentCodes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Builds the bill of materials with quantity 1. An unknown code auto-creates a minimal placeholder component (`other`, name = code, counted in `componentStubsCreated`). A code naming **two or more** live components fails the whole row with `ambiguousComponentMatch` — the cell has no supplier column to disambiguate with, and the oldest match is never picked. `POST /api/v1/ppwr/links` reports the same key, so it is not an escape hatch: make the code unique instead."
          },
          "sizes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "reference": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 120,
                  "description": "The size's identifier, unique within your company."
                },
                "gtin": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "pattern": "^(\\d{8}|\\d{12}|\\d{13}|\\d{14})$",
                  "description": "GTIN of the size: 8, 12, 13 or 14 digits."
                },
                "supplierReference": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "maxLength": 120,
                  "description": "The supplier's own reference for the size (at most 120 characters)."
                },
                "label": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "maxLength": 120,
                  "description": "Human-readable name of the size (at most 120 characters)."
                },
                "widthMm": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0,
                  "description": "Width in mm."
                },
                "heightMm": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0,
                  "description": "Height in mm."
                },
                "depthMm": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0,
                  "description": "Depth in mm."
                }
              },
              "required": [
                "reference"
              ]
            },
            "maxItems": 49,
            "description": "The unit's ADDITIONAL sizes — the primary way to send sizes. On a CREATE the row is one transaction: a refused size (`duplicateFormatReference`, `formatCapReached`) rolls the unit back too. On a row matching an EXISTING unit each size is upserted on its own; sizes the payload omits are never deleted."
          },
          "material": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "plastic",
              "paper_board",
              "glass",
              "metal",
              "wood",
              "composite",
              "other",
              null
            ],
            "description": "Single-part packaging (big bag, pallet, paper sack): the unit's own material family. A row with a `material` gives its unit ONE component (code = `internalRef`, name = `name`, this material) when the unit has no component yet — on a create or on an existing unit; a replay never adds a second. Cannot be combined with `componentCodes` (row is `invalid` with `materialWithComponentCodes`)."
          },
          "massGrams": {
            "type": [
              "string",
              "null"
            ],
            "description": "Single-part packaging: the unit's own mass in grams, written onto the component `material` creates. Requires `material` (else the row is `invalid` with `materialsRequired`)."
          }
        },
        "required": [
          "name",
          "packagingType",
          "role",
          "notes"
        ],
        "description": "One packaging-unit row for `POST /api/v1/ppwr/units`. Upsert key: `internalRef`. **A row without `internalRef` can match nothing and is therefore ALWAYS a create** — the server names the unit with the next generated `PU-<n>`; replaying such a row creates another unit. Cells are coerced exactly as the in-app CSV/Excel importer coerces them, so a JSON-native value and its string spelling are equivalent (`12` = `\"12\"`, `[\"plastic\"]` = `\"plastic;paper_board\"`, `true` = `\"yes\"`/`\"ja\"`/`\"1\"`). An empty or omitted field is a no-op — it never clears a stored value."
      },
      "RateLimitedResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "rate_limited"
                ],
                "description": "Always `rate_limited`."
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation."
              }
            },
            "required": [
              "code",
              "message"
            ],
            "description": "Unlike every other error body, `error` is an object here."
          }
        },
        "required": [
          "error"
        ]
      },
      "ReadinessReport": {
        "type": "object",
        "properties": {
          "contractVersion": {
            "type": "number",
            "enum": [
              1
            ],
            "description": "Readiness envelope version."
          },
          "resource": {
            "type": "object",
            "properties": {
              "module": {
                "type": "string",
                "enum": [
                  "eudr",
                  "ppwr"
                ],
                "description": "Compliance module owning the action."
              },
              "type": {
                "type": "string",
                "enum": [
                  "order",
                  "dds_statement",
                  "ppwr_request",
                  "ppwr_unit"
                ],
                "description": "Closed evaluated resource type."
              },
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Owned evaluated resource UUID."
              },
              "revision": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200,
                "description": "Fingerprint of all mutable facts evaluated for this action."
              }
            },
            "required": [
              "module",
              "type",
              "id",
              "revision"
            ],
            "additionalProperties": false,
            "description": "Exact owned resource and revision evaluated."
          },
          "action": {
            "type": "string",
            "enum": [
              "eudr.dds_draft.create",
              "eudr.dds.submit",
              "ppwr.supplier_reply.submit",
              "ppwr.declaration.issue"
            ],
            "description": "Exact action evaluated; readiness is never global."
          },
          "state": {
            "type": "string",
            "enum": [
              "ready",
              "blocked",
              "pending",
              "unknown",
              "not_applicable"
            ],
            "description": "Current action-scoped readiness state."
          },
          "complete": {
            "type": "boolean",
            "description": "Whether every required evaluator and response segment completed."
          },
          "evaluatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "UTC instant when evaluation completed."
          },
          "rulesetVersion": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Version of the action adapter ruleset."
          },
          "policyVersion": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Fingerprint of effective actor authorization policy."
          },
          "findings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "enum": [
                    "authorization.action_denied",
                    "readiness.evaluation_incomplete",
                    "eudr.dds.not_required",
                    "eudr.dds.supplier_article_missing",
                    "eudr.compliance.not_acceptable",
                    "eudr.dds.not_draft",
                    "eudr.dds.submission_disabled",
                    "eudr.dds.client_id_missing",
                    "eudr.dds.traces_credentials_missing",
                    "eudr.dds.payload_invalid",
                    "ppwr.reply.supplier_action_required",
                    "ppwr.declaration.not_manufacturer",
                    "ppwr.declaration.heavy_metals_outstanding",
                    "ppwr.declaration.pfas_outstanding",
                    "ppwr.declaration.no_components",
                    "ppwr.declaration.manufacturer_identity_missing"
                  ],
                  "description": "Stable machine finding code; never localized prose."
                },
                "effect": {
                  "type": "string",
                  "enum": [
                    "blocking",
                    "pending",
                    "informational"
                  ],
                  "description": "How the finding affects the named action."
                },
                "severity": {
                  "type": "string",
                  "enum": [
                    "error",
                    "warning",
                    "info"
                  ],
                  "description": "Presentation severity, independent of effect."
                },
                "resourcePath": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 300,
                  "description": "Safe logical path to the affected owned resource."
                },
                "owner": {
                  "type": "string",
                  "enum": [
                    "user",
                    "supplier",
                    "system",
                    "external"
                  ],
                  "description": "Actor responsible for resolving the finding."
                },
                "source": {
                  "type": "object",
                  "properties": {
                    "evaluator": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100,
                      "description": "Stable evaluator identifier."
                    },
                    "revision": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "description": "Fingerprint of the facts consumed by this evaluator."
                    }
                  },
                  "required": [
                    "evaluator",
                    "revision"
                  ],
                  "additionalProperties": false,
                  "description": "Authority and source revision for this finding."
                },
                "message": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "description": "Optional localization key; machine behavior uses code."
                    },
                    "params": {
                      "type": "object",
                      "additionalProperties": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 200
                          },
                          {
                            "type": "number"
                          },
                          {
                            "type": "boolean"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "description": "Bounded non-sensitive localization parameters."
                    }
                  },
                  "required": [
                    "key"
                  ],
                  "additionalProperties": false,
                  "description": "Optional safe presentation metadata."
                }
              },
              "required": [
                "code",
                "effect",
                "severity",
                "resourcePath",
                "owner",
                "source"
              ],
              "additionalProperties": false
            },
            "maxItems": 100,
            "description": "Deterministic current findings, capped at 100."
          },
          "nextActions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "command": {
                  "type": "string",
                  "enum": [
                    "createDdsStatement",
                    "open_dds_submission"
                  ],
                  "description": "Closed registered command or browser handoff identifier."
                },
                "commandVersion": {
                  "type": "number",
                  "enum": [
                    1
                  ],
                  "description": "Version of the registered command contract."
                },
                "target": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "order",
                        "dds_statement",
                        "ppwr_request",
                        "ppwr_unit"
                      ],
                      "description": "Closed target resource type."
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Owned target resource UUID."
                    }
                  },
                  "required": [
                    "type",
                    "id"
                  ],
                  "additionalProperties": false,
                  "description": "Exact owned target for the next action."
                },
                "owner": {
                  "type": "string",
                  "enum": [
                    "user",
                    "supplier",
                    "system",
                    "external"
                  ],
                  "description": "Actor authorized to take this next action."
                },
                "executionClass": {
                  "type": "string",
                  "enum": [
                    "direct",
                    "confirmed",
                    "legally_confirmed"
                  ],
                  "description": "Required confirmation boundary."
                },
                "availability": {
                  "type": "string",
                  "enum": [
                    "mcp",
                    "rest",
                    "polygon_browser",
                    "supplier_portal",
                    "system",
                    "external"
                  ],
                  "description": "Currently authorized execution surface."
                },
                "resolves": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "authorization.action_denied",
                      "readiness.evaluation_incomplete",
                      "eudr.dds.not_required",
                      "eudr.dds.supplier_article_missing",
                      "eudr.compliance.not_acceptable",
                      "eudr.dds.not_draft",
                      "eudr.dds.submission_disabled",
                      "eudr.dds.client_id_missing",
                      "eudr.dds.traces_credentials_missing",
                      "eudr.dds.payload_invalid",
                      "ppwr.reply.supplier_action_required",
                      "ppwr.declaration.not_manufacturer",
                      "ppwr.declaration.heavy_metals_outstanding",
                      "ppwr.declaration.pfas_outstanding",
                      "ppwr.declaration.no_components",
                      "ppwr.declaration.manufacturer_identity_missing"
                    ]
                  },
                  "maxItems": 100,
                  "description": "Finding codes this action can address."
                },
                "preconditions": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "current_authorization",
                      "live_revalidation"
                    ]
                  },
                  "minItems": 1,
                  "maxItems": 2,
                  "description": "Checks repeated at the command boundary."
                }
              },
              "required": [
                "command",
                "commandVersion",
                "target",
                "owner",
                "executionClass",
                "availability",
                "resolves",
                "preconditions"
              ],
              "additionalProperties": false
            },
            "maxItems": 20,
            "description": "Registered and currently authorized next actions, capped at 20."
          },
          "truncated": {
            "type": "object",
            "properties": {
              "findingsTruncated": {
                "type": "boolean",
                "description": "Whether findings exceeded the response cap."
              },
              "nextActionsTruncated": {
                "type": "boolean",
                "description": "Whether next actions exceeded the response cap."
              }
            },
            "required": [
              "findingsTruncated",
              "nextActionsTruncated"
            ],
            "additionalProperties": false,
            "description": "Explicit response-cap status; truncation makes the result incomplete."
          }
        },
        "required": [
          "contractVersion",
          "resource",
          "action",
          "state",
          "complete",
          "evaluatedAt",
          "rulesetVersion",
          "policyVersion",
          "findings",
          "nextActions",
          "truncated"
        ],
        "additionalProperties": false
      },
      "Supplier": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the supplier."
          },
          "name": {
            "type": "string",
            "description": "Supplier company name."
          },
          "contactName": {
            "type": "string",
            "description": "Contact person; empty string when none is recorded."
          },
          "country": {
            "type": "string",
            "description": "Country of the supplier as recorded (the value sent on create, e.g. a country name); empty string when unknown."
          },
          "status": {
            "type": "string",
            "description": "Deprecated: legacy data-completeness flag, no longer maintained. Read `articles[].complianceResults` for the supplier's compliance status. One of: `data_incomplete`, `data_complete`, `dds_submitted`."
          },
          "externalSupplierId": {
            "type": [
              "string",
              "null"
            ],
            "description": "External ID from your ERP system"
          },
          "address": {
            "type": "object",
            "properties": {
              "street": {
                "type": "string",
                "description": "Street and house number (or the full one-line address)."
              },
              "city": {
                "type": "string",
                "description": "City; may be empty."
              },
              "postalCode": {
                "type": "string",
                "description": "Postal code; may be empty."
              }
            },
            "required": [
              "street",
              "city",
              "postalCode"
            ],
            "description": "Postal address; absent when none is recorded."
          },
          "email": {
            "type": "string",
            "description": "Contact email; empty string when none is recorded."
          },
          "articles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Article"
            },
            "description": "The articles linked to the supplier. Suppliers embedded in an article carry `[]`."
          },
          "plots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Plot"
            },
            "description": "Suppliers embedded in articles, orders and DDS lines carry `plots: []`. The supplier endpoints serve `SupplierResponse`: distinct plots without geometry, capped at 1000, and articles without a plot list."
          },
          "complianceResults": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ComplianceResult"
            },
            "description": "Compliance results at supplier level. Compliance results live per article (`articles[].complianceResults`); expect `[]` here."
          },
          "isCompanySelf": {
            "type": "boolean",
            "description": "True if this supplier represents your own company (for sale articles)"
          },
          "supplierArticles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "UUID of the supplier article (this supplier's link to one article) — what `supplierArticleIds` of `POST /api/v1/plots` takes."
                },
                "supplierId": {
                  "type": "string",
                  "description": "UUID of the supplier."
                },
                "articleId": {
                  "type": "string",
                  "description": "UUID of the linked article."
                },
                "producerName": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Name of the producer recorded for this link, or `null`."
                },
                "countryOfProduction": {
                  "type": [
                    "array",
                    "null"
                  ],
                  "items": {
                    "type": "string"
                  },
                  "description": "Countries of production declared for this link, as canonical English country names (e.g. `\"Brazil\"`). ISO 3166-1 alpha-2 / alpha-3 codes and localized names are accepted on write and read back as the name; values that do not resolve to a known country are stored as sent; older records may still hold the value as originally sent. `null` when none is recorded."
                },
                "supplierDdsReference": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Reference number of the supplier's own DDS for this article, when recorded; `null` otherwise."
                }
              },
              "required": [
                "id",
                "supplierId",
                "articleId",
                "producerName",
                "countryOfProduction",
                "supplierDdsReference"
              ]
            },
            "description": "The supplier's links to articles (one supplier article per linked article)."
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the supplier was moved to the trash (ISO 8601, UTC); `null` for a live supplier."
          },
          "assignedToUserId": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the user in your company responsible for this supplier, or `null`."
          },
          "otpContactEmail": {
            "type": [
              "string",
              "null"
            ],
            "description": "The email address the supplier confirmed for one-time security codes in the supplier portal, or `null`."
          },
          "otpContactConfirmedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the supplier confirmed `otpContactEmail` (ISO 8601, UTC), or `null`."
          },
          "otpExemptUntil": {
            "type": [
              "string",
              "null"
            ],
            "description": "Until when the supplier is exempt from one-time security codes in the supplier portal (ISO 8601, UTC), or `null`."
          }
        },
        "required": [
          "id",
          "name",
          "contactName",
          "country",
          "status",
          "externalSupplierId",
          "email",
          "articles",
          "plots",
          "complianceResults",
          "isCompanySelf",
          "supplierArticles",
          "deletedAt",
          "assignedToUserId",
          "otpContactEmail",
          "otpContactConfirmedAt",
          "otpExemptUntil"
        ]
      },
      "SupplierCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the supplier."
          },
          "name": {
            "type": "string",
            "description": "Supplier company name."
          },
          "contactName": {
            "type": "string",
            "description": "Contact person; empty string when none is recorded."
          },
          "country": {
            "type": "string",
            "description": "Country of the supplier as recorded (the value sent on create, e.g. a country name); empty string when unknown."
          },
          "email": {
            "type": "string",
            "description": "Contact email; empty string when none is recorded."
          },
          "assignedToUserId": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the user in your company responsible for this supplier, or `null`."
          },
          "externalSupplierId": {
            "type": [
              "string",
              "null"
            ],
            "description": "External ID from your ERP system"
          },
          "address": {
            "type": "object",
            "properties": {
              "street": {
                "type": "string",
                "description": "Street and house number (or the full one-line address)."
              },
              "city": {
                "type": "string",
                "description": "City; may be empty."
              },
              "postalCode": {
                "type": "string",
                "description": "Postal code; may be empty."
              }
            },
            "required": [
              "street",
              "city",
              "postalCode"
            ],
            "description": "Postal address; absent when none is recorded."
          },
          "otpContactEmail": {
            "type": [
              "string",
              "null"
            ],
            "description": "The email address the supplier confirmed for one-time security codes in the supplier portal, or `null`."
          },
          "otpContactConfirmedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the supplier confirmed `otpContactEmail` (ISO 8601, UTC), or `null`."
          },
          "status": {
            "type": "string",
            "description": "Deprecated: legacy data-completeness flag, no longer maintained. Read `articles[].complianceResults` for the supplier's compliance status. One of: `data_incomplete`, `data_complete`, `dds_submitted`."
          },
          "isCompanySelf": {
            "type": "boolean",
            "description": "True if this supplier represents your own company (for sale articles)"
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the supplier was moved to the trash (ISO 8601, UTC); `null` for a live supplier."
          }
        },
        "required": [
          "id",
          "name",
          "contactName",
          "country",
          "email",
          "assignedToUserId",
          "externalSupplierId",
          "otpContactEmail",
          "otpContactConfirmedAt",
          "status",
          "isCompanySelf",
          "deletedAt"
        ],
        "description": "The stored supplier fields. Further keys may be present and are not part of the contract; read the full supplier with `GET /api/v1/suppliers/{id}`."
      },
      "SupplierResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the supplier."
          },
          "name": {
            "type": "string",
            "description": "Supplier company name."
          },
          "contactName": {
            "type": "string",
            "description": "Contact person; empty string when none is recorded."
          },
          "country": {
            "type": "string",
            "description": "Country of the supplier as recorded (the value sent on create, e.g. a country name); empty string when unknown."
          },
          "status": {
            "type": "string",
            "description": "Deprecated: legacy data-completeness flag, no longer maintained. Read `articles[].complianceResults` for the supplier's compliance status. One of: `data_incomplete`, `data_complete`, `dds_submitted`."
          },
          "externalSupplierId": {
            "type": [
              "string",
              "null"
            ],
            "description": "External ID from your ERP system"
          },
          "address": {
            "type": "object",
            "properties": {
              "street": {
                "type": "string",
                "description": "Street and house number (or the full one-line address)."
              },
              "city": {
                "type": "string",
                "description": "City; may be empty."
              },
              "postalCode": {
                "type": "string",
                "description": "Postal code; may be empty."
              }
            },
            "required": [
              "street",
              "city",
              "postalCode"
            ],
            "description": "Postal address; absent when none is recorded."
          },
          "email": {
            "type": "string",
            "description": "Contact email; empty string when none is recorded."
          },
          "articles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SupplierResponseArticle"
            },
            "description": "The supplier's articles, without a plot list: `plots` holds the supplier's distinct plots; per-article plots via GET /articles/{id}."
          },
          "plots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlotListItem"
            },
            "description": "Distinct plots of the supplier without geometry, at most 1000 (ordered by id); fetch geometry via GET /plots/{id}."
          },
          "complianceResults": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ComplianceResult"
            },
            "description": "Compliance results at supplier level. Compliance results live per article (`articles[].complianceResults`); expect `[]` here."
          },
          "isCompanySelf": {
            "type": "boolean",
            "description": "True if this supplier represents your own company (for sale articles)"
          },
          "supplierArticles": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "UUID of the supplier article (this supplier's link to one article) — what `supplierArticleIds` of `POST /api/v1/plots` takes."
                },
                "supplierId": {
                  "type": "string",
                  "description": "UUID of the supplier."
                },
                "articleId": {
                  "type": "string",
                  "description": "UUID of the linked article."
                },
                "producerName": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Name of the producer recorded for this link, or `null`."
                },
                "countryOfProduction": {
                  "type": [
                    "array",
                    "null"
                  ],
                  "items": {
                    "type": "string"
                  },
                  "description": "Countries of production declared for this link, as canonical English country names (e.g. `\"Brazil\"`). ISO 3166-1 alpha-2 / alpha-3 codes and localized names are accepted on write and read back as the name; values that do not resolve to a known country are stored as sent; older records may still hold the value as originally sent. `null` when none is recorded."
                },
                "supplierDdsReference": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Reference number of the supplier's own DDS for this article, when recorded; `null` otherwise."
                }
              },
              "required": [
                "id",
                "supplierId",
                "articleId",
                "producerName",
                "countryOfProduction",
                "supplierDdsReference"
              ]
            },
            "description": "The supplier's links to articles (one supplier article per linked article)."
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the supplier was moved to the trash (ISO 8601, UTC); `null` for a live supplier."
          },
          "assignedToUserId": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the user in your company responsible for this supplier, or `null`."
          },
          "otpContactEmail": {
            "type": [
              "string",
              "null"
            ],
            "description": "The email address the supplier confirmed for one-time security codes in the supplier portal, or `null`."
          },
          "otpContactConfirmedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the supplier confirmed `otpContactEmail` (ISO 8601, UTC), or `null`."
          },
          "otpExemptUntil": {
            "type": [
              "string",
              "null"
            ],
            "description": "Until when the supplier is exempt from one-time security codes in the supplier portal (ISO 8601, UTC), or `null`."
          },
          "plotsTruncated": {
            "type": "boolean",
            "description": "true when the supplier has more than 1000 distinct plots and `plots` holds only the first 1000 by id."
          }
        },
        "required": [
          "id",
          "name",
          "contactName",
          "country",
          "status",
          "externalSupplierId",
          "email",
          "articles",
          "plots",
          "complianceResults",
          "isCompanySelf",
          "supplierArticles",
          "deletedAt",
          "assignedToUserId",
          "otpContactEmail",
          "otpContactConfirmedAt",
          "otpExemptUntil",
          "plotsTruncated"
        ],
        "description": "A supplier as returned by GET /suppliers and GET /suppliers/{id}."
      },
      "SupplierResponseArticle": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "UUID of the article."
          },
          "name": {
            "type": "string",
            "description": "Article name."
          },
          "shortDescription": {
            "type": "string",
            "description": "Short description of the article; empty string when none was given."
          },
          "internalArticleNr": {
            "type": "string",
            "description": "Internal article number (your ERP ID), unique per company. A per-order copy of an article carries `<internalArticleNr>#<orderNumber>`; the number to show to people is `externalArticleNr` when set, else `internalArticleNr`."
          },
          "externalArticleNr": {
            "type": [
              "string",
              "null"
            ],
            "description": "External article number, e.g. a supplier's or customer's number. On a per-order copy it holds the original article's `internalArticleNr`."
          },
          "ean": {
            "type": [
              "string",
              "null"
            ],
            "description": "EAN / GTIN barcode, or `null`."
          },
          "hsCode": {
            "type": "string",
            "description": "Harmonized System code"
          },
          "articleType": {
            "type": "string",
            "description": "`purchase` (bought from a supplier) or `sale` (sold by your company)."
          },
          "eudrRelevant": {
            "type": "boolean",
            "description": "Automatically determined from HS code"
          },
          "needsManualCheck": {
            "type": "boolean",
            "description": "`true` when the EUDR classification derived from the HS code should be checked by a person."
          },
          "sourceScope": {
            "type": "string",
            "description": "`standing`: the article's source is fixed. `perOrder`: the article is a template whose source varies per order; order import creates one copy per order from it."
          },
          "hsPlausibility": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "description": "Stored result of an advisory check of the HS code against the article description, or `null` when not checked. Stored only: it never warns about or blocks a create or update. The object's shape is not part of the v1 contract and may change — do not depend on it."
          },
          "suppliers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Supplier"
            },
            "description": "The suppliers linked to the article. Embedded suppliers carry empty `articles` and `plots`."
          },
          "complianceResults": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ComplianceResult"
            },
            "description": "The EUDR compliance result per supplier link of the article."
          },
          "geoComplianceResults": {
            "type": "array",
            "items": {},
            "description": "Geolocation compliance details. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "legalComplianceResults": {
            "type": "array",
            "items": {},
            "description": "Legal compliance details. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "legalDocuments": {
            "type": "array",
            "items": {},
            "description": "Legal documents on record. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "legalCategoryResults": {
            "type": "array",
            "items": {},
            "description": "Per-category legal compliance results. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "questionnaires": {
            "type": "array",
            "items": {},
            "description": "Supplier questionnaire responses. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "countryOfProduction": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Countries of production declared on one of the article's supplier links (which one is not specified), or `null`."
          },
          "commodityGroup": {
            "type": "string",
            "description": "EUDR commodity group, derived from the HS code unless set explicitly. One of the `CommodityGroup` values."
          },
          "weightPerPieceKg": {
            "type": [
              "number",
              "null"
            ],
            "description": "Weight of one piece in kg, used to derive net mass from a piece count; `null` when unknown."
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the article was moved to the trash (ISO 8601, UTC); `null` for a live article."
          },
          "certifications": {
            "type": "array",
            "items": {},
            "description": "Certifications (e.g. FSC, PEFC) on record for the article; absent when the article has no supplier link. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          },
          "ownSupplierArticleIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "UUIDs of the article's own supplier articles (one per linked supplier); absent when the article has no supplier link."
          },
          "supplierLinks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "supplierId": {
                  "type": "string",
                  "description": "UUID of the linked supplier."
                },
                "supplierArticleId": {
                  "type": "string",
                  "description": "UUID of the supplier article: this article as supplied by that supplier."
                }
              },
              "required": [
                "supplierId",
                "supplierArticleId"
              ]
            },
            "description": "The article's supplier links. `supplierArticleId` addresses this article for one supplier: pass it in `supplierArticleIds` of `POST /api/v1/plots`. Present on the article endpoints and on order-line articles; `[]` when the article has no supplier."
          },
          "inputArticles": {
            "type": "array",
            "items": {},
            "description": "Upstream input articles recorded for the article's supply chain; absent when there are none. Present, but the item shape is not part of the v1 contract and may change — do not depend on it."
          }
        },
        "required": [
          "id",
          "name",
          "shortDescription",
          "internalArticleNr",
          "externalArticleNr",
          "ean",
          "hsCode",
          "articleType",
          "eudrRelevant",
          "needsManualCheck",
          "sourceScope",
          "hsPlausibility",
          "suppliers",
          "complianceResults",
          "geoComplianceResults",
          "legalComplianceResults",
          "legalDocuments",
          "legalCategoryResults",
          "questionnaires",
          "countryOfProduction",
          "commodityGroup",
          "weightPerPieceKg",
          "deletedAt"
        ],
        "description": "An article inside `SupplierResponse.articles` — `Article` without `plots` (use GET /articles/{id})."
      },
      "UpdateArticleInput": {
        "type": "object",
        "properties": {
          "fields": {
            "type": "object",
            "description": "Article fields to update. Any other key is dropped silently.",
            "properties": {
              "name": {
                "type": "string",
                "description": "Article name."
              },
              "shortDescription": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Short description."
              },
              "internalArticleNr": {
                "type": "string",
                "description": "Internal article number (your ERP ID), unique per company."
              },
              "externalArticleNr": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "External article number, e.g. a supplier's or customer's number."
              },
              "ean": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "EAN / GTIN barcode."
              },
              "hsCode": {
                "type": "string",
                "description": "Changing the HS code will recalculate EUDR relevance"
              },
              "articleType": {
                "$ref": "#/components/schemas/ArticleType"
              },
              "eudrRelevant": {
                "type": "boolean",
                "description": "Explicit EUDR classification. Sending it (or `commodityGroup`) is treated as a confirmed override: it wins over the HS-code auto-detection and sets the manual-check flag to `false`. On an article that already carries material rows the override is dropped instead — `eudrRelevant`, `commodityGroup` and `needsManualCheck` are then all left untouched."
              },
              "commodityGroup": {
                "$ref": "#/components/schemas/CommodityGroup"
              },
              "needsManualCheck": {
                "type": "boolean",
                "description": "Marks the article's classification as needing a manual check. Sent on its own, the value is stored as sent. It is overwritten when the same request triggers a classification: changing `hsCode` or `articleType` without an explicit override recomputes it, and an `eudrRelevant`/`commodityGroup` override sets it to `false`. On an article that already carries material rows neither happens — nothing is recomputed, and a value sent together with an override is dropped along with the override (the stored flag stays unchanged)."
              },
              "weightPerPieceKg": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Weight of one piece, in kg. Must be a finite number greater than 0 — anything else is a `400`. `null` clears the value.",
                "exclusiveMinimum": 0
              },
              "sourceScope": {
                "type": "string",
                "enum": [
                  "standing",
                  "perOrder"
                ],
                "description": "`standing` — the article's source is fixed (default). `perOrder` — the article is a template whose source varies per order; order import creates one copy of the article per order."
              }
            }
          },
          "supplierIds": {
            "type": "array",
            "description": "Replace all supplier associations with this list of supplier IDs",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      },
      "UpdateDdsInput": {
        "type": "object",
        "properties": {
          "referenceNumber": {
            "type": "string",
            "minLength": 1,
            "maxLength": 14,
            "description": "TRACES reference number (stored trimmed and upper-cased). Changing it requires `verificationNumber` in the same request."
          },
          "verificationNumber": {
            "type": "string",
            "minLength": 5,
            "maxLength": 35,
            "description": "TRACES verification number (stored trimmed and upper-cased)."
          },
          "type": {
            "type": "string",
            "enum": [
              "import",
              "export",
              "trade",
              "domestic_production"
            ],
            "description": "Activity type (see `DdsType`)."
          }
        }
      },
      "UpdateOrderInput": {
        "type": "object",
        "description": "Update order fields and/or replace order lines. When `lines` is provided, all existing lines are deleted and replaced. Any key other than the ones below is dropped silently.",
        "properties": {
          "orderNumber": {
            "type": "string",
            "description": "New order number, unique per company."
          },
          "orderDate": {
            "type": "string",
            "format": "date-time",
            "description": "Order date, ISO 8601."
          },
          "deliveryDate": {
            "type": "string",
            "format": "date-time",
            "description": "Optional ISO 8601 delivery date. Applies only while no line of the order has its own date (`lines[].deliveryDate`, sent or stored): then it lands as sent. Once a line is dated, the order's `deliveryDate` is the earliest line date and this value is ignored (still `200`, nothing changed)."
          },
          "supplierId": {
            "type": "string",
            "format": "uuid",
            "description": "UUID of an existing supplier of your company."
          },
          "orderType": {
            "$ref": "#/components/schemas/OrderType"
          },
          "lines": {
            "type": "array",
            "description": "Replaces all existing order lines",
            "items": {
              "type": "object",
              "description": "Exactly one of `articleId` / `articleNumber` (the same across all lines); at least one of `quantity` / `pieceCount`. Replace-all. `articleNumber` lines cannot be combined with header fields in one request (`400 headerAndNumberLinesSeparately`).",
              "properties": {
                "positionId": {
                  "type": "string",
                  "maxLength": 64,
                  "description": "Position number of this line in your ERP. All lines or none; unique within the order."
                },
                "articleId": {
                  "type": "string",
                  "format": "uuid",
                  "description": "UUID of an existing article of your company."
                },
                "articleNumber": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Internal article number, resolved like `BatchOrderInput.articleNumber`."
                },
                "hsCode": {
                  "type": "string",
                  "description": "Required when `articleNumber` names no article. For an existing article, read only with per-order article copies enabled — same rules as `BatchOrderInput.hsCode`."
                },
                "quantity": {
                  "type": "number",
                  "minimum": 0,
                  "description": "Net mass in kilograms. Required unless `pieceCount` is provided."
                },
                "pieceCount": {
                  "type": "integer",
                  "exclusiveMinimum": 0,
                  "description": "Number of pieces. Used to derive net mass when `quantity` is omitted."
                },
                "volumeM3": {
                  "type": "number",
                  "exclusiveMinimum": 0,
                  "description": "Volume in m³ — feeds the EUDR DDS supplementary unit (MTQ)."
                },
                "dryWeight90Kg": {
                  "type": "number",
                  "exclusiveMinimum": 0,
                  "description": "Kilograms of 90 %-dry substance — feeds the EUDR DDS supplementary unit (KSD)."
                },
                "deliveryDate": {
                  "type": "string",
                  "format": "date-time",
                  "description": "This position's own delivery date, ISO 8601. Omitted: the line keeps its stored date. When any line ends up dated (sent or kept), the order's `deliveryDate` is the earliest line date (a `deliveryDate` sent in the same body is ignored), and a line without a date first takes the order's previous `deliveryDate` as its own (so a line can follow the order's date only until the next update that sends lines)."
                }
              }
            }
          }
        }
      },
      "UpdatePlotInput": {
        "type": "object",
        "properties": {
          "supplierArticleIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The complete new set of supplier articles for this plot. It **replaces** the current links: links not in the list are removed. At least one id, at most 5000 distinct ids (duplicates are collapsed); a non-uuid id is a `400`."
          },
          "species": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlotSpecies"
            },
            "maxItems": 500,
            "description": "Wood species of the plot, same shape as on create. Optional; when sent it replaces the stored species. Needed when the new links make the plot `wood` and it has no scientific species stored."
          }
        },
        "required": [
          "supplierArticleIds"
        ]
      },
      "UpdateSupplierInput": {
        "type": "object",
        "properties": {
          "fields": {
            "type": "object",
            "description": "Supplier fields to update",
            "properties": {
              "name": {
                "type": "string",
                "description": "Supplier company name."
              },
              "contactName": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Contact person."
              },
              "country": {
                "type": "string",
                "description": "Country of the supplier."
              },
              "email": {
                "type": "string",
                "format": "email",
                "description": "Contact email."
              },
              "address": {
                "$ref": "#/components/schemas/Address"
              },
              "externalSupplierId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Your ERP id of the supplier."
              }
            }
          },
          "articleIds": {
            "type": "array",
            "description": "Replace all article associations with this list of article IDs",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      },
      "ValidationIssue": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Machine code of the issue, e.g. `invalid_type`, `too_small`, `custom`."
          },
          "path": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                }
              ]
            },
            "description": "Location of the offending value in the request: object keys and 0-based array positions."
          },
          "message": {
            "type": "string",
            "description": "Human-readable English explanation. The wording may change; match on `code` and `path`."
          }
        },
        "required": [
          "code",
          "path",
          "message"
        ],
        "additionalProperties": {},
        "description": "One validation issue. Issue-specific keys (e.g. `expected`, `minimum`) may accompany the three listed."
      },
      "ZsvrCategory": {
        "type": "string",
        "enum": [
          "10000",
          "20000",
          "30000",
          "40000",
          "50000",
          "60000",
          "70000",
          "80000"
        ],
        "description": "VerpackG material category: `10000` glass, `20000` paper/board/carton, `30000` ferrous metals, `40000` aluminium, `50000` plastics, `60000` beverage cartons, `70000` other composites, `80000` other materials."
      }
    },
    "parameters": {}
  },
  "paths": {
    "/api/v1/articles": {
      "get": {
        "operationId": "listArticles",
        "summary": "List Articles",
        "description": "Retrieve a paginated list of articles. Supports filtering by article number, HS code, supplier number, order number, species, commodity group, article type, and EUDR relevance.",
        "tags": [
          "Articles"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Filter by internal article number (ERP ID), exact match. A per-order copy of an article is `<internalArticleNr>#<orderNumber>` — encode `#` as `%23`."
            },
            "required": false,
            "description": "Filter by internal article number (ERP ID), exact match. A per-order copy of an article is `<internalArticleNr>#<orderNumber>` — encode `#` as `%23`.",
            "name": "internalArticleNr",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by external article number"
            },
            "required": false,
            "description": "Filter by external article number",
            "name": "externalArticleNr",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by HS code"
            },
            "required": false,
            "description": "Filter by HS code",
            "name": "hsCode",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by the supplier number from your ERP (`externalSupplierId`) of a supplier linked to the article"
            },
            "required": false,
            "description": "Filter by the supplier number from your ERP (`externalSupplierId`) of a supplier linked to the article",
            "name": "externalSupplierId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by order number: articles on a line of that order"
            },
            "required": false,
            "description": "Filter by order number: articles on a line of that order",
            "name": "orderNumber",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by species: articles with a linked plot naming this scientific name (exact match)"
            },
            "required": false,
            "description": "Filter by species: articles with a linked plot naming this scientific name (exact match)",
            "name": "species",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "cattle",
                "cocoa",
                "coffee",
                "oil_palm",
                "rubber",
                "soya",
                "wood",
                "non_relevant"
              ],
              "description": "Filter by commodity group"
            },
            "required": false,
            "description": "Filter by commodity group",
            "name": "commodityGroup",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "purchase",
                "sale"
              ],
              "description": "Filter by article type"
            },
            "required": false,
            "description": "Filter by article type",
            "name": "articleType",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ],
              "description": "Filter by EUDR relevance"
            },
            "required": false,
            "description": "Filter by EUDR relevance",
            "name": "eudrRelevant",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100,
              "description": "Maximum number of results to return (default 100, max 1000)."
            },
            "required": false,
            "description": "Maximum number of results to return (default 100, max 1000).",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "default": 0,
              "description": "Number of results to skip for pagination."
            },
            "required": false,
            "description": "Number of results to skip for pagination.",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of articles",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ArticleResponse"
                  }
                },
                "example": [
                  {
                    "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                    "name": "Pine plank 20 mm",
                    "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                    "internalArticleNr": "ART-1001",
                    "externalArticleNr": null,
                    "ean": null,
                    "hsCode": "4407.11",
                    "articleType": "purchase",
                    "eudrRelevant": true,
                    "needsManualCheck": false,
                    "sourceScope": "standing",
                    "hsPlausibility": null,
                    "geoComplianceResults": [],
                    "legalComplianceResults": [],
                    "legalDocuments": [],
                    "legalCategoryResults": [],
                    "questionnaires": [],
                    "commodityGroup": "wood",
                    "weightPerPieceKg": 2.5,
                    "deletedAt": null,
                    "suppliers": [
                      {
                        "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                        "name": "Sawmill Example GmbH",
                        "contactName": "Alex Example",
                        "country": "Germany",
                        "status": "data_complete",
                        "externalSupplierId": "LIEF-4711",
                        "address": {
                          "street": "Industriestraße 12",
                          "city": "Musterstadt",
                          "postalCode": "12345"
                        },
                        "email": "sales@sawmill.example",
                        "articles": [],
                        "plots": [],
                        "complianceResults": [],
                        "isCompanySelf": false,
                        "supplierArticles": [],
                        "deletedAt": null,
                        "assignedToUserId": null,
                        "otpContactEmail": null,
                        "otpContactConfirmedAt": null,
                        "otpExemptUntil": null
                      }
                    ],
                    "plots": [
                      {
                        "id": "8f3b5d2a-6e19-4c74-a8d3-0b7e2f9c4a16",
                        "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                        "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                        "name": "Example Farm plot 3",
                        "species": [
                          {
                            "commonName": "Loblolly pine",
                            "scientificName": "Pinus taeda"
                          }
                        ],
                        "country": "BR",
                        "size": 2.35,
                        "requiresAreaPlausibilityReview": false,
                        "commodityGroup": "wood",
                        "productionDateFrom": "2025-01-01T00:00:00.000Z",
                        "productionDateTo": "2025-12-31T00:00:00.000Z",
                        "producerName": "Example Forestry Ltda.",
                        "createdAt": "2026-03-02T09:15:00.000Z",
                        "deforestationRiskResult": 0,
                        "updatedAt": "2026-03-02T09:21:41.000Z",
                        "analysisStatus": "completed",
                        "forestPercentage": 0,
                        "isDegraded": false
                      }
                    ],
                    "plotsTruncated": false,
                    "complianceResults": [
                      {
                        "id": "4d9a1f7e-2c38-4e65-9b0d-3a6f8c2e1b47",
                        "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65",
                        "overallStatus": "compliant",
                        "geoStatus": "compliant",
                        "legalStatus": "compliant",
                        "manuallyOverridden": false,
                        "evidenceOpen": false,
                        "generatedReportUrl": null,
                        "generatedAt": null,
                        "updatedAt": "2026-03-02T09:25:00.000Z"
                      }
                    ],
                    "countryOfProduction": [
                      "BR"
                    ],
                    "certifications": [],
                    "ownSupplierArticleIds": [
                      "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                    ],
                    "supplierLinks": [
                      {
                        "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                        "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                      }
                    ]
                  }
                ]
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createArticle",
        "summary": "Create Article",
        "description": "Create a single article (synchronous), or bulk-import articles (asynchronous). For purchase articles, a supplier must be specified (via `supplierId` or `supplierName`). Sale articles are automatically linked to your company. Batch rows upsert idempotently on `internalArticleNr`. **Batch form (array, or `{\"rows\": […]}` envelope, max 5000 rows) is asynchronous:** it stages an import job and returns `202` with a `jobId` — poll `GET /api/v1/import-jobs/{jobId}` for progress and the final result. A single object stays synchronous (`201`). See the Batch Import guide.",
        "tags": [
          "Articles"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/CreateArticleInput"
                  },
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/BatchArticleInput"
                    },
                    "minItems": 1,
                    "maxItems": 5000,
                    "description": "Batch import (bare array form) — asynchronous, returns 202"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "rows": {
                        "type": "array",
                        "items": {
                          "$ref": "#/components/schemas/BatchArticleInput"
                        },
                        "minItems": 1,
                        "maxItems": 5000,
                        "description": "The rows, at most 5000 per request."
                      }
                    },
                    "required": [
                      "rows"
                    ],
                    "description": "Batch envelope form (unknown extra keys are ignored)"
                  }
                ]
              },
              "examples": {
                "single": {
                  "summary": "One article (synchronous, 201)",
                  "value": {
                    "name": "Pine plank 20 mm",
                    "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                    "internalArticleNr": "ART-1001",
                    "hsCode": "4407.11",
                    "articleType": "purchase",
                    "weightPerPieceKg": 2.5,
                    "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94"
                  }
                },
                "batch": {
                  "summary": "Batch import (asynchronous, 202)",
                  "value": {
                    "rows": [
                      {
                        "name": "Pine plank 20 mm",
                        "internalArticleNr": "ART-1001",
                        "hsCode": "4407.11",
                        "articleType": "purchase",
                        "weightPerPieceKg": 2.5,
                        "supplierName": "Sawmill Example GmbH",
                        "supplierExternalId": "LIEF-4711"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Article created successfully (single)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "article": {
                      "$ref": "#/components/schemas/ArticleCreated"
                    }
                  },
                  "required": [
                    "article"
                  ]
                },
                "example": {
                  "article": {
                    "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                    "name": "Pine plank 20 mm",
                    "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                    "internalArticleNr": "ART-1001",
                    "externalArticleNr": null,
                    "ean": null,
                    "hsCode": "4407.11",
                    "articleType": "purchase",
                    "sourceScope": "standing",
                    "eudrRelevant": true,
                    "commodityGroup": "wood",
                    "needsManualCheck": false,
                    "hsPlausibility": null,
                    "deletedAt": null
                  }
                }
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/BatchAccepted"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "An article with this `internalArticleNr` already exists (cannot be overridden), or the article has overridable `warnings` (`duplicateName`, `duplicateEan`) — resend with `acknowledgeWarnings: true`. Single-object form only.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "Article has unresolved warnings. Resubmit with acknowledgeWarnings=true to override.",
                  "warnings": [
                    {
                      "type": "duplicateName",
                      "existingInternalArticleNr": "ART-0999"
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/articles/{id}": {
      "get": {
        "operationId": "getArticle",
        "summary": "Get Article by ID",
        "description": "Retrieve one article of your company with its suppliers, supplier links, compliance results and its distinct plots (without geometry, at most 1000 — see `plotsTruncated`). A deleted article and an article of another company answer `404`. Requires `articles:read`.",
        "tags": [
          "Articles"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Article details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArticleResponse"
                },
                "example": {
                  "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                  "name": "Pine plank 20 mm",
                  "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                  "internalArticleNr": "ART-1001",
                  "externalArticleNr": null,
                  "ean": null,
                  "hsCode": "4407.11",
                  "articleType": "purchase",
                  "eudrRelevant": true,
                  "needsManualCheck": false,
                  "sourceScope": "standing",
                  "hsPlausibility": null,
                  "geoComplianceResults": [],
                  "legalComplianceResults": [],
                  "legalDocuments": [],
                  "legalCategoryResults": [],
                  "questionnaires": [],
                  "commodityGroup": "wood",
                  "weightPerPieceKg": 2.5,
                  "deletedAt": null,
                  "suppliers": [
                    {
                      "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                      "name": "Sawmill Example GmbH",
                      "contactName": "Alex Example",
                      "country": "Germany",
                      "status": "data_complete",
                      "externalSupplierId": "LIEF-4711",
                      "address": {
                        "street": "Industriestraße 12",
                        "city": "Musterstadt",
                        "postalCode": "12345"
                      },
                      "email": "sales@sawmill.example",
                      "articles": [],
                      "plots": [],
                      "complianceResults": [],
                      "isCompanySelf": false,
                      "supplierArticles": [],
                      "deletedAt": null,
                      "assignedToUserId": null,
                      "otpContactEmail": null,
                      "otpContactConfirmedAt": null,
                      "otpExemptUntil": null
                    }
                  ],
                  "plots": [
                    {
                      "id": "8f3b5d2a-6e19-4c74-a8d3-0b7e2f9c4a16",
                      "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                      "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                      "name": "Example Farm plot 3",
                      "species": [
                        {
                          "commonName": "Loblolly pine",
                          "scientificName": "Pinus taeda"
                        }
                      ],
                      "country": "BR",
                      "size": 2.35,
                      "requiresAreaPlausibilityReview": false,
                      "commodityGroup": "wood",
                      "productionDateFrom": "2025-01-01T00:00:00.000Z",
                      "productionDateTo": "2025-12-31T00:00:00.000Z",
                      "producerName": "Example Forestry Ltda.",
                      "createdAt": "2026-03-02T09:15:00.000Z",
                      "deforestationRiskResult": 0,
                      "updatedAt": "2026-03-02T09:21:41.000Z",
                      "analysisStatus": "completed",
                      "forestPercentage": 0,
                      "isDegraded": false
                    }
                  ],
                  "plotsTruncated": false,
                  "complianceResults": [
                    {
                      "id": "4d9a1f7e-2c38-4e65-9b0d-3a6f8c2e1b47",
                      "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65",
                      "overallStatus": "compliant",
                      "geoStatus": "compliant",
                      "legalStatus": "compliant",
                      "manuallyOverridden": false,
                      "evidenceOpen": false,
                      "generatedReportUrl": null,
                      "generatedAt": null,
                      "updatedAt": "2026-03-02T09:25:00.000Z"
                    }
                  ],
                  "countryOfProduction": [
                    "BR"
                  ],
                  "certifications": [],
                  "ownSupplierArticleIds": [
                    "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                  ],
                  "supplierLinks": [
                    {
                      "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                      "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateArticle",
        "summary": "Update Article",
        "description": "Update article fields and/or replace supplier associations.",
        "tags": [
          "Articles"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateArticleInput"
              },
              "example": {
                "fields": {
                  "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm, planed"
                },
                "supplierIds": [
                  "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "Always `true` on success."
                    },
                    "article": {
                      "$ref": "#/components/schemas/ArticleResponse"
                    }
                  },
                  "required": [
                    "success",
                    "article"
                  ]
                },
                "example": {
                  "success": true,
                  "article": {
                    "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                    "name": "Pine plank 20 mm",
                    "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm, planed",
                    "internalArticleNr": "ART-1001",
                    "externalArticleNr": null,
                    "ean": null,
                    "hsCode": "4407.11",
                    "articleType": "purchase",
                    "eudrRelevant": true,
                    "needsManualCheck": false,
                    "sourceScope": "standing",
                    "hsPlausibility": null,
                    "geoComplianceResults": [],
                    "legalComplianceResults": [],
                    "legalDocuments": [],
                    "legalCategoryResults": [],
                    "questionnaires": [],
                    "commodityGroup": "wood",
                    "weightPerPieceKg": 2.5,
                    "deletedAt": null,
                    "suppliers": [
                      {
                        "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                        "name": "Sawmill Example GmbH",
                        "contactName": "Alex Example",
                        "country": "Germany",
                        "status": "data_complete",
                        "externalSupplierId": "LIEF-4711",
                        "address": {
                          "street": "Industriestraße 12",
                          "city": "Musterstadt",
                          "postalCode": "12345"
                        },
                        "email": "sales@sawmill.example",
                        "articles": [],
                        "plots": [],
                        "complianceResults": [],
                        "isCompanySelf": false,
                        "supplierArticles": [],
                        "deletedAt": null,
                        "assignedToUserId": null,
                        "otpContactEmail": null,
                        "otpContactConfirmedAt": null,
                        "otpExemptUntil": null
                      }
                    ],
                    "plots": [
                      {
                        "id": "8f3b5d2a-6e19-4c74-a8d3-0b7e2f9c4a16",
                        "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                        "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                        "name": "Example Farm plot 3",
                        "species": [
                          {
                            "commonName": "Loblolly pine",
                            "scientificName": "Pinus taeda"
                          }
                        ],
                        "country": "BR",
                        "size": 2.35,
                        "requiresAreaPlausibilityReview": false,
                        "commodityGroup": "wood",
                        "productionDateFrom": "2025-01-01T00:00:00.000Z",
                        "productionDateTo": "2025-12-31T00:00:00.000Z",
                        "producerName": "Example Forestry Ltda.",
                        "createdAt": "2026-03-02T09:15:00.000Z",
                        "deforestationRiskResult": 0,
                        "updatedAt": "2026-03-02T09:21:41.000Z",
                        "analysisStatus": "completed",
                        "forestPercentage": 0,
                        "isDegraded": false
                      }
                    ],
                    "plotsTruncated": false,
                    "complianceResults": [
                      {
                        "id": "4d9a1f7e-2c38-4e65-9b0d-3a6f8c2e1b47",
                        "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65",
                        "overallStatus": "compliant",
                        "geoStatus": "compliant",
                        "legalStatus": "compliant",
                        "manuallyOverridden": false,
                        "evidenceOpen": false,
                        "generatedReportUrl": null,
                        "generatedAt": null,
                        "updatedAt": "2026-03-02T09:25:00.000Z"
                      }
                    ],
                    "countryOfProduction": [
                      "BR"
                    ],
                    "certifications": [],
                    "ownSupplierArticleIds": [
                      "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                    ],
                    "supplierLinks": [
                      {
                        "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                        "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Another article already uses this `internalArticleNr`, or `code: FORK_SOURCE_SCOPE_LOCKED` on a per-order copy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "An article with this internal article number already exists."
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteArticle",
        "summary": "Delete Article",
        "description": "Move an article to the trash (soft delete), together with its supplier articles and the data attached to them, and the plots that are linked to no other live supplier article. Orders that reference the article are not changed. A per-order copy of an article that is still on an order line cannot be deleted: `409` with `code: FORK_HAS_ORDER` — delete the order first. An id that names no live article of your company answers `404`. Requires `articles:write`.",
        "tags": [
          "Articles"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "Always `true` on success."
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`code: FORK_HAS_ORDER` — the article is a per-order copy that is still on an order. Nothing was deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "This per-order copy still has an order — delete the order first",
                  "code": "FORK_HAS_ORDER"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/suppliers": {
      "get": {
        "operationId": "listSuppliers",
        "summary": "List Suppliers",
        "description": "Retrieve the suppliers associated with your company, one page at a time (`limit` default 100, max 1000). Pass `externalSupplierId` to look up a supplier by your ERP supplier number.",
        "tags": [
          "Suppliers"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Filter by the supplier number from your ERP (`externalSupplierId`): exact, case-sensitive match after trimming whitespace. Returns at most one supplier; your own company and suppliers invited by another supplier are not listed."
            },
            "required": false,
            "description": "Filter by the supplier number from your ERP (`externalSupplierId`): exact, case-sensitive match after trimming whitespace. Returns at most one supplier; your own company and suppliers invited by another supplier are not listed.",
            "name": "externalSupplierId",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100,
              "description": "Maximum number of results to return (default 100, max 1000)."
            },
            "required": false,
            "description": "Maximum number of results to return (default 100, max 1000).",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "default": 0,
              "description": "Number of results to skip for pagination."
            },
            "required": false,
            "description": "Number of results to skip for pagination.",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of suppliers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SupplierResponse"
                  }
                },
                "example": [
                  {
                    "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                    "name": "Sawmill Example GmbH",
                    "contactName": "Alex Example",
                    "country": "Germany",
                    "status": "data_complete",
                    "externalSupplierId": "LIEF-4711",
                    "address": {
                      "street": "Industriestraße 12",
                      "city": "Musterstadt",
                      "postalCode": "12345"
                    },
                    "email": "sales@sawmill.example",
                    "articles": [
                      {
                        "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                        "name": "Pine plank 20 mm",
                        "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                        "internalArticleNr": "ART-1001",
                        "externalArticleNr": null,
                        "ean": null,
                        "hsCode": "4407.11",
                        "articleType": "purchase",
                        "eudrRelevant": true,
                        "needsManualCheck": false,
                        "sourceScope": "standing",
                        "hsPlausibility": null,
                        "geoComplianceResults": [],
                        "legalComplianceResults": [],
                        "legalDocuments": [],
                        "legalCategoryResults": [],
                        "questionnaires": [],
                        "commodityGroup": "wood",
                        "weightPerPieceKg": 2.5,
                        "deletedAt": null,
                        "suppliers": [],
                        "complianceResults": [
                          {
                            "id": "4d9a1f7e-2c38-4e65-9b0d-3a6f8c2e1b47",
                            "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65",
                            "overallStatus": "compliant",
                            "geoStatus": "compliant",
                            "legalStatus": "compliant",
                            "manuallyOverridden": false,
                            "evidenceOpen": false,
                            "generatedReportUrl": null,
                            "generatedAt": null,
                            "updatedAt": "2026-03-02T09:25:00.000Z"
                          }
                        ],
                        "countryOfProduction": [
                          "BR"
                        ],
                        "certifications": [],
                        "ownSupplierArticleIds": [
                          "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                        ]
                      }
                    ],
                    "plots": [
                      {
                        "id": "8f3b5d2a-6e19-4c74-a8d3-0b7e2f9c4a16",
                        "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                        "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                        "name": "Example Farm plot 3",
                        "species": [
                          {
                            "commonName": "Loblolly pine",
                            "scientificName": "Pinus taeda"
                          }
                        ],
                        "country": "BR",
                        "size": 2.35,
                        "requiresAreaPlausibilityReview": false,
                        "commodityGroup": "wood",
                        "productionDateFrom": "2025-01-01T00:00:00.000Z",
                        "productionDateTo": "2025-12-31T00:00:00.000Z",
                        "producerName": "Example Forestry Ltda.",
                        "createdAt": "2026-03-02T09:15:00.000Z",
                        "deforestationRiskResult": 0,
                        "updatedAt": "2026-03-02T09:21:41.000Z",
                        "analysisStatus": "completed",
                        "forestPercentage": 0,
                        "isDegraded": false
                      }
                    ],
                    "complianceResults": [],
                    "isCompanySelf": false,
                    "supplierArticles": [
                      {
                        "id": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65",
                        "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                        "articleId": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                        "producerName": "Example Forestry Ltda.",
                        "countryOfProduction": [
                          "BR"
                        ],
                        "supplierDdsReference": null
                      }
                    ],
                    "deletedAt": null,
                    "assignedToUserId": null,
                    "otpContactEmail": null,
                    "otpContactConfirmedAt": null,
                    "otpExemptUntil": null,
                    "plotsTruncated": false
                  }
                ]
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createSupplier",
        "summary": "Create Supplier",
        "description": "Create a single supplier (synchronous), or bulk-import suppliers (asynchronous). Batch rows upsert idempotently on `externalSupplierId` (or name). **Batch form (array, or `{\"rows\": […]}` envelope, max 5000 rows) is asynchronous:** it stages an import job and returns `202` with a `jobId` — poll `GET /api/v1/import-jobs/{jobId}` for progress and the final result. A single object stays synchronous (`201`). See the Batch Import guide.",
        "tags": [
          "Suppliers"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/CreateSupplierInput"
                  },
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/BatchSupplierInput"
                    },
                    "minItems": 1,
                    "maxItems": 5000,
                    "description": "Batch import (bare array form) — asynchronous, returns 202"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "rows": {
                        "type": "array",
                        "items": {
                          "$ref": "#/components/schemas/BatchSupplierInput"
                        },
                        "minItems": 1,
                        "maxItems": 5000,
                        "description": "The rows, at most 5000 per request."
                      }
                    },
                    "required": [
                      "rows"
                    ],
                    "description": "Batch envelope form (unknown extra keys are ignored)"
                  }
                ]
              },
              "examples": {
                "single": {
                  "summary": "One supplier (synchronous, 201)",
                  "value": {
                    "name": "Sawmill Example GmbH",
                    "contactName": "Alex Example",
                    "email": "sales@sawmill.example",
                    "externalSupplierId": "LIEF-4711",
                    "country": "Germany",
                    "address": {
                      "street": "Industriestraße 12",
                      "city": "Musterstadt",
                      "postalCode": "12345"
                    }
                  }
                },
                "batch": {
                  "summary": "Batch import (asynchronous, 202)",
                  "value": {
                    "rows": [
                      {
                        "name": "Sawmill Example GmbH",
                        "email": "sales@sawmill.example",
                        "contactName": "Alex Example",
                        "country": "Germany",
                        "address": "Industriestraße 12, 12345 Musterstadt",
                        "externalSupplierId": "LIEF-4711"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Supplier created successfully (single)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "supplier": {
                      "$ref": "#/components/schemas/SupplierCreated"
                    }
                  },
                  "required": [
                    "supplier"
                  ]
                },
                "example": {
                  "supplier": {
                    "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                    "name": "Sawmill Example GmbH",
                    "contactName": "Alex Example",
                    "country": "Germany",
                    "email": "sales@sawmill.example",
                    "assignedToUserId": null,
                    "externalSupplierId": "LIEF-4711",
                    "address": {
                      "street": "Industriestraße 12",
                      "city": "Musterstadt",
                      "postalCode": "12345"
                    },
                    "otpContactEmail": null,
                    "otpContactConfirmedAt": null,
                    "status": "data_incomplete",
                    "isCompanySelf": false,
                    "deletedAt": null
                  }
                }
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/BatchAccepted"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "A supplier with the same identity already exists. Single-object form only.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/suppliers/{id}": {
      "get": {
        "operationId": "getSupplier",
        "summary": "Get Supplier by ID",
        "description": "Retrieve details of a specific supplier including linked articles, plots, and compliance results.",
        "tags": [
          "Suppliers"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Supplier details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupplierResponse"
                },
                "example": {
                  "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                  "name": "Sawmill Example GmbH",
                  "contactName": "Alex Example",
                  "country": "Germany",
                  "status": "data_complete",
                  "externalSupplierId": "LIEF-4711",
                  "address": {
                    "street": "Industriestraße 12",
                    "city": "Musterstadt",
                    "postalCode": "12345"
                  },
                  "email": "sales@sawmill.example",
                  "articles": [
                    {
                      "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                      "name": "Pine plank 20 mm",
                      "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                      "internalArticleNr": "ART-1001",
                      "externalArticleNr": null,
                      "ean": null,
                      "hsCode": "4407.11",
                      "articleType": "purchase",
                      "eudrRelevant": true,
                      "needsManualCheck": false,
                      "sourceScope": "standing",
                      "hsPlausibility": null,
                      "geoComplianceResults": [],
                      "legalComplianceResults": [],
                      "legalDocuments": [],
                      "legalCategoryResults": [],
                      "questionnaires": [],
                      "commodityGroup": "wood",
                      "weightPerPieceKg": 2.5,
                      "deletedAt": null,
                      "suppliers": [],
                      "complianceResults": [
                        {
                          "id": "4d9a1f7e-2c38-4e65-9b0d-3a6f8c2e1b47",
                          "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65",
                          "overallStatus": "compliant",
                          "geoStatus": "compliant",
                          "legalStatus": "compliant",
                          "manuallyOverridden": false,
                          "evidenceOpen": false,
                          "generatedReportUrl": null,
                          "generatedAt": null,
                          "updatedAt": "2026-03-02T09:25:00.000Z"
                        }
                      ],
                      "countryOfProduction": [
                        "BR"
                      ],
                      "certifications": [],
                      "ownSupplierArticleIds": [
                        "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                      ]
                    }
                  ],
                  "plots": [
                    {
                      "id": "8f3b5d2a-6e19-4c74-a8d3-0b7e2f9c4a16",
                      "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                      "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                      "name": "Example Farm plot 3",
                      "species": [
                        {
                          "commonName": "Loblolly pine",
                          "scientificName": "Pinus taeda"
                        }
                      ],
                      "country": "BR",
                      "size": 2.35,
                      "requiresAreaPlausibilityReview": false,
                      "commodityGroup": "wood",
                      "productionDateFrom": "2025-01-01T00:00:00.000Z",
                      "productionDateTo": "2025-12-31T00:00:00.000Z",
                      "producerName": "Example Forestry Ltda.",
                      "createdAt": "2026-03-02T09:15:00.000Z",
                      "deforestationRiskResult": 0,
                      "updatedAt": "2026-03-02T09:21:41.000Z",
                      "analysisStatus": "completed",
                      "forestPercentage": 0,
                      "isDegraded": false
                    }
                  ],
                  "complianceResults": [],
                  "isCompanySelf": false,
                  "supplierArticles": [
                    {
                      "id": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65",
                      "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                      "articleId": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                      "producerName": "Example Forestry Ltda.",
                      "countryOfProduction": [
                        "BR"
                      ],
                      "supplierDdsReference": null
                    }
                  ],
                  "deletedAt": null,
                  "assignedToUserId": null,
                  "otpContactEmail": null,
                  "otpContactConfirmedAt": null,
                  "otpExemptUntil": null,
                  "plotsTruncated": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateSupplier",
        "summary": "Update Supplier",
        "description": "Update supplier fields and/or replace article associations. Uses a nested structure with `fields` for data updates and `articleIds` for link management.",
        "tags": [
          "Suppliers"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateSupplierInput"
              },
              "example": {
                "fields": {
                  "contactName": "Alex Example",
                  "email": "orders@sawmill.example"
                },
                "articleIds": [
                  "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "Always `true` on success."
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The change would duplicate another supplier.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteSupplier",
        "summary": "Delete Supplier",
        "description": "Move a supplier to the trash (soft delete), together with its supplier articles, the plots that become orphaned with them, its supply-chain entities and any suppliers invited underneath it; the invitations it issued are removed outright. An id that names no live supplier of your company still answers `200` and deletes nothing — this route does not answer `404`. A malformed id answers `400`.",
        "tags": [
          "Suppliers"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "Always `true` on success."
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/orders": {
      "get": {
        "operationId": "listOrders",
        "summary": "List Orders",
        "description": "Retrieve orders (purchase and sale) associated with your company, each with the DDS statements linked to it (`ddsReferences`). This is the read-back path for an ERP integration: push orders with `POST /api/v1/orders`, then read them here to collect the TRACES reference and verification number for each order, keyed by your own `orderNumber`.\n\nAll query parameters are optional. A request with none returns the first 100 orders (`limit` default 100, max 1000); page with `offset` until a short page. Malformed parameter values are rejected with `400` rather than ignored, so a polling integration can never silently receive the full set in place of the subset it asked for.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Return only orders whose own data or DDS linkage changed at or after this instant (inclusive). ISO 8601 with `Z` or an offset (URL-encode `+` as `%2B`); passed once. Deletions and unlinking are not covered — see the Batch Import guide for the delta-sync pattern."
            },
            "required": false,
            "description": "Return only orders whose own data or DDS linkage changed at or after this instant (inclusive). ISO 8601 with `Z` or an offset (URL-encode `+` as `%2B`); passed once. Deletions and unlinking are not covered — see the Batch Import guide for the delta-sync pattern.",
            "name": "changedSince",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ],
              "description": "Restrict to orders that already have a DDS statement linked (`true`), or to orders that have none yet (`false`). Note this means a DDS is *linked*, not that it has been submitted to TRACES — a linked but unsubmitted DDS appears with an empty `referenceNumber`. A withdrawn or rejected DDS, or one deleted before it was filed with TRACES, does not count as linked (`false` returns the order; its `ddsReferences` is empty). Do not combine `true` with `changedSince` in a delta poll: the filter hides an order whose DDS was withdrawn or rejected, or deleted before it was filed with TRACES."
            },
            "required": false,
            "description": "Restrict to orders that already have a DDS statement linked (`true`), or to orders that have none yet (`false`). Note this means a DDS is *linked*, not that it has been submitted to TRACES — a linked but unsubmitted DDS appears with an empty `referenceNumber`. A withdrawn or rejected DDS, or one deleted before it was filed with TRACES, does not count as linked (`false` returns the order; its `ddsReferences` is empty). Do not combine `true` with `changedSince` in a delta poll: the filter hides an order whose DDS was withdrawn or rejected, or deleted before it was filed with TRACES.",
            "name": "hasDdsReference",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "done",
                "notRelevant"
              ],
              "description": "Restrict to orders with this derived `status` (see the `status` field). One value, passed once; any other value or a repeated key is rejected with `400`."
            },
            "required": false,
            "description": "Restrict to orders with this derived `status` (see the `status` field). One value, passed once; any other value or a repeated key is rejected with `400`.",
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of order numbers to return, e.g. `ORD-1,ORD-2`. Maximum 1000 values; the answer is still paged, so send `limit` when you name more than 100. Pass the parameter once — repeating the key is rejected rather than silently using only the first value. An empty list is rejected with `400`."
            },
            "required": false,
            "description": "Comma-separated list of order numbers to return, e.g. `ORD-1,ORD-2`. Maximum 1000 values; the answer is still paged, so send `limit` when you name more than 100. Pass the parameter once — repeating the key is rejected rather than silently using only the first value. An empty list is rejected with `400`.",
            "name": "orderNumbers",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100,
              "description": "Maximum number of results to return (default 100, max 1000)."
            },
            "required": false,
            "description": "Maximum number of results to return (default 100, max 1000).",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "default": 0,
              "description": "Number of results to skip for pagination. Results are returned in a stable total order, so paging with `limit` and `offset` never skips or repeats an order."
            },
            "required": false,
            "description": "Number of results to skip for pagination. Results are returned in a stable total order, so paging with `limit` and `offset` never skips or repeats an order.",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of orders",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Order"
                  }
                },
                "example": [
                  {
                    "id": "1b7f3e9d-4a26-4c85-b9e1-5d0a8c3f7e42",
                    "supplier": {
                      "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                      "name": "Sawmill Example GmbH",
                      "contactName": "Alex Example",
                      "country": "Germany",
                      "status": "data_complete",
                      "externalSupplierId": "LIEF-4711",
                      "address": {
                        "street": "Industriestraße 12",
                        "city": "Musterstadt",
                        "postalCode": "12345"
                      },
                      "email": "sales@sawmill.example",
                      "articles": [],
                      "plots": [],
                      "complianceResults": [],
                      "isCompanySelf": false,
                      "supplierArticles": [],
                      "deletedAt": null,
                      "assignedToUserId": null,
                      "otpContactEmail": null,
                      "otpContactConfirmedAt": null,
                      "otpExemptUntil": null
                    },
                    "orderNumber": "PO-2026-0042",
                    "orderDate": "2026-02-16T00:00:00.000Z",
                    "deliveryDate": "2026-04-30T00:00:00.000Z",
                    "orderType": "purchase",
                    "lines": [
                      {
                        "id": "6e2a9c4f-1b73-4d58-8f06-9c3e7a1b5d28",
                        "article": {
                          "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                          "name": "Pine plank 20 mm",
                          "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                          "internalArticleNr": "ART-1001",
                          "externalArticleNr": null,
                          "ean": null,
                          "hsCode": "4407.11",
                          "articleType": "purchase",
                          "eudrRelevant": true,
                          "needsManualCheck": false,
                          "sourceScope": "standing",
                          "hsPlausibility": null,
                          "geoComplianceResults": [],
                          "legalComplianceResults": [],
                          "legalDocuments": [],
                          "legalCategoryResults": [],
                          "questionnaires": [],
                          "commodityGroup": "wood",
                          "weightPerPieceKg": 2.5,
                          "deletedAt": null,
                          "suppliers": [],
                          "plots": [],
                          "complianceResults": [],
                          "countryOfProduction": null,
                          "supplierLinks": [
                            {
                              "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                              "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                            }
                          ]
                        },
                        "quantity": 12500,
                        "pieceCount": 5000,
                        "volumeM3": 25,
                        "dryWeight90Kg": null,
                        "positionId": "00010",
                        "deliveryDate": "2026-04-30T00:00:00.000Z"
                      }
                    ],
                    "totalVolume": 12500,
                    "ddsReferences": [
                      {
                        "id": "0c5e8a2f-7d49-4b16-9e3a-2f8d6b4c1a73",
                        "referenceNumber": "26DEXXXXXXXX01",
                        "verificationNumber": "AB12CD34"
                      }
                    ],
                    "status": "done"
                  }
                ]
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createOrder",
        "summary": "Create Order",
        "description": "Create a single order (synchronous), or bulk-import orders (asynchronous). Batch imports use a flat structure — each row is one order line, grouped by `orderNumber`; supplier/article are resolved by name/number; orders upsert idempotently on `orderNumber`. After import, the system automatically attempts to assign each order to a matching DDS statement if auto-assignment is enabled. **A batch that names an order must carry ALL of that order's lines** — a batch that would delete stored lines fails with `lineReplacementRequired` unless the envelope sets `\"replaceLines\": true`. `positionId` works in both forms: every line of an order carries one or none does (`positionIdMixed`), and an id appears once per order (`duplicatePositionId`) — in the single-object form both answer `400` with that `code`. **Batch form (array, or `{\"rows\": […]}` envelope, max 5000 rows) is asynchronous:** it stages an import job and returns `202` with a `jobId` — poll `GET /api/v1/import-jobs/{jobId}` for progress and the final result. A single object stays synchronous (`201`). See the Batch Import guide.",
        "tags": [
          "Orders"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/CreateOrderInput"
                  },
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/BatchOrderInput"
                    },
                    "minItems": 1,
                    "maxItems": 5000,
                    "description": "Batch import (bare array form) — asynchronous, returns 202"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "rows": {
                        "type": "array",
                        "items": {
                          "$ref": "#/components/schemas/BatchOrderInput"
                        },
                        "minItems": 1,
                        "maxItems": 5000,
                        "description": "The rows, at most 5000 per request."
                      },
                      "replaceLines": {
                        "type": "boolean",
                        "default": false,
                        "description": "Authorize wholesale replacement of an existing order's line set. Without it, a batch that would delete stored order lines fails all-or-nothing with `lineReplacementRequired`."
                      }
                    },
                    "required": [
                      "rows"
                    ],
                    "description": "Batch envelope form (orders only: optional `replaceLines` flag)"
                  }
                ]
              },
              "examples": {
                "single": {
                  "summary": "One order (synchronous, 201)",
                  "value": {
                    "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                    "orderNumber": "PO-2026-0042",
                    "orderDate": "2026-02-16T00:00:00.000Z",
                    "deliveryDate": "2026-04-30T00:00:00.000Z",
                    "orderType": "purchase",
                    "lines": [
                      {
                        "positionId": "00010",
                        "articleId": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                        "quantity": 12500,
                        "pieceCount": 5000,
                        "volumeM3": 25
                      }
                    ]
                  }
                },
                "batch": {
                  "summary": "Batch import, one row per order line (asynchronous, 202)",
                  "value": {
                    "rows": [
                      {
                        "orderNumber": "PO-2026-0042",
                        "orderDate": "2026-02-16",
                        "deliveryDate": "2026-04-30",
                        "orderType": "purchase",
                        "supplierName": "Sawmill Example GmbH",
                        "supplierExternalId": "LIEF-4711",
                        "articleNumber": "ART-1001",
                        "hsCode": "4407.11",
                        "positionId": "00010",
                        "quantity": 12500,
                        "pieceCount": 5000,
                        "volumeM3": 25
                      }
                    ],
                    "replaceLines": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Order created successfully (single)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "order": {
                      "$ref": "#/components/schemas/Order"
                    }
                  },
                  "required": [
                    "order"
                  ]
                },
                "example": {
                  "order": {
                    "id": "1b7f3e9d-4a26-4c85-b9e1-5d0a8c3f7e42",
                    "supplier": {
                      "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                      "name": "Sawmill Example GmbH",
                      "contactName": "Alex Example",
                      "country": "Germany",
                      "status": "data_complete",
                      "externalSupplierId": "LIEF-4711",
                      "address": {
                        "street": "Industriestraße 12",
                        "city": "Musterstadt",
                        "postalCode": "12345"
                      },
                      "email": "sales@sawmill.example",
                      "articles": [],
                      "plots": [],
                      "complianceResults": [],
                      "isCompanySelf": false,
                      "supplierArticles": [],
                      "deletedAt": null,
                      "assignedToUserId": null,
                      "otpContactEmail": null,
                      "otpContactConfirmedAt": null,
                      "otpExemptUntil": null
                    },
                    "orderNumber": "PO-2026-0042",
                    "orderDate": "2026-02-16T00:00:00.000Z",
                    "deliveryDate": "2026-04-30T00:00:00.000Z",
                    "orderType": "purchase",
                    "lines": [
                      {
                        "id": "6e2a9c4f-1b73-4d58-8f06-9c3e7a1b5d28",
                        "article": {
                          "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                          "name": "Pine plank 20 mm",
                          "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                          "internalArticleNr": "ART-1001",
                          "externalArticleNr": null,
                          "ean": null,
                          "hsCode": "4407.11",
                          "articleType": "purchase",
                          "eudrRelevant": true,
                          "needsManualCheck": false,
                          "sourceScope": "standing",
                          "hsPlausibility": null,
                          "geoComplianceResults": [],
                          "legalComplianceResults": [],
                          "legalDocuments": [],
                          "legalCategoryResults": [],
                          "questionnaires": [],
                          "commodityGroup": "wood",
                          "weightPerPieceKg": 2.5,
                          "deletedAt": null,
                          "suppliers": [],
                          "plots": [],
                          "complianceResults": [],
                          "countryOfProduction": null,
                          "supplierLinks": [
                            {
                              "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                              "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                            }
                          ]
                        },
                        "quantity": 12500,
                        "pieceCount": 5000,
                        "volumeM3": 25,
                        "dryWeight90Kg": null,
                        "positionId": "00010",
                        "deliveryDate": "2026-04-30T00:00:00.000Z"
                      }
                    ],
                    "totalVolume": 12500,
                    "ddsReferences": [],
                    "status": "open"
                  }
                }
              }
            }
          },
          "202": {
            "$ref": "#/components/responses/BatchAccepted"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "Single-object form: an order with this `orderNumber` already exists. No order was created. (The batch form updates the existing order instead.)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/orders/{id}": {
      "get": {
        "operationId": "getOrder",
        "summary": "Get Order by ID",
        "description": "Retrieve one order of your company with its supplier, its lines (each with its article) and the DDS statements linked to it (`ddsReferences`), plus the derived `status`. An order of another company answers `404`. Requires `orders:read`.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Order details including lines and DDS references",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                },
                "example": {
                  "id": "1b7f3e9d-4a26-4c85-b9e1-5d0a8c3f7e42",
                  "supplier": {
                    "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                    "name": "Sawmill Example GmbH",
                    "contactName": "Alex Example",
                    "country": "Germany",
                    "status": "data_complete",
                    "externalSupplierId": "LIEF-4711",
                    "address": {
                      "street": "Industriestraße 12",
                      "city": "Musterstadt",
                      "postalCode": "12345"
                    },
                    "email": "sales@sawmill.example",
                    "articles": [],
                    "plots": [],
                    "complianceResults": [],
                    "isCompanySelf": false,
                    "supplierArticles": [],
                    "deletedAt": null,
                    "assignedToUserId": null,
                    "otpContactEmail": null,
                    "otpContactConfirmedAt": null,
                    "otpExemptUntil": null
                  },
                  "orderNumber": "PO-2026-0042",
                  "orderDate": "2026-02-16T00:00:00.000Z",
                  "deliveryDate": "2026-04-30T00:00:00.000Z",
                  "orderType": "purchase",
                  "lines": [
                    {
                      "id": "6e2a9c4f-1b73-4d58-8f06-9c3e7a1b5d28",
                      "article": {
                        "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                        "name": "Pine plank 20 mm",
                        "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                        "internalArticleNr": "ART-1001",
                        "externalArticleNr": null,
                        "ean": null,
                        "hsCode": "4407.11",
                        "articleType": "purchase",
                        "eudrRelevant": true,
                        "needsManualCheck": false,
                        "sourceScope": "standing",
                        "hsPlausibility": null,
                        "geoComplianceResults": [],
                        "legalComplianceResults": [],
                        "legalDocuments": [],
                        "legalCategoryResults": [],
                        "questionnaires": [],
                        "commodityGroup": "wood",
                        "weightPerPieceKg": 2.5,
                        "deletedAt": null,
                        "suppliers": [],
                        "plots": [],
                        "complianceResults": [],
                        "countryOfProduction": null,
                        "supplierLinks": [
                          {
                            "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                            "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                          }
                        ]
                      },
                      "quantity": 12500,
                      "pieceCount": 5000,
                      "volumeM3": 25,
                      "dryWeight90Kg": null,
                      "positionId": "00010",
                      "deliveryDate": "2026-04-30T00:00:00.000Z"
                    }
                  ],
                  "totalVolume": 12500,
                  "ddsReferences": [
                    {
                      "id": "0c5e8a2f-7d49-4b16-9e3a-2f8d6b4c1a73",
                      "referenceNumber": "26DEXXXXXXXX01",
                      "verificationNumber": "AB12CD34"
                    }
                  ],
                  "status": "done"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateOrder",
        "summary": "Update Order",
        "description": "Update order fields (orderNumber, orderDate, supplierId) and/or replace order lines. When `lines` is provided, all existing lines are replaced.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateOrderInput"
              },
              "example": {
                "lines": [
                  {
                    "positionId": "00010",
                    "articleId": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                    "quantity": 12500,
                    "pieceCount": 5000,
                    "volumeM3": 25,
                    "deliveryDate": "2026-05-08T00:00:00.000Z"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "Always `true` on success."
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Two cases, told apart by `error`. `\"An order with this order number already exists.\"`: the body's `orderNumber` belongs to another order of your company; nothing was changed. `\"Order number changed concurrently; retry\"` (only when `lines` name articles by `articleNumber`): the order number was changed by another request while this one ran. The lines may already be stored as a new order under the order's previous number — read the orders back (`GET /api/v1/orders?orderNumbers=…`) before retrying.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "Order number changed concurrently; retry"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteOrder",
        "summary": "Delete Order",
        "description": "Permanently delete an order together with its lines and its links to DDS statements. There is no trash for orders. The DDS statements and the articles stay; the statements' assigned volume (`assignedVolume`, `remainingVolume`) no longer counts this order. An id that names no order of your company answers `404`. Requires `orders:write`.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "Always `true` on success."
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/orders/{id}/origin-confirmation": {
      "post": {
        "operationId": "requestOrderOriginConfirmation",
        "summary": "Request Supplier Origin Confirmation",
        "description": "Call this after uploading all current buyer-provided plots for the selected lines of one order. The supplier is asked to attest the current origin data; previous-order data is not copied and buyer authorship is preserved. Every `supplierArticleId` must be a live, EUDR-relevant link for an article line of this exact order and its supplier, and every target must already have a live plot. Validation is all-or-nothing. Requires `orders:write` and the tenant's per-order origin-confirmation automation to be enabled. Before queueing, the endpoint durably fences the selected targets against any previous-order copy. A successful `202` means queued; request publication and email delivery are asynchronous. An enqueue failure is a `500`, never a misleading `202`; the durable fence remains safe for an idempotent retry. Repeating the same finalization merges into the active supplier request and does not send another creation email.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OriginConfirmationInput"
              },
              "example": {
                "supplierArticleIds": [
                  "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Origin confirmation queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OriginConfirmationAccepted"
                },
                "example": {
                  "status": "queued",
                  "orderId": "1b7f3e9d-4a26-4c85-b9e1-5d0a8c3f7e42",
                  "supplierArticleCount": 1
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`origin_confirmation_disabled` when the tenant is not configured for per-order EUDR origin confirmation; `origin_confirmation_plots_missing` when any target has no live plot; `origin_confirmation_processing` when a supplier answer is already being processed. Nothing is queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "Every supplier article must have at least one live plot",
                  "code": "origin_confirmation_plots_missing"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/dds-statements": {
      "get": {
        "operationId": "listDdsStatements",
        "summary": "List DDS Statements",
        "description": "Retrieve your company's Due Diligence Statements, one page at a time (`limit` default 100, max 1000), including article volumes, assigned orders, and submission status.",
        "tags": [
          "DDS Statements"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100,
              "description": "Maximum number of results to return (default 100, max 1000)."
            },
            "required": false,
            "description": "Maximum number of results to return (default 100, max 1000).",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "default": 0,
              "description": "Number of results to skip for pagination."
            },
            "required": false,
            "description": "Number of results to skip for pagination.",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of DDS statements",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DdsStatement"
                  }
                },
                "example": [
                  {
                    "id": "0c5e8a2f-7d49-4b16-9e3a-2f8d6b4c1a73",
                    "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                    "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                    "name": "Pine planks PO-2026-0042",
                    "country": "Germany",
                    "referenceNumber": "26DEXXXXXXXX01",
                    "verificationNumber": "AB12CD34",
                    "tracesUuid": "b5f0c3e8-2a47-4d91-9e6b-7c1a8f3d5e24",
                    "submittedOn": "2026-03-03T10:00:00.000Z",
                    "type": "import",
                    "source": "internal",
                    "articles": [
                      {
                        "id": "3a9d7e1c-5f62-4a08-b4c7-6e1f0d8a2b59",
                        "ddsStatementId": "0c5e8a2f-7d49-4b16-9e3a-2f8d6b4c1a73",
                        "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65",
                        "volume": 12500,
                        "supplementaryUnitValue": null,
                        "percentageEstimationOrDeviation": null,
                        "article": {
                          "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                          "name": "Pine plank 20 mm",
                          "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                          "internalArticleNr": "ART-1001",
                          "externalArticleNr": null,
                          "ean": null,
                          "hsCode": "4407.11",
                          "articleType": "purchase",
                          "eudrRelevant": true,
                          "needsManualCheck": false,
                          "sourceScope": "standing",
                          "hsPlausibility": null,
                          "geoComplianceResults": [],
                          "legalComplianceResults": [],
                          "legalDocuments": [],
                          "legalCategoryResults": [],
                          "questionnaires": [],
                          "commodityGroup": "wood",
                          "weightPerPieceKg": 2.5,
                          "deletedAt": null,
                          "suppliers": [],
                          "plots": [],
                          "complianceResults": [],
                          "countryOfProduction": null
                        },
                        "supplier": {
                          "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                          "name": "Sawmill Example GmbH",
                          "contactName": "Alex Example",
                          "country": "Germany",
                          "status": "data_complete",
                          "externalSupplierId": "LIEF-4711",
                          "address": {
                            "street": "Industriestraße 12",
                            "city": "Musterstadt",
                            "postalCode": "12345"
                          },
                          "email": "sales@sawmill.example",
                          "articles": [],
                          "plots": [],
                          "complianceResults": [],
                          "isCompanySelf": false,
                          "supplierArticles": [],
                          "deletedAt": null,
                          "assignedToUserId": null,
                          "otpContactEmail": null,
                          "otpContactConfirmedAt": null,
                          "otpExemptUntil": null
                        },
                        "plots": [
                          {
                            "id": "8f3b5d2a-6e19-4c74-a8d3-0b7e2f9c4a16",
                            "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                            "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                            "name": "Example Farm plot 3",
                            "species": [
                              {
                                "commonName": "Loblolly pine",
                                "scientificName": "Pinus taeda"
                              }
                            ],
                            "country": "BR",
                            "size": 2.35,
                            "requiresAreaPlausibilityReview": false,
                            "commodityGroup": "wood",
                            "productionDateFrom": "2025-01-01T00:00:00.000Z",
                            "productionDateTo": "2025-12-31T00:00:00.000Z",
                            "producerName": "Example Forestry Ltda.",
                            "createdAt": "2026-03-02T09:15:00.000Z",
                            "deforestationRiskResult": 0,
                            "updatedAt": "2026-03-02T09:21:41.000Z",
                            "analysisStatus": "completed",
                            "forestPercentage": 0,
                            "isDegraded": false
                          }
                        ],
                        "plotsTruncated": false,
                        "assignedVolume": 12500,
                        "remainingVolume": 0
                      }
                    ],
                    "orders": [
                      {
                        "id": "1b7f3e9d-4a26-4c85-b9e1-5d0a8c3f7e42",
                        "supplier": {
                          "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                          "name": "Sawmill Example GmbH",
                          "contactName": "Alex Example",
                          "country": "Germany",
                          "status": "data_complete",
                          "externalSupplierId": "LIEF-4711",
                          "address": {
                            "street": "Industriestraße 12",
                            "city": "Musterstadt",
                            "postalCode": "12345"
                          },
                          "email": "sales@sawmill.example",
                          "articles": [],
                          "plots": [],
                          "complianceResults": [],
                          "isCompanySelf": false,
                          "supplierArticles": [],
                          "deletedAt": null,
                          "assignedToUserId": null,
                          "otpContactEmail": null,
                          "otpContactConfirmedAt": null,
                          "otpExemptUntil": null
                        },
                        "orderNumber": "PO-2026-0042",
                        "orderDate": "2026-02-16T00:00:00.000Z",
                        "deliveryDate": "2026-04-30T00:00:00.000Z",
                        "orderType": "purchase",
                        "lines": [
                          {
                            "id": "6e2a9c4f-1b73-4d58-8f06-9c3e7a1b5d28",
                            "article": {
                              "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                              "name": "Pine plank 20 mm",
                              "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                              "internalArticleNr": "ART-1001",
                              "externalArticleNr": null,
                              "ean": null,
                              "hsCode": "4407.11",
                              "articleType": "purchase",
                              "eudrRelevant": true,
                              "needsManualCheck": false,
                              "sourceScope": "standing",
                              "hsPlausibility": null,
                              "geoComplianceResults": [],
                              "legalComplianceResults": [],
                              "legalDocuments": [],
                              "legalCategoryResults": [],
                              "questionnaires": [],
                              "commodityGroup": "wood",
                              "weightPerPieceKg": 2.5,
                              "deletedAt": null,
                              "suppliers": [],
                              "plots": [],
                              "complianceResults": [],
                              "countryOfProduction": null,
                              "supplierLinks": [
                                {
                                  "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                                  "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                                }
                              ]
                            },
                            "quantity": 12500,
                            "pieceCount": 5000,
                            "volumeM3": 25,
                            "dryWeight90Kg": null,
                            "positionId": "00010",
                            "deliveryDate": "2026-04-30T00:00:00.000Z"
                          }
                        ],
                        "totalVolume": 12500,
                        "ddsReferences": [
                          {
                            "id": "0c5e8a2f-7d49-4b16-9e3a-2f8d6b4c1a73",
                            "referenceNumber": "26DEXXXXXXXX01",
                            "verificationNumber": "AB12CD34"
                          }
                        ],
                        "status": "done"
                      }
                    ],
                    "status": "validated",
                    "statusUpdatedAt": "2026-03-03T10:04:00.000Z",
                    "errorMessage": null,
                    "declaration": true,
                    "fullName": "Alex Example",
                    "notes": null,
                    "totalVolume": 12500,
                    "totalAssignedVolume": 12500,
                    "totalRemainingVolume": 0,
                    "verificationResult": null,
                    "verificationCheckedAt": null,
                    "groupHeadId": null,
                    "memberCount": 0
                  }
                ]
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createDdsStatement",
        "summary": "Create DDS Statement",
        "description": "Create a new Due Diligence Statement. The supplier must exist and the specified articles must be linked to that supplier. The DDS is created in `draft` status. A delivery that exceeds TRACES' per-statement limits (1000 producers per commodity, 25 MiB of geolocation per statement — the plots of an article are counted once per line that declares them) is created as a statement group: `id` is the group head, `memberIds` the member statements that carry the plots. Submit every member first; the head becomes submittable once all members are validated.",
        "tags": [
          "DDS Statements"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDdsInput"
              },
              "example": {
                "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                "type": "import",
                "name": "Pine planks PO-2026-0042",
                "articles": [
                  {
                    "articleId": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                    "amount": "12500"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "DDS statement created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "ID of the newly created DDS statement — the group head when a group was created."
                    },
                    "memberIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      },
                      "description": "IDs of the member statements when the delivery had to be split into a statement group (in member order); empty for a single statement."
                    }
                  },
                  "required": [
                    "id",
                    "memberIds"
                  ]
                },
                "example": {
                  "id": "0c5e8a2f-7d49-4b16-9e3a-2f8d6b4c1a73",
                  "memberIds": []
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "Refused without writing anything: by the manual compliance check (at least one article is not compliant, pending review, has no compliance result, or carries an unresolved risk signal), or because the delivery cannot be split into filable TRACES statements (see `error`).",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "compliance_blocked"
                          ],
                          "description": "Refused by your company's opt-in manual compliance check (Settings → Automations)."
                        },
                        "details": {
                          "type": "object",
                          "properties": {
                            "blockingArticles": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "supplierArticleId": {
                                    "type": "string",
                                    "format": "uuid",
                                    "description": "The supplier article that failed the check (`supplierLinks[].supplierArticleId` of `GET /api/v1/articles`)."
                                  },
                                  "articleNumber": {
                                    "type": "string",
                                    "description": "The article's external article number when set, else its internal one."
                                  },
                                  "articleName": {
                                    "type": "string",
                                    "description": "The article's name."
                                  }
                                },
                                "required": [
                                  "supplierArticleId",
                                  "articleNumber",
                                  "articleName"
                                ]
                              },
                              "description": "The requested articles that failed the check."
                            }
                          },
                          "required": [
                            "blockingArticles"
                          ],
                          "description": "What blocked the statement."
                        }
                      },
                      "required": [
                        "error",
                        "details"
                      ]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "dds_partition_producer_too_large",
                            "group_volume_too_small"
                          ],
                          "description": "`dds_partition_producer_too_large`: one producer's plots alone exceed the 25 MiB TRACES geolocation cap, no split can file them. `group_volume_too_small`: splitting the delivery would give a member a quantity below 1, which TRACES rejects."
                        }
                      },
                      "required": [
                        "error"
                      ]
                    }
                  ]
                },
                "example": {
                  "error": "compliance_blocked",
                  "details": {
                    "blockingArticles": [
                      {
                        "supplierArticleId": "6c1e8a4d-2f97-4b35-a0e6-8d4c2f7b9a13",
                        "articleNumber": "ART-1003",
                        "articleName": "Pine beam 60 mm"
                      }
                    ]
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/dds-statements/{id}": {
      "get": {
        "operationId": "getDdsStatement",
        "summary": "Get DDS Statement",
        "description": "Retrieve one Due Diligence Statement of your company with its article lines (volumes and declared plots without geometry, at most 1000 per line), the orders linked to it and its TRACES numbers. A group head additionally carries `members`, a group member `groupHeadReferenceNumber`. A deleted statement and a statement of another company answer `404`. Requires `dds:read`.",
        "tags": [
          "DDS Statements"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "DDS statement details including articles, volumes, and linked orders",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DdsStatement"
                },
                "example": {
                  "id": "0c5e8a2f-7d49-4b16-9e3a-2f8d6b4c1a73",
                  "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                  "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                  "name": "Pine planks PO-2026-0042",
                  "country": "Germany",
                  "referenceNumber": "26DEXXXXXXXX01",
                  "verificationNumber": "AB12CD34",
                  "tracesUuid": "b5f0c3e8-2a47-4d91-9e6b-7c1a8f3d5e24",
                  "submittedOn": "2026-03-03T10:00:00.000Z",
                  "type": "import",
                  "source": "internal",
                  "articles": [
                    {
                      "id": "3a9d7e1c-5f62-4a08-b4c7-6e1f0d8a2b59",
                      "ddsStatementId": "0c5e8a2f-7d49-4b16-9e3a-2f8d6b4c1a73",
                      "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65",
                      "volume": 12500,
                      "supplementaryUnitValue": null,
                      "percentageEstimationOrDeviation": null,
                      "article": {
                        "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                        "name": "Pine plank 20 mm",
                        "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                        "internalArticleNr": "ART-1001",
                        "externalArticleNr": null,
                        "ean": null,
                        "hsCode": "4407.11",
                        "articleType": "purchase",
                        "eudrRelevant": true,
                        "needsManualCheck": false,
                        "sourceScope": "standing",
                        "hsPlausibility": null,
                        "geoComplianceResults": [],
                        "legalComplianceResults": [],
                        "legalDocuments": [],
                        "legalCategoryResults": [],
                        "questionnaires": [],
                        "commodityGroup": "wood",
                        "weightPerPieceKg": 2.5,
                        "deletedAt": null,
                        "suppliers": [],
                        "plots": [],
                        "complianceResults": [],
                        "countryOfProduction": null
                      },
                      "supplier": {
                        "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                        "name": "Sawmill Example GmbH",
                        "contactName": "Alex Example",
                        "country": "Germany",
                        "status": "data_complete",
                        "externalSupplierId": "LIEF-4711",
                        "address": {
                          "street": "Industriestraße 12",
                          "city": "Musterstadt",
                          "postalCode": "12345"
                        },
                        "email": "sales@sawmill.example",
                        "articles": [],
                        "plots": [],
                        "complianceResults": [],
                        "isCompanySelf": false,
                        "supplierArticles": [],
                        "deletedAt": null,
                        "assignedToUserId": null,
                        "otpContactEmail": null,
                        "otpContactConfirmedAt": null,
                        "otpExemptUntil": null
                      },
                      "plots": [
                        {
                          "id": "8f3b5d2a-6e19-4c74-a8d3-0b7e2f9c4a16",
                          "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                          "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                          "name": "Example Farm plot 3",
                          "species": [
                            {
                              "commonName": "Loblolly pine",
                              "scientificName": "Pinus taeda"
                            }
                          ],
                          "country": "BR",
                          "size": 2.35,
                          "requiresAreaPlausibilityReview": false,
                          "commodityGroup": "wood",
                          "productionDateFrom": "2025-01-01T00:00:00.000Z",
                          "productionDateTo": "2025-12-31T00:00:00.000Z",
                          "producerName": "Example Forestry Ltda.",
                          "createdAt": "2026-03-02T09:15:00.000Z",
                          "deforestationRiskResult": 0,
                          "updatedAt": "2026-03-02T09:21:41.000Z",
                          "analysisStatus": "completed",
                          "forestPercentage": 0,
                          "isDegraded": false
                        }
                      ],
                      "plotsTruncated": false,
                      "assignedVolume": 12500,
                      "remainingVolume": 0
                    }
                  ],
                  "orders": [
                    {
                      "id": "1b7f3e9d-4a26-4c85-b9e1-5d0a8c3f7e42",
                      "supplier": {
                        "id": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                        "name": "Sawmill Example GmbH",
                        "contactName": "Alex Example",
                        "country": "Germany",
                        "status": "data_complete",
                        "externalSupplierId": "LIEF-4711",
                        "address": {
                          "street": "Industriestraße 12",
                          "city": "Musterstadt",
                          "postalCode": "12345"
                        },
                        "email": "sales@sawmill.example",
                        "articles": [],
                        "plots": [],
                        "complianceResults": [],
                        "isCompanySelf": false,
                        "supplierArticles": [],
                        "deletedAt": null,
                        "assignedToUserId": null,
                        "otpContactEmail": null,
                        "otpContactConfirmedAt": null,
                        "otpExemptUntil": null
                      },
                      "orderNumber": "PO-2026-0042",
                      "orderDate": "2026-02-16T00:00:00.000Z",
                      "deliveryDate": "2026-04-30T00:00:00.000Z",
                      "orderType": "purchase",
                      "lines": [
                        {
                          "id": "6e2a9c4f-1b73-4d58-8f06-9c3e7a1b5d28",
                          "article": {
                            "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                            "name": "Pine plank 20 mm",
                            "shortDescription": "Kiln-dried pine plank, 20 × 100 × 2400 mm",
                            "internalArticleNr": "ART-1001",
                            "externalArticleNr": null,
                            "ean": null,
                            "hsCode": "4407.11",
                            "articleType": "purchase",
                            "eudrRelevant": true,
                            "needsManualCheck": false,
                            "sourceScope": "standing",
                            "hsPlausibility": null,
                            "geoComplianceResults": [],
                            "legalComplianceResults": [],
                            "legalDocuments": [],
                            "legalCategoryResults": [],
                            "questionnaires": [],
                            "commodityGroup": "wood",
                            "weightPerPieceKg": 2.5,
                            "deletedAt": null,
                            "suppliers": [],
                            "plots": [],
                            "complianceResults": [],
                            "countryOfProduction": null,
                            "supplierLinks": [
                              {
                                "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                                "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                              }
                            ]
                          },
                          "quantity": 12500,
                          "pieceCount": 5000,
                          "volumeM3": 25,
                          "dryWeight90Kg": null,
                          "positionId": "00010",
                          "deliveryDate": "2026-04-30T00:00:00.000Z"
                        }
                      ],
                      "totalVolume": 12500,
                      "ddsReferences": [
                        {
                          "id": "0c5e8a2f-7d49-4b16-9e3a-2f8d6b4c1a73",
                          "referenceNumber": "26DEXXXXXXXX01",
                          "verificationNumber": "AB12CD34"
                        }
                      ],
                      "status": "done"
                    }
                  ],
                  "status": "validated",
                  "statusUpdatedAt": "2026-03-03T10:04:00.000Z",
                  "errorMessage": null,
                  "declaration": true,
                  "fullName": "Alex Example",
                  "notes": null,
                  "totalVolume": 12500,
                  "totalAssignedVolume": 12500,
                  "totalRemainingVolume": 0,
                  "verificationResult": null,
                  "verificationCheckedAt": null,
                  "groupHeadId": null,
                  "memberCount": 0
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateDdsStatement",
        "summary": "Update DDS Statement",
        "description": "Update DDS statement metadata: reference number, verification number, or type. Only an external statement (`source: external`, one filed outside Polygon One) can be changed; any other statement answers `404`.",
        "tags": [
          "DDS Statements"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateDdsInput"
              },
              "example": {
                "referenceNumber": "26DEXXXXXXXX07",
                "verificationNumber": "EF56GH78"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "Always `true` on success."
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteDdsStatement",
        "summary": "Delete DDS Statement",
        "description": "Delete a DDS statement in Polygon One. This does **not** withdraw a submitted statement in TRACES. A statement that has submission records is moved to the trash (soft delete) and kept for the retention period; any other statement is deleted permanently. Deleting a draft group head also moves its draft members to the trash. A member of a grouped DDS cannot be deleted on its own: the request answers `409` with `code: GROUP_MEMBER_DELETE_REFUSED` and nothing is deleted. For an external statement (`source: external`), the compliance status of the supplier articles it covered is recalculated. An id that names no live statement of your company answers `404`. Requires `dds:write`.",
        "tags": [
          "DDS Statements"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "Always `true` on success."
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`code: GROUP_MEMBER_DELETE_REFUSED` — the statement is a member of a grouped DDS. Nothing was deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/plots": {
      "get": {
        "operationId": "listPlots",
        "summary": "List Plots",
        "description": "Retrieve your company's plots — a bounded list without geometry and link ids; read one plot by id for those. Requires `plots:read`.",
        "tags": [
          "Plots"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100,
              "description": "Maximum number of results to return (default 100, max 1000)."
            },
            "required": false,
            "description": "Maximum number of results to return (default 100, max 1000).",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "default": 0,
              "description": "Number of results to skip for pagination."
            },
            "required": false,
            "description": "Number of results to skip for pagination.",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of plots",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PlotListItem"
                  }
                },
                "example": [
                  {
                    "id": "8f3b5d2a-6e19-4c74-a8d3-0b7e2f9c4a16",
                    "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                    "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                    "name": "Example Farm plot 3",
                    "species": [
                      {
                        "commonName": "Loblolly pine",
                        "scientificName": "Pinus taeda"
                      }
                    ],
                    "country": "BR",
                    "size": 2.35,
                    "requiresAreaPlausibilityReview": false,
                    "commodityGroup": "wood",
                    "productionDateFrom": "2025-01-01T00:00:00.000Z",
                    "productionDateTo": "2025-12-31T00:00:00.000Z",
                    "producerName": "Example Forestry Ltda.",
                    "createdAt": "2026-03-02T09:15:00.000Z",
                    "deforestationRiskResult": 0,
                    "updatedAt": "2026-03-02T09:21:41.000Z",
                    "analysisStatus": "completed",
                    "forestPercentage": 0,
                    "isDegraded": false
                  }
                ]
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createPlot",
        "summary": "Create Plot",
        "description": "Create a plot. Requires `plots:write`. A new plot starts with `analysisStatus: pending`; the deforestation analysis runs asynchronously — read the result later with `GET /api/v1/plots/{id}`.\n\n**Server-owned fields are ignored.** The request cannot set an analysis status, analysis or risk result, timestamps or image data.\n\n**Idempotent retry.** If your company already has a plot with the same `name` and `country` (case and whitespace ignored), the same geometry and exactly the same set of `supplierArticleIds`, no second plot is created and no second analysis is run: the answer is again `201`, with `deduplicated: true` and the stored plot in `created`. Non-empty `producerName`, `productionDateFrom`, `productionDateTo` and `species` from the request **are applied** to the stored plot where they differ (`updated: true`); empty or omitted values never clear a stored value. Name, country, geometry, links, size and commodity group of the stored plot stay unchanged. The effective-group rules (see **Commodity group**) also apply to a retry: a repeat of a stored plot that is `wood` through its links needs `species`, and a repeat whose links give no single group needs `commodityGroup`. A fresh create answers `{ \"created\": …, \"deduplicated\": false }`.\n\n**Linking.** Pass `supplierArticleIds` on creation, or create the plot first and link it with `PATCH /api/v1/plots/{id}`. Supplier-article ids are in `supplierArticles[].id` of `GET /api/v1/suppliers` and `GET /api/v1/suppliers/{id}`, and in `supplierLinks[].supplierArticleId` of `GET /api/v1/articles` (also for a per-order copy of an article).\n\n**Geometry quality checks.** The geometry passes the same EUDR/TRACES checks as the import in the app, and the plot stores the result: coordinates rounded to 6 decimal places, a Z (altitude) ordinate dropped, duplicate consecutive vertices removed, rings closed and oriented, interior rings (holes) removed, and a self-intersecting polygon repaired (the repair may split it into a `MultiPolygon`). A Feature stays a Feature with its `properties`; a bare geometry stays bare. Every repair that changes the shape is named in `warnings` (`POLYGON_HOLES_REMOVED`, `POLYGON_SELF_INTERSECTION_REPAIRED`); `warnings` describes the geometry stored by this request, so it is `[]` on a deduplicated answer. **Removing a hole or repairing a cut-out makes the excluded area part of the plot** — the plot area grows by it. Precision is counted from the digits as written in the request (`0.248300` counts as 6): 6 or more decimals is the EUDR format; 5 (`COORDINATE_PRECISION_BORDERLINE`) and 4 (`COORDINATE_PRECISION_LOW`) are accepted with a warning; 3 or fewer is `400` with `code: plot_precision_too_low` and `precisionDigits`. A geometry the checks refuse is `400` with `code: plot_geometry_invalid` (missing or malformed `coordinates`, too few or no distinct vertices, a degenerate ring) or `code: plot_geometry_self_intersection_unrepairable` (the repair failed, or would change the area by more than 2 %). A geometry with more than 20,000 vertices (positions, counted as sent) is `400` with `code: plot_geometry_too_many_vertices` before any of these checks runs. Nothing is saved on a `400`. Coordinates are never swapped: latitude/longitude out of range stays a `400` (`code: plot_coordinates_out_of_range`). Other request refusals carry a `code` too: `plot_supplier_article_ids_invalid` (also when `supplierArticleIds` is sent but is not an array; `null` counts as no links), `plot_species_incomplete`, `plot_species_required`.\n\n**Commodity group.** Without `commodityGroup` (or with `non_relevant`) the plot takes the group of its linked supplier articles: the one group they all share, or `wood` when any of them is wood. Without `commodityGroup`, the answer is `400` with `code: plot_commodity_group_required` when there are no links or the linked supplier articles give no single commodity group (different groups, `non_relevant` or deleted articles) — send `commodityGroup`. The rules that depend on the group judge this effective group: a plot that becomes `wood` through its links needs a scientific species (`plot_species_required`), and a point whose effective group is `cattle` takes the cattle cap (20,000 ha instead of 4 ha). Check a geometry without creating anything with `POST /api/v1/plots/validate`.\n\n**Production period.** `productionDateFrom` and `productionDateTo` are a date (`YYYY-MM-DD`) or an ISO date-time; the plot stores the UTC day. A date that cannot be read is `400` with `code: production_date_invalid`; a period that ends before it starts is `400` with `code: production_period_inverted`. Both name the offending date in `field` (`productionDateFrom` or `productionDateTo`). On an idempotent retry the rule applies to the period the stored plot would hold after the merge: sending only `productionDateFrom` after the stored `productionDateTo` is `400` too.",
        "tags": [
          "Plots"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePlotInput"
              },
              "example": {
                "name": "Example Farm plot 3",
                "country": "BR",
                "commodityGroup": "wood",
                "size": 2.35,
                "species": [
                  {
                    "commonName": "Loblolly pine",
                    "scientificName": "Pinus taeda"
                  }
                ],
                "producerName": "Example Forestry Ltda.",
                "productionDateFrom": "2025-01-01",
                "productionDateTo": "2025-12-31",
                "geojson": {
                  "type": "Polygon",
                  "coordinates": [
                    [
                      [
                        -50.512347,
                        -25.432613
                      ],
                      [
                        -50.510843,
                        -25.432613
                      ],
                      [
                        -50.510843,
                        -25.431216
                      ],
                      [
                        -50.512347,
                        -25.431216
                      ],
                      [
                        -50.512347,
                        -25.432613
                      ]
                    ]
                  ]
                },
                "supplierArticleIds": [
                  "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Plot created, or an identical plot already existed (see `deduplicated`)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "created": {
                      "$ref": "#/components/schemas/Plot"
                    },
                    "deduplicated": {
                      "type": "boolean",
                      "description": "`false`: a new plot was created and its analysis queued. `true`: an identical plot already existed; `created` is the stored plot and no second plot or analysis run was created."
                    },
                    "updated": {
                      "type": "boolean",
                      "description": "Only when `deduplicated` is `true`: whether non-empty `producerName`, `productionDateFrom`, `productionDateTo` or `species` from the request were applied to the stored plot."
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PlotGeometryWarning"
                      },
                      "description": "What the geometry quality checks changed or noted in the geometry THIS request stored (see the description). `[]` when nothing was changed or noted, and always `[]` when `deduplicated` is `true` (nothing was stored; the stored plot keeps its geometry)."
                    }
                  },
                  "required": [
                    "created",
                    "deduplicated",
                    "warnings"
                  ]
                },
                "example": {
                  "created": {
                    "id": "8f3b5d2a-6e19-4c74-a8d3-0b7e2f9c4a16",
                    "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                    "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                    "name": "Example Farm plot 3",
                    "species": [
                      {
                        "commonName": "Loblolly pine",
                        "scientificName": "Pinus taeda"
                      }
                    ],
                    "country": "BR",
                    "size": 2.35,
                    "requiresAreaPlausibilityReview": false,
                    "commodityGroup": "wood",
                    "productionDateFrom": "2025-01-01T00:00:00.000Z",
                    "productionDateTo": "2025-12-31T00:00:00.000Z",
                    "producerName": "Example Forestry Ltda.",
                    "createdAt": "2026-03-02T09:15:00.000Z",
                    "importPrecisionClass": "ok",
                    "importPrecisionDigits": 6,
                    "deforestationRiskResult": null,
                    "updatedAt": "2026-03-02T09:15:00.000Z",
                    "analysisStatus": "pending",
                    "isDegraded": null,
                    "geojson": {
                      "type": "Polygon",
                      "coordinates": [
                        [
                          [
                            -50.512347,
                            -25.432613
                          ],
                          [
                            -50.510843,
                            -25.432613
                          ],
                          [
                            -50.510843,
                            -25.431216
                          ],
                          [
                            -50.512347,
                            -25.431216
                          ],
                          [
                            -50.512347,
                            -25.432613
                          ]
                        ]
                      ]
                    },
                    "supplierArticleIds": [
                      "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                    ]
                  },
                  "deduplicated": false,
                  "warnings": []
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "API key lacks `plots:write`, or one or more `supplierArticleIds` do not belong to your company",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "One or more supplier articles do not belong to your company."
                }
              }
            }
          },
          "409": {
            "description": "Your workspace's plot limit is reached — `code: PLOT_LIMIT_REACHED`, with `scope` (`total`: the cap on live plots; `month`: the cap on plots created this UTC calendar month), `cap`, `current` (plots already counted against that cap) and `requested`. Nothing is written. Contact Polygon One to raise the limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "Plot limit reached: 1000 of 1000 plots are in use. Contact Polygon One to raise the limit.",
                  "code": "PLOT_LIMIT_REACHED",
                  "cap": 1000,
                  "current": 1000,
                  "requested": 1,
                  "scope": "total"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/plots/validate": {
      "post": {
        "operationId": "validatePlot",
        "summary": "Validate Plot Geometry",
        "description": "Dry run of `POST /api/v1/plots`: the same input, the same checks and the same geometry quality pipeline — **nothing is created or changed**, no analysis runs. Requires `plots:read`. Use it to check a geometry before you create the plot.\n\nThe answer is `200` whether the plot would be accepted or not: `valid` says which. `valid: false` carries the `code` create would answer in `errors`; `geometry` and `measuredAreaHa` are then `null`. `valid: true` carries the geometry exactly as create would store it, its geodesic area in hectares (`null` for a point) and the same `warnings`. Only a body that is not valid JSON is a `400`.\n\nA geometry with more than 20,000 vertices is `valid: false` with `plot_geometry_too_many_vertices`, as on create.\n\n`commodityGroup`, `size` and `species` are optional here and checked only when sent. When `supplierArticleIds` are sent and all belong to your company, the commodity group is derived from them as on create, and `plot_commodity_group_required` (links that give no single commodity group), `plot_species_required` and the point cap judge that group. If any id is not one of yours, nothing is derived and only a sent `commodityGroup` is judged; the id itself is not refused here. When your plot limit is reached, the answer is `valid: false` with `PLOT_LIMIT_REACHED` (create answers `409`); it is judged as for a new plot. Not checked (create checks them): whether the `supplierArticleIds` belong to your company (create answers `403`) and whether an identical plot already exists (create then answers `deduplicated: true`, also at the limit).",
        "tags": [
          "Plots"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePlotInput"
              },
              "example": {
                "name": "Example Farm plot 3",
                "country": "BR",
                "commodityGroup": "wood",
                "species": [
                  {
                    "commonName": "Loblolly pine",
                    "scientificName": "Pinus taeda"
                  }
                ],
                "geojson": {
                  "type": "Polygon",
                  "coordinates": [
                    [
                      [
                        -50.512347,
                        -25.432613
                      ],
                      [
                        -50.510843,
                        -25.432613
                      ],
                      [
                        -50.510843,
                        -25.431216
                      ],
                      [
                        -50.512347,
                        -25.431216
                      ],
                      [
                        -50.512347,
                        -25.432613
                      ]
                    ]
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The verdict create would give; nothing written",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlotValidation"
                },
                "example": {
                  "valid": true,
                  "errors": [],
                  "warnings": [],
                  "precision": {
                    "digits": 6,
                    "class": "ok"
                  },
                  "geometry": {
                    "type": "Polygon",
                    "coordinates": [
                      [
                        [
                          -50.512347,
                          -25.432613
                        ],
                        [
                          -50.510843,
                          -25.432613
                        ],
                        [
                          -50.510843,
                          -25.431216
                        ],
                        [
                          -50.512347,
                          -25.431216
                        ],
                        [
                          -50.512347,
                          -25.432613
                        ]
                      ]
                    ]
                  },
                  "measuredAreaHa": 2.35
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "API key lacks `plots:read`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/plots/{id}": {
      "get": {
        "operationId": "getPlot",
        "summary": "Get Plot by ID",
        "description": "Retrieve one plot with its GeoJSON geometry, the supplier-article links it belongs to and the stored geo analysis result (`analysis`). Requires `plots:read`.\n\n**Analysis result.** `analysis` is the last **stored** result. It is `null` when none was ever stored (a new plot, a `skipped` or `exempt` plot, an analysis that could not run) or after the geometry changed. While a re-analysis is running (`in_progress`), or after a re-analysis failed, it can still carry the previous result — compare `assessedAt`. `riskLevel: INVALID` comes with `analysisStatus: failed`. The texts are English and are the sentences the plot report prints (`GET /api/v1/plots/{id}/report`). This is a geospatial risk assessment, not a standalone determination of EUDR compliance.",
        "tags": [
          "Plots"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Plot details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlotDetail"
                },
                "example": {
                  "id": "8f3b5d2a-6e19-4c74-a8d3-0b7e2f9c4a16",
                  "companyId": "3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17",
                  "createdByUserId": "9b2e7d41-0c6a-4f38-8e15-2a7c9d3b6f80",
                  "name": "Example Farm plot 3",
                  "species": [
                    {
                      "commonName": "Loblolly pine",
                      "scientificName": "Pinus taeda"
                    }
                  ],
                  "country": "BR",
                  "size": 2.35,
                  "requiresAreaPlausibilityReview": false,
                  "commodityGroup": "wood",
                  "productionDateFrom": "2025-01-01T00:00:00.000Z",
                  "productionDateTo": "2025-12-31T00:00:00.000Z",
                  "producerName": "Example Forestry Ltda.",
                  "createdAt": "2026-03-02T09:15:00.000Z",
                  "deforestationRiskResult": 0,
                  "updatedAt": "2026-03-02T09:21:41.000Z",
                  "analysisStatus": "completed",
                  "forestPercentage": 0,
                  "isDegraded": false,
                  "importPrecisionClass": "ok",
                  "importPrecisionDigits": 6,
                  "geojson": {
                    "type": "Polygon",
                    "coordinates": [
                      [
                        [
                          -50.512347,
                          -25.432613
                        ],
                        [
                          -50.510843,
                          -25.432613
                        ],
                        [
                          -50.510843,
                          -25.431216
                        ],
                        [
                          -50.512347,
                          -25.431216
                        ],
                        [
                          -50.512347,
                          -25.432613
                        ]
                      ]
                    ]
                  },
                  "supplierArticleIds": [
                    "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                  ],
                  "analysis": {
                    "riskLevel": "LOW",
                    "assessedAt": "2026-03-02T09:21:40.000Z",
                    "conclusion": "The recorded analysis did not establish post-cutoff deforestation or forest degradation for this plot.",
                    "limitations": [
                      "Complete GFW footprint coverage and a TMF measurement are not established in the stored record. No absence-of-change conclusion is drawn from those sources."
                    ],
                    "evidence": [
                      {
                        "dataset": "JRC GFC 2020",
                        "measurementStatus": "Recorded value; dataset plot coverage not stored",
                        "observation": "Forest baseline value: 0.0% of plot",
                        "relevance": "Forest baseline at cutoff"
                      },
                      {
                        "dataset": "Hansen GFC",
                        "measurementStatus": "Measured",
                        "observation": "Post-2020 loss: 0.0% of plot",
                        "relevance": "Tree-cover loss after cutoff"
                      },
                      {
                        "dataset": "GFW alerts",
                        "measurementStatus": "Complete footprint coverage not established",
                        "observation": "0 alerts; 0 high confidence. No absence conclusion available",
                        "relevance": "Recent disturbance signals"
                      },
                      {
                        "dataset": "JRC TMF AnnualChange",
                        "measurementStatus": "No recorded value; the stored record does not say why",
                        "observation": "The stored result does not preserve why the value is missing.",
                        "relevance": "Tropical forest change"
                      },
                      {
                        "dataset": "JRC GFT 2020",
                        "measurementStatus": "No recorded value; the stored record does not say why",
                        "observation": "The stored result does not preserve why the value is missing.",
                        "relevance": "Forest-type attribution for wood"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updatePlot",
        "summary": "Update Plot Links",
        "description": "Replace the supplier articles a plot is linked to. Requires `plots:write`. The list replaces the current links; links not in it are removed. Optionally send `species` (same shape as on create) in the same request; other plot fields cannot be edited over the API. The compliance status of every affected supplier article is recalculated.\n\n**Commodity group.** A plot whose group is unset or `non_relevant` takes the group of its new links, as on create (`wood` when any of them is wood); an explicit group never changes. A plot that is `wood` after the change needs a scientific species — stored, or sent as `species` — otherwise the answer is `400` with `code: plot_species_required`; an empty `species` list never clears the species of a `wood` plot (same `400`). A plot whose group changed after its analysis ran is re-analysed.\n\nAn id that names no plot of your company (unknown, deleted, or another company's) answers `404`. A supplier-article id that does not belong to your company answers `403`. A malformed plot id, a body that is not valid JSON or an incomplete `species` entry answers `400`. Nothing is changed in any of these cases.",
        "tags": [
          "Plots"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePlotInput"
              },
              "example": {
                "supplierArticleIds": [
                  "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Links replaced",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "Always `true` on success."
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deletePlot",
        "summary": "Delete Plot",
        "description": "Move a plot to the trash (soft delete) together with its supplier-article links. Requires `plots:write`. The compliance status of the previously linked supplier articles is recalculated.",
        "tags": [
          "Plots"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "Always `true` on success."
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/plots/{id}/report": {
      "get": {
        "operationId": "downloadPlotReport",
        "summary": "Download Plot Report",
        "description": "Download the plot report as a PDF attachment: the plot's identity, the recorded geo analysis result with its evidence register, and a map. Requires `plots:read`; in a customer workspace the EUDR module must be enabled for the user the key acts as (a personal key: its owner; a company key: the workspace's highest-ranking active user). English. The report is rendered in every analysis state — before a result exists it states the analysis status instead. Each call renders the report anew (including one map image request): download it once the result is final, do not poll it — poll `GET /api/v1/plots/{id}` for `analysisStatus`.",
        "tags": [
          "Plots"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The plot report",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary",
                  "description": "PDF file."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "API key lacks `plots:read`, or the EUDR module is not enabled for the user the key acts as",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "description": "The plot cannot be rendered: a text field (e.g. the plot or producer name) contains an unbroken run of more than 10,000 characters that contains a character outside Windows-1252 (e.g. CJK). `error` names the run length.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/evidence/upload-url": {
      "post": {
        "operationId": "createEvidenceUploadUrl",
        "summary": "Create Evidence Upload URL",
        "description": "Step 1 of uploading an evidence document (e.g. a legal or origin document) to a supplier article: get a presigned URL, then `PUT` the file bytes to `uploadUrl` with the same `Content-Type` within 10 minutes. Pass the returned `s3Key` as `uploadedS3Key` to `POST /api/v1/evidence`. Accepts the files the in-app evidence upload accepts, at most 10 MB — a wrong type or a larger `fileSize` is a `400`. `fileSize` is signed into `uploadUrl`: a `PUT` of any other length is refused by storage. Requires `evidence:write`.",
        "tags": [
          "Evidence"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EvidenceUploadUrlInput"
              },
              "example": {
                "fileName": "harvest-licence-2025.pdf",
                "contentType": "application/pdf",
                "fileSize": 482113
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned upload URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvidenceUploadUrl"
                },
                "example": {
                  "uploadUrl": "https://example-bucket.s3.eu-central-1.amazonaws.com/pending/operator/3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17/6a0e4c8f-2b57-4d93-8b1f-0e6c4a2d9f85-harvest-licence-2025.pdf?X-Amz-…",
                  "s3Key": "pending/operator/3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17/6a0e4c8f-2b57-4d93-8b1f-0e6c4a2d9f85-harvest-licence-2025.pdf"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/evidence": {
      "post": {
        "operationId": "createEvidence",
        "summary": "Attach Evidence",
        "description": "Attach evidence to the supplier article named by `supplierId` + `articleId` (for per-order origin: the per-order copy's id and its `supplierLinks[].supplierId`). For a new file, send `uploadedS3Key`, `uploadedFileName`, `uploadedFileSize` and `uploadedMimeType` after using the upload URL; the `file` field instead is for small files only (at most 4.5 MB, the platform request cap). To attach a file already stored by your company to another supplier article, send only its `reuseS3Key` from an earlier successful response — no second upload or metadata fields. Exactly one of these three upload sources is allowed. Each call attaches to one supplier article and starts asynchronous analysis. The document is recorded as uploaded by you (the API key's user), not by the supplier. No supplier link of your company for `supplierId` + `articleId` answers `404` (another company's link answers the same); an `uploadedS3Key` not issued to your company, or a `reuseS3Key` that your company does not own, answers `403`. Requires `evidence:write`.",
        "tags": [
          "Evidence"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/EvidenceInput"
              },
              "examples": {
                "upload": {
                  "summary": "Attach a newly uploaded file",
                  "value": {
                    "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                    "articleId": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36",
                    "uploadedS3Key": "pending/operator/3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17/6a0e4c8f-2b57-4d93-8b1f-0e6c4a2d9f85-harvest-licence-2025.pdf",
                    "uploadedFileName": "harvest-licence-2025.pdf",
                    "uploadedFileSize": "482113",
                    "uploadedMimeType": "application/pdf",
                    "evidenceType": "legal_compliance"
                  }
                },
                "reuse": {
                  "summary": "Attach the same stored file to another article without uploading it again",
                  "value": {
                    "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                    "articleId": "1a7c3e9d-6b28-4f50-8d14-2b9e6c3a7f41",
                    "reuseS3Key": "evidence/2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65/0f7b2d9e-5c31-4a86-b4e0-8d2a6c1f9e57-harvest-licence-2025.pdf",
                    "evidenceType": "legal_compliance"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Evidence attached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Evidence"
                },
                "example": {
                  "id": "8d2c6f0a-3e95-4a78-b1d4-9f0e5a3c7b62",
                  "s3Key": "evidence/2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65/0f7b2d9e-5c31-4a86-b4e0-8d2a6c1f9e57-harvest-licence-2025.pdf",
                  "fileName": "harvest-licence-2025.pdf",
                  "fileSize": 482113,
                  "mimeType": "application/pdf",
                  "message": "Evidence document uploaded successfully. Analysis in progress."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "This supplier article already has a live document with these exact bytes — nothing was written. Re-send with `allowDuplicate=true` to attach a second copy anyway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvidenceDuplicate"
                },
                "example": {
                  "error": "duplicate",
                  "existing": {
                    "id": "8d2c6f0a-3e95-4a78-b1d4-9f0e5a3c7b62",
                    "fileName": "harvest-licence-2025.pdf"
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "get": {
        "operationId": "listEvidence",
        "summary": "List Evidence",
        "description": "List the live evidence documents of one supplier article. A supplier article of another company answers `403`. Requires `evidence:read` (an `evidence:write` key satisfies it).",
        "tags": [
          "Evidence"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The supplier article (`supplierLinks[].supplierArticleId` of `GET /api/v1/articles`)."
            },
            "required": true,
            "description": "The supplier article (`supplierLinks[].supplierArticleId` of `GET /api/v1/articles`).",
            "name": "supplierArticleId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "legal_compliance",
                "questionnaire"
              ],
              "description": "Only documents of this type."
            },
            "required": false,
            "description": "Only documents of this type.",
            "name": "evidenceType",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "description": "Maximum number of documents to return (max 1000). Without `limit` and `offset` the whole list is returned; with either, the default page size is 100."
            },
            "required": false,
            "description": "Maximum number of documents to return (max 1000). Without `limit` and `offset` the whole list is returned; with either, the default page size is 100.",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "description": "Number of documents to skip. Documents are returned oldest upload first in a stable order, so paging with `limit` and `offset` until a short page never skips or repeats a document."
            },
            "required": false,
            "description": "Number of documents to skip. Documents are returned oldest upload first in a stable order, so paging with `limit` and `offset` until a short page never skips or repeats a document.",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Evidence documents",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "evidence": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EvidenceDocument"
                      },
                      "description": "The live evidence documents of the supplier article."
                    }
                  },
                  "required": [
                    "evidence"
                  ]
                },
                "example": {
                  "evidence": [
                    {
                      "id": "8d2c6f0a-3e95-4a78-b1d4-9f0e5a3c7b62",
                      "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65",
                      "supplierId": "5a1d8c3e-7f24-4b9a-a6e0-1c3f5b8d2e94",
                      "fileName": "harvest-licence-2025.pdf",
                      "fileSize": 482113,
                      "mimeType": "application/pdf",
                      "evidenceType": "legal_compliance",
                      "sourceType": "user_upload",
                      "verificationStatus": "auto_verified",
                      "supplierAuthored": false,
                      "uploadedAt": "2026-03-02T10:05:00.000Z",
                      "validUntil": "2027-12-31T00:00:00.000Z",
                      "mappings": [
                        {
                          "id": "0e4a8c2d-6f71-4b39-a5c8-4d2f9b1e7a03",
                          "evidenceId": "8d2c6f0a-3e95-4a78-b1d4-9f0e5a3c7b62",
                          "supplierArticleId": "2e8f6a3c-9d17-4b52-8c4a-7f1e3d9b0a65",
                          "category": "land_use_rights",
                          "documentType": "land_rights",
                          "countryCode": "BR",
                          "status": "accepted",
                          "confidence": 0.9,
                          "decidedAt": "2026-03-02T10:07:00.000Z"
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/import-jobs/{jobId}": {
      "get": {
        "operationId": "getImportJob",
        "summary": "Get Import Job",
        "description": "Poll an async batch import job for status, progress and — once `completed` — the merged result. Requires the job kind's read scope (`articles:read`, `suppliers:read`, `orders:read`, or `packaging:read` for a PPWR quantity job; the corresponding write scope implies it). Poll every ~2 s and back off for large jobs; `completed` and `failed` are terminal. An unknown job id and another company's job id both return the same `404`.",
        "tags": [
          "Import Jobs"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Job id returned by the batch `POST` (also in its `Location` header)"
            },
            "required": true,
            "description": "Job id returned by the batch `POST` (also in its `Location` header)",
            "name": "jobId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "The import job",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportJob"
                },
                "example": {
                  "jobId": "d2f7a4c9-8e15-4b63-9a2d-1c6e5f0b8d37",
                  "kind": "articles",
                  "source": "erp",
                  "runId": null,
                  "status": "completed",
                  "progress": {
                    "total": 1,
                    "processed": 1,
                    "failed": 0
                  },
                  "result": {
                    "imported": [
                      {
                        "internalArticleNr": "ART-1001",
                        "id": "7c4e2b19-3a85-4d6f-b210-8e9a5c1d7f36"
                      }
                    ],
                    "updated": [],
                    "failed": [],
                    "skipped": 0,
                    "skippedRows": [],
                    "consolidatedRows": 0
                  },
                  "error": null,
                  "createdAt": "2026-02-02T08:40:00.000Z",
                  "finishedAt": "2026-02-02T08:40:05.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/readiness": {
      "get": {
        "operationId": "getReadiness",
        "summary": "Get Action Readiness",
        "description": "Evaluate one owned resource for one exact action. This is a current explanatory snapshot, never authorization for a later write. Missing and foreign resources both answer `404`; unsupported resource/action pairs answer `400 not_supported`. Supplier reply readiness viewed by a buyer never grants supplier authority. Orders require `orders:read`, DDS statements require `dds:read`, and PPWR targets require `packaging:read`; the matching write scope satisfies each read scope. The corresponding EUDR or PPWR module must be enabled.",
        "tags": [
          "Readiness"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "order",
                "dds_statement",
                "ppwr_request",
                "ppwr_unit"
              ]
            },
            "required": true,
            "name": "resourceType",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "resourceId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "eudr.dds_draft.create",
                "eudr.dds.submit",
                "ppwr.supplier_reply.submit",
                "ppwr.declaration.issue"
              ]
            },
            "required": true,
            "name": "action",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Action-scoped readiness report",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessReport"
                },
                "example": {
                  "contractVersion": 1,
                  "resource": {
                    "module": "eudr",
                    "type": "order",
                    "id": "1b7f3e9d-4a26-4c85-b9e1-5d0a8c3f7e42",
                    "revision": "dds_draft_create_preflight:abc123"
                  },
                  "action": "eudr.dds_draft.create",
                  "state": "ready",
                  "complete": true,
                  "findings": [],
                  "nextActions": [
                    {
                      "command": "createDdsStatement",
                      "commandVersion": 1,
                      "target": {
                        "type": "order",
                        "id": "1b7f3e9d-4a26-4c85-b9e1-5d0a8c3f7e42"
                      },
                      "owner": "user",
                      "executionClass": "direct",
                      "availability": "mcp",
                      "resolves": [],
                      "preconditions": [
                        "current_authorization",
                        "live_revalidation"
                      ]
                    }
                  ],
                  "evaluatedAt": "2026-10-08T10:00:00.000Z",
                  "rulesetVersion": "eudr-dds-draft-create-v1",
                  "policyVersion": "policy:def456",
                  "truncated": {
                    "findingsTruncated": false,
                    "nextActionsTruncated": false
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/article-units": {
      "get": {
        "operationId": "listPpwrArticleUnits",
        "summary": "List Packaging Units Linked to an Article or Order",
        "description": "Resolve exactly one owned article or order through its live article links to live packaging units. Results are ordered by unit reference then id and use an opaque keyset cursor. Missing and foreign targets return an empty page. Requires `packaging:read` (a `packaging:write` key satisfies it); customer workspace with the PPWR module enabled.",
        "tags": [
          "PPWR Packaging Data"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Article id. Pass exactly one of articleId or orderId."
            },
            "required": false,
            "description": "Article id. Pass exactly one of articleId or orderId.",
            "name": "articleId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Order id. Pass exactly one of articleId or orderId."
            },
            "required": false,
            "description": "Order id. Pass exactly one of articleId or orderId.",
            "name": "orderId",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Opaque nextCursor from the previous page."
            },
            "required": false,
            "description": "Opaque nextCursor from the previous page.",
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Linked packaging units",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PpwrArticleUnits"
                },
                "example": {
                  "items": [
                    {
                      "id": "a4c8e2f6-9b13-4d75-a1e8-3f7c0b6d9e52",
                      "internalRef": "U-1",
                      "name": "Tea filter folding box",
                      "packagingType": "sales",
                      "role": "manufacturer"
                    }
                  ],
                  "nextCursor": null,
                  "hasMore": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/components": {
      "get": {
        "operationId": "listPpwrComponents",
        "summary": "List Packaging Components",
        "description": "Retrieve your company's live packaging components as stored. Soft-deleted components are never returned. Rows are ordered naturally by `code` (`CMP-2` before `CMP-10`), then by `id`, so paging can neither repeat nor skip a component. Requires `packaging:read` (a `packaging:write` key satisfies it); customer workspace with the PPWR module enabled.",
        "tags": [
          "PPWR Packaging Data"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Return the components carrying exactly this code. **This narrows to a set, not to a row:** a code is unique per supplier (components without a supplier form their own group), so the same code may exist once in your own catalogue and once under a supplier who replied with it. Combine with `supplierId` to pick one. An empty value is no filter."
            },
            "required": false,
            "description": "Return the components carrying exactly this code. **This narrows to a set, not to a row:** a code is unique per supplier (components without a supplier form their own group), so the same code may exist once in your own catalogue and once under a supplier who replied with it. Combine with `supplierId` to pick one. An empty value is no filter.",
            "name": "code",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Narrow to the components of one supplier: a supplier UUID, or the literal `none` for your own components (those without a supplier). A value that is neither matches nothing rather than widening the result."
            },
            "required": false,
            "description": "Narrow to the components of one supplier: a supplier UUID, or the literal `none` for your own components (those without a supplier). A value that is neither matches nothing rather than widening the result.",
            "name": "supplierId",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100,
              "description": "Maximum number of results to return (default 100, max 1000)."
            },
            "required": false,
            "description": "Maximum number of results to return (default 100, max 1000).",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "default": 0,
              "description": "Number of results to skip for pagination."
            },
            "required": false,
            "description": "Number of results to skip for pagination.",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of packaging components",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PpwrComponent"
                  }
                },
                "example": [
                  {
                    "id": "e7b3c1a5-2d84-4f96-8c0e-4a9f6d2b7e13",
                    "code": "K-1",
                    "name": "Folding box",
                    "supplierId": null,
                    "materials": [
                      "paper_board"
                    ],
                    "polymer": null,
                    "massGrams": "12.5",
                    "recycledContentPct": "80",
                    "recycledContentSource": "pcr",
                    "recycledContentMethod": "physical",
                    "contactSensitive": false,
                    "foodContact": false,
                    "heavyMetalsMgPerKg": "12",
                    "heavyMetalsValueKind": "measured",
                    "heavyMetalsBasis": "test_report",
                    "heavyMetalsMethod": "CEN/CR 13695-1",
                    "heavyMetalsRecycledGlassDerogation": false,
                    "heavyMetalsEvidenceId": "5f9b3d7e-0a64-4c21-8e5f-2c8a4b6d0e71",
                    "pfasCompliant": null,
                    "pfasBasis": null,
                    "pfasMethod": null,
                    "pfasTotalFluorineMgPerKg": null,
                    "pfasTotalFluorineValueKind": "measured",
                    "pfasSumPpb": null,
                    "pfasSumValueKind": "measured",
                    "pfasEvidenceId": null,
                    "lastProvidedBySupplierId": null,
                    "lastProvidedAt": null,
                    "notes": null,
                    "createdAt": "2026-04-07T08:00:00.000Z",
                    "updatedAt": "2026-04-07T08:20:00.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "upsertPpwrComponents",
        "summary": "Upsert Packaging Components",
        "description": "Bulk upsert of packaging components — the same engine, row schema, validation and idempotency as the in-app CSV/Excel importer. Upsert key: `code` plus the resolved supplier. Fill-only by default: an empty cell never clears a stored value, a cell that fills an empty field is applied automatically, and a cell that would overwrite a non-empty (including supplier- or AI-attested) value needs `overwrite: true` — without it the whole batch is refused with `409` and nothing is written. Provenance and evidence columns are never writable through this API. At most 1000 rows per request (`400` otherwise). Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Packaging Data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/PpwrComponentRow"
                    },
                    "maxItems": 1000,
                    "description": "Bare array form."
                  },
                  {
                    "$ref": "#/components/schemas/PpwrComponentIntakeInput"
                  }
                ]
              },
              "example": {
                "rows": [
                  {
                    "code": "K-1",
                    "name": "Folding box",
                    "materials": [
                      "paper_board"
                    ],
                    "massGrams": "12.5",
                    "recycledContentPct": "80",
                    "recycledContentSource": "pcr",
                    "recycledContentMethod": "physical",
                    "heavyMetalsMgPerKg": "12",
                    "heavyMetalsBasis": "test_report",
                    "heavyMetalsMethod": "CEN/CR 13695-1"
                  }
                ],
                "overwrite": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Intake result (partial accept — see the schema).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PpwrIntakeResult"
                },
                "example": {
                  "imported": 1,
                  "updated": [],
                  "skipped": [],
                  "failed": [],
                  "invalid": [],
                  "suppliersCreated": []
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/PpwrOverwriteRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/components/{id}": {
      "get": {
        "operationId": "getPpwrComponent",
        "summary": "Get Packaging Component by ID",
        "description": "Retrieve one packaging component as stored. A component of another company, a soft-deleted component and an `id` that is not a UUID all answer `404` — never `403`. Requires `packaging:read` (a `packaging:write` key satisfies it); customer workspace with the PPWR module enabled.",
        "tags": [
          "PPWR Packaging Data"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Packaging component details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PpwrComponent"
                },
                "example": {
                  "id": "e7b3c1a5-2d84-4f96-8c0e-4a9f6d2b7e13",
                  "code": "K-1",
                  "name": "Folding box",
                  "supplierId": null,
                  "materials": [
                    "paper_board"
                  ],
                  "polymer": null,
                  "massGrams": "12.5",
                  "recycledContentPct": "80",
                  "recycledContentSource": "pcr",
                  "recycledContentMethod": "physical",
                  "contactSensitive": false,
                  "foodContact": false,
                  "heavyMetalsMgPerKg": "12",
                  "heavyMetalsValueKind": "measured",
                  "heavyMetalsBasis": "test_report",
                  "heavyMetalsMethod": "CEN/CR 13695-1",
                  "heavyMetalsRecycledGlassDerogation": false,
                  "heavyMetalsEvidenceId": "5f9b3d7e-0a64-4c21-8e5f-2c8a4b6d0e71",
                  "pfasCompliant": null,
                  "pfasBasis": null,
                  "pfasMethod": null,
                  "pfasTotalFluorineMgPerKg": null,
                  "pfasTotalFluorineValueKind": "measured",
                  "pfasSumPpb": null,
                  "pfasSumValueKind": "measured",
                  "pfasEvidenceId": null,
                  "lastProvidedBySupplierId": null,
                  "lastProvidedAt": null,
                  "notes": null,
                  "createdAt": "2026-04-07T08:00:00.000Z",
                  "updatedAt": "2026-04-07T08:20:00.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/units": {
      "get": {
        "operationId": "listPpwrUnits",
        "summary": "List Packaging Units",
        "description": "Retrieve your company's live packaging units — the endpoint that resolves a generated `PU-<n>` reference back to the unit and to the UUID the detail route takes. Soft-deleted units are never returned. Rows are ordered by `name`, then by `id`, so paging can neither repeat nor skip a unit. Requires `packaging:read` (a `packaging:write` key satisfies it); customer workspace with the PPWR module enabled.",
        "tags": [
          "PPWR Packaging Data"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Return only the unit carrying exactly this reference (the upsert key of `POST /api/v1/ppwr/units`). An empty value is not a filter that matches nothing — it is no filter at all."
            },
            "required": false,
            "description": "Return only the unit carrying exactly this reference (the upsert key of `POST /api/v1/ppwr/units`). An empty value is not a filter that matches nothing — it is no filter at all.",
            "name": "internalRef",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "doc"
              ],
              "description": "`doc` adds `docState` and `activeDeclaration` to every row — whether the unit has a Declaration of Conformity, and which one. Opt-in because it costs an extra read per page. Passed once; any other value is a `400`."
            },
            "required": false,
            "description": "`doc` adds `docState` and `activeDeclaration` to every row — whether the unit has a Declaration of Conformity, and which one. Opt-in because it costs an extra read per page. Passed once; any other value is a `400`.",
            "name": "include",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100,
              "description": "Maximum number of results to return (default 100, max 1000)."
            },
            "required": false,
            "description": "Maximum number of results to return (default 100, max 1000).",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "default": 0,
              "description": "Number of results to skip for pagination."
            },
            "required": false,
            "description": "Number of results to skip for pagination.",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of packaging units",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PpwrUnitListItem"
                  }
                },
                "example": [
                  {
                    "id": "a4c8e2f6-9b13-4d75-a1e8-3f7c0b6d9e52",
                    "name": "Tea filter folding box",
                    "internalRef": "U-1",
                    "packagingType": "sales",
                    "role": "manufacturer",
                    "recyclabilityGrade": "A",
                    "reusable": false,
                    "componentCount": 1,
                    "completeness": "complete",
                    "missingFields": [],
                    "obligationStatus": "on_track",
                    "reuseStatus": "not_reusable"
                  }
                ]
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "upsertPpwrUnits",
        "summary": "Upsert Packaging Units",
        "description": "Bulk upsert of packaging units, keyed on `internalRef`. A row may carry its additional sizes (`sizes[]`) and the additive `articleNumbers` / `componentCodes` directives in the same call. **A row without `internalRef` is always a create** — the server assigns the next `PU-<n>`, and read the generated references back with `GET /api/v1/ppwr/units` (or `GET /api/v1/ppwr/units?internalRef=…`) before importing links or article links. Same fill-only column policy and `overwrite` confirmation as the component intake. At most 1000 rows per request (`400` otherwise). A request may additionally carry at most 1000 `sizes` entries across all its rows. Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Packaging Data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/PpwrUnitRow"
                    },
                    "maxItems": 1000,
                    "description": "Bare array form."
                  },
                  {
                    "$ref": "#/components/schemas/PpwrUnitIntakeInput"
                  }
                ]
              },
              "example": {
                "rows": [
                  {
                    "internalRef": "U-1",
                    "name": "Tea filter folding box",
                    "packagingType": "sales",
                    "role": "manufacturer",
                    "recyclabilityGrade": "A",
                    "gtin": "2000000000015",
                    "widthMm": "120",
                    "heightMm": "75",
                    "depthMm": "60",
                    "marketMemberStates": [
                      "DE"
                    ],
                    "notes": "Folding box for 20 tea filters; sales packaging for the retail shelf.",
                    "placedUnderOwnBrand": true,
                    "articleNumbers": [
                      "ART-2001"
                    ],
                    "componentCodes": [
                      "K-1"
                    ]
                  }
                ],
                "overwrite": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Intake result (partial accept — see the schema).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PpwrIntakeResult"
                },
                "example": {
                  "imported": 1,
                  "updated": [],
                  "skipped": [],
                  "failed": [],
                  "invalid": [],
                  "sizesCreated": 0,
                  "articleLinksCreated": 1,
                  "articleNumbersUnmatched": 0,
                  "componentLinksCreated": 1,
                  "componentStubsCreated": 0,
                  "suppliersCreated": [],
                  "unitsWithoutComponents": 0,
                  "mainPartsCreated": 0
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/PpwrOverwriteRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/units/{id}": {
      "get": {
        "operationId": "getPpwrUnit",
        "summary": "Get Packaging Unit by ID",
        "description": "Retrieve one packaging unit with its stored fields, all of its sizes (`formats`, primary first) and its bill of materials (`components`). A unit of another company, a soft-deleted unit and an `id` that is not a UUID all answer `404` — never `403`, which would confirm that the id exists somewhere. Requires `packaging:read` (a `packaging:write` key satisfies it); customer workspace with the PPWR module enabled.",
        "tags": [
          "PPWR Packaging Data"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Packaging unit details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PpwrUnitDetail"
                },
                "example": {
                  "id": "a4c8e2f6-9b13-4d75-a1e8-3f7c0b6d9e52",
                  "name": "Tea filter folding box",
                  "internalRef": "U-1",
                  "packagingType": "sales",
                  "role": "manufacturer",
                  "recyclabilityGrade": "A",
                  "reusable": false,
                  "format": null,
                  "gradeSource": "declared",
                  "placedUnderOwnBrand": true,
                  "modifiesConformity": false,
                  "isProducer": true,
                  "targetRotations": null,
                  "averageRotations": null,
                  "averageRotationMethod": null,
                  "reconditioningProcess": null,
                  "recyclabilityReference": null,
                  "marketMemberStates": [
                    "DE"
                  ],
                  "notes": "Folding box for 20 tea filters; sales packaging for the retail shelf.",
                  "supplierId": null,
                  "supplierRoleOverride": null,
                  "reuseSystemMemberId": null,
                  "gtin": "2000000000015",
                  "widthMm": "120",
                  "heightMm": "75",
                  "depthMm": "60",
                  "supplierCountry": null,
                  "formats": [
                    {
                      "id": "b9e1d5a3-6c27-4f84-9d0b-8a2e4c7f1b36",
                      "packagingSpecId": "a4c8e2f6-9b13-4d75-a1e8-3f7c0b6d9e52",
                      "reference": "U-1",
                      "gtin": "2000000000015",
                      "supplierReference": null,
                      "label": null,
                      "widthMm": "120",
                      "heightMm": "75",
                      "depthMm": "60",
                      "isPrimary": true,
                      "sortOrder": 0
                    },
                    {
                      "id": "c7d2f8b4-3a61-4e09-8b5c-1d6e9f2a4c80",
                      "packagingSpecId": "a4c8e2f6-9b13-4d75-a1e8-3f7c0b6d9e52",
                      "reference": "U-1-40",
                      "gtin": "2000000000022",
                      "supplierReference": null,
                      "label": "40 tea filters",
                      "widthMm": "120",
                      "heightMm": "75",
                      "depthMm": "110",
                      "isPrimary": false,
                      "sortOrder": 1
                    }
                  ],
                  "components": [
                    {
                      "code": "K-1",
                      "name": "Folding box",
                      "supplierId": null,
                      "polymer": null,
                      "materials": [
                        "paper_board"
                      ],
                      "massGrams": "12.5",
                      "recycledContentPct": "80",
                      "foodContact": false,
                      "heavyMetalsMgPerKg": "12",
                      "heavyMetalsValueKind": "measured",
                      "pfasCompliant": null,
                      "recycledContentSource": "pcr",
                      "recycledContentMethod": "physical",
                      "contactSensitive": false,
                      "heavyMetalsBasis": "test_report",
                      "heavyMetalsRecycledGlassDerogation": false,
                      "pfasBasis": null,
                      "pfasTotalFluorineMgPerKg": null,
                      "pfasSumPpb": null,
                      "linkId": "c3f6a9d2-1e58-4b47-8a3c-5d9b2e7f0c14",
                      "componentId": "e7b3c1a5-2d84-4f96-8c0e-4a9f6d2b7e13",
                      "quantity": 1,
                      "completeness": "complete",
                      "missingFields": []
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/declarations": {
      "get": {
        "operationId": "listPpwrDeclarations",
        "summary": "List Declarations of Conformity",
        "description": "Retrieve your company's Declarations of Conformity (metadata only — the PDF is at each row's `pdfUrl`). A family declaration is one row; `specIds` lists every unit it covers and `activeSpecIds` the units it is currently the active DoC for. Soft-deleted declarations are never returned, and a permanently deleted declaration disappears from the list without a tombstone (also under `changedSince`). Rows are ordered by `issuedAt` (newest first, drafts last), then by `id`. Requires `packaging:read` (a `packaging:write` key satisfies it); customer workspace with the PPWR module enabled.",
        "tags": [
          "PPWR Declarations of Conformity"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Only declarations covering this packaging unit (any version — the unit's DoC history)."
            },
            "required": false,
            "description": "Only declarations covering this packaging unit (any version — the unit's DoC history).",
            "name": "specId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "issued",
                "superseded",
                "withdrawn"
              ]
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "generated",
                "collected"
              ]
            },
            "required": false,
            "name": "origin",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Only declarations that changed at or after this instant (inclusive): issued, withdrawn, verified, collected file lost, superseded, or `activeSpecIds` shrank because a newer declaration took over one of its units — the replaced declaration and its successor both match. ISO 8601 with `Z` or an offset. Drafts carry no timestamp and never match."
            },
            "required": false,
            "description": "Only declarations that changed at or after this instant (inclusive): issued, withdrawn, verified, collected file lost, superseded, or `activeSpecIds` shrank because a newer declaration took over one of its units — the replaced declaration and its successor both match. ISO 8601 with `Z` or an offset. Drafts carry no timestamp and never match.",
            "name": "changedSince",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100,
              "description": "Maximum number of results to return (default 100, max 1000)."
            },
            "required": false,
            "description": "Maximum number of results to return (default 100, max 1000).",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "default": 0,
              "description": "Number of results to skip for pagination."
            },
            "required": false,
            "description": "Number of results to skip for pagination.",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of declarations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PpwrDeclaration"
                  }
                },
                "example": [
                  {
                    "id": "f1a5c9e3-4b72-4d86-b3f0-7e2a6c8d1b95",
                    "version": 1,
                    "status": "issued",
                    "origin": "generated",
                    "referenceNumber": "DOC-U-1-A4C8E2-V1",
                    "issuedAt": "2026-04-14T12:00:00.000Z",
                    "withdrawnAt": null,
                    "supersededAt": null,
                    "supersedesId": null,
                    "verified": true,
                    "isFallback": false,
                    "pdfUrl": "/api/v1/ppwr/declarations/f1a5c9e3-4b72-4d86-b3f0-7e2a6c8d1b95/pdf",
                    "specIds": [
                      "a4c8e2f6-9b13-4d75-a1e8-3f7c0b6d9e52"
                    ],
                    "activeSpecIds": [
                      "a4c8e2f6-9b13-4d75-a1e8-3f7c0b6d9e52"
                    ]
                  }
                ]
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/declarations/{id}": {
      "get": {
        "operationId": "getPpwrDeclaration",
        "summary": "Get Declaration of Conformity by ID",
        "description": "Retrieve one Declaration of Conformity (metadata). A declaration of another company, a soft-deleted one and an `id` that is not a UUID all answer `404`. Requires `packaging:read` (a `packaging:write` key satisfies it); customer workspace with the PPWR module enabled.",
        "tags": [
          "PPWR Declarations of Conformity"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Declaration details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PpwrDeclaration"
                },
                "example": {
                  "id": "f1a5c9e3-4b72-4d86-b3f0-7e2a6c8d1b95",
                  "version": 1,
                  "status": "issued",
                  "origin": "generated",
                  "referenceNumber": "DOC-U-1-A4C8E2-V1",
                  "issuedAt": "2026-04-14T12:00:00.000Z",
                  "withdrawnAt": null,
                  "supersededAt": null,
                  "supersedesId": null,
                  "verified": true,
                  "isFallback": false,
                  "pdfUrl": "/api/v1/ppwr/declarations/f1a5c9e3-4b72-4d86-b3f0-7e2a6c8d1b95/pdf",
                  "specIds": [
                    "a4c8e2f6-9b13-4d75-a1e8-3f7c0b6d9e52"
                  ],
                  "activeSpecIds": [
                    "a4c8e2f6-9b13-4d75-a1e8-3f7c0b6d9e52"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/declarations/{id}/pdf": {
      "get": {
        "operationId": "downloadPpwrDeclarationPdf",
        "summary": "Download Declaration of Conformity",
        "description": "Download the DoC file — each declaration's `pdfUrl`. A generated DoC is rendered from the snapshot frozen at signing, after re-verifying its hash; a collected DoC is the manufacturer's uploaded file, served unchanged whatever valid `lang` is sent; an unsupported `lang` answers `400` for every declaration. Same `404` rule as the declaration detail, and `404` whenever the declaration's `pdfUrl` is `null` (a collected DoC whose uploaded file is no longer on record). Requires `packaging:read` (a `packaging:write` key satisfies it); customer workspace with the PPWR module enabled.",
        "tags": [
          "PPWR Declarations of Conformity"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Render language of a generated DoC, matched case-insensitively: `de`, `en`, `fr`, `es`, `it`, `nl`, `bg`, `cs`, `da`, `el`, `et`, `fi`, `hr`, `hu`, `lt`, `lv`, `pl`, `pt`, `ro`, `sk`, `sl`, `sv`, `all`. Absent or empty means `de`; any other value answers `400` listing the supported codes, for every declaration. `all` returns a ZIP with one PDF per official language of the markets the declaration's active units are placed on (Art. 39(2); for a family, the active unit with the lowest id), limited to the languages the document is generated in — every official EU language except Irish (`ga`) and Maltese (`mt`), so Ireland and Malta are covered by English. A declaration with no active unit (withdrawn or superseded), or whose markets name no generated language, gets a one-entry ZIP holding German. The `Content-Language` response header lists the languages the response contains."
            },
            "required": false,
            "description": "Render language of a generated DoC, matched case-insensitively: `de`, `en`, `fr`, `es`, `it`, `nl`, `bg`, `cs`, `da`, `el`, `et`, `fi`, `hr`, `hu`, `lt`, `lv`, `pl`, `pt`, `ro`, `sk`, `sl`, `sv`, `all`. Absent or empty means `de`; any other value answers `400` listing the supported codes, for every declaration. `all` returns a ZIP with one PDF per official language of the markets the declaration's active units are placed on (Art. 39(2); for a family, the active unit with the lowest id), limited to the languages the document is generated in — every official EU language except Irish (`ga`) and Maltese (`mt`), so Ireland and Malta are covered by English. A declaration with no active unit (withdrawn or superseded), or whose markets name no generated language, gets a one-entry ZIP holding German. The `Content-Language` response header lists the languages the response contains.",
            "name": "lang",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "The DoC file",
            "headers": {
              "Content-Language": {
                "description": "A generated DoC only: the language codes the file contains, comma-separated (`de`; for `lang=all` exactly the ZIP's entries, e.g. `de, fr`). Absent for a collected DoC, whose language is the manufacturer's.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "description": "The DoC."
                }
              },
              "application/zip": {
                "schema": {
                  "type": "string",
                  "description": "`lang=all`: one PDF per required language."
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "description": "A collected DoC uploaded as an image."
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "description": "A collected DoC uploaded as an image."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Snapshot integrity check failed; the file is refused rather than served.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "The frozen snapshot cannot be rendered.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "423": {
            "description": "`{ \"error\": \"scan_blocked\" }` — the uploaded file failed the malware scan.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "scan_blocked"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/formats": {
      "post": {
        "operationId": "upsertPpwrFormats",
        "summary": "Upsert Packaging Sizes",
        "description": "Upsert the sizes (formats) a packaging unit comes in, keyed on (`specInternalRef`, `reference`). Idempotent and blank-is-keep: a replayed row comes back as `skipped`, and an omitted field keeps the stored value — this endpoint can add and change size data, never clear it. Same column policy and `overwrite` confirmation as the unit intake: filling an empty field is automatic, changing a stored value (including the unit's own GTIN and dimensions on its PRIMARY size) needs `overwrite: true`, otherwise the batch is refused with `409 overwriteRequired` and nothing is written. A unit carries at most 50 sizes (`formatCapReached`). Sizes can also be sent on the unit intake itself (`sizes[]` or grouped rows), which is the primary way. At most 1000 rows per request (`400` otherwise). Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Packaging Data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/PpwrFormatRow"
                    },
                    "maxItems": 1000,
                    "description": "Bare array form."
                  },
                  {
                    "$ref": "#/components/schemas/PpwrFormatIntakeInput"
                  }
                ]
              },
              "example": {
                "rows": [
                  {
                    "specInternalRef": "U-1",
                    "reference": "U-1-40",
                    "label": "40 tea filters",
                    "gtin": "2000000000022",
                    "widthMm": "120",
                    "heightMm": "75",
                    "depthMm": "110"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Intake result (partial accept — see the schema).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PpwrIntakeResult"
                },
                "example": {
                  "imported": 1,
                  "updated": [],
                  "skipped": [],
                  "failed": [],
                  "invalid": []
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/PpwrOverwriteRequired"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/links": {
      "post": {
        "operationId": "createPpwrLinks",
        "summary": "Create Bill-of-Materials Links",
        "description": "Create component⇄unit links — a full bill of materials in one request. Create-only and idempotent, so there is no `overwrite` flag and no overwrite confirmation. Unknown unit references and component codes are per-row errors, never auto-created (unlike the unit intake's `componentCodes` column, which creates a placeholder component for an unknown code). At most 1000 rows per request (`400` otherwise). Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Packaging Data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/PpwrLinkRow"
                    },
                    "maxItems": 1000,
                    "description": "Bare array form."
                  },
                  {
                    "$ref": "#/components/schemas/PpwrLinkIntakeInput"
                  }
                ]
              },
              "example": {
                "rows": [
                  {
                    "specInternalRef": "U-1",
                    "componentCode": "K-1",
                    "quantity": 1
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/PpwrIntakeResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/article-links": {
      "post": {
        "operationId": "createPpwrArticleLinks",
        "summary": "Create Article Links",
        "description": "Create unit⇄article links — the whole SKU mapping in one request. Create-only and idempotent. An unknown article number or unit reference is a per-row error and nothing is created — unlike the unit intake's `articleNumbers` column, which skips unmatched numbers silently. At most 1000 rows per request (`400` otherwise). Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Packaging Data"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/PpwrArticleLinkRow"
                    },
                    "maxItems": 1000,
                    "description": "Bare array form."
                  },
                  {
                    "$ref": "#/components/schemas/PpwrArticleLinkIntakeInput"
                  }
                ]
              },
              "example": {
                "rows": [
                  {
                    "specInternalRef": "U-1",
                    "articleNumber": "ART-2001"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/PpwrIntakeResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/quantities": {
      "post": {
        "operationId": "pushPpwrQuantities",
        "summary": "Push SKU Quantities",
        "description": "The recurring ERP feed: how many pieces of each SKU were placed on which market in which year. **Asynchronous** — the request stages an import job and returns `202` with a `jobId`; poll `GET /api/v1/import-jobs/{jobId}` (needs `packaging:read`) until `status` is terminal. Row validation runs BEFORE staging, so a malformed batch is a `400` you see immediately, never a job that fails minutes later. At most 5000 rows (`413`), at least one row (`400`). Restatement is the norm: the upsert is idempotent on (`articleNumber`, `periodYear`, `market`). A packaging unit's placed figure is computed from the stored SKU rows whenever it is read — the sum of its linked SKUs' quantities, per size when every linked SKU of a multi-size unit names a size, otherwise on the unit level — so link changes take effect without a re-push. A unit with a figure typed in the app on either level uses the typed figures; it surfaces in the job result's `conflicts`, and clearing its typed figures lets the feed's figure apply immediately. Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Quantities & Volume Reports"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/PpwrQuantityRow"
                    },
                    "minItems": 1,
                    "maxItems": 5000,
                    "description": "Bare array form — no `replaceScope`."
                  },
                  {
                    "$ref": "#/components/schemas/PpwrQuantityIntakeInput"
                  }
                ]
              },
              "example": {
                "rows": [
                  {
                    "articleNumber": "ART-2001",
                    "periodYear": 2025,
                    "market": "DE",
                    "quantity": "120000"
                  }
                ],
                "replaceScope": "period-market"
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/BatchAccepted"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/tonnage": {
      "post": {
        "operationId": "pushPpwrTonnage",
        "summary": "Push Material Tonnage",
        "description": "The aggregate-kg mode, for a producer whose packaging composition is not modelled unit by unit — and the same rows that declare the ambiguous material families (metals, composites) when you report quantities per SKU. **LUCID (Germany) only.** Synchronous, upsert keyed on (`zsvrCategory`, `periodYear`, `market`). A category a human entered in the app is reported in `skipped` with `manualOverridePresent` rather than overwritten; delete that override in the app and the next push recreates it as ERP-owned. At most 1000 rows per request (`400` otherwise). Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Quantities & Volume Reports"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/PpwrTonnageRow"
                    },
                    "maxItems": 1000,
                    "description": "Bare array form."
                  },
                  {
                    "$ref": "#/components/schemas/PpwrTonnageIntakeInput"
                  }
                ]
              },
              "example": {
                "rows": [
                  {
                    "periodYear": 2025,
                    "market": "DE",
                    "zsvrCategory": "20000",
                    "tonnageKg": 1500,
                    "note": "Paper and board, total from the ERP"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tonnage result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PpwrTonnageResult"
                },
                "example": {
                  "written": [
                    {
                      "periodYear": 2025,
                      "market": "DE",
                      "zsvrCategory": "20000"
                    }
                  ],
                  "skipped": [],
                  "failed": [],
                  "invalid": []
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deletePpwrTonnage",
        "summary": "Delete Material Tonnage",
        "description": "Remove one tonnage row, addressed by the same key `POST` upserts on: `zsvrCategory`, `periodYear` and `market` as query parameters. Until it is removed, the row replaces the figure derived from your packaging units for that category; afterwards the derived figure counts again. A row a human entered in the app is not removed: `409` with `code: manualOverridePresent` — delete it in the app. A key with no row answers `404`, so repeating a successful delete is a `404` that changes nothing. Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Quantities & Volume Reports"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 2000,
              "maximum": 2100
            },
            "required": true,
            "name": "periodYear",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[A-Z]{2}$"
            },
            "required": true,
            "name": "market",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "10000",
                "20000",
                "30000",
                "40000",
                "50000",
                "60000",
                "70000",
                "80000"
              ]
            },
            "required": true,
            "name": "zsvrCategory",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "Always `true` on success."
                    }
                  },
                  "required": [
                    "success"
                  ]
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "`code: manualOverridePresent` — the figure was entered in the app. Nothing was deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "This category's figure was entered in the app; remove it there.",
                  "code": "manualOverridePresent"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/mengenmeldung/reports": {
      "get": {
        "operationId": "listMengenmeldungReports",
        "summary": "List Volume Reports",
        "description": "List the generated reports, newest first. Metadata only — never the frozen computation. Filters and paging are optional; paging is applied after the filters. An invalid value for a known parameter is a `400`; unrecognized parameter names are ignored. Requires `packaging:read`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Quantities & Volume Reports"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 2000,
              "maximum": 2100
            },
            "required": false,
            "name": "periodYear",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[A-Z]{2}$",
              "description": "ISO alpha-2 (case-insensitive)."
            },
            "required": false,
            "description": "ISO alpha-2 (case-insensitive).",
            "name": "market",
            "in": "query"
          },
          {
            "schema": {
              "$ref": "#/components/schemas/MengenmeldungStatus"
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100,
              "description": "Maximum number of results to return (default 100, max 1000)."
            },
            "required": false,
            "description": "Maximum number of results to return (default 100, max 1000).",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "default": 0,
              "description": "Number of results to skip for pagination."
            },
            "required": false,
            "description": "Number of results to skip for pagination.",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones)."
            },
            "required": false,
            "description": "Comma-separated list of the resource's top-level keys to return (per element for a list), e.g. `id,name`; omit for the full body. Top-level only; whitespace is trimmed and duplicates count once. `fields` never adds keys: a selected optional key that is absent on a row stays absent. `400` when passed more than once, when empty, or when it names an unknown key (the error names it and lists the allowed ones).",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Reports, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MengenmeldungReport"
                  }
                },
                "example": [
                  {
                    "id": "2b6d0f4a-8c39-4e17-9f5a-1a7c3e9d6b28",
                    "periodYear": 2025,
                    "market": "DE",
                    "format": "lucid_de",
                    "reportType": "HJM1",
                    "systemOperatorId": "DE1234567890123",
                    "xsdVersion": "1.0",
                    "status": "generated",
                    "version": 1,
                    "supersedesId": null,
                    "snapshotHash": "9f2c4e6a8b0d1f3e5a7c9b2d4f6e8a0c1b3d5f7e9a2c4b6d8f0e1a3c5b7d9f2e",
                    "generatedAt": "2026-04-20T07:30:00.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "generateMengenmeldungReport",
        "summary": "Generate Volume Report",
        "description": "Generate and freeze a report for one period, market and register. Re-generating the same scope (period, market, register and `reportType`) after the data changed is the normal flow: the new report supersedes the previous one of the same `reportType` (its `version` increments, the old row stays listed as `superseded`); a report of another type stays active. A `422` names precisely which data is not declarable yet, item by item — nothing is written. Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Quantities & Volume Reports"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateMengenmeldungInput"
              },
              "example": {
                "periodYear": 2025,
                "market": "DE",
                "format": "lucid_de",
                "reportType": "HJM1",
                "systemOperatorId": "DE1234567890123"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Report generated and frozen",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "UUID of the new report — what `GET /api/v1/ppwr/mengenmeldung/{reportId}/xml` takes."
                    },
                    "version": {
                      "type": "integer",
                      "description": "Version of the report within its (`periodYear`, `market`, `format`) scope; each regeneration increments it."
                    },
                    "systemOperatorId": {
                      "type": "string",
                      "description": "`lucid_de` only: the LUCID SystemOperatorID the report was generated with — the one you sent, or your workspace's stored one when you omitted it. Absent for the worksheet registers."
                    }
                  },
                  "required": [
                    "id",
                    "version"
                  ]
                },
                "example": {
                  "id": "2b6d0f4a-8c39-4e17-9f5a-1a7c3e9d6b28",
                  "version": 1,
                  "systemOperatorId": "DE1234567890123"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`{ \"error\": \"reportAlreadyGenerated\" }` — two generations for the same scope raced; one of them won. Re-list and retry if you still need a newer version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "error": "reportAlreadyGenerated"
                }
              }
            }
          },
          "422": {
            "description": "Data not declarable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MengenmeldungNotDeclarable"
                },
                "example": {
                  "error": "blocking_errors",
                  "blockingErrors": [
                    {
                      "kind": "missing_mass",
                      "specRef": "U-2",
                      "componentCode": "K-2",
                      "componentName": "Lid",
                      "material": null,
                      "familyLabelsDe": null
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/mengenmeldung/{reportId}/xml": {
      "get": {
        "operationId": "downloadMengenmeldungReport",
        "summary": "Download Volume Report File",
        "description": "Download the report artifact as an attachment: for `lucid_de` the LUCID Datenmeldung XML (`application/xml`), for the worksheet registers the JSON transcription worksheet (`application/json`). The file is re-derived from the report's frozen snapshot after re-verifying its SHA-256, so a downloaded report is byte-identical to what was generated, every time. Requires `packaging:read`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Quantities & Volume Reports"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Report id from the list endpoint."
            },
            "required": true,
            "description": "Report id from the list endpoint.",
            "name": "reportId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The report file",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string",
                  "description": "LUCID Datenmeldung XML (`lucid_de`)."
                }
              },
              "application/json": {
                "schema": {
                  "type": "string",
                  "description": "Transcription worksheet (worksheet registers)."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Snapshot integrity check failed; the file is refused rather than served.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/documents/upload-url": {
      "post": {
        "operationId": "createPpwrDocumentUploadUrl",
        "summary": "Create Document Upload URL",
        "description": "Step 1 of uploading a document (Nachweis): get a presigned URL, then `PUT` the file bytes to `uploadUrl` with the same `Content-Type` within 10 minutes. Pass the returned `s3Key` as `storageKey` to `POST /api/v1/ppwr/documents`. Accepts the same files as the in-app upload: PDF, JPEG, PNG, at most 10 MB — a wrong type is a `400`. `fileSize` is validated against the limit when the upload URL is issued and signed into `uploadUrl`: a `PUT` of any other length is refused by storage. Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Documents"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PpwrDocumentUploadUrlInput"
              },
              "example": {
                "fileName": "heavy-metals-test-report-k1.pdf",
                "contentType": "application/pdf",
                "fileSize": 312640
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned upload URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PpwrDocumentUploadUrl"
                },
                "example": {
                  "uploadUrl": "https://example-bucket.s3.eu-central-1.amazonaws.com/pending/operator/3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17/1d5f9a3c-7e28-4b64-9c0a-3e8b6d2f4a19-heavy-metals-test-report-k1.pdf?X-Amz-…",
                  "s3Key": "pending/operator/3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17/1d5f9a3c-7e28-4b64-9c0a-3e8b6d2f4a19-heavy-metals-test-report-k1.pdf"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/ppwr/documents": {
      "post": {
        "operationId": "createPpwrDocument",
        "summary": "Attach Document",
        "description": "Step 2: attach the uploaded file to a packaging unit (`target.packagingSpecId`) or component (`target.componentId`) — exactly as the in-app \"Nachweis hochladen\": the document is accepted (`approved`) with the given `type`, and for an analysable type AI extraction is queued when your plan includes it (`extractionQueued`; otherwise `aiSkippedReason` says why). Target ids are UUIDs — resolve them with `GET /api/v1/ppwr/units?internalRef=…` or `GET /api/v1/ppwr/components`. A unit or component of another company, a deleted one, a `storageKey` not issued to your company, and a unit-only `type` (`technical_doc`, `declaration_of_conformity`, `marking`) on a component all answer `404 {\"error\": \"target\"}`. A `storageKey` that was already consumed by a successful attach (or has expired) answers `404 {\"error\": \"upload_missing\"}` — start again at step 1. Re-use-system targets are not supported (`400 {\"error\": \"unsupported_target\"}`); a `target` with more than one id is `400 {\"error\": \"ambiguous_target\"}`. Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.",
        "tags": [
          "PPWR Documents"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PpwrDocumentInput"
              },
              "example": {
                "type": "heavy_metals",
                "storageKey": "pending/operator/3f6c2a8e-5b1d-4c7e-9a2f-6d8b1e4c0a17/1d5f9a3c-7e28-4b64-9c0a-3e8b6d2f4a19-heavy-metals-test-report-k1.pdf",
                "fileName": "heavy-metals-test-report-k1.pdf",
                "target": {
                  "componentId": "e7b3c1a5-2d84-4f96-8c0e-4a9f6d2b7e13"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Document attached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PpwrDocument"
                },
                "example": {
                  "id": "5f9b3d7e-0a64-4c21-8e5f-2c8a4b6d0e71",
                  "extractionQueued": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "A live document of your company already has these exact bytes — nothing was written. Re-send with `allowDuplicate: true` to attach a second copy anyway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PpwrDocumentDuplicate"
                },
                "example": {
                  "error": "duplicate",
                  "existing": {
                    "id": "5f9b3d7e-0a64-4c21-8e5f-2c8a4b6d0e71",
                    "fileName": "heavy-metals-test-report-k1.pdf",
                    "anchor": {
                      "kind": "component",
                      "ref": "K-1",
                      "name": "Folding box"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  },
  "webhooks": {}
}
