This is a semi automatically generated API Client for the Ryhti API. The client library is generated by the OpenAPI Generator project and modified to fit the needs of the Ryhti project.
The library includes clients for the Ryhti Data Exchange Layer Api (Palveluväylä / Xroad) and the Public Validation API. Those share same models, but have different API endpoints.
This project is developed and maintained by Gispo Finland Ltd. and is not affiliated with the Ryhti project.
pip install git+https://github.com/GispoCoding/ryhti-api-client.gitThis project uses uv for development.
Python files gererated by the OpenAPI Generator are not meant to be edited manually. Instead, the API specifications are edited in the api_specs directory and the client is regenerated using the scripts provided.
uv run pytest
uv run bash scripts/generate_client.sh v2026-release-8
uv run bash scripts/copy_generated_client.sh public
# Inspect modified files and commit changes
uv run bash scripts/copy_generated_client.sh xroad
# Inspect modified files and commit (Amend) changesgenerate_client.sh patches the downloaded specs before generation: besides the description and
server tweaks it runs scripts/add_discriminators.jq, which adds discriminator mappings to the
oneOf properties, narrows each subclass' dataType/type enum to its own value and keeps that
tag property first so the generated models and docs keep their field order. The upstream specs
leave the unions ambiguous, which makes the generated client fail with "Multiple matches found".
copy_generated_client.sh ends by running scripts/fix_discriminated_unions.py, which replaces the
generated oneOf wrapper classes (PlanRegulationValue, AdditionalInformationValue,
RyhtiGeometryGeometry) with pydantic discriminated unions: AttributeValue and GeoJsonGeometry
become typing.Union aliases of the concrete classes, the tag fields become Literal[...], and the
consuming fields use Field(discriminator=...). So PlanRegulation.value is a plain CodeValue,
TextValue, etc. instead of a wrapper with actual_instance. The copy script then runs
ruff check --fix and ruff format on the package. Both scripts are idempotent.