A passport is the regulatory record of one battery. It is a draft until published; publishing puts it on the public resolver, freezes a hashed version for the archive and counts it as issued.
Publishing is gated on the server: the battery needs a place of manufacture, and its model must be complete for its category. The same rule applies in the app and over the API.
Personalise the samples. Paste a test key and every snippet uses it — and your own model and passport ids.
/v1/passportsList passports
Every passport of your organisation across models, newest first, a page at a time, each with its derived display status and links to its public page, JSON-LD and QR codes. updated_since also catches passports whose only change is a new dynamic-data event, so one query finds everything that changed.
Parameters9
limitintegerqueryoptionalPage size, 1–200. Default 50.
cursorstringqueryoptionalThe
next_cursorof the previous page. Omit for the first page.model_idstringqueryoptionalOnly passports of this model.
serialstringqueryoptionalExact serial number.
unique_identifierstringqueryoptionalExact passport identifier, e.g.
C-7KQ2M9XHT4R.statusstringqueryoptionalDerived display status:
draft,pending,published,attention,repurposed,wasteorrecycled.published"true" | "false"queryoptionalOnly published, or only draft, passports.
updated_sinceISO 8601 date or date-timequeryoptionalChanged — or given new dynamic data — at or after this instant.
created_sinceISO 8601 date or date-timequeryoptionalCreated at or after this instant.
Responses
- 200OK — A page of passports.
Errors2
- 400
Validation faileddetailsnames each invalid field. - 401
unauthorizedThe key is missing, unknown or revoked.
Response fields · 200
object- idstring
- uniqueIdentifierstring
Immutable, resolvable identifier printed in the QR code.
- serialNumberstring | null
- itemIdstring
- modelIdstring
- placeOfManufacturestring | null
- dateOfManufacturestring · date-time | null
- statusstring
Annex XIII 4(c).
One of
ORIGINALREPURPOSEDREUSEDREMANUFACTUREDWASTE - lifecycleStatestring
One of
ACTIVECEASED_RECYCLED - displayStatusstring
One of
draftpendingpublishedattentionrepurposedwasterecycled - attentionReasonsarray of string
One of
registration_failedmissing_place_of_manufactureoperator_verification_lapsed - publishedAtstring · date-time | null
- registrationStatusstring | null
One of
pendingregisteredfailed - publicstring | null
The URL the QR code encodes.
- publicJsonstring
- jsonLdstring
- qrSvgstring
- qrPngstring
- createdAtstring · date-time
- updatedAtstring · date-time
- has_morebooleanrequired
- next_cursorstring | nullrequired
Pass as
cursorto get the next page.
curl "https://dppapi-production.up.railway.app/v1/passports?model_id=cm1q8x2k40003l70f9a8s7d6e&updated_since=2027-06-01T00%3A00%3A00Z&limit=200" \-H "Authorization: Bearer $DPP_API_KEY"{"data": [{"id": "cm1q8y0bq0006l70fx9y8z7w6","uniqueIdentifier": "C-7KQ2M9XHT4R","serialNumber": "C48-2027-0001","itemId": "cm1q8y0bq0005l70fq2r3t4u5","modelId": "cm1q8x2k40003l70f9a8s7d6e","placeOfManufacture": "Stuttgart, Germany","dateOfManufacture": "2027-01-15T00:00:00.000Z","status": "ORIGINAL","lifecycleState": "ACTIVE","displayStatus": "pending","attentionReasons": [],"publishedAt": "2027-01-15T10:02:11.000Z","registrationStatus": "pending","links": {"public": "https://dppapi-production.up.railway.app/p/C-7KQ2M9XHT4R",/v1/passports/{id}Get a passport
The full passport, every access tier: status, lifecycle state, the battery’s uniqueIdentifier, modelFields and itemFields, dynamic events (newest first), a derived displayStatus with attentionReasons, and parents / children for repurposed, re-used or remanufactured lineage.
Parameters1
idstringpathrequiredThe passport id.
Responses
- 200OK — The passport (abridged).
Errors2
- 401
unauthorizedThe key is missing, unknown or revoked. - 404
Not foundNo passport with this id in your organisation.
curl "https://dppapi-production.up.railway.app/v1/passports/cm1q8y0bq0006l70fx9y8z7w6" \-H "Authorization: Bearer $DPP_API_KEY"{"id": "cm1q8y0bq0006l70fx9y8z7w6","batteryItemId": "cm1q8y0bq0005l70fq2r3t4u5","uniqueIdentifier": "C-7KQ2M9XHT4R","responsibleOrgId": "cm1q7v0aa0000l70f1a2b3c4d","status": "ORIGINAL","lifecycleState": "ACTIVE","qrResolverUrl": "https://dppapi-production.up.railway.app/p/C-7KQ2M9XHT4R","publishedAt": "2027-01-15T10:02:11.000Z","displayStatus": "pending","attentionReasons": [],"modelFields": { "manufacturerName": "Example Batteries GmbH" },"itemFields": { "measuredCapacityAtPlacing": 15.2 },"events": [],"parents": [],"children": []}/v1/passports/{id}/publishPublish a passport
Publishes one passport. Takes no body — do not send Content-Type: application/json without one. Publishing an already-published passport returns it unchanged.
Parameters1
idstringpathrequiredThe passport id.
Headers2
Idempotency-KeystringheaderoptionalOptional. A unique string per logical operation (a UUID is ideal). The first response is stored for 24 hours and replayed for retries; see Idempotency.
X-DPP-Dry-Run"true"headeroptionalOptional, live keys. Validate the write in full and store nothing. Test keys always dry-run; see Test keys.
Responses
- 200OK — The published passport.
- 422Unprocessable — Refused by the publish gate;
blockerslists every reason.
Errors6
- 401
unauthorizedThe key is missing, unknown or revoked. - 402
plan_upgrade_requiredPublishing needs a paid plan. - 403
insufficient_scopeThe key has nowritescope. - 404
Not foundNo passport with this id in your organisation. - 409
Passport has ceased (recycled)A recycled passport cannot be published. - 422
publish_blockedblockershasmissing_place_of_manufactureand/ormodel_incomplete(with themissingfields).
Webhooks fired
curl -X POST "https://dppapi-production.up.railway.app/v1/passports/cm1q8y0bq0006l70fx9y8z7w6/publish" \-H "Authorization: Bearer $DPP_API_KEY"{"error": "publish_blocked","message": "This battery has no place of manufacture (Annex VI A(3)); the Registry refuses a passport without one.","blockers": [{"reason": "missing_place_of_manufacture","message": "This battery has no place of manufacture (Annex VI A(3)); the Registry refuses a passport without one."}],"request_id": "3f1c2a9e-8d4b-4c6f-9e2a-7b5d1c0e8f34"}/v1/passports/publishPublish many passports
Publishes up to 1,000 passports, one row at a time: 200 when every row succeeded, 207 when at least one did not. Failed rows carry error: not_found, ceased, missing_place_of_manufacture or model_incomplete (with message).
Request body1
idsstring[], 1–1000requiredPassport ids.
Headers2
Idempotency-KeystringheaderoptionalOptional. A unique string per logical operation (a UUID is ideal). The first response is stored for 24 hours and replayed for retries; see Idempotency.
X-DPP-Dry-Run"true"headeroptionalOptional, live keys. Validate the write in full and store nothing. Test keys always dry-run; see Test keys.
Responses
- 207Multi-Status — Per-row results.
Errors5
- 400
Validation faileddetailsnames each invalid field. - 401
unauthorizedThe key is missing, unknown or revoked. - 402
plan_upgrade_requiredPublishing needs a paid plan. - 403
insufficient_scopeThe key has nowritescope. - 422
idempotency_key_reusedTheIdempotency-Keywas already used with a different body.
Webhooks fired
curl -X POST "https://dppapi-production.up.railway.app/v1/passports/publish" \-H "Authorization: Bearer $DPP_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: 7b3e0c52-1f7d-4b8a-9a52-2f0e6d1c9a44" \-d '{"ids": ["cm1q8y0bq0006l70fx9y8z7w6","cm1q8y0bq0008l70fa1b2c3d4"]}'{"requested": 2,"published": 1,"failed": 1,"results": [{ "id": "cm1q8y0bq0006l70fx9y8z7w6", "ok": true },{ "id": "cm1q8y0bq0008l70fa1b2c3d4", "ok": false, "error": "missing_place_of_manufacture" }]}/v1/passports/{id}/statusChange status
REPURPOSED, REUSED and REMANUFACTURED create a new linked passport for the battery’s next life (Art. 77(7)): a new identifier, published at once, linked to this one, with its state-of-health history marked as reset. This passport keeps its identifier and takes the new status. WASTE and ORIGINAL change the status in place.
To record that a battery was recycled, use Mark as recycled — that ends the passport.
Parameters1
idstringpathrequiredThe passport id.
Request body3
status"ORIGINAL" | "REPURPOSED" | "REUSED" | "REMANUFACTURED" | "WASTE"requiredThe new status.
newResponsibleOrgIdstringoptionalFor a fork: the organisation responsible for the new passport. Defaults to the current one.
notestring, ≤ 500optionalKept on the history entry.
Headers2
Idempotency-KeystringheaderoptionalOptional. A unique string per logical operation (a UUID is ideal). The first response is stored for 24 hours and replayed for retries; see Idempotency.
X-DPP-Dry-Run"true"headeroptionalOptional, live keys. Validate the write in full and store nothing. Test keys always dry-run; see Test keys.
Responses
- 201Created — A repurpose, re-use or remanufacture: the new linked passport.
- 200OK —
WASTEorORIGINAL: the updated passport.
Errors5
- 400
Validation faileddetailsnames each invalid field. - 401
unauthorizedThe key is missing, unknown or revoked. - 403
insufficient_scopeThe key has nowritescope. - 404
Not foundNo passport with this id in your organisation. - 409
Passport has ceased (recycled)The passport was recycled.
Webhooks fired
Response fields · 201
object- forkedboolean = true
- childPassportobject
- childUidstring
curl -X PATCH "https://dppapi-production.up.railway.app/v1/passports/cm1q8y0bq0006l70fx9y8z7w6/status" \-H "Authorization: Bearer $DPP_API_KEY" \-H "Content-Type: application/json" \-d '{"status": "REPURPOSED","note": "Second life as stationary storage"}'{"forked": true,"childUid": "C-9PXR4T2KWM7","childPassport": {"id": "cm1qc2k8d0031l70fz1y2x3w4","status": "REPURPOSED","lifecycleState": "ACTIVE","publishedAt": "2031-03-02T08:00:00.000Z","qrResolverUrl": "https://dppapi-production.up.railway.app/p/C-9PXR4T2KWM7"}}/v1/passports/{id}/recycleMark as recycled
The battery has been recycled, so its passport ceases to exist (Art. 77(8)): status WASTE, lifecycle state CEASED_RECYCLED, a status change in the history, and from then on the public resolver answers 410 Gone. This cannot be undone.
Parameters1
idstringpathrequiredThe passport id.
Request body1
notestring, ≤ 500optionalOptional. Kept on the history entry.
Headers2
Idempotency-KeystringheaderoptionalOptional. A unique string per logical operation (a UUID is ideal). The first response is stored for 24 hours and replayed for retries; see Idempotency.
X-DPP-Dry-Run"true"headeroptionalOptional, live keys. Validate the write in full and store nothing. Test keys always dry-run; see Test keys.
Responses
- 200OK — The ceased passport.
Errors4
- 401
unauthorizedThe key is missing, unknown or revoked. - 403
insufficient_scopeThe key has nowritescope. - 404
Not foundNo passport with this id in your organisation. - 409
organisation_frozenThe organisation is frozen and read-only.
Webhooks fired
curl -X POST "https://dppapi-production.up.railway.app/v1/passports/cm1q8y0bq0006l70fx9y8z7w6/recycle" \-H "Authorization: Bearer $DPP_API_KEY" \-H "Content-Type: application/json" \-d '{"note": "Received by recycler, certificate R-2031-0042"}'/v1/passports/{id}/versionsPublished versions
The archive of frozen, hashed copies of what the passport published, newest first — the answer to "what did this passport claim in 2027?" in 2031.
Parameters1
idstringpathrequiredThe passport id.
Responses
- 200OK — The versions (snapshot abridged).
Errors2
- 401
unauthorizedThe key is missing, unknown or revoked. - 404
Not foundNo passport with this id in your organisation.
curl "https://dppapi-production.up.railway.app/v1/passports/cm1q8y0bq0006l70fx9y8z7w6/versions" \-H "Authorization: Bearer $DPP_API_KEY"{"versions": [{"id": "cm1qd9e1f0040l70fa9b8c7d6","passportId": "cm1q8y0bq0006l70fx9y8z7w6","version": 1,"contentHash": "9f2c4e1a7b3d5f6081a2c3e4d5f60718293a4b5c6d7e8f901a2b3c4d5e6f7a8b","publishedAt": "2027-01-15T10:02:11.000Z","snapshot": { "uniqueIdentifier": "C-7KQ2M9XHT4R", "status": "ORIGINAL" }}]}/v1/passports/{id}/qr.svgQR code
The QR code that resolves to the passport, as SVG (qr.svg, vector, for label artwork) or PNG (qr.png, print grade). It encodes the passport’s qrResolverUrl.
Parameters1
idstringpathrequiredThe passport id.
Responses
- 200OK —
image/svg+xml(orimage/pngforqr.png).
Errors2
- 401
unauthorizedThe key is missing, unknown or revoked. - 404
Not foundNo passport with this id in your organisation.
curl "https://dppapi-production.up.railway.app/v1/passports/cm1q8y0bq0006l70fx9y8z7w6/qr.svg" \-H "Authorization: Bearer $DPP_API_KEY"image/svg+xml (or image/png for qr.png).