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)usesdefault_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:
AsyncAxHubClientmirrorsrequestand generated operation facades. - Route inventory:
ROUTES,CONTEXT_ROUTES,ERROR_CODES, andOPERATION_METHODS. - Errors: catch
AxHubErrorand branch oncode,category,status, andretryable.
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_foundor410. - Table delete is hard enough for client assertions: a follow-up table inspect returns
404 not_foundor410. - Table grant delete is a soft revoke: the grant can remain in
listGrants, but the same grant id must haverevokedAtset. 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, idcc1e58f1-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 5xx0. - 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-863c31c44460finishedsucceeded, 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: passdefaultTenantId/AXHUB_TENANT_IDbefore callingapps.create.tokenType must be explicit: set PAT mode when using a PAT. PATs are sent asX-Api-Key; JWTs are sent asAuthorization: Bearer.slug_takenorschema_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_failedon 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c5e5c687a11432ecd3a8777dc2d40e8d67dd398f08e36c28389a029761f820c
|
|
| MD5 |
31bf6e731d984e5c69d7a91b58cc245b
|
|
| BLAKE2b-256 |
b4dc66625e3197451621220698f4986406e64db2b0ab0a075e6573005b9e6227
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
axhub_sdk-0.3.1.tar.gz -
Subject digest:
5c5e5c687a11432ecd3a8777dc2d40e8d67dd398f08e36c28389a029761f820c - Sigstore transparency entry: 1772933666
- Sigstore integration time:
-
Permalink:
jocoding-ax-partners/axhub-sdk-python@8bafa90e7d9319b78514a1e95b19c0fb3b73d558 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/jocoding-ax-partners
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8bafa90e7d9319b78514a1e95b19c0fb3b73d558 -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27f21ba927d2a699c0ed7ca30bcbca348f4140bcf21f3dd5c54b2da2d3df87a0
|
|
| MD5 |
41bdf00a0b422c264b46dd25a8e346a3
|
|
| BLAKE2b-256 |
2e29b3ed28c0c8e58c2d046ee5b298cf0b3a71e3ee3a8cd722c6e8967a375b86
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
axhub_sdk-0.3.1-py3-none-any.whl -
Subject digest:
27f21ba927d2a699c0ed7ca30bcbca348f4140bcf21f3dd5c54b2da2d3df87a0 - Sigstore transparency entry: 1772933744
- Sigstore integration time:
-
Permalink:
jocoding-ax-partners/axhub-sdk-python@8bafa90e7d9319b78514a1e95b19c0fb3b73d558 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/jocoding-ax-partners
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8bafa90e7d9319b78514a1e95b19c0fb3b73d558 -
Trigger Event:
push
-
Statement type: