# BatteryPass developer documentation > Integration API of BatteryPass for EU digital battery passports: read models, units, values, passports and exports with an organisation API key, follow changes, stage spreadsheet imports, report condition data and lifecycle events, and verify public passports. Every link leads to the Markdown version of a page. This index is in English; the German one is at https://passport.kabin.sh/docs/de/llms.txt. ## Get started - [Introduction](https://passport.kabin.sh/docs/en.md): What the BatteryPass integration API does, what stays in the portal, and where to start. - [Quickstart](https://passport.kabin.sh/docs/en/quickstart.md): Create an API key, make your first request and read a passport in a few minutes. - [Authentication](https://passport.kabin.sh/docs/en/authentication.md): Organisation API keys, their scopes, what a key may do and how to rotate it. - [Errors](https://passport.kabin.sh/docs/en/errors.md): How the API reports errors as RFC 9457 Problem Details with stable codes and a request id. - [Pagination](https://passport.kabin.sh/docs/en/pagination.md): Read long lists page by page with `limit` and an opaque `cursor`. - [Rate limits](https://passport.kabin.sh/docs/en/rate-limits.md): How many requests BatteryPass accepts, and how to back off after a 429. - [Retries and idempotency](https://passport.kabin.sh/docs/en/idempotency.md): Which requests you can safely repeat after a timeout, and how to avoid duplicate events. - [Stability and versioning](https://passport.kabin.sh/docs/en/versioning.md): What integrations can rely on, how the API changes and where to download the contract. - [Environments and base URL](https://passport.kabin.sh/docs/en/environments.md): Where your organisation's API lives, which addresses it serves and how to test safely. ## Get started: Concepts - [Battery models, versions and units](https://passport.kabin.sh/docs/en/concepts/battery-models.md): How BatteryPass separates the product, its technical states and the individual batteries, and where each value lives. - [Passports and versions](https://passport.kabin.sh/docs/en/concepts/passports.md): The passport of a unit, its statuses, its signed and immutable versions, the differences between them and the exports. - [Access tiers](https://passport.kabin.sh/docs/en/concepts/access-tiers.md): Which passport data is public, which is restricted, and how BatteryPass keeps restricted data out of public responses. - [Provenance and review](https://passport.kabin.sh/docs/en/concepts/provenance-and-review.md): 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. - [Condition data and lifecycle events](https://passport.kabin.sh/docs/en/concepts/condition-and-lifecycle.md): How measured condition data reaches a passport without a review step, how the re-publication policy works, and what lifecycle events record. - [GS1 Digital Link and resolver](https://passport.kabin.sh/docs/en/concepts/digital-link.md): The link on every QR code, and how the resolver sends browsers to the public page and machines to the public JSON. - [Signatures](https://passport.kabin.sh/docs/en/concepts/signatures.md): What BatteryPass signs in each passport version, how the hash and the Ed25519 signature are computed, and how to check them with the published keys. ## Get started: General - [Security and data protection](https://passport.kabin.sh/docs/en/general/security.md): How BatteryPass protects API access and passport data, and what your integration should do and avoid. - [Support](https://passport.kabin.sh/docs/en/general/support.md): How to get help with an integration, what to include in a request, and where the status of features is documented. - [Glossary](https://passport.kabin.sh/docs/en/general/glossary.md): The domain and API terms used in this documentation, in English and German. ## Guides - [Guides](https://passport.kabin.sh/docs/en/guides.md): Task-oriented walkthroughs for the jobs an integration does most, with requests, responses and the errors that matter. - [Verify a passport signature offline](https://passport.kabin.sh/docs/en/guides/verify-signature.md): Check with the public JSON and the published keys alone that the public data of a passport is exactly what its BatteryPass instance signed. - [Push condition data from a battery management system](https://passport.kabin.sh/docs/en/guides/push-condition-data.md): Report measured values such as state of charge or full cycles with updateCondition, and read what was accepted, skipped and re-published. - [Record lifecycle events](https://passport.kabin.sh/docs/en/guides/record-lifecycle-events.md): Report inspections, repairs and other events in the life of a unit with createLifecycleEvent, and read the lifecycle with listLifecycleEvents. - [Export passports](https://passport.kabin.sh/docs/en/guides/export-passports.md): Download the BatteryPass JSON, the PDF and the QR code of a passport version, and the units of your organisation as a spreadsheet. - [Sync units into your system](https://passport.kabin.sh/docs/en/guides/sync-units.md): Copy the units of your organisation into an ERP, MES or database with cursor paging, resume after an interruption and detect what changed. - [Handle errors and retries](https://passport.kabin.sh/docs/en/guides/handle-errors.md): Decide which answers to retry and which to fix, back off with jitter, honour Retry-After and log the request_id. - [Resolve a QR code or GS1 Digital Link](https://passport.kabin.sh/docs/en/guides/resolve-digital-link.md): From a scanned GS1 Digital Link to the public passport JSON, through the resolver or by GTIN and serial number. - [Handle API keys securely](https://passport.kabin.sh/docs/en/guides/secure-key-handling.md): Where keys belong, which scope each system gets, how to rotate without downtime and what to do when a key leaks. - [Connect AI tools with MCP](https://passport.kabin.sh/docs/en/guides/mcp.md): Use the BatteryPass integration API from Claude Code, Cursor, VS Code and other MCP clients with an organisation API key. ## Recipes - [Recipes](https://passport.kabin.sh/docs/en/recipes.md): Short, runnable programs for common integration jobs, each in cURL, TypeScript, Python and Go. - [Nightly condition push](https://passport.kabin.sh/docs/en/recipes/nightly-condition-push.md): A scheduled job that reads last night's measurements from your own source and sends one updateCondition per unit, with backoff on 429. - [QR labels for a production batch](https://passport.kabin.sh/docs/en/recipes/qr-labels-for-a-batch.md): List the published units of a batch by serial number prefix and save the QR code of each one as an SVG file for label printing. - [Data warehouse sync](https://passport.kabin.sh/docs/en/recipes/data-warehouse-sync.md): Page through all units and their current values and write one JSON line per unit, ready to load into a data warehouse. - [Verify signatures of several passports](https://passport.kabin.sh/docs/en/recipes/verify-signatures.md): Check the Ed25519 signatures of a list of public passports offline, loading the key set once, and print one result per passport. - [Published passports of a model](https://passport.kabin.sh/docs/en/recipes/published-passports-of-a-model.md): List every unit of a battery model with a published passport and print passport id, current version and public link as CSV. ## Integrations - [Connecting your ERP securely](https://passport.kabin.sh/docs/en/integrations.md): How an ERP, its middleware and BatteryPass work together, who does what, and what never leaves your systems. - [The security model of an ERP integration](https://passport.kabin.sh/docs/en/integrations/security.md): Keys and scopes, secrets and rotation, transport, safe retries, the outbox, thin events, stale writes, data minimisation, the audit trail and the OWASP API Top 10. - [iPaaS and middleware](https://passport.kabin.sh/docs/en/integrations/ipaas.md): Call the BatteryPass API from n8n, Make, Power Automate, MuleSoft, Boomi, Workato, Zapier and SAP Integration Suite with a key from the platform's secret store, and poll the change feed. - [How BatteryPass relates to battery passport standards](https://passport.kabin.sh/docs/en/integrations/standards.md): DIN DKE SPEC 99100, the IDTA Digital Battery Passport submodels, Catena-X CX-0160 and the BatteryPass data model, and what BatteryPass maps today and what it does not. ## Integrations: Workflows - [Units from production](https://passport.kabin.sh/docs/en/integrations/workflows/units-from-production.md): Stage the serial numbers of finished batteries as an import with a key of scope import; members review, commit, approve and publish in the portal. - [Passport links back into the ERP](https://passport.kabin.sh/docs/en/integrations/workflows/passport-links-to-erp.md): 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. - [Condition data from BMS and service](https://passport.kabin.sh/docs/en/integrations/workflows/condition-from-bms.md): 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. - [Returns and repairs as lifecycle events](https://passport.kabin.sh/docs/en/integrations/workflows/returns-and-repairs.md): Completed service, repair and return orders in the ERP become lifecycle events of the unit, without customer data and without duplicates. - [Product change leads to a new model version](https://passport.kabin.sh/docs/en/integrations/workflows/product-change.md): A change to the product master in the ERP notifies the person responsible, who creates a new model version in BatteryPass; declared data is never written automatically. ## Integrations: ERP systems - [abas ERP](https://passport.kabin.sh/docs/en/integrations/erp/abas-erp.md): What is known about connecting abas ERP to BatteryPass, and what still has to be clarified. - [Microsoft Dynamics 365 Business Central](https://passport.kabin.sh/docs/en/integrations/erp/dynamics-365-business-central.md): How Business Central hands serial numbers to BatteryPass through its API and a custom API page. - [Microsoft Dynamics 365 Finance and Supply Chain Management](https://passport.kabin.sh/docs/en/integrations/erp/dynamics-365-finance-operations.md): How Dynamics 365 Finance and Supply Chain Management works with BatteryPass through data entities and business events. - [Microsoft Dynamics NAV 2018](https://passport.kabin.sh/docs/en/integrations/erp/dynamics-nav-2018.md): How Dynamics NAV 2018 can supply serial numbers until an upgrade, and why new integrations target Business Central. - [Epicor Kinetic](https://passport.kabin.sh/docs/en/integrations/erp/epicor-kinetic.md): How Epicor Kinetic could supply serial numbers to BatteryPass through REST API v2. - [IFS Cloud](https://passport.kabin.sh/docs/en/integrations/erp/ifs-cloud.md): How IFS Cloud could supply serial numbers to BatteryPass through its OData projections. - [Infor CloudSuite (M3, LN)](https://passport.kabin.sh/docs/en/integrations/erp/infor-cloudsuite.md): How Infor M3 and Infor LN reach BatteryPass through the ION API Gateway. - [Odoo](https://passport.kabin.sh/docs/en/integrations/erp/odoo.md): How Odoo 19 hands lots and serial numbers to BatteryPass through the JSON-2 API. - [Oracle Fusion Cloud Supply Chain Management](https://passport.kabin.sh/docs/en/integrations/erp/oracle-fusion-scm.md): How Oracle Fusion Cloud SCM provides work order serial numbers to BatteryPass through its REST API and Oracle Integration. - [Oracle NetSuite](https://passport.kabin.sh/docs/en/integrations/erp/oracle-netsuite.md): How Oracle NetSuite hands inventory numbers to BatteryPass through SuiteTalk REST and SuiteQL. - [proALPHA ERP](https://passport.kabin.sh/docs/en/integrations/erp/proalpha.md): Connecting proALPHA to BatteryPass with a file export until an interface is confirmed. - [Sage X3](https://passport.kabin.sh/docs/en/integrations/erp/sage-x3.md): What is known about connecting Sage X3 to BatteryPass, and what still has to be clarified. - [SAP Business One](https://passport.kabin.sh/docs/en/integrations/erp/sap-business-one.md): How SAP Business One feeds serial numbers to BatteryPass through the Service Layer. - [SAP S/4HANA Cloud Public Edition](https://passport.kabin.sh/docs/en/integrations/erp/sap-s4hana-cloud.md): How SAP S/4HANA Cloud Public Edition hands serial numbers to BatteryPass and takes passport links back. - [SAP S/4HANA (on-premise and Private Edition)](https://passport.kabin.sh/docs/en/integrations/erp/sap-s4hana-on-premise.md): How an on-premise SAP S/4HANA or a Private Edition hands serial numbers to BatteryPass. - [weclapp](https://passport.kabin.sh/docs/en/integrations/erp/weclapp.md): How weclapp hands articles and serial numbers to BatteryPass through its REST API. - [Xentral](https://passport.kabin.sh/docs/en/integrations/erp/xentral.md): How Xentral hands products and deliveries to BatteryPass through its REST API and webhooks. ## API reference - [API reference](https://passport.kabin.sh/docs/en/api-reference.md): Every operation of the published contract, with a playground and code samples. ## API reference: Catalog - [The units as a spreadsheet with the import's columns](https://passport.kabin.sh/docs/en/api-reference/catalog/export-units.md): Any member. The units matching the filters (at most 10 000) with the columns of an import: model, version, the unit's fields and every unit-level field with a value, so the file can be edited and imported again (`docs/architecture.md` §7). XLSX by default. - [A battery model](https://passport.kabin.sh/docs/en/api-reference/catalog/get-battery-model.md): Any member. - [A unit](https://passport.kabin.sh/docs/en/api-reference/catalog/get-battery.md): Any member. - [A model version](https://passport.kabin.sh/docs/en/api-reference/catalog/get-model-version.md): Any member. - [Units (individual batteries) of the active organisation](https://passport.kabin.sh/docs/en/api-reference/catalog/list-batteries.md): Any member. Ordered by serial number, then id; filter by model, version, passport status, serial number prefix or the import that created the units. - [List the battery models of the active organisation](https://passport.kabin.sh/docs/en/api-reference/catalog/list-battery-models.md): Any member. Ordered by name, then id. Archived models only with `include_archived=true`. - [Versions of a battery model, newest effective date first](https://passport.kabin.sh/docs/en/api-reference/catalog/list-model-versions.md): Any member. At most 200. ## API reference: Values - [Registry evaluation of the unit-level fields](https://passport.kabin.sh/docs/en/api-reference/values/get-battery-completeness.md): Any member. Evaluated against the category, the unit's putting-into-service date (else its manufacturing date, else the version's effective date) and the organisation's facts; includes the summary of its model version. - [Registry evaluation of the model-level fields](https://passport.kabin.sh/docs/en/api-reference/values/get-model-version-completeness.md): Any member. Evaluated against the category, the version's effective date and the organisation's facts. - [All revisions of one unit-level value, newest first](https://passport.kabin.sh/docs/en/api-reference/values/list-battery-value-history.md): Any member. - [Current unit-level values of a unit](https://passport.kabin.sh/docs/en/api-reference/values/list-battery-values.md): Any member. One entry per field that has (or had) a value; `value` is null when it was cleared. - [All revisions of one model-level value, newest first](https://passport.kabin.sh/docs/en/api-reference/values/list-model-version-value-history.md): Any member. - [Current model-level values of a version](https://passport.kabin.sh/docs/en/api-reference/values/list-model-version-values.md): Any member. One entry per field that has (or had) a value; `value` is null when it was cleared. ## API reference: Evidence - [Download the file](https://passport.kabin.sh/docs/en/api-reference/evidence/download-evidence.md): Documents of the tiers `public` and `legitimate_interest` can be downloaded by any member; `authority` and `internal` documents by editors and above. Always sent as an attachment. - [One document with its revisions and where it is used](https://passport.kabin.sh/docs/en/api-reference/evidence/get-evidence.md): Any member. - [The evidence library, newest first](https://passport.kabin.sh/docs/en/api-reference/evidence/list-evidence.md): Any member. Superseded revisions are left out unless `include_superseded=true`. ## API reference: Passports - [The BatteryPass v2.0 export of a version (all tiers)](https://passport.kabin.sh/docs/en/api-reference/passports/export-passport-json.md): Any member. The stored export, including restricted data; sent as an attachment. Its schema report is in `getPassportVersion` (advisory, ADR-012). - [A PDF of a version with every tier, restricted rows tagged, the signature and the QR code](https://passport.kabin.sh/docs/en/api-reference/passports/export-passport-pdf.md): Any member. - [The QR code of the unit's GS1 Digital Link](https://passport.kabin.sh/docs/en/api-reference/passports/get-passport-qr.md): Any member. Rendered on demand from `gs1_digital_link` (error correction M, quiet zone of four modules). Only once the identifiers are locked (`409 conflict` before). - [What changed from an earlier version to this one](https://passport.kabin.sh/docs/en/api-reference/passports/get-passport-version-diff.md): Any member. Compares the signed snapshots field by field; `against` defaults to the previous version. - [One published version with its signed snapshot and validation report](https://passport.kabin.sh/docs/en/api-reference/passports/get-passport-version.md): Any member. - [The passport of a unit](https://passport.kabin.sh/docs/en/api-reference/passports/get-passport.md): Any member. A unit whose identifiers are not locked and that was never published has a passport in status `draft` without `passport_id`. - [The passport's registration with the EU registry](https://passport.kabin.sh/docs/en/api-reference/passports/get-registry-submission-status.md): Any member. The EU digital product passport registry has no interface for economic operators yet (`docs/regulatory-reference.md`), so the registration is `not_available` and nothing is submitted. A passport is never shown as registered without the registry's confirmation. - [The published versions of a unit's passport, newest first](https://passport.kabin.sh/docs/en/api-reference/passports/list-passport-versions.md): Any member. With `at`, only versions published at or before that instant: the first item is the version that was valid then (history by date for the portal, with every tier). ## API reference: Lifecycle - [Record an event in the life of a unit](https://passport.kabin.sh/docs/en/api-reference/lifecycle/create-lifecycle-event.md): Editor and above, or an API key with the `condition` scope (source `api`, ADR-017). `occurred_on` lies between the manufacturing date and today. `evidence_ids` name documents of the evidence library (a diagnostic report, a repair protocol). Events are records: they do not change the unit's data; condition values are reported with `updateCondition`, second life with `createSecondLifeBattery`. - [The condition data of a unit (the registry's dynamic fields)](https://passport.kabin.sh/docs/en/api-reference/lifecycle/get-condition.md): Any member. The dynamic fields visible for the unit and their current values with `measured_at`. - [The lifecycle of a unit, newest first](https://passport.kabin.sh/docs/en/api-reference/lifecycle/list-lifecycle-events.md): Any member. Events recorded by members, service-partner reports, condition updates and second life. - [Report measured condition data (merge)](https://passport.kabin.sh/docs/en/api-reference/lifecycle/update-condition.md): Editor and above, or an API key with the `condition` scope (source `api`, ADR-016, ADR-017). Merge semantics: only the named fields change, `null` clears a field. Each value has a `measured_at` (its own or the request's), which must not lie in the future or before the manufacturing date. Fields that are not dynamic fields of the unit are refused (`unknown_field`); so is the whole update when a value is invalid or the merged condition data fails a cross-field check. A value older than the stored one, or equal to it, is skipped and listed. Accepted values are stored as approved measurements and recorded as a `condition_update` lifecycle event; a published passport is re-published as the organisation's `condition_republish` setting says (immediately in this request, or by the daily job). ## API reference: Registry - [Version, content hash and status of the field registry in use](https://passport.kabin.sh/docs/en/api-reference/registry/get-registry-info.md): Any signed-in user. - [The editor schema of a battery category](https://passport.kabin.sh/docs/en/api-reference/registry/get-registry-schema.md): Any signed-in user. Sections and fields with bilingual labels, help, tier, the requirement rule for the category (before dates, conditions and values are applied; per-target status comes from the completeness operations), validation schema and export paths. - [The registry in use and how many of the organisation's passports need an update](https://passport.kabin.sh/docs/en/api-reference/registry/get-registry-status.md): Any member. After a new registry version is deployed, a job re-evaluates the organisation's published passports; passports with a newly missing required value become `update_needed` (they stay online) and their versions get an `update_passports` task. ## API reference: Facilities - [Manufacturing facilities of the active organisation](https://passport.kabin.sh/docs/en/api-reference/facilities/list-facilities.md): Any member. Ordered by name, then id. ## API reference: Public - [A public document of a public passport](https://passport.kabin.sh/docs/en/api-reference/public/download-public-passport-document.md): No authentication. Only documents of the `public` tier that a public field of a published version names (for example the EU declaration of conformity); everything else is `404`. - [The public passport of a unit, looked up by GTIN and serial number](https://passport.kabin.sh/docs/en/api-reference/public/get-public-passport-by-product-id.md): No authentication. Same response as `getPublicPassport`. - [The public passport as it was at a point in time](https://passport.kabin.sh/docs/en/api-reference/public/get-public-passport-version.md): No authentication. The version with `published_at ≤ at < valid_until`; `404` before the first publication. Versions are immutable, so the response is cached for a day. - [The public passport (current version)](https://passport.kabin.sh/docs/en/api-reference/public/get-public-passport.md): No authentication. Only the `public` tier, as stored when the version was published (ADR-013). Passports that are not public (`qr_locked`, `withdrawn`, `suspended`, `deleted_recycled`) answer with their status and no content. Cached for 5 minutes; rate-limited per client address. - [Check the signatures of a version on the server](https://passport.kabin.sh/docs/en/api-reference/public/verify-passport.md): No authentication. A convenience: the same check works offline with the public JSON and `/.well-known/batterypass/keys.json` (ADR-004, ADR-013). Without `version_no`, the current version. ## API reference: Changes - [The organisation's changes, oldest first, for polling](https://passport.kabin.sh/docs/en/api-reference/changes/list-changes.md): Any member, or an API key with the `read` scope (ADR-026). The organisation's changes in the order they became visible, oldest first, as `{id, occurred_at, entity_type, entity_id, action}`: no values, no actors, no personal data; read the entity for its current state. Keep `next_cursor` of the last page and ask again later: a change appears only once every transaction that started before it has finished, so a cursor never skips a change that commits late. `next_cursor` is set whenever the page has items, also on the last page; an empty page keeps the cursor you sent (`next_cursor` null). Without `cursor` the feed starts at the beginning of the organisation's history. ## API reference: Imports - [Upload a spreadsheet of units](https://passport.kabin.sh/docs/en/api-reference/imports/create-import.md): Editor and above, or an API key with the `import` scope (ADR-026). A CSV (UTF-8, UTF-16 or Windows-1252; `;`, `,`, tab or `|` separated) or XLSX file of at most 10 MB, 10 000 rows and 200 columns; the first non-empty row holds the headers. The answer is the import with a mapping proposed from the headers (registry CSV headers, aliases, labels; units such as `(kWh)` are converted), or taken from the import preset named in `preset` (the ERP registry): a preset maps the columns it knows by their headers and leaves the others unmapped. A key stages the import only: members of the organisation commit it and approve its values in the portal, so declared data still enters through a member's decision. - [One import with its mapping and summary](https://passport.kabin.sh/docs/en/api-reference/imports/get-import.md): Any member, or an API key with the `import` scope (ADR-026). Poll it after `validateImport`: the status becomes `validated` (or `failed`) and `summary` counts valid, warning, error and duplicate rows. - [Imports of the active organisation, newest first](https://passport.kabin.sh/docs/en/api-reference/imports/list-imports.md): Any member, or an API key with the `import` scope (ADR-026). An import staged with a key names the key in `created_by_api_key` instead of `created_by`. - [Map the columns of an import](https://passport.kabin.sh/docs/en/api-reference/imports/update-import-mapping.md): Editor and above, or an API key with the `import` scope (ADR-026), while the import is not being processed or committed. Each target at most once; `unit` is the unit a column's numbers are written in when it differs from the field's. With `preset` (an import preset of the ERP registry) the mapping is taken from the preset by the file's headers and `mapping` must be empty. A validated import must be validated again. - [Start validating every row of an import](https://passport.kabin.sh/docs/en/api-reference/imports/validate-import.md): Editor and above, or an API key with the `import` scope (ADR-026). A job reads every row with the mapping, validates it with the editor's validators and finds duplicate serial numbers in the file and in the database (after removing surrounding spaces and invisible characters). Requires a serial number column and a model column or `options.battery_model_id`. Follow the import with `getImport` until its status is `validated` or `failed`. ## Optional - [Changelog](https://passport.kabin.sh/docs/en/changelog.md): What changed in the integration API and in this documentation. - [OpenAPI (JSON)](https://passport.kabin.sh/docs/openapi.json): The published OpenAPI contract - [OpenAPI (YAML)](https://passport.kabin.sh/docs/openapi.yaml): The published OpenAPI contract