Skip to main content

basyx-client

PyPI version Python versions License CI

Python CLI & SDK for the AAS Part 2 API v3.x

A high-level, BaSyx-model-native HTTP client with first-class CLI support.

Why basyx-client?

Working with the AAS Part 2 API directly is painful:

  1. Identifier encoding - Every identifier must be base64url encoded (without padding!)
  2. idShortPath encoding - Brackets in paths like Sensors[0] must be URL-encoded as %5B0%5D
  3. No typed responses - You get raw dictionaries, not BaSyx model objects
  4. Manual error handling - Status codes must be checked and mapped to meaningful errors

basyx-client eliminates all of this friction:

from basyx_client import AASClient

# All encoding happens automatically
with AASClient("http://localhost:8081") as client:
    # Get an AAS - returns basyx.aas.model.AssetAdministrationShell, not dict
    aas = client.shells.get("https://acme.org/ids/aas/55")
    print(aas.id_short)  # Type-safe attribute access

    # Access submodel elements with array indices - brackets encoded automatically
    temp = client.submodels.elements.get_value(
        "https://acme.org/ids/sm/sensors",
        "Measurements[0].Temperature"  # [0] becomes %5B0%5D automatically
    )

Installation

pip install basyx-client

Docker (GHCR)

The GitHub Actions workflow publishes a Docker image on release:

docker pull ghcr.io/hadijannat/basyx-client:<version>

The image contains Python with basyx-client installed and defaults to python.

CLI Quick Start

Install with CLI support:

pip install basyx-client[cli]

Use the basyx command to interact with AAS servers:

# List all AAS shells
basyx shells list --url http://localhost:8081

# Get a specific shell
basyx shells get "urn:example:aas:1" --url http://localhost:8081

# Get a submodel element value
basyx elements get-value "urn:example:sm:1" "Sensors.Temperature"

# Set a value
basyx elements set-value "urn:example:sm:1" "Sensors.Temperature" "25.5"

# Use JSON output for scripting
basyx --format json shells list | jq '.[].id'

CLI Configuration

Save server settings in ~/.basyx/config.yaml:

# Initialize config with defaults
basyx config init

# Set default server URL
basyx config set url http://localhost:8081

# Use named profiles
basyx --profile production shells list

CLI Commands

Command Group Operations
basyx shells list, get, create, delete, refs, asset-info
basyx submodels list, get, create, delete, value
basyx elements list, get, get-value, set-value, create, delete, invoke
basyx registry shells list, get, create, delete
basyx registry submodels list, get, create, delete
basyx aasx list, get, download, upload, delete
basyx discovery lookup, link, unlink, list-links
basyx concepts list, get, create, delete
basyx config show, set, get, profiles, init

See basyx --help or the CLI documentation for full details.

Features

  • First-class CLI - Full command-line interface for all API operations
  • Automatic encoding - Base64url for identifiers, URL-encoding for idShortPath
  • Typed responses - Returns basyx.aas.model.* objects, not dictionaries
  • Sync + async - Both synchronous and asynchronous operation support
  • Full auth suite - Bearer, Basic, OAuth2 client credentials, mTLS certificates
  • Proper exceptions - ResourceNotFoundError, ConflictError, etc. instead of generic errors
  • Pagination helpers - Easy iteration through paginated results
  • Element helpers - $metadata, $reference, $path, async operation status/result

Quick Start

Basic Usage

Note: the BaSyx Docker images in docker-compose.yml expose the API at the root (http://localhost:8081, no /api/v3.0). Some deployments mount the API at /api/v3.0 — set base_url accordingly.

from basyx_client import AASClient

with AASClient("http://localhost:8081") as client:
    # List all AAS
    result = client.shells.list()
    for aas in result.items:
        print(f"{aas.id_short}: {aas.id}")

    # Get a specific AAS
    aas = client.shells.get("urn:example:aas:machine-001")

    # Get a submodel
    sm = client.submodels.get("urn:example:sm:operational-data")

    # Get/set element values
    temp = client.submodels.elements.get_value(
        "urn:example:sm:operational-data",
        "Sensors.Temperature"
    )
    client.submodels.elements.set_value(
        "urn:example:sm:operational-data",
        "Sensors.Temperature",
        25.5
    )

Async Usage

import asyncio
from basyx_client import AASClient

async def main():
    async with AASClient("http://localhost:8081") as client:
        # Concurrent fetches
        aas1, aas2 = await asyncio.gather(
            client.shells.get_async("urn:example:aas:1"),
            client.shells.get_async("urn:example:aas:2"),
        )
        print(aas1.id_short, aas2.id_short)

asyncio.run(main())

Authentication

from basyx_client import AASClient
from basyx_client.auth import BearerAuth, OAuth2ClientCredentials

# Bearer token
client = AASClient("http://localhost:8081", auth=BearerAuth("my-token"))

# Basic auth (shorthand)
client = AASClient("http://localhost:8081", auth=("username", "password"))

# OAuth2 client credentials
client = AASClient("http://localhost:8081", auth=OAuth2ClientCredentials(
    token_url="https://auth.example.com/oauth/token",
    client_id="my-client",
    client_secret="my-secret",
    scope="aas:read aas:write",
))

# mTLS
client = AASClient(
    "https://secure.example.com",
    cert=("/path/to/cert.pem", "/path/to/key.pem"),
)

Error Handling

from basyx_client import AASClient
from basyx_client.exceptions import ResourceNotFoundError, ConflictError

with AASClient("http://localhost:8081") as client:
    try:
        aas = client.shells.get("urn:nonexistent:aas")
    except ResourceNotFoundError as e:
        print(f"AAS not found: {e.message}")
        print(f"URL: {e.url}")

    try:
        client.shells.create(my_aas)
    except ConflictError:
        print("AAS already exists")

Pagination

from basyx_client import AASClient
from basyx_client.pagination import iterate_pages

with AASClient("http://localhost:8081/api/v3.0") as client:
    # Manual pagination
    result = client.shells.list(limit=10)
    while result.has_more:
        for aas in result.items:
            process(aas)
        result = client.shells.list(limit=10, cursor=result.cursor)

    # Automatic pagination
    for aas in iterate_pages(lambda limit, cursor: client.shells.list(limit, cursor)):
        process(aas)

API Coverage

Endpoint Status
AAS Repository (/shells) ✅ Full
Submodel Repository (/submodels) ✅ Full
Submodel Elements (/submodels/{id}/submodel-elements/{path}) ✅ Full
Concept Descriptions (/concept-descriptions) ✅ Full
AAS Registry (/shell-descriptors) ✅ Full
Submodel Registry (/submodel-descriptors) ✅ Full
AASX Server (/packages) ✅ Full
Discovery (/lookup/shells) ✅ Full

Documentation

Full documentation is available at the docs site:

Development

# Install with all dependencies
pip install -e ".[dev,cli,docs]"

# Run tests
pytest tests/unit -v

# Run linter
ruff check src tests

# Type checking
mypy src

# Build documentation
mkdocs serve  # Preview at localhost:8000

# Integration tests (requires Docker)
docker compose up -d
pytest tests/integration -v
docker compose down

Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

License

Apache License 2.0

Metadata

Release files for basyx-client 0.1.4

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

Source distribution (sdist)

Source distribution for basyx-client 0.1.4
File Size Uploaded Provenance
basyx_client-0.1.4.tar.gz 84.6 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for basyx-client 0.1.4
File Interpreter ABI Platform
basyx_client-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 140.7 kB

Release files / basyx_client-0.1.4.tar.gz

Download URL basyx_client-0.1.4.tar.gz
Size 84.6 kB
Tags Source
SHA-256 checksum
How to use checksums
4f94ab36143f569793ee00366ea84939e760fbe80e6853ea016c210619babf92
BLAKE2b-256 checksum
How to use checksums
06585d6b17b3ac734c891130a8654e7a3f8143b112caa464bf8d11d02bc9b714
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Jan 21, 2026.

Transparency log

Release files / basyx_client-0.1.4-py3-none-any.whl

Download URL basyx_client-0.1.4-py3-none-any.whl
Size 56.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
21155c055c91aeca35b4dc8442188b074e01e6a45b065a42c5c461560e464228
BLAKE2b-256 checksum
How to use checksums
5e4dd6c2a907e4715b6433b9a206b50c531f2bbab74db48ac7d30d294b7164fe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Jan 21, 2026.

Transparency log

Security for basyx-client 0.1.4

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 basyx_client-0.1.4.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 Jan 21, 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.

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