Condition data and lifecycle events
How measured condition data reaches a passport without a review step, how the re-publication policy works, and what lifecycle events record.
A battery's passport does not stop at the factory. Two kinds of information follow it through its life:
condition data, the measured state of health and usage of a unit, and lifecycle events, the record of
what happened to it. Both can be reported through the API with a key that has the condition scope.
Condition data
Condition data are the registry's dynamic fields (the section condition, Annex XIII point 4): measured values
of one unit, such as condition.capacity_fade, condition.remaining_capacity,
condition.number_of_full_cycles or, for EV batteries, condition.state_of_certified_energy. Which fields apply
depends on the battery category; getCondition lists them in
field_keys, with their current values and measured_at.
In the current registry all condition fields are in the legitimate_interest tier, so they never appear in the
public JSON (Access tiers).
Measurements, not declarations
What a battery management system measured is not something a reviewer can verify better than the device. A condition update is therefore accepted as a measurement, without the review step that declared data needs:
- each value is stored directly as
approved, with itsmeasured_at, itssource(apifor a key,supplierfor a service partner's report,manualfor a member); a member is named inrecorded_by, a key in theapi_keyof the update's lifecycle event (values carry no key); reviewed_atis the time of acceptance, and there is no reviewer, so the four-eyes rule does not apply;- every accepted update records a
condition_updatelifecycle event and an audit entry.
Condition values that a member types into the unit editor or imports from a spreadsheet keep the normal review (Provenance and review).
Reporting an update
updateCondition merges the values you send into the
unit's condition data:
curl -s -X PATCH "$BATTERYPASS_URL/api/v1/batteries/$BATTERY_ID/condition" \
-H "Authorization: Bearer $BATTERYPASS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"measured_at": "2026-10-24T06:00:00Z",
"note": "Weekly BMS reading",
"values": [
{ "field_key": "condition.capacity_fade", "value": 3.2 },
{ "field_key": "condition.number_of_full_cycles", "value": 412 }
]
}'| Rule | Effect |
|---|---|
| Merge | Only the named fields change; null clears a field. At most 50 values per request. |
measured_at | Each value has its own or the request's. It must not lie in the future or before the unit's manufacturing date. |
| Older or equal measurement | A value measured before the stored one, or at the same time with the same value, is skipped and listed in skipped[] (older_measurement, unchanged). |
| All or nothing | A field that is not a dynamic field of the unit (unknown_field), an invalid value, or merged data that fails a cross-field check refuses the whole update. |
The response lists accepted values, skipped ones, the recorded event and the publication outcome.
Re-publication policy
When the unit's passport is published, accepted condition data has to reach a new passport version. The
organisation chooses when, in its settings in the portal (condition_republish, returned by getCondition as
republish):
| Policy | Behaviour |
|---|---|
immediate (default) | The same request publishes the next version, with the reason condition update and no member as publisher. |
daily | A daily job at 02:00 UTC publishes every published passport whose unit received condition data after its current version, so a day's updates become one version. |
publication.outcome in the response tells you what happened:
outcome | Meaning |
|---|---|
published | A new version was published in this request. |
unchanged | Nothing in the passport changed, so no version was added. |
scheduled | The daily job will publish it. |
blocked | The publish gate refused (see blockers); the update stays accepted and the passport becomes update_needed, still online. |
not_published | The unit has no published passport yet. |
Lifecycle events
A lifecycle event records something that happened to a unit on a given day. Report one with
createLifecycleEvent and read the history, newest
first, with listLifecycleEvents.
Type you can report (ReportedEventType) | Typical use |
|---|---|
placed_on_market | The battery was placed on the market |
put_into_service | The battery was put into service |
inspection | An inspection or diagnosis |
repair | A repair |
component_replaced | A module, cell or other component was replaced |
condition_update | A condition reading worth recording on its own |
waste | The battery became waste |
recycled | The battery was recycled |
custom | Anything else, described in description |
BatteryPass records two more kinds itself: condition_update for every accepted condition update, and
repurposed, reused or remanufactured when a member creates a second-life battery in the portal.
An event has occurred_on (a date between the manufacturing date and today), an optional description (up to
2000 characters) and up to 20 evidence_ids, documents that already exist in the evidence library such as a
repair protocol. Events reported with a key carry source api and name the key in api_key.
Events are records: they change no data of the unit. A put_into_service event does not set the unit's
putting_into_service date, and waste or recycled does not change its battery status or end its passport.
Report measured values with updateCondition; members change unit data in the portal. Events cannot be edited
or deleted afterwards.
Next steps
Provenance and review
Every value keeps its source, author, time and evidence and is superseded rather than overwritten; declared data is reviewed before it enters a passport, with a second person when the organisation's four-eyes rule is on.
GS1 Digital Link
The link on every QR code, and how the resolver sends browsers to the public page and machines to the public JSON.