axowl-sdk (Python)
Backend SDK for Axowl: verify Axowl end-user access tokens on your server,
read the caller's permissions, and — when a decision must see revocations made after the token was
issued — ask Axowl directly. Mirrors @axowl/sdk-backend (Node) and Axowl.Sdk.Identity.Client (.NET).
pip install axowl-sdk # + "axowl-sdk[fastapi]" for the FastAPI dependency
Verify a token (no server round trip)
from axowl import AxowlConfig, verify_token, has_permission, AxowlAuthError
config = AxowlConfig(
org_slug="my-org", # your Axowl org
audience="app_my_main", # optional: your application key — rejects tokens minted for another app
base_url="https://api.axowl.com", # default
)
try:
ctx = verify_token(bearer_token, config)
except AxowlAuthError as e:
... # e.reason ∈ missing_token | invalid_token | expired | signature | issuer | audience | jwks
ctx.user_id, ctx.email, ctx.org_slug, ctx.connected_id, ctx.is_employee
ctx.permissions # ["wallet.read", "report.*"] — decoded from the token
has_permission(ctx.permissions, "report.monthly") # True (wildcards honoured)
- Signature: RS256 against
{base_url}/api/public/orgs/{org_slug}/.well-known/jwks.json. Keys are cached for 10 minutes; an unknownkid(rotation) triggers a re-fetch. - Issuer must equal
{base_url}/api/public/orgs/{org_slug}— what Axowl writes into the token. exp/nbfenforced (leeway_secondson the config if your clock drifts).
FastAPI
from fastapi import Depends, FastAPI
from axowl import AxowlConfig, AxowlContext
from axowl.fastapi import AxowlAuth
auth = AxowlAuth(AxowlConfig(org_slug="my-org", audience="app_my_main"))
app = FastAPI()
@app.get("/wallet")
def wallet(ctx: AxowlContext = Depends(auth)):
return {"user": ctx.email}
@app.post("/wallet/withdraw")
def withdraw(ctx: AxowlContext = Depends(auth.require("wallet.withdraw"))):
...
401 {"error": ..., "reason": ...} for a missing/invalid token, 403 {"error": ..., "required": [...]}
for a missing scope — the same shapes as the Express middleware.
Any other framework: call extract_bearer_token(request.headers["Authorization"]) then verify_token.
Server-authoritative checks
The JWT fast path cannot see a permission revoked after the token was issued. For those decisions
ask Axowl with your org API key (ah_live_…):
from axowl import AxowlIdentityClient
identity = AxowlIdentityClient(api_key="ah_live_...", base_url="https://api.axowl.com")
res = identity.introspect(bearer_token) # → IntrospectResult(active, principal, expires_at, issued_at)
res = identity.check_permission(bearer_token, "wallet.withdraw") # → PermissionCheckResult(granted, matched_scopes, reason)
Both are synchronous and stdlib-only (urllib); run them in a thread from async code.
Permission matching
Same rules as every other Axowl SDK and the server:
| pattern | scope | match |
|---|---|---|
sap.fi.document.post |
sap.fi.document.post |
yes |
sap.fi.* |
sap.fi.document.post |
yes |
* |
anything | yes |
sap.fi |
sap.fi.document.post |
no (a prefix without * is not a wildcard) |
Tests
pip install -e ".[test]" && pytest
Metadata
Release files for axowl-sdk 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| axowl_sdk-0.1.1.tar.gz | 13.0 kB | With provenance | Details for axowl_sdk-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| axowl_sdk-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for axowl_sdk-0.1.1-py3-none-any.whl |
Total release size: 25.0 kB
Release files / axowl_sdk-0.1.1.tar.gz
| Download URL | axowl_sdk-0.1.1.tar.gz |
|---|---|
| Size | 13.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9dd4ddd54c2c43666812e38776dcdf1ff18b39c0cabb94c725c1c30e73e04200
|
|
BLAKE2b-256 checksum How to use checksums |
e2eae00f2166d8e43eefc38a93e1837ab0417aa481d83229ab507e7c992cd3fe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 26, 2026.
Transparency logRelease files / axowl_sdk-0.1.1-py3-none-any.whl
| Download URL | axowl_sdk-0.1.1-py3-none-any.whl |
|---|---|
| Size | 12.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6b4f8e524d3352a3ad3521baab00297b4ab5f3049ac957ae7d34d49d3c7cefcb
|
|
BLAKE2b-256 checksum How to use checksums |
bdb37592474e16db6a12744b1254eefb5b039ba011637b87d7c375765ab95a56
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 26, 2026.
Transparency logSecurity for axowl-sdk 0.1.1
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
Both files in this release have been uploaded with provenance metadata.
Attestation for axowl_sdk-0.1.1.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 Sep 26, 2026.
Transparency logA 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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.