Skip to main content

AX Hub Python SDK

Project description

AX Hub Python SDK

AX Hub Python SDK for https://api.axhub.ai. It gives agents a dependency-light client, generated backend route metadata, sync and async generated operation facades, typed error metadata, conformance tests, and a live-testable app/data workflow.

Install

pip install axhub-sdk==0.2.0

Local development:

python3 -m venv .venv
source .venv/bin/activate
pip install -e .

Required environment for agent work

export AXHUB_TOKEN="<short-lived PAT>"
export AXHUB_TENANT_ID="cc1e58f1-8e46-4ac7-96c1-190c4cdd5b70"   # test tenant
export AXHUB_TENANT_SLUG="test"

PAT mode is explicit: TokenType.PAT sends X-Api-Key. JWT mode is TokenType.JWT and sends Authorization: Bearer.

Agent quickstart: create a disposable app and table

import os, time
from axhub_sdk import AxHubClient, TokenType

client = AxHubClient(
    base_url="https://api.axhub.ai",
    token=os.environ["AXHUB_TOKEN"],
    token_type=TokenType.PAT,
    default_tenant_id=os.environ["AXHUB_TENANT_ID"],
    default_tenant_slug=os.environ.get("AXHUB_TENANT_SLUG", "test"),
)

me = client.request("authGetApiV1Me")
user_id = me.get("userId") or (me.get("user") or {}).get("id")
if not user_id:
    raise RuntimeError("authGetApiV1Me did not return a user id")

suffix = str(int(time.time() * 1000))[-8:]
slug = f"agent-py-{suffix}"
table = f"items{suffix[-6:]}"

app = client.apps.create({
    "slug": slug,
    "name": "Agent Python README QA",
    "visibility": "private",
    "auth_mode": "anonymous",
    "resource_tier": "S",
    "deploy_method": "docker",
    "subdomain": slug,
})
app_id = app["id"]

client.request(
    "schemaPostApiV1AppsByAppIDTables",
    path_params={"appID": app_id},
    body={
        "table_name": table,
        "owner_column": "owner_id",
        "columns": [
            {"name": "owner_id", "type": "uuid", "nullable": False},
            {"name": "title", "type": "text", "nullable": False},
            {"name": "status", "type": "text", "nullable": False},
        ],
    },
)

row = client.request(
    "schemaPostDataByTenantSlugByAppSlugByTable",
    path_params={"tenantSlug": "test", "appSlug": slug, "table": table},
    body={"owner_id": user_id, "title": "hello", "status": "new"},
)
print("created", app_id, table, row["id"])

How to call the full API surface

  • High-level app create: client.apps.create(body) uses default_tenant_id.
  • Any route by operation id: client.request(operation_id, path_params={...}, query={...}, body={...}).
  • Generated facade: client.data.schema_post_data_by_tenant_slug_by_app_slug_by_table(path_params={...}, body={...}).
  • Async client: AsyncAxHubClient mirrors request and generated operation facades.
  • Route inventory: ROUTES, CONTEXT_ROUTES, ERROR_CODES, and OPERATION_METHODS.
  • Errors: catch AxHubError and branch on code, category, status, and retryable.

Dynamic app, schema, and data operations

Use the high-level apps.create helper for the first app, then use generated operation IDs for every backend route. Request bodies use backend wire keys, usually snake_case. Responses are normalized to camelCase in this SDK family, so read tableName, requestId, revokedAt, and similar keys from responses.

Task Operation ID Required path params Success assertion
Create env var appsPostApiV1AppsByAppIDEnvVars appID env.list includes key
Delete env var appsDeleteApiV1AppsByAppIDEnvVarsByKey appID, key env.list no longer includes key
Create table schemaPostApiV1AppsByAppIDTables appID response tableName equals requested name
Inspect table schemaGetApiV1AppsByAppIDTablesByTableName appID, tableName response id and tableName match
Add column schemaPostApiV1AppsByAppIDTablesByTableNameColumns appID, tableName inspect contains column name
Drop column schemaDeleteApiV1AppsByAppIDTablesByTableNameColumnsByColumnName appID, tableName, columnName inspect no longer contains column name
Add table grant schemaPostApiV1AppsByAppIDTablesByTableNameGrants appID, tableName response has grant id
List grants schemaGetApiV1AppsByAppIDTablesByTableNameGrants appID, tableName list contains grant id
Revoke/delete grant schemaDeleteApiV1AppsByAppIDTablesByTableNameGrantsByGrantID appID, tableName, grantID list still contains grant with revokedAt set
Insert row schemaPostDataByTenantSlugByAppSlugByTable tenantSlug, appSlug, table response has row id and submitted fields
Get row schemaGetDataByTenantSlugByAppSlugByTableById tenantSlug, appSlug, table, id response row id matches
Update row schemaPatchDataByTenantSlugByAppSlugByTableById tenantSlug, appSlug, table, id response contains patched fields
List rows schemaGetDataByTenantSlugByAppSlugByTable tenantSlug, appSlug, table items contains row id
Count rows schemaGetDataByTenantSlugByAppSlugByTableCount tenantSlug, appSlug, table count matches expected fixture count
Browse admin rows schemaGetApiV1AppsByAppIDTablesByTableNameRows appID, tableName response has rows and columns arrays
Delete row schemaDeleteDataByTenantSlugByAppSlugByTableById tenantSlug, appSlug, table, id follow-up get returns 404 or 410
Delete table schemaDeleteApiV1AppsByAppIDTablesByTableName appID, tableName follow-up inspect returns 404 or 410
Delete app appsDeleteApiV1AppsByAppID, then appsDeleteApiV1AppsByAppIDPermanent appID app is soft-deleted, then permanently deleted

Important semantics from live QA:

  • Row delete is hard enough for client assertions: a follow-up row get returns 404 not_found or 410.
  • Table delete is hard enough for client assertions: a follow-up table inspect returns 404 not_found or 410.
  • Table grant delete is a soft revoke: the grant can remain in listGrants, but the same grant id must have revokedAt set. Do not assert disappearance.
  • Deployment creation without a connected git/bootstrap source can return a precondition-style 4xx. That verifies SDK error handling, not a deploy bug.

Live QA evidence agents can trust

The SDK behavior documented here reflects live production QA against the AX Hub test tenant on 2026-06-08.

  • Tenant used for destructive QA: slug test, id cc1e58f1-8e46-4ac7-96c1-190c4cdd5b70.
  • Go, Java, Kotlin, Python, and Ruby each ran the generated all-operation sweep against 189 backend routes: SDK exceptions 0, backend 5xx 0.
  • Go, Java, Kotlin, Python, and Ruby each passed strict destructive DB QA: 22 live steps, 17 assertions, 7 cleanup calls. The flow created an app, env var, table, column, table grant, row, then updated, listed, counted, browsed, deleted, and re-read to prove deletion semantics.
  • Node ran the full production mutation suite and a real app bootstrap/deploy wait. Deployment id d3a48ce3-0f9c-4bab-aa07-863c31c44460 finished succeeded, then the app was deleted permanently.

Do not print tokens. Use short-lived PATs for agent QA and revoke them after the run.

Verification commands

Use local tests for every docs/code change. Run live tests only when you intentionally want destructive QA against test.

python3 -m unittest discover -s tests -v

# Destructive live all-operation sweep, only with a disposable PAT.
AXHUB_LIVE_ALL_METHODS=1 \
AXHUB_TOKEN="$AXHUB_TOKEN" \
AXHUB_LIVE_TENANT_ID="$AXHUB_TENANT_ID" \
AXHUB_LIVE_TENANT_SLUG="$AXHUB_TENANT_SLUG" \
PYTHONPATH=src python3 -m unittest tests.test_live_all_operations_e2e -v

Troubleshooting for agents

  • tenant_id_required: pass defaultTenantId / AXHUB_TENANT_ID before calling apps.create.
  • tokenType must be explicit: set PAT mode when using a PAT. PATs are sent as X-Api-Key; JWTs are sent as Authorization: Bearer.
  • slug_taken or schema_name_taken: append a timestamp suffix and retry. Never reuse fixture names in live destructive QA.
  • permission_denied / not_admin: the SDK is working. The token lacks the role for that route.
  • precondition_failed on deploy: connect git or use the app bootstrap flow first.
  • 4xx responses are expected for negative assertions. SDK bugs are unexpected exceptions, response decode failures, or backend 5xx during a valid call.

Release

See RELEASE.md for tag order, environment approvals, registry prerequisites, and smoke-test handling.

License

Apache-2.0.

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

axhub_sdk-0.3.1.tar.gz (50.5 kB view details)

Uploaded Source

Built Distribution

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

axhub_sdk-0.3.1-py3-none-any.whl (34.5 kB view details)

Uploaded Python 3

File details

Details for the file axhub_sdk-0.3.1.tar.gz.

File metadata

  • Download URL: axhub_sdk-0.3.1.tar.gz
  • Upload date:
  • Size: 50.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for axhub_sdk-0.3.1.tar.gz
Algorithm Hash digest
SHA256 5c5e5c687a11432ecd3a8777dc2d40e8d67dd398f08e36c28389a029761f820c
MD5 31bf6e731d984e5c69d7a91b58cc245b
BLAKE2b-256 b4dc66625e3197451621220698f4986406e64db2b0ab0a075e6573005b9e6227

See more details on using hashes here.

Provenance

The following attestation bundles were made for axhub_sdk-0.3.1.tar.gz:

Publisher: release.yml on jocoding-ax-partners/axhub-sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file axhub_sdk-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: axhub_sdk-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 34.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for axhub_sdk-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 27f21ba927d2a699c0ed7ca30bcbca348f4140bcf21f3dd5c54b2da2d3df87a0
MD5 41bdf00a0b422c264b46dd25a8e346a3
BLAKE2b-256 2e29b3ed28c0c8e58c2d046ee5b298cf0b3a71e3ee3a8cd722c6e8967a375b86

See more details on using hashes here.

Provenance

The following attestation bundles were made for axhub_sdk-0.3.1-py3-none-any.whl:

Publisher: release.yml on jocoding-ax-partners/axhub-sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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