Before you start
You need an approved retailer organisation and an API key from API keys. Copy the secret when it is shown, because it is shown only once. Your access to an installation also requires that its ICP is on Orion's Halswell Flex list, the registry shows your trader as the current retailer, and the customer has explicitly authorised your organisation.
1. Authenticate
Send your key in the Authorization header on every request. Keys begin with aer_. Never put keys in URLs or logs. Customer login tokens and user API keys are not accepted.
export AOTEA_API_ORIGIN='https://<confirmed-api-host>'
export AOTEA_RETAILER_API_KEY='<your-retailer-key>'
curl --fail-with-body \
-H "Authorization: Bearer $AOTEA_RETAILER_API_KEY" \
"$AOTEA_API_ORIGIN/api/v1.0.1/retailers/me"2. Discover batteries
curl --fail-with-body \
-H "Authorization: Bearer $AOTEA_RETAILER_API_KEY" \
"$AOTEA_API_ORIGIN/api/v1.0.1/retailers/installations"[
{
"installation_id": "11111111-1111-4111-8111-111111111111",
"icp": "<authorised-icp>",
"batteries": ["22222222-2222-4222-8222-222222222222"],
"control_authorised": true
}
]An empty list means no installation currently meets every access check. control_authorised describes the customer's grant; it does not mean dispatch is commissioned.
3. Read telemetry
export AOTEA_BATTERY_ID='<battery-id-from-installations>'
curl --fail-with-body \
-H "Authorization: Bearer $AOTEA_RETAILER_API_KEY" \
"$AOTEA_API_ORIGIN/api/v1.0.1/retailers/batteries/$AOTEA_BATTERY_ID/telemetry"{
"battery_id": "22222222-2222-4222-8222-222222222222",
"observed_at": "2026-10-12T01:00:00Z",
"operating_state": "charging",
"state_of_charge_percent": 60.0,
"real_power_import_export_kw": 2.5,
"battery_available_capacity_kwh": 4.5
}- operating_state
- charging, discharging, idle or unavailable
- state_of_charge_percent
- State of charge from 0 to 100; null if unknown
- real_power_import_export_kw
- Real grid power in kW; positive import, negative export
- battery_available_capacity_kwh
- Estimated remaining DC energy above reserve, adjusted for state of health
- observed_at
- Latest sample timestamp (UTC), retained even if the sample is stale
Stale samples return unavailable with null measurements. Never treat a null as zero or use it for dispatch. Poll at a frequency agreed with Aotea; on HTTP 429 honour Retry-After and back off.
4. Control (not yet available)
The control contract is published for review. Today a valid request returns 501 control_not_commissioned and no command is sent. Do not automatically retry control requests.
Errors
Errors return JSON with code and message. Key retries off the HTTP status, not the body.
| HTTP | Meaning | Action |
|---|---|---|
| 400 | Invalid UUID, JSON, mode or power limit | Correct the request |
| 401 | Missing, invalid, expired or revoked retailer key | Check the credential or rotate it |
| 403 | Key lacks the requested permission | Ask your organisation administrator |
| 404 | Battery absent or access not authorised | Refresh the installation list |
| 409 | Telemetry or device limits unavailable for control | Wait for fresh device reports |
| 429 | Trader or overall IP quota exceeded | Honour Retry-After and back off |
| 501 | Retailer dispatch not commissioned. No command was sent | Await availability |
| 503 | API disabled, policy unavailable or registry stale | Retry reads later; contact Aotea if persistent |
Reference
The machine-readable contract is the retailer OpenAPI schema. It contains only retailer operations. Questions: support@aoteaenergy.com.