Developers · API endpoints

Models

Create, list, update and validate battery models, and run the missing-field analysis for the model’s category.

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

Este artículo aún no está disponible en español; se muestra a continuación en inglés.

A battery model holds the data every battery of one design shares — the model-level data points of Annex VI and Annex XIII. Values live in fields, keyed by the names in the field catalogue; category, capacityKwh and chemistry are properties of the model itself.

A model must be complete for its category before its passports can be published. GET /models/{id}/completeness tells you what is missing; POST /models/validate asks the same question about a draft before anything is stored.

Personalise the samples. Paste a test key and every snippet uses it — and your own model and passport ids.

GET/v1/models
read scope

List models

Your battery models, newest first, a page at a time — each with its completeness for its category and how many batteries it has and how many are published. Filter by category, completeness, or updated_since to sync only what changed.

Parameters5

  • limitintegerqueryoptional

    Page size, 1–200. Default 50.

  • cursorstringqueryoptional

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

  • category"EV" | "LMT" | "INDUSTRIAL"queryoptional

    Only models of this category.

  • updated_sinceISO 8601 date or date-timequeryoptional

    Only models changed at or after this instant.

  • complete"true" | "false"queryoptional

    Only complete, or only incomplete, models.

Responses

  • 200OK — A page of models.

Errors2

Response fields · 200

object
  • has_morebooleanrequired
  • next_cursorstring | nullrequired

    Pass as cursor to get the next page.

GET /v1/models
curl "https://dppapi-production.up.railway.app/v1/models?category=LMT&complete=false" \-H "Authorization: Bearer $DPP_API_KEY"
200 OK · A page of models.
{"data": [{"id": "cm1q8x2k40003l70f9a8s7d6e","name": "Cargo 48V 15Ah","category": "LMT","capacityKwh": 0.72,"chemistry": "Lithium-ion NMC","templateKey": "battery","industrialExternalStorage": false,"createdAt": "2027-01-15T09:12:44.120Z","updatedAt": "2027-01-15T11:40:02.019Z","requiredFilled": 39,"requiredTotal": 41,"complete": false,"itemCount": 100,"publishedCount": 0}],"has_more": true,"next_cursor": "eyJpZCI6ImNtMXE4eTBicTAwMDZsNzBmeDl5OHo3dzYifQ"}
POST/v1/models
write scope

Create a model

Creates a battery model. Industrial batteries are in passport scope only above 2 kWh (Art. 77(1)), so an INDUSTRIAL model with capacityKwh of 2 or less is refused.

Request body7

  • category"EV" | "LMT" | "INDUSTRIAL"required

    Battery category. Decides which data points are required.

  • namestring, 1–200required

    Your name for the model.

  • capacityKwhnumber > 0required

    Energy capacity in kWh. Must exceed 2 for INDUSTRIAL.

  • chemistrystring, 1–120required

    Battery chemistry (Annex VI A(7)), e.g. "Lithium-ion NMC".

  • industrialExternalStoragebooleanoptional

    Industrial battery with exclusively external storage. Default false.

  • templateKeystringoptional

    Category template. Default "battery".

  • fieldsobjectoptional

    Model-level data points keyed by API field name.

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 — The new model.

Errors6

Webhooks fired

Response fields · 201

object
  • idstring
  • namestring
  • categorystring

    One ofEVLMTINDUSTRIAL

  • capacityKwhnumber
  • chemistrystring
  • fieldsobject

    Template field values keyed by field name — see GET /v1/field-catalog.

  • createdAtstring · date-time
  • updatedAtstring · date-time
POST /v1/models
curl -X POST "https://dppapi-production.up.railway.app/v1/models" \-H "Authorization: Bearer $DPP_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: 7b3e0c52-1f7d-4b8a-9a52-2f0e6d1c9a44" \-d '{"category": "LMT","name": "Cargo 48V 15Ah","capacityKwh": 0.72,"chemistry": "Lithium-ion NMC","fields": {"manufacturerName": "Example Batteries GmbH","ratedCapacity": 15,"nominalVoltage": 48}}'
201 Created · The new model.
{"id": "cm1q8x2k40003l70f9a8s7d6e","templateKey": "battery","category": "LMT","industrialExternalStorage": false,"name": "Cargo 48V 15Ah","capacityKwh": 0.72,"chemistry": "Lithium-ion NMC","fields": {"manufacturerName": "Example Batteries GmbH","ratedCapacity": 15,"nominalVoltage": 48},"createdAt": "2027-01-15T09:12:44.120Z","updatedAt": "2027-01-15T09:12:44.120Z"}
GET/v1/models/{id}
read scope

Get a model

One model with its conformity record, documents, carbon-footprint and recycled-content declarations, and _count.items, the number of batteries created for it.

Parameters1

  • idstringpathrequired

    The model id.

Responses

  • 200OK — The model (abridged).

Errors2

  • 401unauthorized The key is missing, unknown or revoked.
  • 404Not found No model with this id in your organisation.

Response fields · 200

object
  • idstring
  • namestring
  • categorystring

    One ofEVLMTINDUSTRIAL

  • capacityKwhnumber
  • chemistrystring
  • fieldsobject

    Template field values keyed by field name — see GET /v1/field-catalog.

  • createdAtstring · date-time
  • updatedAtstring · date-time
GET /v1/models/{id}
curl "https://dppapi-production.up.railway.app/v1/models/cm1q8x2k40003l70f9a8s7d6e" \-H "Authorization: Bearer $DPP_API_KEY"
200 OK · The model (abridged).
{"id": "cm1q8x2k40003l70f9a8s7d6e","templateKey": "battery","category": "LMT","industrialExternalStorage": false,"name": "Cargo 48V 15Ah","capacityKwh": 0.72,"chemistry": "Lithium-ion NMC","fields": {"manufacturerName": "Example Batteries GmbH","ratedCapacity": 15,"nominalVoltage": 48},"createdAt": "2027-01-15T09:12:44.120Z","updatedAt": "2027-01-15T09:12:44.120Z"}
PATCH/v1/models/{id}
write scope

Update a model

Changes the name, chemistry or field values. fields is merged into what is stored: send only what changes, and a partial update never blanks the rest. Category and capacity cannot change — create a new model instead.

Every change is written to the audit trail.

Parameters1

  • idstringpathrequired

    The model id.

Request body3

  • namestring, 1–200optional

    New name.

  • chemistrystring, 1–120optional

    New chemistry.

  • fieldsobjectoptional

    Field values to add or replace, merged into the stored ones.

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 updated model.

Errors6

Webhooks fired

Response fields · 200

object
  • idstring
  • namestring
  • categorystring

    One ofEVLMTINDUSTRIAL

  • capacityKwhnumber
  • chemistrystring
  • fieldsobject

    Template field values keyed by field name — see GET /v1/field-catalog.

  • createdAtstring · date-time
  • updatedAtstring · date-time
PATCH /v1/models/{id}
curl -X PATCH "https://dppapi-production.up.railway.app/v1/models/cm1q8x2k40003l70f9a8s7d6e" \-H "Authorization: Bearer $DPP_API_KEY" \-H "Content-Type: application/json" \-d '{"fields": {"hazardousSubstances": "None above reporting thresholds","extinguishingAgent": "Water, foam"}}'
200 OK · The updated model.
{"id": "cm1q8x2k40003l70f9a8s7d6e","templateKey": "battery","category": "LMT","industrialExternalStorage": false,"name": "Cargo 48V 15Ah","capacityKwh": 0.72,"chemistry": "Lithium-ion NMC","fields": {"manufacturerName": "Example Batteries GmbH","ratedCapacity": 15,"nominalVoltage": 48},"createdAt": "2027-01-15T09:12:44.120Z","updatedAt": "2027-01-15T09:12:44.120Z"}
GET/v1/models/{id}/completeness
read scope

Missing-field analysis

Compares the model with the obligations of its category. missing holds required data points still empty — they block publishing. conditionalUnset holds "if applicable" ones, as prompts. Required documents (the EU Declaration of Conformity) and model properties (chemistry) are included.

Battery-level fields are answered per battery; the newest battery stands in as the sample, and with no batteries yet those fields read as unanswered.

Parameters1

  • idstringpathrequired

    The model id.

Responses

  • 200OK — The report (abridged).

Errors2

  • 401unauthorized The key is missing, unknown or revoked.
  • 404Not found No model with this id in your organisation.

Response fields · 200

object
  • categorystring
  • requiredTotalinteger
  • requiredFilledinteger
  • completeboolean
GET /v1/models/{id}/completeness
curl "https://dppapi-production.up.railway.app/v1/models/cm1q8x2k40003l70f9a8s7d6e/completeness" \-H "Authorization: Bearer $DPP_API_KEY"
200 OK · The report (abridged).
{"category": "LMT","requiredTotal": 41,"requiredFilled": 39,"complete": false,"missing": [{"name": "EU Declaration of Conformity","label": "EU Declaration of Conformity","point": 1,"annexRef": "Annex XIII 1(r) / Art. 18","granularity": "model"}],"conditionalUnset": [],"missingByPoint": { "1": 2 }}
POST/v1/models/validate
read scope

Validate a draft model

A stateless completeness check: send the body you would send to POST /models and get the model-level analysis back, without creating anything. unknownFields names field keys the template does not recognise — usually a typo in your mapping. Use it in an ERP form or a CI job to know whether a product record is passport-ready before it is pushed.

It changes nothing, so it needs only the read scope, and a test key gets the real analysis — not a dry-run envelope.

Request body2

  • …objectrequired

    The same body as Create a model.

  • documentTypesstring[]optional

    Documents you will upload, e.g. ["EU Declaration of Conformity"], so they count as present.

Responses

  • 200OK — The analysis (abridged).

Errors2

Response fields · 200

object
  • validboolean
  • completeboolean
  • requiredTotalinteger
  • requiredFilledinteger
  • unknownFieldsarray of string
POST /v1/models/validate
curl -X POST "https://dppapi-production.up.railway.app/v1/models/validate" \-H "Authorization: Bearer $DPP_API_KEY" \-H "Content-Type: application/json" \-d '{"category": "EV","name": "Pack 400V 82kWh","capacityKwh": 82,"chemistry": "Lithium-ion NMC 811","fields": {"manufacturerName": "Example Batteries GmbH","ratedCapacity": 205,"nominalVoltag": 400},"documentTypes": ["EU Declaration of Conformity"]}'
200 OK · The analysis (abridged).
{"valid": true,"complete": false,"requiredTotal": 38,"requiredFilled": 4,"missing": [{"name": "nominalVoltage","label": "Nominal voltage","point": 1,"annexRef": "Annex XIII 1(h)","granularity": "model"}],"conditionalUnset": [],"unknownFields": ["nominalVoltag"]}

Preferencias de cookies

Tú decides qué cookies se usan. Puedes cambiar tu elección en cualquier momento desde «Configuración de cookies» en el pie de página. Política de privacidad

Necesarias

Siempre activas

Imprescindibles para que el sitio funcione: tu tema claro/oscuro y esta elección de cookies se guardan en tu navegador. No sirven para rastrearte.

Analítica

Google Analytics 4 mide cómo se usan las páginas mediante estadísticas, lo que nos ayuda a mejorar el sitio. Si aceptas, instala cookies y mide tu visita por completo. Si rechazas, no instala cookies, pero Google aún puede recibir datos técnicos como la página vista, el tipo de navegador y la dirección IP.

_ga, _ga_* · hasta 2 años · Google