Handle API keys securely
Where keys belong, which scope each system gets, how to rotate without downtime and what to do when a key leaks.
An API key (bp_live_…) belongs to your organisation, not to a person. Whoever holds it reads what a viewer of
your organisation reads, including restricted passport data and exports, and with the scope condition reports
measurements and events in your organisation's name. Treat every key like a password. How keys work is described
in Authentication; the wider picture in
Security and data protection.
Owners create and revoke keys in the portal under Settings → API keys. There is no API for it, and a key's secret is shown only once, when it is created.
Rules
| Rule | Why |
|---|---|
| Keep keys in a secrets manager (or your platform's secret store) and hand them to the process as an environment variable | They stay out of code, images and backups |
| Never put a key into source code, a repository, a container image, a URL, a log line, a ticket or a chat | Each of these is copied, indexed or kept for years |
| Never ship a key to a browser, a mobile app or a device in the field | Anything on a client can be read; public passport reads need no key at all |
Send keys only in the Authorization: Bearer header, only over HTTPS | Headers do not end up in access logs and browser histories the way URLs do |
| One key per system | You can revoke one system without stopping the others, and the portal shows when each key was last used |
| The smallest scope that works | A leaked read key cannot report data; a leaked condition key cannot read your data |
Which scope for which system
| System | Scope |
|---|---|
| ERP or MES that copies units and passports | read |
| Data warehouse or reporting | read |
| Battery management system or gateway that sends measurements | condition |
| Service partner's system that reports inspections and repairs | condition |
| A tool that looks up condition fields before it sends | read and condition, or two separate keys |
| Middleware that stages units from production as an import | import (members commit and approve) |
A key is not limited to some models or units: a condition key you hand to a service partner can report for
every unit of your organisation. Hand it only to partners you would let do that.
Load the key at start
Read the key from the environment once, fail early when it is missing, and never print it:
# In a systemd unit, a CI secret or your orchestrator's secret store, not in a script under version control
export BATTERYPASS_API_KEY="$(cat /run/secrets/batterypass_api_key)"If your HTTP client or proxy logs requests, make sure it masks the Authorization header.
Rotate without downtime
Keys do not expire. Rotate them on a schedule you choose, and whenever someone who knew a key leaves. An organisation can have 25 active keys, so old and new key fit side by side during the switch.
Create the new key
An owner creates a key with the same scopes and a name that tells the two apart, for example
ERP sync 2026-10, and puts the secret straight into the secrets manager.
Deploy it
Point the system at the new secret and restart or reload it. Both keys work at the same time, so nothing fails in between.
Check that the new key is used
In Settings → API keys, the new key shows a recent Last used time and the old one stops changing. The time is updated at most once a minute.
Revoke the old key
Revoke the old key. Revocation is immediate and final; the key stays in the list as revoked.
When a key leaks
A key leaked when it appeared anywhere outside your secrets manager: a commit, a log, a screenshot, a support ticket, a former employee's notes.
Revoke it now
An owner revokes the key in Settings → API keys. From that moment every request with it is
401 unauthenticated. Do this first, before you know whether the key was misused.
Replace it
Create a new key with the same scopes and deploy it as in the rotation above. The system that used the old key is down until then, which is the price of revoking first.
Check what happened
Writes made with a key are recorded with the key as the actor: look at the portal's audit log and at lifecycle
events with source: api and the key's name in api_key. Reads are not recorded, so assume that everything the
key could read was read.
Remove the copy
Delete the key from where it leaked (rewrite the commit, purge the log, edit the ticket), even though it no longer works, so that scanners stop flagging it.
Find keys before others do
Secrets have a fixed shape: bp_live_ followed by 43 base64url characters (letters, digits, - and _). Add the pattern
bp_live_[A-Za-z0-9_-]{43} to your secret scanner and pre-commit hooks. The portal shows the first 12 characters
of each key, enough to match a finding to a key without exposing the secret.
All keys of your organisation share one limit of 600 requests per minute, so a leaked key that is still active can also slow down your legitimate integrations (Rate limits).