Condition data from BMS and service
A battery management system or a service tool reports measurements per unit with updateCondition; newer measurements are accepted, older ones skipped, and the passport is re-published by your policy.
Dynamic battery data (state of health, capacity fade, full cycles, temperatures) comes from the battery management
system (BMS), a monitoring platform or a service tool, sometimes through the ERP's service module. In this workflow
the middleware reports it per unit with updateCondition.
The details of the operation are in Push condition data; this page shows
the workflow around it.
sequenceDiagram
participant BMS as BMS or service tool
participant MW as Middleware
participant BP as BatteryPass API
BMS->>MW: new measurements per serial number
MW->>MW: look up the BatteryPass id in its own mapping
alt serial not mapped yet
MW->>BP: listBatteries with serial_prefix (scope read)
BP-->>MW: the unit
end
MW->>BP: updateCondition with measured_at (scope condition)
BP-->>MW: accepted, skipped, publication
BP->>BP: condition_update event naming the key, re-publication by policy
Trigger: The BMS or the service tool has new measurements of a unit.
Key scopes: readcondition
| # | Who | What | Operation |
|---|---|---|---|
| 1 | Middleware | Collects the new measurements per unit with the time of measurement. | |
| 2 | Middleware | Finds the unit by its serial number (filter serial_prefix) and keeps the BatteryPass id in its own mapping table. | listBatteries read |
| 3 | Middleware | Reports the values with measured_at; older or equally old measurements are skipped, so a retry does no harm. | updateCondition condition |
| 4 | BatteryPass | Stores the accepted values as measurements (approved without a reviewer, ADR-016), records a condition_update lifecycle event that names the key, and re-publishes immediately or daily as the organisation has set it. |
Security
- A key of its own per BMS platform or service partner, with the scopes condition and read.
- On 429 the middleware waits the seconds of Retry-After, otherwise it retries with exponential backoff and jitter.
Data minimisation
- Only the unit's dynamic fields; no location data, no vehicle or owner data.
The key
One key per BMS platform or service partner, with the scopes condition (to report) and read (to find units).
Two keys, one per scope, work just as well. A condition key can report for every unit of your organisation, so
hand a key to a service partner only if you would let the partner do that.
Find the unit once
The middleware keeps a mapping table from serial number to the BatteryPass id. For a serial it does not know yet,
it asks listBatteries with serial_prefix and picks the unit
whose serial_number matches exactly (serial numbers are unique per model; add battery_model_id when two models
share a numbering scheme):
curl -sS "$BATTERYPASS_URL/api/v1/batteries?serial_prefix=SV2027-000184&limit=10" \
-H "Authorization: Bearer $BATTERYPASS_BMS_KEY" | jq '.items[] | select(.serial_number == "SV2027-000184") | .id'Report the measurements
curl -sS -X PATCH "$BATTERYPASS_URL/api/v1/batteries/0192a3f0-5b7c-7d21-8e4f-6a2b9c1d3e5f/condition" \
-H "Authorization: Bearer $BATTERYPASS_BMS_KEY" \
-H "Content-Type: application/json" \
-d '{"measured_at": "2026-10-24T06:00:00Z", "note": "BMS daily report",
"values": [{"field_key": "condition.capacity_fade", "value": 3.5},
{"field_key": "condition.number_of_full_cycles", "value": 412}]}'Because a measurement equal to or older than the stored one is skipped, sending the same reading again after a timeout changes nothing: this is what makes the retry above safe. Send measurements of one unit in the order they were taken.
What BatteryPass does with them
- Accepted values are stored as approved measurements without a reviewer (measured data has no review step) with
their
measured_at. - The update records a
condition_updatelifecycle event; that event names the key (api_key) and has the sourceapi. The values themselves do not carry the key. The audit log names the key as the actor. - A published passport is re-published as your organisation's setting says: at once (
publication.outcomeispublishedorunchanged) or by the daily job (scheduled).blockedmeans a required value is missing now; the passport isupdate_neededand a member must act.
What never flows
Only the unit's dynamic fields (registry section condition). No location or GPS data, no vehicle or owner data,
no operator names. A note is free text that ends up in the unit's history: fill it from a fixed template.
Failure handling
| Answer | Meaning | What to do |
|---|---|---|
400 validation_error | A field that is not a dynamic field of the unit (unknown_field), a value outside its range, a time in the future or before manufacture, or a failing cross-field check | Fix the reading; the whole update was refused. |
401 unauthenticated | Key missing, unknown or revoked | Check the secret; alert. |
403 forbidden | The key lacks the scope condition | Use the right key. |
404 not_found | The unit is not in your organisation | Refresh the mapping table. |
409 conflict | The unit's model is archived | Stop reporting for it. |
429 rate_limited | Too many requests | Wait Retry-After seconds; spread daily reports over time. |
5xx, timeout | Unknown outcome | Retry the same body with backoff; repeated measurements are skipped. |
Passport links back into the ERP
Follow the change feed with a read key and store each unit's GS1 Digital Link, passport status and QR code on its serial number record in the ERP.
Returns and repairs
Completed service, repair and return orders in the ERP become lifecycle events of the unit, without customer data and without duplicates.