Developers · API endpoints

Passports

List, read, publish, change the status of and recycle passports; QR codes and the version archive.

Version
v1.0.0
Base URL
https://dppapi-production.up.railway.app/v1
Format
JSON · OpenAPI 3.1
FeedbackLast updated

Dieser Artikel liegt noch nicht auf Deutsch vor und wird unten auf Englisch angezeigt.

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.

GET/v1/passports
read scope

List 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

  • limitintegerqueryoptional

    Page size, 1–200. Default 50.

  • cursorstringqueryoptional

    The next_cursor of the previous page. Omit for the first page.

  • model_idstringqueryoptional

    Only passports of this model.

  • serialstringqueryoptional

    Exact serial number.

  • unique_identifierstringqueryoptional

    Exact passport identifier, e.g. C-7KQ2M9XHT4R.

  • statusstringqueryoptional

    Derived display status: draft, pending, published, attention, repurposed, waste or recycled.

  • published"true" | "false"queryoptional

    Only published, or only draft, passports.

  • updated_sinceISO 8601 date or date-timequeryoptional

    Changed — or given new dynamic data — at or after this instant.

  • created_sinceISO 8601 date or date-timequeryoptional

    Created at or after this instant.

Responses

  • 200OK — A page of passports.

Errors2

Response fields · 200

object
  • has_morebooleanrequired
  • next_cursorstring | nullrequired

    Pass as cursor to get the next page.

GET /v1/passports
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"
200 OK · A page of passports.
{"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",
GET/v1/passports/{id}
read scope

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

  • idstringpathrequired

    The passport id.

Responses

  • 200OK — The passport (abridged).

Errors2

  • 401unauthorized The key is missing, unknown or revoked.
  • 404Not found No passport with this id in your organisation.
GET /v1/passports/{id}
curl "https://dppapi-production.up.railway.app/v1/passports/cm1q8y0bq0006l70fx9y8z7w6" \-H "Authorization: Bearer $DPP_API_KEY"
200 OK · The passport (abridged).
{"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": []}
POST/v1/passports/{id}/publish
write scope

Publish 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

  • idstringpathrequired

    The passport id.

Headers2

  • Idempotency-Keystringheaderoptional

    Optional. 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"headeroptional

    Optional, 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; blockers lists every reason.

Errors6

Webhooks fired

POST /v1/passports/{id}/publish
curl -X POST "https://dppapi-production.up.railway.app/v1/passports/cm1q8y0bq0006l70fx9y8z7w6/publish" \-H "Authorization: Bearer $DPP_API_KEY"
422 Unprocessable · Refused by the publish gate; blockers lists every reason.
{"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"}
POST/v1/passports/publish
write scope

Publish 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–1000required

    Passport ids.

Headers2

  • Idempotency-Keystringheaderoptional

    Optional. 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"headeroptional

    Optional, 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

Webhooks fired

POST /v1/passports/publish
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"]}'
207 Multi-Status · Per-row results.
{"requested": 2,"published": 1,"failed": 1,"results": [{ "id": "cm1q8y0bq0006l70fx9y8z7w6", "ok": true },{ "id": "cm1q8y0bq0008l70fa1b2c3d4", "ok": false, "error": "missing_place_of_manufacture" }]}
PATCH/v1/passports/{id}/status
write scope

Change 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

  • idstringpathrequired

    The passport id.

Request body3

  • status"ORIGINAL" | "REPURPOSED" | "REUSED" | "REMANUFACTURED" | "WASTE"required

    The new status.

  • newResponsibleOrgIdstringoptional

    For a fork: the organisation responsible for the new passport. Defaults to the current one.

  • notestring, ≤ 500optional

    Kept on the history entry.

Headers2

  • Idempotency-Keystringheaderoptional

    Optional. 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"headeroptional

    Optional, 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 — WASTE or ORIGINAL: the updated passport.

Errors5

Webhooks fired

Response fields · 201

object
  • forkedboolean = true
  • childPassportobject
  • childUidstring
PATCH /v1/passports/{id}/status
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"}'
201 Created · A repurpose, re-use or remanufacture: the new linked passport.
{"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"}}
POST/v1/passports/{id}/recycle
write scope

Mark 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

  • idstringpathrequired

    The passport id.

Request body1

  • notestring, ≤ 500optional

    Optional. Kept on the history entry.

Headers2

  • Idempotency-Keystringheaderoptional

    Optional. 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"headeroptional

    Optional, live keys. Validate the write in full and store nothing. Test keys always dry-run; see Test keys.

Responses

  • 200OK — The ceased passport.

Errors4

Webhooks fired

POST /v1/passports/{id}/recycle
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"}'
200The ceased passport.
GET/v1/passports/{id}/versions
read scope

Published 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

  • idstringpathrequired

    The passport id.

Responses

  • 200OK — The versions (snapshot abridged).

Errors2

  • 401unauthorized The key is missing, unknown or revoked.
  • 404Not found No passport with this id in your organisation.
GET /v1/passports/{id}/versions
curl "https://dppapi-production.up.railway.app/v1/passports/cm1q8y0bq0006l70fx9y8z7w6/versions" \-H "Authorization: Bearer $DPP_API_KEY"
200 OK · The versions (snapshot abridged).
{"versions": [{"id": "cm1qd9e1f0040l70fa9b8c7d6","passportId": "cm1q8y0bq0006l70fx9y8z7w6","version": 1,"contentHash": "9f2c4e1a7b3d5f6081a2c3e4d5f60718293a4b5c6d7e8f901a2b3c4d5e6f7a8b","publishedAt": "2027-01-15T10:02:11.000Z","snapshot": { "uniqueIdentifier": "C-7KQ2M9XHT4R", "status": "ORIGINAL" }}]}
GET/v1/passports/{id}/qr.svg
read scope

QR 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

  • idstringpathrequired

    The passport id.

Responses

  • 200OK — image/svg+xml (or image/png for qr.png).

Errors2

  • 401unauthorized The key is missing, unknown or revoked.
  • 404Not found No passport with this id in your organisation.
GET /v1/passports/{id}/qr.svg
curl "https://dppapi-production.up.railway.app/v1/passports/cm1q8y0bq0006l70fx9y8z7w6/qr.svg" \-H "Authorization: Bearer $DPP_API_KEY"
200image/svg+xml (or image/png for qr.png).

Cookie-Einstellungen

Sie entscheiden, welche Cookies verwendet werden. Ihre Wahl können Sie jederzeit über „Cookie-Einstellungen“ im Footer ändern. Datenschutzerklärung

Notwendig

Immer aktiv

Für den Betrieb der Website erforderlich: Ihr Hell-/Dunkel-Design und diese Cookie-Auswahl werden in Ihrem Browser gespeichert. Sie dienen nicht dem Tracking.

Analyse

Google Analytics 4 misst über Statistiken, wie Seiten genutzt werden, und hilft uns, die Website zu verbessern. Wenn Sie zustimmen, setzt es Cookies und erfasst Ihren Besuch vollständig. Wenn Sie ablehnen, setzt es keine Cookies, doch Google kann weiterhin technische Daten erhalten, etwa die aufgerufene Seite, Ihren Browsertyp und Ihre IP-Adresse.

_ga, _ga_* · bis zu 2 Jahre · Google