aranet-cloud
Async Python client for the Aranet Cloud REST API.
Wraps the public Aranet Cloud OpenAPI 3.0 spec — 25 of its 27 read-only
GET endpoints (all but the two attachment-metadata endpoints) — and
returns typed dataclass models. Designed primarily as the backing library
for the
aranet-cloud-homeassistant
HACS integration, but usable as a standalone Python client.
Status: Alpha (0.2.x). The OpenAPI mapping is stable; the public Python surface may still evolve as the HA integration drives requirements. Pin to a minor version in production.
Install
pip install aranet-cloud
Python 3.11+ required. Single runtime dependency: aiohttp.
Quick start
import asyncio
from aranet_cloud import AranetCloudClient
async def main() -> None:
async with AranetCloudClient(api_key="...") as client:
# List every sensor on your account
sensors = await client.get_sensors()
for s in sensors:
print(f" {s.serial} {s.name:<30s} type={s.type}")
# Latest reading per (sensor × metric), with name resolution
readings, links = await client.get_measurements_last()
for r in readings:
metric = links.name("metric", r.metric) or r.metric
unit = links.name("unit", r.unit) or r.unit
print(f" {r.sensor:>10s} {metric:>22s}: {r.value} {unit}")
asyncio.run(main())
Output against a typical home/garden account:
A0005 Bedroom type=S4V1
A0001 Kitchen type=S4V1
...
4000005 Temperature: 72.5 °F
4000005 Humidity: 30 %
4000005 CO₂: 757 ppm
4000005 Atmospheric Pressure: 697.9 mmHg
...
Authentication
The Aranet Cloud API uses a single header — ApiKey: <your-key>. No
OAuth, no token refresh. Generate a key from your Aranet Cloud dashboard
under Account → API.
AranetCloudClient(api_key="vku...")
What's covered
25 of the 27 GET endpoints in the public OpenAPI spec (all but the two attachment-metadata endpoints — the file/thumbnail downloads are wrapped):
| Domain | Methods |
|---|---|
| Sensors | get_sensors, get_sensor, get_sensor_types, get_sensor_type |
| Measurements | get_measurements_last, iter_measurements_history (paginated) |
| Telemetry | get_telemetry_last, iter_telemetry_history (paginated) |
| Bases | get_bases, get_base |
| Alarms | get_alarms_actual, get_alarms_history, get_alarm_rules, get_alarm_rule |
| Assets | get_assets, get_asset |
| Tags | get_tags, get_tag |
| Catalog | get_metrics, get_metric, get_unit |
| Attachments | download_sensor_attachment, download_asset_attachment |
See docs/architecture.md for the full API
reference, edge cases discovered during live probing, and design notes.
Pagination
History endpoints are paginated by the server. The library hides the mechanics via async iterators:
async for reading in client.iter_measurements_history(sensor="4000005", hours=24):
print(reading.time, reading.value)
The iterator follows the next token transparently until the server
returns no more data. Mind the time windows — /measurements/history
without a sensor filter caps at 7 days; with a sensor filter it caps at
6 months.
Exception hierarchy
AranetError ← base; catch this for a blanket handler
├── AranetConnectionError ← network, timeout, TLS, DNS
├── AranetAuthError ← 401 (key wrong/missing/revoked) - NOT transient
├── AranetValidationError ← 400 (carries correlation_id from API)
├── AranetRateLimitError ← 429 (with retry_after if present)
├── AranetServerError ← 5xx after exhausted retries
└── AranetNotFoundError ← 404 (rare; API often returns 200 {} instead)
Auth errors deserve special handling — the Aranet API returns 401 as
plain text (not JSON), so AranetAuthError doesn't carry a
correlation ID. Validation errors are JSON with error[].id correlation
tokens, preserved on AranetValidationError.correlation_id for support
escalations.
Design
- Async-first (
aiohttp). Use as an async context manager (auto session) or inject an existingClientSession— the HA-friendly pattern. - Typed: every response shape modelled as a dataclass with
from_dictthat ignores unknown fields, forward-compatible with new server fields. - Pagination hidden:
iter_*_history()async generators follownexttokens transparently. - Retry/backoff on 5xx, 429, and transient network failures.
Exponential backoff
1s, 2s, 4s, …capped at 30 s; 3 retries by default (so 1s, 2s, 4s). A serverRetry-Afteron 429 is honoured — also clamped to the 30 s cap, so a hostile/misconfigured value can't stall the caller. - Polite-spacing floor (250 ms) between successive requests. The Aranet API has no documented rate limit, but we don't hammer.
- Never logs the API key. Debug logs cover request method, path, status, and body size; the key is in headers only.
Standalone usage outside Home Assistant
The library has no HA dependencies and is fine to use in standalone Python scripts, FastAPI services, data-ingestion pipelines, etc.:
async with AranetCloudClient(api_key="...") as client:
# Pull 24 hours of CO₂ readings for a single sensor
readings = [
r async for r in client.iter_measurements_history(
sensor="4000005", metric="3", hours=24,
)
]
print(f"got {len(readings)} CO₂ samples")
Development
git clone https://github.com/jasonjhofmann/aranet-cloud
cd aranet-cloud
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest # 50 tests
ruff check . # lint
mypy src # type-check (strict)
uv build # build wheel + sdist (what CI publishes)
License
Apache 2.0
Release files for aranet-cloud 0.2.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aranet_cloud-0.2.3.tar.gz | 60.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aranet_cloud-0.2.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 88.8 kB
Release files / aranet_cloud-0.2.3.tar.gz
| Download URL | aranet_cloud-0.2.3.tar.gz |
|---|---|
| Size | 60.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
886447d3fe17c1b86db8e46e47f8b05c5a779c931662a8eaf975f7c0b33bf8c5
|
|
BLAKE2b-256 checksum How to use checksums |
1c8f32490625125afdcacfe7ee702dd7a64c7439a3374870e1dfc0c6340ee57c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency logRelease files / aranet_cloud-0.2.3-py3-none-any.whl
| Download URL | aranet_cloud-0.2.3-py3-none-any.whl |
|---|---|
| Size | 28.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
20435a940846cfb9c45d626205ee413afa85b8b559823c7103d8ca1b67ed7fc4
|
|
BLAKE2b-256 checksum How to use checksums |
7cab1ede64028b746f981428d76eb1e8c8d0bccdc491863ee4e1670b39d12696
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency log