/api/v1/passports/{id}/history
API key
List a passport's archived versions
The archived versions of a passport, newest first. Every metadata write (PUT /api/v1/passports/{id}, a bulk upsert, an AAS re-ingest) and every lifecycle change (PUT …/status) archives the state it replaced, so version *N* is the metadata that was current until validUntil (the instant the change was recorded) and from the previous version's validUntil — or the passport's creation — before that; the live passport is version currentVersion and is read with GET /api/v1/passports/{id}. Archiving starts with the first change, so a never-changed passport lists no versions.
This is the retrieval EN 18221:2026 §4.2 describes for archived versions, at the owner tier: the caller's workspace only, under the same visibility as the passport itself. A version is a DOCUMENT: the single-version reads below return it as one, with the EN 18223 header, its body at the root and its own proof. This list carries summaries only — read a version to get its document.
Who may read this. Two authorised actors, and the anonymous tier is refused — EN 18221:2026 §4.2 makes an archived version retrievable by authenticated and authorised actors ONLY. (1) The owning or operator-bound tenant, via an op_dpp_token_… API key: the version is unmasked, exactly as that tenant's live read is. (2) The holder of a legitimate-interest or authority grant covering this passport (dpp_li_… / dpp_auth_… as a Bearer token or ?grant=): the version is masked to the grant tier — the Battery Reg. Annex XIII(2)-(4) restricted keys are readable, the owner-only keys are not — so a version discloses exactly what the live read discloses to the same caller, and no more. A grant-unlocked response carries Cache-Control: private, no-store and Referrer-Policy: no-referrer. Attribution (changedBy, changeReason) is owner-only and reads null for a grant holder: it names the staff who edited a row, not regulated product data. A DRAFT is never revealed to a grant. Every read is recorded in the passport's access audit log.
Parameters
| Name | In | Type | Description | |
|---|---|---|---|---|
id |
path | string | required | Passport UUID, caller-supplied |
page |
query | integer | optional | 1-based page number (digits only; non-numeric falls back to 1). default1 · min 1 |
limit |
query | integer | optional | Page size. Clamped to 1–200; non-numeric falls back to the default 100. default100 · min 1 · max 200 |
Example
curl -X GET "https://staging.opendpp-node.dev/api/v1/passports/string/history" \
-H "Authorization: Bearer $OPENDPP_API_KEY"
Responses
The archived versions, newest first, with the standard pagination envelope. currentVersion is the live passport's version number (one more than total).
Example 200 response
{
"success": true,
"passportId": "9b2fa884-1c3d-4e5f-8a6b-7c8d9e0f1a2b",
"productId": "09501101530003",
"currentVersion": 4,
"page": 1,
"limit": 50,
"total": 3,
"totalPages": 1,
"versions": [
{
"version": 3,
"validUntil": "2026-08-20T14:02:10.000Z",
"recordedAt": "2026-08-20T14:02:10.000Z",
"changedBy": "user:anna@example.com",
"changeReason": "Status changed: ACTIVE → RECALLED"
},
{
"version": 2,
"validUntil": "2026-07-01T08:15:22.000Z",
"recordedAt": "2026-07-01T08:15:22.000Z",
"changedBy": "key:3f2a9c1e",
"changeReason": "Annual capacity re-test"
},
{
"version": 1,
"validUntil": "2026-06-12T09:41:00.000Z",
"recordedAt": "2026-06-12T09:41:00.000Z",
"changedBy": "key:3f2a9c1e",
"changeReason": "Initial correction"
}
]
}No credential was presented at all. An archived version is for authenticated and authorised actors only (EN 18221:2026 §4.2), so the anonymous tier is refused rather than served a masked version. A credential that simply unlocks nothing gets the 404 instead, which discloses no existence.
Example 401 response
{
"success": false,
"error": "Unauthorized",
"message": "An owner credential or a covering access grant is required to read a passport's archived versions."
}The API key is scoped to another economic operator than the passport's.
Example 403 response
{
"success": false,
"error": "Forbidden",
"message": "Your access is restricted to Economic Operator: 2d1e9c7a-4b3f-4e8d-9a6c-1f2e3d4c5b6a"
}No passport readable with the presented credential has this id, productId or Digital Link URL. The SAME answer covers another workspace's passport, a grant scoped elsewhere, a revoked or expired grant, and a DRAFT viewed by anyone but its owner — existence is never disclosed to a caller who may not read it.
Example 404 response
{
"success": false,
"error": "Not Found",
"message": "No passport with ID or Product ID 9b2fa884-1c3d-4e5f-8a6b-7c8d9e0f1a2b is readable with your credential"
}