Skip to main content

aiohortos

Async Python client for the Ridder HortOS Automation API, the cloud API behind HortiMaX greenhouse process controllers.

This is a community-built library. It is not an official Ridder product, it is not certified by Ridder, and Ridder does not support it. Ridder's support covers the HortOS Automation API itself; anything about this library belongs on its issue tracker.

The API is still evolving and Ridder does not guarantee backward compatibility for community integrations, so a future API change can alter or remove what this library returns. Pin a version.

The library is read-only: it authenticates with an API key and reads controllers, their health, and their readouts. It never writes setpoints.

pip install aiohortos

Usage

import asyncio

from aiohortos import HortosClient


async def main() -> None:
    async with HortosClient("your-api-key") as client:
        for device in await client.get_devices():
            print(device.name, device.label)
            for readout in await client.get_latest_readouts(device.name):
                print(
                    f"  {readout.source.display_name}: "
                    f"{readout.identifier} = {readout.value} {readout.unit or ''}"
                )


asyncio.run(main())

Pass an existing session to share a connection pool — which is what you want inside an application that already has one:

async with aiohttp.ClientSession() as session:
    client = HortosClient("your-api-key", session=session)

The client also accepts a base_url, for on-premise HortOS installations that serve the same API from your own network.

API surface

Method Returns
authenticate() TokenPair — normally not needed; every call authenticates on demand
get_device_names() list[str] of controller identifiers
get_devices() list[Device] with the friendly label
get_devices_health() list[DeviceHealth] — online state, sync state
get_readout_definitions(device) list[ReadoutDefinition]
get_latest_readouts(device) list[Readout] with the newest value each
get_readout_history(...) list[ReadoutValue] over a window of ≤ 24 hours

Errors all derive from HortosError:

  • HortosAuthenticationError — the API key or token was rejected (HTTP 401/403)
  • HortosConnectionError — the API could not be reached, or timed out
  • HortosResponseError — an unexpected status or payload, with .status

Notes on the API

  • Tokens live 15 minutes and are renewed with a refresh token valid 7 days. The client handles both, and re-authenticates when a token is rejected.

  • The API allows 100 requests per 15 seconds per key. The library does not throttle; pace your own polling.

  • Unchanged readouts are refreshed at most every 5 minutes, so polling faster than that gains nothing.

  • Readout identifiers follow <CamelCaseSubject>-<Kind>, e.g. VentPositionLeewardSide-Measured. One upstream typo exists in the wild: IrrigationVolume-Measuered.

  • Some readouts have unitIdentifier: "Scalar" and a numeric value that is really an enumeration member id from a table the API does not expose. They are returned as-is. CardinalWindDirection is the one decoded so far:

    from aiohortos import decode_cardinal_wind_direction
    
    decode_cardinal_wind_direction(8783)  # 247.5, i.e. WSW
    decode_cardinal_wind_direction(1234)  # None — not a member of the table
    

    The 16 compass points occupy contiguous ids 8772–8787 on a HortiMaX controller, clockwise in 22.5° steps, confirmed over a day of history and cross-checked against the official app. Anything outside that block, or not a whole number, decodes to None rather than to a plausible bearing.

  • Readout.name embeds the source's user-defined name and is a poor label on its own — build names from identifier and source instead.

Ridder's Swagger UI documents the API at https://hortos.ridder.com/api/process-control/index.html. The OpenAPI document lives at {base_url}/v1/swagger.json and needs a bearer token.

Development

uv venv && uv pip install -e . --group dev
pytest
ruff check . && ruff format --check . && mypy src

Disclaimer

This library is not affiliated with, endorsed by, or certified by Ridder, and carries no warranty. "Ridder", "HortOS" and "HortiMaX" are used only to name the API and the products this library talks to; they are trademarks of their respective owner.

Metadata

Release files for aiohortos 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aiohortos 0.3.1
File Size Uploaded Provenance Actions
aiohortos-0.3.1.tar.gz 66.1 kB With provenance Details for aiohortos-0.3.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for aiohortos 0.3.1
File Interpreter ABI Platform Actions
aiohortos-0.3.1-py3-none-any.whl Python 3 none any Details for aiohortos-0.3.1-py3-none-any.whl

Total release size: 81.7 kB

Release files / aiohortos-0.3.1.tar.gz

Download URL aiohortos-0.3.1.tar.gz
Size 66.1 kB
Tags Source
SHA-256 checksum
How to use checksums
c35339660ae20e7889c8f2671fdcfe8bb5a6f2f6403d42b75801adc8eb0db4c0
BLAKE2b-256 checksum
How to use checksums
b1d333824cfc97f04b03ad770d82faa1cc5aef8f2af1fce70ced590781eedb71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.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 Jul 26, 2026.

Transparency log

Release files / aiohortos-0.3.1-py3-none-any.whl

Download URL aiohortos-0.3.1-py3-none-any.whl
Size 15.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
89a909d3b1fd46bb84a6fdda076881dd7a7f5cc54c741ae45536ce02faf5036b
BLAKE2b-256 checksum
How to use checksums
bbe1a8de77ef28d7759dce9a49146fa3fc36cac7b1200aa87d87c51eebf1adfc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.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 Jul 26, 2026.

Transparency log

Security for aiohortos 0.3.1

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for aiohortos-0.3.1.tar.gz

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 Jul 26, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page