---
title: "Create a single passport."
method: POST
path: "/api/v1/passports"
tags: ["Passports"]
---

# Create a single passport.

`POST /api/v1/passports`

## Request

- Base URL: `https://app.tracepass.eu`
- URL: `https://app.tracepass.eu/api/v1/passports`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://app.tracepass.eu/api/oauth/authorize`, token URL `https://app.tracepass.eu/api/oauth/token`, scopes: `passports:write`)

Create a single Digital Product Passport. The passport is
bound to a product (`productId`) and identified by a GS1
GTIN + serial unique within that GTIN. New passports start
in `draft` status — fields are populated via subsequent
PATCH calls and the passport is published from the
dashboard once review is complete.

Counts as one v1 write AND consumes one DPP slot from the
plan's `maxDpps` quota — when that quota is exhausted and
the plan supports overage, returns 402 with an
`overage_required` body. Retry with
`confirmOverage: true` to accept the per-passport charge.

**Second-life batteries (Art. 77(7) of Regulation (EU) 2023/1542).**
A battery that is repurposed, remanufactured or prepared for reuse
gets a new passport linked to the original one(s). Send a `lineage`
block naming each predecessor, either by `internalPassportId` (one
of your own passports) or by its resolvable `identifier`. The
platform derives `batteryStatus` from the triggers, stores the block
immutably, and adds a `successors` link on your own predecessor
passports. A rule violation returns 422 with a `code`-style `error`
(see `PassportCreateUnprocessable`).

## Headers

- `Idempotency-Key` string

## Request body

- CreatePassportInput: Exactly one of `identifier` (EN 18219 scheme-tagged) or the legacy `gs1` block must be supplied. When `identifier` is provided with `scheme: "gs1"` the platform also writes the legacy `gs1` block for backward compatibility. Battery passports may only carry `gs1` or `iso15459` identifiers (Art. 77(3) Battery Regulation).
  - `productId` string, required: MongoDB ObjectId hex string (24 chars).
  - `identifier` union
    - object: GS1 GTIN + serial number (scheme "gs1"). Required for battery passports.
      - `scheme` 'gs1', required
      - `gtin` string, required: GS1 GTIN with a valid check digit. Accepts 8 digits (GTIN-8), 12 digits (GTIN-12/UPC-A), 13 digits (GTIN-13/EAN-13), or 14 digits (GTIN-14). All forms are left-padded to 14 digits before storage; stored and returned values are always 14 digits.
      - `serialNumber` string, required
      - `digitalLinkUri` string, uri
    - object: ISO/IEC 15459 identifier (scheme "iso15459"). Also valid for battery passports.
      - `scheme` 'iso15459', required
      - `issuingAgencyCode` string, required
      - `primaryId` string, required
      - `serial` string
      - `raw` string: The ISO/IEC 15459 unique identifier: issuing agency code + primary id + serial, concatenated. Always derived by the server from the parts; a value sent on create is ignored. Present on every read.
      - `uri` string, uri: The ISO/IEC 18975 Data-Identifier query-form resolver URL generated by the server, following EN 18219 Table B.12: `https://id.tracepass.eu/?.25P=<IAC><primaryId>&.S=<serial>` (`.S` component omitted when there is no serial; parameter values are percent-encoded). Always derived by the server from the identifier parts; present on every read.
    - object: IEC 61406 Identification Link — an https URI (scheme "iec61406"). Not valid for battery passports (Battery Regulation Art. 77(3) requires gs1 or iso15459).
      - `scheme` 'iec61406', required
      - `uri` string, uri, required
    - object: W3C DID Core identifier (scheme "did"). Not valid for battery passports (Battery Regulation Art. 77(3) requires gs1 or iso15459).
      - `scheme` 'did', required
      - `did` string, required
      - `method` string, required
    - object: Digital Object Identifier — ISO 26324 (scheme "doi"). Stored as bare `10.<registrant>/<suffix>`. Any `https://doi.org/` or `doi:` prefix is stripped on input; the DOI resolves as `https://doi.org/<doi>`. `granularity` is REQUIRED per EN 18219 §5.6.2(b): a DOI product identifier must declare whether it identifies the product model, a production batch, or an individual item. Not valid for battery passports (Battery Regulation Art. 77(3) requires gs1 or iso15459).
      - `scheme` 'doi', required
      - `doi` string, required
      - `granularity` 'model' | 'batch' | 'item', required: Whether the DOI identifies the product model, a production batch, or an individual item (EN 18219 §5.6.2(b)). Must be supplied on create; returned unchanged on read.
  - `gs1` object: Legacy GS1 identifier block. Prefer `identifier` with `scheme: "gs1"` on new integrations.
    - `gtin` string, required: GS1 GTIN with a valid check digit. Accepts 8 digits (GTIN-8), 12 digits (GTIN-12/UPC-A), 13 digits (GTIN-13/EAN-13), or 14 digits (GTIN-14). All forms are left-padded to 14 digits before storage; stored and returned values are always 14 digits.
    - `serialNumber` string, required
  - `parties` PartyMap: Map of role → Party. Each role appears at most once.
  - `lineage` LineageInput: Battery passports only. Links a second-life battery's new passport to the original battery passport(s), as Art. 77(7) of Regulation (EU) 2023/1542 requires. Immutable after create. `batteryStatus` is derived from the triggers (repurposed, remanufactured, …). Rules (422): `lineage_not_applicable` (non-battery), `duplicate_predecessor`, `status_trigger_mismatch` (the product's default `batteryStatus` contradicts the triggers), `predecessor_reason_required` (no predecessors and no reason), `predecessor_not_found`, `invalid_gtin_check_digit`. A second-life `batteryStatus` with no lineage block returns `successor_passport_required`.
    - `predecessors` LineagePredecessorInput[], required
      - `identifier` string: Resolvable identifier of the predecessor passport (http(s) URL, `urn:`, or bare token).
      - `internalPassportId` string: MongoDB ObjectId hex string (24 chars).
      - `trigger` 'preparation_for_reuse' | 'preparation_for_repurposing' | 'repurposing' | 'remanufacturing', required: The Art. 77(7) operation that produced the successor battery.
    - `noPredecessorReason` string: Only with an empty `predecessors` list: why no original passport exists, e.g. a battery placed on the market before 18 Feb 2027.
  - `confirmOverage` boolean: Accept the per-passport overage charge when the plan's `maxDpps` quota is already exhausted. Required only after a 402 response on a previous attempt.

## Response `201`

Passport created. When the `parties` block carries an LEI
that GLEIF reports as lapsed, retired or inactive, or whose
legal name differs, the response adds `warnings`; an LEI
GLEIF does not know, or reports as annulled or duplicate,
is a 400 instead (see `upsertParty`).

- object
  - `_id` string: MongoDB ObjectId hex string (24 chars).
  - `companyId` string: MongoDB ObjectId hex string (24 chars).
  - `productId` string: MongoDB ObjectId hex string (24 chars).
  - `templateId` string: MongoDB ObjectId hex string (24 chars).
  - `identifier` union
    - object: GS1 GTIN + serial number (scheme "gs1"). Required for battery passports.
      - `scheme` 'gs1', required
      - `gtin` string, required: GS1 GTIN with a valid check digit. Accepts 8 digits (GTIN-8), 12 digits (GTIN-12/UPC-A), 13 digits (GTIN-13/EAN-13), or 14 digits (GTIN-14). All forms are left-padded to 14 digits before storage; stored and returned values are always 14 digits.
      - `serialNumber` string, required
      - `digitalLinkUri` string, uri
    - object: ISO/IEC 15459 identifier (scheme "iso15459"). Also valid for battery passports.
      - `scheme` 'iso15459', required
      - `issuingAgencyCode` string, required
      - `primaryId` string, required
      - `serial` string
      - `raw` string: The ISO/IEC 15459 unique identifier: issuing agency code + primary id + serial, concatenated. Always derived by the server from the parts; a value sent on create is ignored. Present on every read.
      - `uri` string, uri: The ISO/IEC 18975 Data-Identifier query-form resolver URL generated by the server, following EN 18219 Table B.12: `https://id.tracepass.eu/?.25P=<IAC><primaryId>&.S=<serial>` (`.S` component omitted when there is no serial; parameter values are percent-encoded). Always derived by the server from the identifier parts; present on every read.
    - object: IEC 61406 Identification Link — an https URI (scheme "iec61406"). Not valid for battery passports (Battery Regulation Art. 77(3) requires gs1 or iso15459).
      - `scheme` 'iec61406', required
      - `uri` string, uri, required
    - object: W3C DID Core identifier (scheme "did"). Not valid for battery passports (Battery Regulation Art. 77(3) requires gs1 or iso15459).
      - `scheme` 'did', required
      - `did` string, required
      - `method` string, required
    - object: Digital Object Identifier — ISO 26324 (scheme "doi"). Stored as bare `10.<registrant>/<suffix>`. Any `https://doi.org/` or `doi:` prefix is stripped on input; the DOI resolves as `https://doi.org/<doi>`. `granularity` is REQUIRED per EN 18219 §5.6.2(b): a DOI product identifier must declare whether it identifies the product model, a production batch, or an individual item. Not valid for battery passports (Battery Regulation Art. 77(3) requires gs1 or iso15459).
      - `scheme` 'doi', required
      - `doi` string, required
      - `granularity` 'model' | 'batch' | 'item', required: Whether the DOI identifies the product model, a production batch, or an individual item (EN 18219 §5.6.2(b)). Must be supplied on create; returned unchanged on read.
  - `identifierKey` string: Canonical dedup key in `<scheme>:<parts>` form, e.g. `gs1:00012345678905:SN-001` or `did:did:example:123`. Globally unique (sparse index) — the same identifier cannot exist across different accounts.
  - `gs1` GS1Block
    - `gtin` string, required: GS1 GTIN with a valid check digit. Accepts 8 digits (GTIN-8), 12 digits (GTIN-12/UPC-A), 13 digits (GTIN-13/EAN-13), or 14 digits (GTIN-14). All forms are left-padded to 14 digits before storage; stored and returned values are always 14 digits.
    - `serialNumber` string, required
    - `digitalLinkUri` string, uri
  - `status` 'draft' | 'in_review' | 'approved' | 'published' | 'suspended' | 'expired' | 'archived'
  - `completionPercentage` integer
  - `fieldCounts` object
    - `total` integer
    - `empty` integer
    - `approved` integer
    - `pendingReview` integer
    - `flagged` integer
  - `fields` object
  - `parties` PartyMap: Map of role → Party. Each role appears at most once.
  - `lineage` PassportLineage: The stored, immutable lineage block of a successor battery passport.
    - `predecessors` object[]
      - `identifier` string
      - `trigger` 'preparation_for_reuse' | 'preparation_for_repurposing' | 'repurposing' | 'remanufacturing': The Art. 77(7) operation that produced the successor battery.
      - `internalPassportId` string: MongoDB ObjectId hex string (24 chars).
    - `noPredecessorReason` string
  - `dynamicDataAsOf` string, date-time, nullable: `measuredAt` of the newest battery measurement applied to this passport; null before the first one. Returned with `format=full`.
  - `successors` PassportSuccessor[]: Forward links to successor passports created from this one (same account only). Never changes this passport's fields.
    - `passportId` string: MongoDB ObjectId hex string (24 chars).
    - `identifier` string: Canonical resolvable URI of the successor passport.
    - `addedAt` string, date-time
  - `publishedAt` string, date-time
  - `suspendedAt` string, date-time
  - `suspensionReason` string
  - `archivedAt` string, date-time
  - `createdAt` string, date-time
  - `updatedAt` string, date-time
  - `warnings` object[]: Non-blocking findings from the GLEIF check of an LEI the write set (see `upsertParty`). Present only when non-empty. The value was saved; the warning says what GLEIF reports about it.
    - `role` 'manufacturer' | 'importer' | 'authorisedRepresentative' | 'distributor' | 'recycler' | 'producerResponsibilityOrg'
    - `path` string[], required
    - `message` string, required

## Other responses

- `400`: Validation error or malformed request.
- `401`: Missing or invalid API key.
- `402`: DPP quota exhausted; retry with `confirmOverage: true` to accept the per-passport charge.
- `403`: Plan-gate or workspace permission denied.
- `404`: Resource doesn't exist or is in a different workspace.
- `409`: Conflict — duplicate model on a product, GTIN registered to a different tenant, serial collision within a GTIN.
- `422`: Either the Idempotency-Key was reused with a different body, or a battery `lineage` rule failed. Lineage failures carry the rule code in `error` (e.g. `duplicate_predecessor`, `predecessor_not_found`, `status_trigger_mismatch`) and a human-readable `message`.
- `429`: Daily v1 write or passport-read budget exhausted. Resets at 00:00 UTC.

---

[API](https://skmtc.dev/tracepass/apis/tracepass-api.md) · [All operations](https://skmtc.dev/tracepass/apis/tracepass-api/llms.txt) · [OpenAPI document](https://skmtc.dev/tracepass/apis/tracepass-api/revisions/60ddeb25638b?raw)
