Skip to content

API reference

Battery health scores over HTTP.

Calibrated battery health scores over HTTP: SoH bands, degradation, residual, risk flags, drift monitoring. Authenticated with a bearer key, metered per tier, and errored in RFC7807 problem+json. This page renders from the committed OpenAPI document, so it stays in step with the live contract.

API
Ionscore API
Version
0.1.0
Surface
/v1
Media
application/json

Authentication

Bearer keys, sandbox and production.

An Ionscore API key presented as a bearer token: 'Authorization: Bearer <key>' (bk_ / bk_sbx_ prefixes). Present it on every call to a protected endpoint; the health check and model card need no key.

Present the key

http header
Authorization: Bearer bk_sbx_your_sandbox_key

A missing or unknown key returns 401 with a urn:ionscore:unauthorized body. Sandbox keys carry the bk_sbx_ prefix; production keys carry bk_.

Sandbox vs production

bk_sbx_Sandbox

Scores the built-in demo fleet. Pass a packId to score a seeded pack; no telemetry of your own required.

bk_Production

Scores your packs from inline telemetry (identity plus observations). A packId lookup is refused with 403 urn:ionscore:sandbox-only.

Getting a key. Keys are issued by the Ionscore team today, not self-serve: tell us the tenant and tier and we mint one with the admin CLI. There is no key dashboard yet.

Monthly quota tiers

A key carries a tier that caps billable scores per UTC month; crossing it returns 429 with a urn:ionscore:quota-exceeded body. Caps are published defaults and are operator-overridable per deployment. Drift is metered separately and never counts against this quota.

Monthly score quota by tier: key prefix, cap on billable scores per month, and use.
TierKey prefixScores / monthUse
sandboxbk_sbx_1,000Isolated demo tier; score the seeded fleet by packId.
pilotbk_10,000An evaluating customer scoring real telemetry.
productionbk_100,000A live customer in steady-state use.

Quickstart

Three calls against https://api.ionscore.dev: confirm the surface is live, score a demo pack in sandbox, then score your own telemetry in production.

Check the surface is live (public)

curl
curl https://api.ionscore.dev/v1/healthz

Score a demo pack with a sandbox key

curl
curl -X POST https://api.ionscore.dev/v1/score \
  -H "Authorization: Bearer bk_sbx_your_sandbox_key" \
  -H "Content-Type: application/json" \
  -d '{"packId":"ABCDE12345FGHIJ67890K"}'

Score your own telemetry in production

curl
curl -X POST https://api.ionscore.dev/v1/score \
  -H "Authorization: Bearer bk_your_production_key" \
  -H "Content-Type: application/json" \
  -d '{"identity":{"packId":"ABCDE12345FGHIJ67890K","chemistry":"NMC","segment":"4W","ratedCapacityKwh":40.0},"observations":[{"months":12,"equivalentFullCycles":180.0,"meanDod":0.6,"fastChargeFraction":0.3,"resistanceProxyOhm":0.02,"resistanceRatio":1.1,"coulombicEfficiency":0.99,"meanPackTempC":30.0}]}'

Errors: problem+json

Every failure is an RFC7807 document served as application/problem+json. The type is a stable urn:ionscore:* token you can branch on; each endpoint below lists the statuses it returns.

problem+json
{
  "type": "urn:ionscore:quota-exceeded",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "monthly score quota reached for this tier"
}

Clients and tools

Typed clients mirror the endpoints method for method; the raw spec and a Postman collection are in the repo.

Endpoints

The /v1 surface.

Four operations: two public reads and two authenticated scoring calls.

GET/v1/healthzPublic

Health check

Liveness and readiness for the /v1 surface. Public, so a probe never needs a key. Returns status ok while the process is up and ready true once the scoring model has loaded.

Example request

curl
curl https://api.ionscore.dev/v1/healthz
GET/v1/model-cardPublic

Model card

The published model card: training setup, held-out error, band coverage, and calibration. Public on purpose, so you can judge the model before you hold a key. The full card is returned under card.

Example request

curl
curl https://api.ionscore.dev/v1/model-card

Errors

Error responses: status, stable problem type token, title, and example detail.
StatusTypeTitleExample detail
503urn:ionscore:auth-backend-unavailableService Unavailablemodel card is not available in this deployment
POST/v1/scoreBearer required

Score a pack

Score one pack and return its state-of-health band, forward degradation, residual value, risk flags, and the derived decision lenses (a PackScore). A sandbox key may score a seeded demo pack by packId; a production key posts inline telemetry.

Request body

application/json - Send packId (a sandbox-only lookup against the seeded fleet) OR an inline identity plus its observation history.

PackIdentityIn

PackIdentityIn fields: name, type, whether required, constraints.
FieldTypeRequiredConstraints
chemistrystringrequired-
climateZonestringoptionaldefault "TEMPERATE"
packIdstringrequiredpattern ^[0-9A-Z]{21}$
ratedCapacityKwhnumberrequired> 0
regionstringoptionaldefault "Unknown"
segmentstringrequired-

ObservableRowIn

ObservableRowIn fields: name, type, whether required, constraints.
FieldTypeRequiredConstraints
coulombicEfficiencynumberrequired-
cumulativeChargeKwhnumberoptionaldefault 0
cumulativeDischargeKwhnumberoptionaldefault 0
cycleCountnumberoptionaldefault 0
equivalentFullCyclesnumberrequired-
fastChargeFractionnumberrequired-
hotHoursCumulativenumberoptionaldefault 0
meanDodnumberrequired-
meanPackTempCnumberrequired-
monthsintegerrequired>= 0
naiveSohProxynumberoptionaldefault 100
resistanceProxyOhmnumberrequired-
resistanceRationumberrequired-

Example request

curl
curl -X POST https://api.ionscore.dev/v1/score \
  -H "Authorization: Bearer bk_sbx_your_sandbox_key" \
  -H "Content-Type: application/json" \
  -d '{"packId":"ABCDE12345FGHIJ67890K"}'

Errors

Error responses: status, stable problem type token, title, and example detail.
StatusTypeTitleExample detail
401urn:ionscore:unauthorizedUnauthorizedmissing credentials: supply 'Authorization: Bearer <key>'
403urn:ionscore:sandbox-onlyForbiddenpackId scoring runs against the built-in demo fleet and is a sandbox-only affordance; a non-sandbox key must post inline telemetry
413urn:ionscore:payload-too-largePayload Too Largeobservations list exceeds the configured maximum
429urn:ionscore:quota-exceededToo Many Requestsmonthly score quota reached for this tier
503urn:ionscore:auth-backend-unavailableService Unavailableauth backend not configured
POST/v1/driftBearer required

Feature drift

A feature-drift report for a batch of inline packs, PSI-compared against the model's training distribution. Metered for monitoring only: it does not draw down the scores quota. Sandbox and production keys are both accepted.

Request body

application/json - A non-empty packs array; each pack is the same identity plus observations shown under Score a pack.

Example request

curl
curl -X POST https://api.ionscore.dev/v1/drift \
  -H "Authorization: Bearer bk_your_production_key" \
  -H "Content-Type: application/json" \
  -d '{"packs":[{"identity":{"packId":"ABCDE12345FGHIJ67890K","chemistry":"NMC","segment":"4W","ratedCapacityKwh":40.0},"observations":[{"months":12,"equivalentFullCycles":180.0,"meanDod":0.6,"fastChargeFraction":0.3,"resistanceProxyOhm":0.02,"resistanceRatio":1.1,"coulombicEfficiency":0.99,"meanPackTempC":30.0}]}]}'

Errors

Error responses: status, stable problem type token, title, and example detail.
StatusTypeTitleExample detail
401urn:ionscore:unauthorizedUnauthorizedmissing credentials: supply 'Authorization: Bearer <key>'
413urn:ionscore:payload-too-largePayload Too Largeobservations list exceeds the configured maximum
429urn:ionscore:rate-limitedToo Many Requestsburst rate limit exceeded; retry after the window resets
503urn:ionscore:auth-backend-unavailableService Unavailableauth backend not configured

Score your fleet.

A pilot gets you a key and scores a sample of your packs end to end, with the same published error discipline.

Request a pilot