# Battery models, versions and units

> How BatteryPass separates the product, its technical states and the individual batteries, and where each value lives.

BatteryPass keeps product data on three levels. Data that every battery of a product shares is maintained
once, on the model version; data that differs per battery lives on the unit. Each unit gets its own passport,
built from both levels when it is published.

```mermaid
flowchart LR
  M["Battery model: name, SKU, GTIN, category"] --> VA["Model version A: superseded"]
  M --> VB["Model version B: approved"]
  VA --> U1["Unit SN-000184"]
  VB --> U2["Unit SN-000417"]
  U2 --> P["Passport of SN-000417"]
```

## The three levels

| Level                          | What it is                                                        | Main fields                                                                                                   | Read with                                                                                                                                                                                                                                                                   |
| ------------------------------ | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Battery model (`BatteryModel`) | The commercial product                                            | `name`, `sku`, `gtin`, `category`, `archived_at`                                                              | [`listBatteryModels`](https://passport.kabin.sh/docs/en/api-reference/catalog/list-battery-models), [`getBatteryModel`](https://passport.kabin.sh/docs/en/api-reference/catalog/get-battery-model)                                                                      |
| Model version (`ModelVersion`) | One technical state of the model, for example after a cell change | `version_label`, `effective_from`, `status`, `unit_count`, `approved_at`, `registry_version`                  | [`listModelVersions`](https://passport.kabin.sh/docs/en/api-reference/catalog/list-model-versions), [`getModelVersion`](https://passport.kabin.sh/docs/en/api-reference/catalog/get-model-version)                                                                      |
| Unit (`Battery`)               | One physical battery with a serial number                         | `serial_number`, `model_version_id`, `manufacturing_date`, `facility_id`, `battery_status`, `passport_status` | [`listBatteries`](https://passport.kabin.sh/docs/en/api-reference/catalog/list-batteries), [`getBattery`](https://passport.kabin.sh/docs/en/api-reference/catalog/get-battery), [`exportUnits`](https://passport.kabin.sh/docs/en/api-reference/catalog/export-units) |

The `category` of a model (`ev`, `lmt`, `industrial`, `stationary`, `industrial_without_bms`) decides which
fields the registry requires for its batteries.

## Model version status

A model version has a start date, `effective_from`, and a status:

| `status`     | Meaning                                                                                                                 |
| ------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `draft`      | In preparation. Units on a draft version cannot be published.                                                           |
| `approved`   | The current technical state. A model has at most one approved version; a reviewer approves it in the portal.            |
| `superseded` | Replaced by a later approved version. It stays readable and keeps its units; their published passports are not changed. |

A version has no end date: it applies from its `effective_from` until a later version takes over. When a unit
is created in the portal or by the spreadsheet import without a named version, BatteryPass assigns the version
in force on the unit's manufacturing date: the one with the latest `effective_from` on or before that date,
preferring approved and superseded versions over drafts. Approving a new version moves no existing unit. Members move units to another version in the portal after a change-impact
preview, and a published passport of a moved unit becomes `update_needed`
([Passports](https://passport.kabin.sh/docs/en/concepts/passports)).

## Which values live where

The [field registry](https://passport.kabin.sh/docs/en/general/glossary) assigns every field a level. Read it with
[`getRegistrySchema`](https://passport.kabin.sh/docs/en/api-reference/registry/get-registry-schema): each field has `level` set to
`model` or `unit`.

| Level         | Typical fields                                                                                                                                                                                                                                                | Values                                                                                                         | Completeness                                                                                                             |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Model version | Manufacturer, mass, warranty, chemistry and composition, hazardous substances, carbon footprint, due diligence, circularity, performance ratings, labels and the declaration of conformity, e.g. `performance.nominal_voltage`, `materials.battery_chemistry` | [`listModelVersionValues`](https://passport.kabin.sh/docs/en/api-reference/values/list-model-version-values) | [`getModelVersionCompleteness`](https://passport.kabin.sh/docs/en/api-reference/values/get-model-version-completeness) |
| Unit          | Serial number, manufacturing date and place, battery status, date of putting into service, and the condition data, e.g. `identification.serial_number`, `condition.capacity_fade`                                                                             | [`listBatteryValues`](https://passport.kabin.sh/docs/en/api-reference/values/list-battery-values)            | [`getBatteryCompleteness`](https://passport.kabin.sh/docs/en/api-reference/values/get-battery-completeness)            |

A few registry fields are attributes of the model or unit itself rather than separate values: the product
name, SKU, GTIN and category of the model; the serial number, manufacturing date, facility, battery status and
date of putting into service of the unit. You read them on `BatteryModel` and `Battery`.

> [!NOTE]
> A unit's completeness response also carries the summary of its model version (`model_version`), so one call
> tells you whether either level still blocks publication.

## Identifiers

| Identifier                      | Where                | Rules                                                                                                                                        |
| ------------------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| GTIN                            | On the battery model | Accepted with 8, 12, 13 or 14 digits and stored as GTIN-14 with a valid check digit                                                          |
| Serial number                   | On the unit          | Letters, digits, `-`, `/` and `.`, at most 50 characters, unique per model                                                                   |
| GTIN and serial number together | The key of the unit  | Unique across all organisations; the [GS1 Digital Link](https://passport.kabin.sh/docs/en/concepts/digital-link) encodes exactly this pair |

Once the identifiers are locked (for label printing before publication, or at the first publication),
`identifiers_locked_at` is set and the serial number and the model's GTIN can no longer change.

Second life: a repurposed, reused or remanufactured battery is a new unit. It names the original in
`predecessor_battery_id` (the original lists it in `successor_battery_ids`) and gets its own passport.

## Reading the catalogue

List the versions of a model, then the units of one version:

```bash title="cURL"
curl -s "$BATTERYPASS_URL/api/v1/battery-models/$MODEL_ID/versions" \
  -H "Authorization: Bearer $BATTERYPASS_API_KEY"

curl -s "$BATTERYPASS_URL/api/v1/batteries?model_version_id=$VERSION_ID&limit=200" \
  -H "Authorization: Bearer $BATTERYPASS_API_KEY"
```

`listModelVersions` returns at most 200 versions, newest `effective_from` first, without a cursor.
`listBatteries` is ordered by serial number and paged with `limit` and `cursor`
([Pagination](https://passport.kabin.sh/docs/en/pagination)); it also filters by `battery_model_id`, `passport_status`,
`serial_prefix` and `import_id`.

> [!NOTE]
> The API reads the catalogue; it does not create or change it. Members create models, versions and units in
> the portal or with the spreadsheet import, and reviewers approve model versions.
