> ## Documentation Index
> Fetch the complete documentation index at: https://help.polygon-one.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Verpackungsstückliste anlegen

> Create component⇄unit links — a full bill of materials in one request. Create-only and idempotent, so there is no `overwrite` flag and no confirm gate. Unknown unit references and component codes are per-row errors, never auto-created (unlike the unit intake's `componentCodes` column, which stubs unknown codes). At most 1000 rows per request (`400` otherwise). Requires `packaging:write`; customer workspace with the PPWR module enabled — see the guide.



## OpenAPI

````yaml POST /api/ppwr/links
openapi: 3.1.0
info:
  title: Polygon One Compliance API
  description: >-
    API for integrating ERP systems with the Polygon One EUDR Compliance
    Platform. Allows management of Articles, Suppliers, Orders, and Due
    Diligence Statements (DDS). PPWR packaging master data, the SKU quantity
    feed and Mengenmeldung reports are covered by the PPWR groups.
  version: 1.0.0
servers:
  - url: https://app.polygon-one.com
    description: Production Server
security:
  - bearerAuth: []
paths:
  /api/ppwr/links:
    post:
      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
        confirm gate. Unknown unit references and component codes are per-row
        errors, never auto-created (unlike the unit intake's `componentCodes`
        column, which stubs unknown codes). At most 1000 rows per request (`400`
        otherwise). Requires `packaging:write`; customer workspace with the PPWR
        module enabled — see the guide.
      operationId: createPpwrLinks
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - type: array
                  items:
                    $ref: '#/components/schemas/PpwrLinkRow'
                  maxItems: 1000
                  description: Bare array form.
                - $ref: '#/components/schemas/PpwrLinkIntakeInput'
      responses:
        '200':
          $ref: '#/components/responses/PpwrIntakeResult'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    PpwrLinkRow:
      type: object
      description: >-
        One bill-of-materials link for `POST /api/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.
      required:
        - specInternalRef
        - componentCode
      properties:
        specInternalRef:
          type: string
          description: '`internalRef` of an existing packaging unit.'
        componentCode:
          type: string
          description: >-
            `code` of an existing component. An ambiguous code is the row error
            `ambiguousComponentMatch`.
        quantity:
          type:
            - integer
            - string
          minimum: 1
          default: 1
          description: Pieces of this component in the unit. Blank = 1.
        massGrams:
          type:
            - number
            - string
          description: >-
            This unit's own mass for ONE piece of the component, in grams.
            Blank/omitted = the component's own mass applies.
        formatReference:
          type: string
          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.
    PpwrLinkIntakeInput:
      type: object
      description: Envelope form for the bill-of-materials intake. Links are create-only.
      required:
        - rows
      properties:
        rows:
          type: array
          items:
            $ref: '#/components/schemas/PpwrLinkRow'
          maxItems: 1000
    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 gate, 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,
            …). 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`.
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
        details:
          description: Additional error details (e.g. validation issues)
      required:
        - error
    PpwrRowError:
      type: object
      description: >-
        A row the upsert engine rejected. Carries no `index` — the engine
        reports by identifier.
      properties:
        identifier:
          type: string
        error:
          type: string
          description: 'Stable machine key (clamped: anything unexpected becomes `dbError`).'
    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
        error:
          type: string
          description: >-
            Usually a stable machine key; a field with no custom message falls
            back to the validator's own English text.
  responses:
    PpwrIntakeResult:
      description: Intake result (partial accept — see the schema).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PpwrIntakeResult'
    BadRequest:
      description: Invalid request data
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Forbidden:
      description: Insufficient permissions for this resource
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: >-
        API key generated in Settings > API Keys. Include as `Authorization:
        Bearer <key>`.

````