Skip to main content

Async Python client for the Austrian eHealth Codierservice API (FHIR R5 ConceptMap).

Project description

ehcsapi

Async Python client for the eHealth Codierservice API (Austrian eHealth, FHIR R5 ConceptMap).

The service maps free-text diagnoses to coded concepts (SNOMED CT, ICD-10, Orphanet). The typical flow is:

  1. create a search episode once,
  2. call find_diagnoses(...) repeatedly while the user types (type-ahead),
  3. call get_codes(...) for the selected diagnosis to obtain the SNOMED/ICD-10 codes,
  4. drop the episode.

The client is async-only (built on httpx.AsyncClient) so it fits naturally into a Django ASGI type-ahead view, where in-flight requests can be cancelled as the user keeps typing.

Installation

uv add ehcsapi          # or: pip install ehcsapi

Requires Python ≥ 3.11. Depends on httpx and cryptography.

Authentication (mutual TLS)

The service requires a client certificate. The operator recommends loading the certificate once at startup and keeping it in memory for the lifetime of the process. This client supports exactly that — pass a pre-built ssl.SSLContext, or in-memory certificate bytes, or a file path:

import ehcsapi

# Recommended: build the context once at startup (e.g. from your central cert service) and reuse it.
ctx = ehcsapi.build_ssl_context(cert_bytes, password="…")   # bytes (PEM or PKCS#12) or a path
client = ehcsapi.AsyncClient("at.nerdocs.aesculaping", ssl_context=ctx)

# Or let the client build it from a path / bytes:
client = ehcsapi.AsyncClient("at.nerdocs.aesculaping", cert="/path/to/client.p12", cert_password="…")

The base URL defaults to production (ehcsapi.PRODUCTION_BASE_URL). For the test system use ehcsapi.TEST_BASE_URL (https://csapi-t.ehealth.gv.at):

client = ehcsapi.AsyncClient("at.nerdocs.aesculaping", base_url=ehcsapi.TEST_BASE_URL, cert=cert)

Usage

Type-ahead (one episode, many keystrokes)

async with ehcsapi.AsyncClient("at.nerdocs.aesculaping", ssl_context=ctx) as cs:
    async with cs.search_episode() as episode:        # POST on enter, DELETE on exit
        hits = await episode.find_diagnoses("influ")  # -> list[Diagnosis]
        codes = await episode.get_codes(hits[0])      # search terms reused from the Diagnosis
        print(codes.icd10)                            # [Coding(code='J11.1', display='Grippe …')]

In a stateless Django view you usually create the episode once, keep its id in the session, and reconstruct a handle per request without a new POST:

episode = cs.episode(request.session["episode_id"])   # existing episode, no round-trip
hits = await episode.find_diagnoses(query)

One-shot lookup

async with ehcsapi.AsyncClient("at.nerdocs.aesculaping", ssl_context=ctx) as cs:
    hits = await cs.find_diagnoses("influenza")        # opens + drops an ad-hoc episode

API surface

Method Endpoint
startup_probe() HEAD /startupprobe
version() / dataset_version() / application_version() GET /version[...]
create_episode() / create_episode_v2() / search_episode() POST .../searchepisode
episode(id) resume an existing episode (no request)
delete_episode(id) / delete_episode_v2(id) DELETE .../searchepisode/{id}
SearchEpisode.find_diagnoses(...) GET .../conceptmap?_query=findDiagnoses
SearchEpisode.get_codes(...) GET .../conceptmap?_query=getCodeByElementId
emit_x(n) / emit_random(n) diagnostic GET /emit/...

Errors raise a CodierserviceError subclass: BadRequestError (400), ForbiddenError (403), SearchEpisodeExpiredError (410 — create a fresh episode), or TransportError for network failures.

Test run against the test system

A runnable smoke script and an opt-in live test hit csapi-t:

# one-off manual run
CSAPI_CLIENT_TLS_CERT_PATH=/path/to/client.p12 CSAPI_CLIENT_TLS_CERT_PASSWORD= \
    python examples/smoke.py influenza

# opt-in pytest
EHCSAPI_LIVE=1 CSAPI_CLIENT_TLS_CERT_PATH=/path/to/client.p12 CSAPI_CLIENT_TLS_CERT_PASSWORD= \
    uv run pytest -m live

The reference OpenAPI document is in docs/openapi.json.

Development

uv sync
uv run pytest          # unit tests, no network
uv run ruff check
uv run mypy src

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ehcsapi-0.1.0.tar.gz (52.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ehcsapi-0.1.0-py3-none-any.whl (12.8 kB view details)

Uploaded Python 3

File details

Details for the file ehcsapi-0.1.0.tar.gz.

File metadata

  • Download URL: ehcsapi-0.1.0.tar.gz
  • Upload date:
  • Size: 52.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"KDE neon","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for ehcsapi-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3f10bc1a21c3db4717433a1763c962cc1e7325ac1c002ae2676908784ba72b15
MD5 4eec0f7d77e3eb8ad519c3c9473bfc40
BLAKE2b-256 54cc5c97aaa84a0b3be16b066d225816e7c91ce3642d3ff2c3dcc11d21d1ba18

See more details on using hashes here.

File details

Details for the file ehcsapi-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ehcsapi-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"KDE neon","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for ehcsapi-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4db360d0bdcf8079662f17b3bb7281eeafefd08207f58e2001e7d23020f2a24a
MD5 1e21f2ffd40860c38d34f029c5c4c4c2
BLAKE2b-256 bd371c71cc3012f43ce56de89682d2fdd6d02234188fbd15bf0c18f8e810674c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page