{
  "openapi": "3.1.0",
  "info": {
    "title": "Itemoo DPP Life Cycle API (EN 18222:2026)",
    "version": "1.0.0",
    "description": "Digital Product Passport life cycle and search API per **EN 18222:2026** (HTTPS/REST binding of clause 8), with the payload per **EN 18223:2026** and errors as **Result** objects (7.2). The `dppApiEndpoint` of Itemoo passports in the EU registry is `https://itemoo.eu/dpp-api`.\n\n**Access.** Reading needs no key: you get the public level. `Authorization: Bearer ipa_…` (recipient token issued by the brand) gives the level of that grant; a brand API key `itm_…` with the `passport` scope gives all levels of the brand’s own passports and is required for writing. Access levels follow Regulation (EU) 2024/1781 Art. 10(1)(g) and Annex XIII of Regulation (EU) 2023/1542. A back-up grant (`ipa_…`, issued by the brand to its back-up DPP service provider) reads every passport of the brand at all levels and may also list them (`GET /backupDpps`) with their versions (`GET /dpps/{dppId}/versions`) — Itemoo extensions for EN 18221:2026 4.5 replication.\n\n**Representation.** `?representation=compressed` (default) or `full`; `Accept: application/ld+json` returns the Itemoo JSON-LD document instead.\n\n**Errors.** `{ message: [{ messageType, code, text, correlationId, timestamp, itemooCode?, params? }] }` — `code` is the generic status (Table 15), `itemooCode` the stable Itemoo code. A retired code answers 404 with `itemooCode: codeRetired`. Every response carries `X-Request-Id` (sent by you or generated) — it is the `correlationId`.\n\n**Timestamps.** Every timestamp in responses is ISO 8601 in UTC with whole seconds (`2026-10-26T12:00:00Z`, EN 18222:2026 7.1). A date sent in the address (`date`) needs a time zone (`Z` or `±hh:mm`) or is a plain date (`YYYY-MM-DD`, start of the day in UTC).\n\n**Limits.** 120 calls per minute per IP address, or per key with a brand key. Over the limit the API answers HTTP `429` with a `Retry-After` header (seconds). This is a deliberate deviation from EN 18222:2026 Table 15, which has no status for rate limiting: the Result body carries the generic `ClientErrorBadRequest` with `itemooCode` `rateLimited` (`rateBlocked` — a longer block after repeated excess), while the HTTP status stays `429` so that standard HTTP clients back off. `DELETE /dpps/{dppId}` answers `405` — a passport is never deleted.\n\n**Registration.** The EU DPP registry serves `POST v1/registerDPP` (EN 18222:2026 5.2); Itemoo does not register on behalf of the brand — the panel exports the registry entry (unique identifiers, `dppApiEndpoint`, backup operator).",
    "x-major-version": "v1"
  },
  "servers": [
    {
      "url": "https://itemoo.eu/dpp-api/v1"
    }
  ],
  "tags": [
    {
      "name": "Life cycle"
    },
    {
      "name": "Back-up"
    },
    {
      "name": "Data elements"
    }
  ],
  "paths": {
    "/dpps/{dppId}": {
      "get": {
        "operationId": "dpp.read",
        "tags": [
          "Life cycle"
        ],
        "summary": "ReadDPPById — the passport",
        "description": "EN 18222:2026 4.2. The current passport at the access level of the caller. CORS is open; public answers are cached for 5 minutes.",
        "parameters": [
          {
            "name": "dppId",
            "in": "path",
            "required": true,
            "description": "Passport identifier: the Itemoo code or the passport URI `https://itemoo.eu/q/{code}` (percent-encoded)",
            "schema": {
              "type": "string"
            },
            "example": "A1B2C3D4"
          },
          {
            "name": "representation",
            "in": "query",
            "required": false,
            "description": "compressed (default) — header and data elements keyed by elementId (EN 18223:2026 5.2); full — `elements[]` with objectType (EN 18223:2026 Annex A)",
            "schema": {
              "type": "string",
              "enum": [
                "compressed",
                "full"
              ]
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Two-letter language of the texts; without it the Accept-Language header decides",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "description": "Optional. `Bearer ipa_…` — recipient token issued by the brand (legitimate interest or authority level); `Bearer itm_…` (or `X-Api-Key`) — brand API key with the `passport` scope: all levels of the brand’s own passports. Without it: the public level.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "`application/ld+json` (without `representation`) returns the Itemoo JSON-LD document of the passport instead.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Accept-Language",
            "in": "header",
            "required": false,
            "description": "Preferred language of the texts and of error messages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalProductPassport"
                }
              }
            }
          },
          "400": {
            "description": "Error — code: DPP_ID_INVALID, DPP_REPRESENTATION_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_ID_INVALID",
              "DPP_REPRESENTATION_INVALID"
            ]
          },
          "401": {
            "description": "Error — code: PASSPORT_GRANT_INVALID, API_KEY_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "PASSPORT_GRANT_INVALID",
              "API_KEY_INVALID"
            ]
          },
          "403": {
            "description": "Error — code: API_KEY_SCOPE_MISSING, KEY_READ_ONLY, BRAND_SUSPENDED, INTEGRATIONS_DISABLED, PLAN_MODULE_MISSING",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_SCOPE_MISSING",
              "KEY_READ_ONLY",
              "BRAND_SUSPENDED",
              "INTEGRATIONS_DISABLED",
              "PLAN_MODULE_MISSING"
            ],
            "x-error-params": {
              "API_KEY_SCOPE_MISSING": [
                "scope"
              ]
            }
          },
          "404": {
            "description": "Error — code: unknownCode, codeRetired, PASSPORT_NONE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "unknownCode",
              "codeRetired",
              "PASSPORT_NONE"
            ],
            "x-error-params": {
              "codeRetired": [
                "brand"
              ]
            }
          },
          "429": {
            "description": "Error — code: rateLimited, rateBlocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "rateLimited",
              "rateBlocked"
            ]
          }
        },
        "x-example": {
          "params": {
            "dppId": "A1B2C3D4"
          }
        }
      },
      "patch": {
        "operationId": "dpp.update",
        "tags": [
          "Life cycle"
        ],
        "summary": "UpdateDPPById — partial update (JSON Merge Patch)",
        "description": "EN 18222:2026 4.7, RFC 7396. Writable: dictionary collections (`battery`, `product`, `repair`, …) down to a dictionary field and `brandFields` (free brand fields by full key). `null` removes a field (a collection: all its fields in this layer). The header may be sent back unchanged; Itemoo elements may not be sent. The patch writes the layer of the code (unit, batch, variant or model): a model field through a unit passport answers `PASSPORT_FIELD_SCOPE`. Access levels stay as they are (a new field gets the dictionary default) — change them with `PUT /v1/passport/products/{sku}`. Every change is validated against the field dictionary first and saved in one transaction as a new passport version (EN 18221:2026 archive). The answer is the updated passport (compressed); if any part fails nothing is changed.",
        "parameters": [
          {
            "name": "dppId",
            "in": "path",
            "required": true,
            "description": "Passport identifier: the Itemoo code or the passport URI `https://itemoo.eu/q/{code}` (percent-encoded)",
            "schema": {
              "type": "string"
            },
            "example": "A1B2C3D4"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "description": "Required. `Bearer itm_…` (or `X-Api-Key`) — brand API key with the `passport` scope, not read-only.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Accept-Language",
            "in": "header",
            "required": false,
            "description": "Preferred language of the texts and of error messages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/merge-patch+json": {
              "schema": {
                "type": "object",
                "propertyNames": {
                  "type": "string"
                },
                "additionalProperties": {},
                "description": "Partial passport (compressed representation)"
              },
              "example": {
                "repair": {
                  "instructions": "https://example.com/repair.pdf"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalProductPassport"
                }
              }
            }
          },
          "400": {
            "description": "Error — code: DPP_KEY_REQUIRED, DPP_ID_INVALID, DPP_PATCH_INVALID, DPP_HEADER_READONLY, DPP_ELEMENT_READONLY, DPP_ELEMENT_UNKNOWN, PASSPORT_FIELDS_INVALID, PASSPORT_FIELD_KEY_INVALID, PASSPORT_FIELD_UNKNOWN, PASSPORT_FIELD_NOT_WRITABLE, PASSPORT_FIELD_SCOPE, PASSPORT_VALUE_INVALID, PASSPORT_PERSONAL_DATA, PASSPORT_UNIT_RECYCLED, DPP_REPRESENTATION_FULL_READONLY",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_KEY_REQUIRED",
              "DPP_ID_INVALID",
              "DPP_PATCH_INVALID",
              "DPP_HEADER_READONLY",
              "DPP_ELEMENT_READONLY",
              "DPP_ELEMENT_UNKNOWN",
              "PASSPORT_FIELDS_INVALID",
              "PASSPORT_FIELD_KEY_INVALID",
              "PASSPORT_FIELD_UNKNOWN",
              "PASSPORT_FIELD_NOT_WRITABLE",
              "PASSPORT_FIELD_SCOPE",
              "PASSPORT_VALUE_INVALID",
              "PASSPORT_PERSONAL_DATA",
              "PASSPORT_UNIT_RECYCLED",
              "DPP_REPRESENTATION_FULL_READONLY"
            ],
            "x-error-params": {
              "DPP_PATCH_INVALID": [
                "element"
              ],
              "DPP_HEADER_READONLY": [
                "element"
              ],
              "DPP_ELEMENT_READONLY": [
                "element"
              ],
              "DPP_ELEMENT_UNKNOWN": [
                "element"
              ],
              "PASSPORT_FIELD_UNKNOWN": [
                "key"
              ],
              "PASSPORT_FIELD_NOT_WRITABLE": [
                "key"
              ],
              "PASSPORT_FIELD_SCOPE": [
                "key"
              ],
              "PASSPORT_VALUE_INVALID": [
                "key"
              ],
              "PASSPORT_PERSONAL_DATA": [
                "key",
                "kind"
              ]
            }
          },
          "401": {
            "description": "Error — code: API_KEY_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ]
          },
          "403": {
            "description": "Error — code: API_KEY_SCOPE_MISSING, KEY_READ_ONLY, BRAND_SUSPENDED, INTEGRATIONS_DISABLED, PLAN_MODULE_MISSING",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_SCOPE_MISSING",
              "KEY_READ_ONLY",
              "BRAND_SUSPENDED",
              "INTEGRATIONS_DISABLED",
              "PLAN_MODULE_MISSING"
            ],
            "x-error-params": {
              "API_KEY_SCOPE_MISSING": [
                "scope"
              ]
            }
          },
          "404": {
            "description": "Error — code: unknownCode, codeRetired, PASSPORT_NONE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "unknownCode",
              "codeRetired",
              "PASSPORT_NONE"
            ],
            "x-error-params": {
              "codeRetired": [
                "brand"
              ]
            }
          },
          "429": {
            "description": "Error — code: rateLimited, rateBlocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "rateLimited",
              "rateBlocked"
            ]
          }
        },
        "x-example": {
          "params": {
            "dppId": "A1B2C3D4"
          }
        }
      },
      "delete": {
        "operationId": "dpp.delete",
        "tags": [
          "Life cycle"
        ],
        "summary": "DeleteDPPById — not allowed",
        "description": "EN 18222:2026 4.8. A passport must stay available for the whole product lifetime (Regulation (EU) 2024/1781 Art. 9–10), so it is never deleted: always 405 `ClientMethodNotAllowed` with `Allow: GET, PATCH`. End of life is a passport status (`dppStatus`, `lifecycle`).",
        "parameters": [
          {
            "name": "dppId",
            "in": "path",
            "required": true,
            "description": "Passport identifier: the Itemoo code or the passport URI `https://itemoo.eu/q/{code}` (percent-encoded)",
            "schema": {
              "type": "string"
            },
            "example": "A1B2C3D4"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "null"
                }
              }
            }
          },
          "405": {
            "description": "Error — code: DPP_DELETE_NOT_ALLOWED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_DELETE_NOT_ALLOWED"
            ]
          },
          "429": {
            "description": "Error — code: rateLimited, rateBlocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "rateLimited",
              "rateBlocked"
            ]
          }
        },
        "x-example": {
          "params": {
            "dppId": "A1B2C3D4"
          }
        }
      }
    },
    "/dppsByProductId/{productId}": {
      "get": {
        "operationId": "dpp.byProductId",
        "tags": [
          "Life cycle"
        ],
        "summary": "ReadDPPByProductId — the passport of a product",
        "description": "EN 18222:2026 4.3. The current passport of the product identified by its unique product identifier (EN 18219:2026): a GS1 Digital Link (`https://…/01/{gtin}`, optionally `/10/{lot}` and `/21/{serial}`), a GTIN, a passport URI or a code — percent-encoded. A GS1 address on a brand domain searches that brand only. One GTIN used by several brands answers 409 `DPP_PRODUCT_AMBIGUOUS` — use `POST /dppsByProductIds`.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "description": "Unique product identifier, percent-encoded",
            "schema": {
              "type": "string"
            },
            "example": "https%3A%2F%2Fitemoo.eu%2F01%2F05901234123457%2F10%2FL1"
          },
          {
            "name": "representation",
            "in": "query",
            "required": false,
            "description": "compressed (default) — header and data elements keyed by elementId (EN 18223:2026 5.2); full — `elements[]` with objectType (EN 18223:2026 Annex A)",
            "schema": {
              "type": "string",
              "enum": [
                "compressed",
                "full"
              ]
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Two-letter language of the texts; without it the Accept-Language header decides",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "description": "Optional. `Bearer ipa_…` — recipient token issued by the brand (legitimate interest or authority level); `Bearer itm_…` (or `X-Api-Key`) — brand API key with the `passport` scope: all levels of the brand’s own passports. Without it: the public level.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "`application/ld+json` (without `representation`) returns the Itemoo JSON-LD document of the passport instead.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Accept-Language",
            "in": "header",
            "required": false,
            "description": "Preferred language of the texts and of error messages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalProductPassport"
                }
              }
            }
          },
          "400": {
            "description": "Error — code: DPP_PRODUCT_ID_INVALID, DPP_REPRESENTATION_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_PRODUCT_ID_INVALID",
              "DPP_REPRESENTATION_INVALID"
            ]
          },
          "401": {
            "description": "Error — code: PASSPORT_GRANT_INVALID, API_KEY_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "PASSPORT_GRANT_INVALID",
              "API_KEY_INVALID"
            ]
          },
          "403": {
            "description": "Error — code: API_KEY_SCOPE_MISSING, KEY_READ_ONLY, BRAND_SUSPENDED, INTEGRATIONS_DISABLED, PLAN_MODULE_MISSING",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_SCOPE_MISSING",
              "KEY_READ_ONLY",
              "BRAND_SUSPENDED",
              "INTEGRATIONS_DISABLED",
              "PLAN_MODULE_MISSING"
            ],
            "x-error-params": {
              "API_KEY_SCOPE_MISSING": [
                "scope"
              ]
            }
          },
          "404": {
            "description": "Error — code: unknownCode, codeRetired, PASSPORT_NONE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "unknownCode",
              "codeRetired",
              "PASSPORT_NONE"
            ],
            "x-error-params": {
              "codeRetired": [
                "brand"
              ]
            }
          },
          "409": {
            "description": "Error — code: DPP_PRODUCT_AMBIGUOUS",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_PRODUCT_AMBIGUOUS"
            ],
            "x-error-params": {
              "DPP_PRODUCT_AMBIGUOUS": [
                "n"
              ]
            }
          },
          "429": {
            "description": "Error — code: rateLimited, rateBlocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "rateLimited",
              "rateBlocked"
            ]
          }
        },
        "x-example": {
          "params": {
            "productId": "05901234123457"
          }
        }
      }
    },
    "/dppsByIdAndDate/{dppId}": {
      "get": {
        "operationId": "dpp.versionByDate",
        "tags": [
          "Life cycle"
        ],
        "summary": "ReadDPPVersionByIdAndDate — the passport at a point in time",
        "description": "EN 18222:2026 4.4. The passport as it was at `date`, rebuilt from the append-only version history. `date` is an ISO 8601 timestamp with a time zone (`Z` or an offset such as `+02:00`) or a plain date (`YYYY-MM-DD` = start of that day in UTC); a timestamp without a time zone answers 400 `DATE_INVALID`. A timestamp without fractional seconds covers that whole second, so the `passportVersion.at` of a response finds that version again. A date in the future answers 400 `DATE_IN_FUTURE` (up to 60 seconds ahead counts as now and returns the current passport).",
        "parameters": [
          {
            "name": "dppId",
            "in": "path",
            "required": true,
            "description": "Passport identifier: the Itemoo code or the passport URI `https://itemoo.eu/q/{code}` (percent-encoded)",
            "schema": {
              "type": "string"
            },
            "example": "A1B2C3D4"
          },
          {
            "name": "representation",
            "in": "query",
            "required": false,
            "description": "compressed (default) — header and data elements keyed by elementId (EN 18223:2026 5.2); full — `elements[]` with objectType (EN 18223:2026 Annex A)",
            "schema": {
              "type": "string",
              "enum": [
                "compressed",
                "full"
              ]
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Two-letter language of the texts; without it the Accept-Language header decides",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": true,
            "description": "Point in time: ISO 8601 with a time zone (`Z` or `±hh:mm`) or a plain date (start of the day, UTC)",
            "schema": {
              "type": "string"
            },
            "example": "2026-10-01T00:00:00Z"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "description": "Optional. `Bearer ipa_…` — recipient token issued by the brand (legitimate interest or authority level); `Bearer itm_…` (or `X-Api-Key`) — brand API key with the `passport` scope: all levels of the brand’s own passports. Without it: the public level.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Accept",
            "in": "header",
            "required": false,
            "description": "`application/ld+json` (without `representation`) returns the Itemoo JSON-LD document of the passport instead.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Accept-Language",
            "in": "header",
            "required": false,
            "description": "Preferred language of the texts and of error messages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DigitalProductPassport"
                }
              }
            }
          },
          "400": {
            "description": "Error — code: DPP_ID_INVALID, DPP_DATE_REQUIRED, DATE_INVALID, DATE_IN_FUTURE, DPP_REPRESENTATION_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_ID_INVALID",
              "DPP_DATE_REQUIRED",
              "DATE_INVALID",
              "DATE_IN_FUTURE",
              "DPP_REPRESENTATION_INVALID"
            ]
          },
          "401": {
            "description": "Error — code: PASSPORT_GRANT_INVALID, API_KEY_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "PASSPORT_GRANT_INVALID",
              "API_KEY_INVALID"
            ]
          },
          "403": {
            "description": "Error — code: API_KEY_SCOPE_MISSING, KEY_READ_ONLY, BRAND_SUSPENDED, INTEGRATIONS_DISABLED, PLAN_MODULE_MISSING",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_SCOPE_MISSING",
              "KEY_READ_ONLY",
              "BRAND_SUSPENDED",
              "INTEGRATIONS_DISABLED",
              "PLAN_MODULE_MISSING"
            ],
            "x-error-params": {
              "API_KEY_SCOPE_MISSING": [
                "scope"
              ]
            }
          },
          "404": {
            "description": "Error — code: unknownCode, codeRetired, PASSPORT_NONE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "unknownCode",
              "codeRetired",
              "PASSPORT_NONE"
            ],
            "x-error-params": {
              "codeRetired": [
                "brand"
              ]
            }
          },
          "429": {
            "description": "Error — code: rateLimited, rateBlocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "rateLimited",
              "rateBlocked"
            ]
          }
        },
        "x-example": {
          "params": {
            "dppId": "A1B2C3D4"
          },
          "query": {
            "date": "2026-10-01T00:00:00Z"
          }
        }
      }
    },
    "/dppsByProductIds": {
      "post": {
        "operationId": "dpp.idsByProductIds",
        "tags": [
          "Life cycle"
        ],
        "summary": "ReadDPPIdsByProductIds — passport identifiers for product identifiers",
        "description": "EN 18222:2026 4.5. Passport URIs of every passport matching the product identifiers (same forms as `dppsByProductId`), page by page: pass `pagingMetadata.cursor` as `cursor` with the same `productIds` until it is missing. Unknown identifiers simply match nothing.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size 1–1000 (default 100)",
            "schema": {
              "type": "string"
            },
            "example": "100"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The cursor of the previous page (opaque, never empty)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "productIds": {
                    "minItems": 1,
                    "maxItems": 1000,
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Unique product identifiers (1–1000)"
                  }
                },
                "required": [
                  "productIds"
                ]
              },
              "example": {
                "productIds": [
                  "https://itemoo.eu/01/05901234123457"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payload": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Passport URIs (digitalProductPassportId)"
                    },
                    "pagingMetadata": {
                      "type": "object",
                      "properties": {
                        "cursor": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "required": [
                    "payload",
                    "pagingMetadata"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Error — code: DPP_PRODUCT_IDS_EXPECTED, DPP_LIMIT_INVALID, DPP_CURSOR_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_PRODUCT_IDS_EXPECTED",
              "DPP_LIMIT_INVALID",
              "DPP_CURSOR_INVALID"
            ]
          },
          "429": {
            "description": "Error — code: rateLimited, rateBlocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "rateLimited",
              "rateBlocked"
            ]
          }
        },
        "x-example": {
          "query": {
            "limit": "100"
          }
        }
      }
    },
    "/dpps/{dppId}/versions": {
      "get": {
        "operationId": "dpp.versions",
        "tags": [
          "Back-up"
        ],
        "summary": "Version history of a passport (Itemoo extension)",
        "description": "Not part of EN 18222:2026 — it makes replication to the back-up DPP service provider possible through this API (EN 18221:2026 4.5). Every version of the passport layers (model, variant, batch, item) with its hash chain, at the access level of the caller: changed fields and values only where the caller sees them, leaf hashes at the authority level. Read a version with `GET /dppsByIdAndDate/{dppId}`.",
        "parameters": [
          {
            "name": "dppId",
            "in": "path",
            "required": true,
            "description": "Passport identifier: the Itemoo code or the passport URI `https://itemoo.eu/q/{code}` (percent-encoded)",
            "schema": {
              "type": "string"
            },
            "example": "A1B2C3D4"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "description": "Optional. `Bearer ipa_…` — recipient token issued by the brand (legitimate interest or authority level); `Bearer itm_…` (or `X-Api-Key`) — brand API key with the `passport` scope: all levels of the brand’s own passports. Without it: the public level.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "level": {
                      "type": "string"
                    },
                    "version": {
                      "anyOf": [
                        {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "versions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      },
                      "description": "Versions, newest first (up to 500)"
                    }
                  },
                  "required": [
                    "code",
                    "level",
                    "versions"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Error — code: DPP_ID_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_ID_INVALID"
            ]
          },
          "401": {
            "description": "Error — code: PASSPORT_GRANT_INVALID, API_KEY_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "PASSPORT_GRANT_INVALID",
              "API_KEY_INVALID"
            ]
          },
          "403": {
            "description": "Error — code: API_KEY_SCOPE_MISSING, KEY_READ_ONLY, BRAND_SUSPENDED, INTEGRATIONS_DISABLED, PLAN_MODULE_MISSING",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_SCOPE_MISSING",
              "KEY_READ_ONLY",
              "BRAND_SUSPENDED",
              "INTEGRATIONS_DISABLED",
              "PLAN_MODULE_MISSING"
            ],
            "x-error-params": {
              "API_KEY_SCOPE_MISSING": [
                "scope"
              ]
            }
          },
          "404": {
            "description": "Error — code: unknownCode, codeRetired, PASSPORT_NONE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "unknownCode",
              "codeRetired",
              "PASSPORT_NONE"
            ],
            "x-error-params": {
              "codeRetired": [
                "brand"
              ]
            }
          },
          "429": {
            "description": "Error — code: rateLimited, rateBlocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "rateLimited",
              "rateBlocked"
            ]
          }
        },
        "x-example": {
          "params": {
            "dppId": "A1B2C3D4"
          }
        }
      }
    },
    "/backupDpps": {
      "get": {
        "operationId": "dpp.backupList",
        "tags": [
          "Back-up"
        ],
        "summary": "All passports of the brand for its back-up provider (Itemoo extension)",
        "description": "Not part of EN 18222:2026. The back-up DPP service provider chosen by the brand (EN 18221:2026 4.3, 4.5) pulls the list of every passport of the brand page by page, then each passport (`GET /dpps/{dppId}`), its versions and its documents (the document URLs of the passport) with the same token. Requires `Authorization: Bearer ipa_…` of a back-up grant issued by the brand (all levels, read-only). Itemoo does not push data: the recovery point objective is how often the provider pulls.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size 1–1000 (default 100)",
            "schema": {
              "type": "string"
            },
            "example": "100"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The cursor of the previous page (opaque, never empty)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "description": "Required. `Bearer ipa_…` — token of the brand’s back-up grant.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payload": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Passport URIs (digitalProductPassportId)"
                    },
                    "pagingMetadata": {
                      "type": "object",
                      "properties": {
                        "cursor": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "required": [
                    "payload",
                    "pagingMetadata"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Error — code: DPP_LIMIT_INVALID, DPP_CURSOR_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_LIMIT_INVALID",
              "DPP_CURSOR_INVALID"
            ]
          },
          "401": {
            "description": "Error — code: PASSPORT_GRANT_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "PASSPORT_GRANT_INVALID"
            ]
          },
          "403": {
            "description": "Error — code: DPP_BACKUP_GRANT_REQUIRED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_BACKUP_GRANT_REQUIRED"
            ]
          },
          "429": {
            "description": "Error — code: rateLimited, rateBlocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "rateLimited",
              "rateBlocked"
            ]
          }
        },
        "x-example": {
          "query": {
            "limit": "100"
          }
        }
      }
    },
    "/dpps": {
      "post": {
        "operationId": "dpp.create",
        "tags": [
          "Life cycle"
        ],
        "summary": "CreateDPP — a passport of a batch or an item",
        "description": "EN 18222:2026 4.6. Creates the passport of a new batch (`uniqueProductIdentifier` with `/10/{lot}`) or a new item (`/21/{serial}`) of a product of the brand that has a passport; data elements in the body are saved with it in one transaction. A model passport exists from the moment the product exists — for a model the answer is 409 (exists) or 400 `DPP_PASSPORT_BLOCK_REQUIRED`. Answers 201 with `Location`.",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "description": "Required. `Bearer itm_…` (or `X-Api-Key`) — brand API key with the `passport` scope, not read-only.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Accept-Language",
            "in": "header",
            "required": false,
            "description": "Preferred language of the texts and of error messages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "digitalProductPassportId": {
                    "type": "string",
                    "description": "Globally unique passport URI"
                  },
                  "uniqueProductIdentifier": {
                    "type": "string"
                  },
                  "granularity": {
                    "type": "string",
                    "enum": [
                      "model",
                      "batch",
                      "item"
                    ]
                  },
                  "dppSchemaVersion": {
                    "type": "string",
                    "examples": [
                      "EN 18223:2026"
                    ]
                  },
                  "dppStatus": {
                    "type": "string",
                    "enum": [
                      "active",
                      "inactive",
                      "archived"
                    ],
                    "description": "active (also during a recall — see `recall`), inactive (end of life of the unit, passport closed by the brand), archived (read-only archive after the brand left Itemoo). The detailed Itemoo status is in `lifecycle`"
                  },
                  "lastUpdated": {
                    "type": "string",
                    "format": "date-time",
                    "description": "UTC, whole seconds"
                  },
                  "economicOperatorId": {
                    "description": "Manufacturer identifier per EN 18219:2026 (ISO/IEC 6523 `ICD:value`, e.g. `0088:` + GLN); null when the brand has not entered one",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "facilityId": {
                    "type": "string"
                  },
                  "contentSpecificationIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Legal acts the passport content follows, e.g. `EU 2024/1781`, `EU 2023/1542`"
                  }
                },
                "required": [
                  "uniqueProductIdentifier"
                ],
                "additionalProperties": {}
              },
              "example": {
                "uniqueProductIdentifier": "https://itemoo.eu/01/05901234123457/10/L2026-10/21/SN-0001",
                "battery": {
                  "manufacturingDate": "2026-10-01"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "digitalProductPassportId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "digitalProductPassportId"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Error — code: DPP_KEY_REQUIRED, DPP_UNIQUE_ID_REQUIRED, DPP_GRANULARITY_MISMATCH, DPP_GRANULARITY_UNSUPPORTED, DPP_PASSPORT_BLOCK_REQUIRED, DPP_PATCH_INVALID, DPP_HEADER_READONLY, DPP_ELEMENT_READONLY, DPP_ELEMENT_UNKNOWN, PASSPORT_FIELDS_INVALID, PASSPORT_FIELD_KEY_INVALID, PASSPORT_FIELD_UNKNOWN, PASSPORT_FIELD_NOT_WRITABLE, PASSPORT_FIELD_SCOPE, PASSPORT_VALUE_INVALID, PASSPORT_PERSONAL_DATA, PASSPORT_UNIT_RECYCLED, SERIALS_REQUIRED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_KEY_REQUIRED",
              "DPP_UNIQUE_ID_REQUIRED",
              "DPP_GRANULARITY_MISMATCH",
              "DPP_GRANULARITY_UNSUPPORTED",
              "DPP_PASSPORT_BLOCK_REQUIRED",
              "DPP_PATCH_INVALID",
              "DPP_HEADER_READONLY",
              "DPP_ELEMENT_READONLY",
              "DPP_ELEMENT_UNKNOWN",
              "PASSPORT_FIELDS_INVALID",
              "PASSPORT_FIELD_KEY_INVALID",
              "PASSPORT_FIELD_UNKNOWN",
              "PASSPORT_FIELD_NOT_WRITABLE",
              "PASSPORT_FIELD_SCOPE",
              "PASSPORT_VALUE_INVALID",
              "PASSPORT_PERSONAL_DATA",
              "PASSPORT_UNIT_RECYCLED",
              "SERIALS_REQUIRED"
            ],
            "x-error-params": {
              "DPP_GRANULARITY_MISMATCH": [
                "granularity"
              ],
              "DPP_PATCH_INVALID": [
                "element"
              ],
              "DPP_HEADER_READONLY": [
                "element"
              ],
              "DPP_ELEMENT_READONLY": [
                "element"
              ],
              "DPP_ELEMENT_UNKNOWN": [
                "element"
              ],
              "PASSPORT_FIELD_UNKNOWN": [
                "key"
              ],
              "PASSPORT_FIELD_NOT_WRITABLE": [
                "key"
              ],
              "PASSPORT_FIELD_SCOPE": [
                "key"
              ],
              "PASSPORT_VALUE_INVALID": [
                "key"
              ],
              "PASSPORT_PERSONAL_DATA": [
                "key",
                "kind"
              ]
            }
          },
          "401": {
            "description": "Error — code: API_KEY_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ]
          },
          "403": {
            "description": "Error — code: API_KEY_SCOPE_MISSING, KEY_READ_ONLY, BRAND_SUSPENDED, INTEGRATIONS_DISABLED, PLAN_MODULE_MISSING",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_SCOPE_MISSING",
              "KEY_READ_ONLY",
              "BRAND_SUSPENDED",
              "INTEGRATIONS_DISABLED",
              "PLAN_MODULE_MISSING"
            ],
            "x-error-params": {
              "API_KEY_SCOPE_MISSING": [
                "scope"
              ]
            }
          },
          "404": {
            "description": "Error — code: PRODUCT_NOT_FOUND",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "PRODUCT_NOT_FOUND"
            ]
          },
          "409": {
            "description": "Error — code: DPP_EXISTS, BATCH_EXISTS, BATCH_RECALLED_NO_UNITS, CODES_SEQ_CONFLICT",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_EXISTS",
              "BATCH_EXISTS",
              "BATCH_RECALLED_NO_UNITS",
              "CODES_SEQ_CONFLICT"
            ],
            "x-error-params": {
              "BATCH_EXISTS": [
                "lot"
              ],
              "BATCH_RECALLED_NO_UNITS": [
                "lot"
              ]
            }
          },
          "429": {
            "description": "Error — code: rateLimited, rateBlocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "rateLimited",
              "rateBlocked"
            ]
          }
        },
        "x-example": {}
      }
    },
    "/dpps/{dppId}/elements/{elementIdPath}": {
      "get": {
        "operationId": "dpp.element.read",
        "tags": [
          "Data elements"
        ],
        "summary": "ReadDataElement — one data element",
        "description": "EN 18222:2026 6.2. The element at the JSONPath in the compressed passport visible to the caller — a value, or with `representation=full` a typed data element (SingleValuedDataElement, DataElementCollection, …).",
        "parameters": [
          {
            "name": "dppId",
            "in": "path",
            "required": true,
            "description": "Passport identifier: the Itemoo code or the passport URI `https://itemoo.eu/q/{code}` (percent-encoded)",
            "schema": {
              "type": "string"
            },
            "example": "A1B2C3D4"
          },
          {
            "name": "elementIdPath",
            "in": "path",
            "required": true,
            "description": "JSONPath (RFC 9535) from `$` with name selectors (`.name`, `['name']`); an index (`[0]`) only when reading",
            "schema": {
              "type": "string"
            },
            "example": "$.battery.chemistry"
          },
          {
            "name": "representation",
            "in": "query",
            "required": false,
            "description": "compressed (default) — header and data elements keyed by elementId (EN 18223:2026 5.2); full — `elements[]` with objectType (EN 18223:2026 Annex A)",
            "schema": {
              "type": "string",
              "enum": [
                "compressed",
                "full"
              ]
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Two-letter language of the texts; without it the Accept-Language header decides",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "description": "Optional. `Bearer ipa_…` — recipient token issued by the brand (legitimate interest or authority level); `Bearer itm_…` (or `X-Api-Key`) — brand API key with the `passport` scope: all levels of the brand’s own passports. Without it: the public level.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Accept-Language",
            "in": "header",
            "required": false,
            "description": "Preferred language of the texts and of error messages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "description": "The data element"
                }
              }
            }
          },
          "400": {
            "description": "Error — code: DPP_ID_INVALID, DPP_ELEMENT_PATH_UNSUPPORTED, DPP_REPRESENTATION_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_ID_INVALID",
              "DPP_ELEMENT_PATH_UNSUPPORTED",
              "DPP_REPRESENTATION_INVALID"
            ]
          },
          "401": {
            "description": "Error — code: PASSPORT_GRANT_INVALID, API_KEY_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "PASSPORT_GRANT_INVALID",
              "API_KEY_INVALID"
            ]
          },
          "403": {
            "description": "Error — code: API_KEY_SCOPE_MISSING, KEY_READ_ONLY, BRAND_SUSPENDED, INTEGRATIONS_DISABLED, PLAN_MODULE_MISSING",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_SCOPE_MISSING",
              "KEY_READ_ONLY",
              "BRAND_SUSPENDED",
              "INTEGRATIONS_DISABLED",
              "PLAN_MODULE_MISSING"
            ],
            "x-error-params": {
              "API_KEY_SCOPE_MISSING": [
                "scope"
              ]
            }
          },
          "404": {
            "description": "Error — code: unknownCode, codeRetired, PASSPORT_NONE, DPP_ELEMENT_NOT_FOUND",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "unknownCode",
              "codeRetired",
              "PASSPORT_NONE",
              "DPP_ELEMENT_NOT_FOUND"
            ],
            "x-error-params": {
              "codeRetired": [
                "brand"
              ],
              "DPP_ELEMENT_NOT_FOUND": [
                "path"
              ]
            }
          },
          "429": {
            "description": "Error — code: rateLimited, rateBlocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "rateLimited",
              "rateBlocked"
            ]
          }
        },
        "x-example": {
          "params": {
            "dppId": "A1B2C3D4",
            "elementIdPath": "$.productInfo.name"
          }
        }
      },
      "patch": {
        "operationId": "dpp.element.update",
        "tags": [
          "Data elements"
        ],
        "summary": "UpdateDataElement — change one data element",
        "description": "EN 18222:2026 6.3. The body is the new content of the element (`null` removes it; a collection is merged). Same rules as `PATCH /dpps/{dppId}`. The answer is the element after the change.",
        "parameters": [
          {
            "name": "dppId",
            "in": "path",
            "required": true,
            "description": "Passport identifier: the Itemoo code or the passport URI `https://itemoo.eu/q/{code}` (percent-encoded)",
            "schema": {
              "type": "string"
            },
            "example": "A1B2C3D4"
          },
          {
            "name": "elementIdPath",
            "in": "path",
            "required": true,
            "description": "JSONPath (RFC 9535) from `$` with name selectors (`.name`, `['name']`); an index (`[0]`) only when reading",
            "schema": {
              "type": "string"
            },
            "example": "$.battery.chemistry"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "description": "Required. `Bearer itm_…` (or `X-Api-Key`) — brand API key with the `passport` scope, not read-only.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Accept-Language",
            "in": "header",
            "required": false,
            "description": "Preferred language of the texts and of error messages.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/merge-patch+json": {
              "schema": {
                "description": "New content of the element"
              },
              "example": "LFP"
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "description": "The element after the change"
                }
              }
            }
          },
          "400": {
            "description": "Error — code: DPP_KEY_REQUIRED, DPP_ID_INVALID, DPP_PATCH_INVALID, DPP_HEADER_READONLY, DPP_ELEMENT_READONLY, DPP_ELEMENT_UNKNOWN, PASSPORT_FIELDS_INVALID, PASSPORT_FIELD_KEY_INVALID, PASSPORT_FIELD_UNKNOWN, PASSPORT_FIELD_NOT_WRITABLE, PASSPORT_FIELD_SCOPE, PASSPORT_VALUE_INVALID, PASSPORT_PERSONAL_DATA, PASSPORT_UNIT_RECYCLED, DPP_ELEMENT_PATH_UNSUPPORTED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "DPP_KEY_REQUIRED",
              "DPP_ID_INVALID",
              "DPP_PATCH_INVALID",
              "DPP_HEADER_READONLY",
              "DPP_ELEMENT_READONLY",
              "DPP_ELEMENT_UNKNOWN",
              "PASSPORT_FIELDS_INVALID",
              "PASSPORT_FIELD_KEY_INVALID",
              "PASSPORT_FIELD_UNKNOWN",
              "PASSPORT_FIELD_NOT_WRITABLE",
              "PASSPORT_FIELD_SCOPE",
              "PASSPORT_VALUE_INVALID",
              "PASSPORT_PERSONAL_DATA",
              "PASSPORT_UNIT_RECYCLED",
              "DPP_ELEMENT_PATH_UNSUPPORTED"
            ],
            "x-error-params": {
              "DPP_PATCH_INVALID": [
                "element"
              ],
              "DPP_HEADER_READONLY": [
                "element"
              ],
              "DPP_ELEMENT_READONLY": [
                "element"
              ],
              "DPP_ELEMENT_UNKNOWN": [
                "element"
              ],
              "PASSPORT_FIELD_UNKNOWN": [
                "key"
              ],
              "PASSPORT_FIELD_NOT_WRITABLE": [
                "key"
              ],
              "PASSPORT_FIELD_SCOPE": [
                "key"
              ],
              "PASSPORT_VALUE_INVALID": [
                "key"
              ],
              "PASSPORT_PERSONAL_DATA": [
                "key",
                "kind"
              ]
            }
          },
          "401": {
            "description": "Error — code: API_KEY_INVALID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ]
          },
          "403": {
            "description": "Error — code: API_KEY_SCOPE_MISSING, KEY_READ_ONLY, BRAND_SUSPENDED, INTEGRATIONS_DISABLED, PLAN_MODULE_MISSING",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_SCOPE_MISSING",
              "KEY_READ_ONLY",
              "BRAND_SUSPENDED",
              "INTEGRATIONS_DISABLED",
              "PLAN_MODULE_MISSING"
            ],
            "x-error-params": {
              "API_KEY_SCOPE_MISSING": [
                "scope"
              ]
            }
          },
          "404": {
            "description": "Error — code: unknownCode, codeRetired, PASSPORT_NONE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "unknownCode",
              "codeRetired",
              "PASSPORT_NONE"
            ],
            "x-error-params": {
              "codeRetired": [
                "brand"
              ]
            }
          },
          "429": {
            "description": "Error — code: rateLimited, rateBlocked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "rateLimited",
              "rateBlocked"
            ]
          }
        },
        "x-example": {
          "params": {
            "dppId": "A1B2C3D4",
            "elementIdPath": "$.battery.chemistry"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Result": {
        "type": "object",
        "properties": {
          "message": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "messageType": {
                  "type": "string",
                  "enum": [
                    "Info",
                    "Warning",
                    "Error",
                    "Exception"
                  ]
                },
                "code": {
                  "type": "string",
                  "enum": [
                    "ClientErrorBadRequest",
                    "ClientNotAuthorized",
                    "ClientForbidden",
                    "ClientErrorResourceNotFound",
                    "ClientMethodNotAllowed",
                    "ClientResourceConflict",
                    "ServerInternalError",
                    "ServerNotImplemented",
                    "ServerErrorBadGateway"
                  ],
                  "description": "Generic status code (EN 18222:2026 Table 15)"
                },
                "text": {
                  "type": "string",
                  "description": "Human-readable text in the Accept-Language language (default: English)"
                },
                "correlationId": {
                  "description": "The request id — the `X-Request-Id` header of the request or of the response",
                  "type": "string"
                },
                "timestamp": {
                  "type": "string",
                  "format": "date-time",
                  "description": "UTC, whole seconds (`2026-10-26T12:00:00Z`)"
                },
                "itemooCode": {
                  "description": "Stable Itemoo error code — use it in your integration",
                  "type": "string"
                },
                "params": {
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {}
                }
              },
              "required": [
                "messageType",
                "code",
                "text",
                "timestamp"
              ]
            }
          }
        },
        "required": [
          "message"
        ],
        "description": "Every error response is a Result object (EN 18222:2026 7.2)."
      },
      "DigitalProductPassport": {
        "type": "object",
        "properties": {
          "digitalProductPassportId": {
            "type": "string",
            "description": "Globally unique passport URI"
          },
          "uniqueProductIdentifier": {
            "type": "string",
            "description": "GS1 Digital Link of the code level (with batch and serial number) or the code URI (EN 18219:2026)"
          },
          "granularity": {
            "type": "string",
            "enum": [
              "model",
              "batch",
              "item"
            ]
          },
          "dppSchemaVersion": {
            "type": "string",
            "examples": [
              "EN 18223:2026"
            ]
          },
          "dppStatus": {
            "type": "string",
            "enum": [
              "active",
              "inactive",
              "archived"
            ],
            "description": "active (also during a recall — see `recall`), inactive (end of life of the unit, passport closed by the brand), archived (read-only archive after the brand left Itemoo). The detailed Itemoo status is in `lifecycle`"
          },
          "lastUpdated": {
            "type": "string",
            "format": "date-time",
            "description": "UTC, whole seconds"
          },
          "economicOperatorId": {
            "description": "Manufacturer identifier per EN 18219:2026 (ISO/IEC 6523 `ICD:value`, e.g. `0088:` + GLN); null when the brand has not entered one",
            "type": [
              "string",
              "null"
            ]
          },
          "facilityId": {
            "type": "string"
          },
          "contentSpecificationIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Legal acts the passport content follows, e.g. `EU 2024/1781`, `EU 2023/1542`"
          }
        },
        "required": [
          "digitalProductPassportId",
          "uniqueProductIdentifier",
          "granularity",
          "dppSchemaVersion",
          "dppStatus",
          "lastUpdated",
          "economicOperatorId",
          "contentSpecificationIds"
        ],
        "additionalProperties": {},
        "description": "Passport per EN 18223:2026: the header, then data elements. Dictionary fields are collections by key segment (`battery.chemistry` → `battery: { chemistry }`), the brand’s own fields are in `brandFields`, and Itemoo elements (`productInfo`, `productIdentity`, `economicOperators`, `accessLevel`, `lifecycle`, `recall`, `passportVersion`, `backup`, `relatedDocuments`, `passportComponents`, `unit`) are read-only. With `representation=full` the data elements come as `elements[]`."
      }
    }
  }
}