Async Python client for the Aranet Cloud REST API
Project description
aranet-cloud
Async Python client for the Aranet Cloud REST API.
Wraps every endpoint in the public Aranet Cloud OpenAPI 3.0 spec — 27
read-only GET 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: Pre-release (0.1.x). The OpenAPI mapping is stable; the public Python surface may 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
All 27 GET endpoints in the public OpenAPI spec:
| 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, 8s)capped at 30 s; max 3 retries by default. - 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 # 23 tests, ~0.7s
ruff check . # lint
mypy src # type-check (strict)
python -m build # build wheel + sdist
License
Apache 2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aranet_cloud-0.2.1.tar.gz.
File metadata
- Download URL: aranet_cloud-0.2.1.tar.gz
- Upload date:
- Size: 50.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40da97318c0a85685b8c3306a51b0ad2006ad356c40655364cbabdffa2d25c36
|
|
| MD5 |
45b5ccc99f436afa55bcfabea76ef197
|
|
| BLAKE2b-256 |
fe425aee149cc6e58402022a797f160715f3a2c37a5332b20eb8d226568cafd2
|
Provenance
The following attestation bundles were made for aranet_cloud-0.2.1.tar.gz:
Publisher:
publish.yml on jasonjhofmann/aranet-cloud
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aranet_cloud-0.2.1.tar.gz -
Subject digest:
40da97318c0a85685b8c3306a51b0ad2006ad356c40655364cbabdffa2d25c36 - Sigstore transparency entry: 1787393884
- Sigstore integration time:
-
Permalink:
jasonjhofmann/aranet-cloud@b96fcbf97d7672cd3daa1aedc320632c1069103e -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/jasonjhofmann
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b96fcbf97d7672cd3daa1aedc320632c1069103e -
Trigger Event:
release
-
Statement type:
File details
Details for the file aranet_cloud-0.2.1-py3-none-any.whl.
File metadata
- Download URL: aranet_cloud-0.2.1-py3-none-any.whl
- Upload date:
- Size: 27.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
def951885002a08ca7ff4bf7023bd244b88741c0d56080915ff229dfdefddb79
|
|
| MD5 |
b4ef7c67142c17185d53104c71055cee
|
|
| BLAKE2b-256 |
29718681a26b5ab7641a82a0d52a841a66dcf0eb8387132c116b9ca0f00c9397
|
Provenance
The following attestation bundles were made for aranet_cloud-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on jasonjhofmann/aranet-cloud
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aranet_cloud-0.2.1-py3-none-any.whl -
Subject digest:
def951885002a08ca7ff4bf7023bd244b88741c0d56080915ff229dfdefddb79 - Sigstore transparency entry: 1787394033
- Sigstore integration time:
-
Permalink:
jasonjhofmann/aranet-cloud@b96fcbf97d7672cd3daa1aedc320632c1069103e -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/jasonjhofmann
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b96fcbf97d7672cd3daa1aedc320632c1069103e -
Trigger Event:
release
-
Statement type: