Skip to main content
knoxcall is the official KnoxCall client for Python. One import gives you a sync client (thread- and fork-safe, share it as a module-level singleton) or an async client for FastAPI and friends. Every method’s return shape is a TypedDict in knoxcall.types, so IDEs and mypy see the exact server fields.

Install

Not yet published to PyPI — install from the monorepo path or via git. Requires Python 3.10+.

Create a client

With no explicit credentials, the SDK auto-detects in priority order: a pre-acquired token env var (KNOXCALL_ACCESS_TOKEN / KNOXCALL_API_KEY), the credentials file written by knoxcall login (~/.knoxcall/credentials.json), workload identity (GitHub Actions, GCP, AWS IRSA, Azure Managed Identity, Vercel, CircleCI — no stored secrets in CI), then KNOXCALL_CLIENT_ID + KNOXCALL_CLIENT_SECRET. Legacy API keys — a pre-acquired key or token still works everywhere: KnoxCall(api_key="tk_live_...") accepts a minted kc_… token or a legacy tk_… / AKE… key. It is sent as-is and never auto-renewed — prefer knoxcall login or client credentials for new integrations.

Log in once with the CLI

The package ships the knoxcall command. Sign in once in your browser and every script, notebook, and agent on the machine picks the credential up automatically — no env vars, no keys in code:
Credentials are stored in ~/.knoxcall/credentials.json (file mode 0600). The stored tenant and base URL seed the client automatically; explicit constructor arguments or env vars always win. Access tokens refresh themselves, and refreshes are cross-process safe (file lock + atomic rotation of the single-use refresh token). If a refresh fails because the credential was revoked or expired, the SDK raises AuthenticationError telling you to run knoxcall login again. Select a non-default profile with KNOXCALL_PROFILE (or StoredCredentials(profile=...)). The same file is picked up by all five SDKs — log in once, use any language.

Manage resources

Create a route, then list with pagination — single-object methods return data unwrapped; paginated lists return the full {"data": [...], "meta": {...}} page; iterate() walks every page:
The sync client exposes the identical surface without await. The same pattern covers every resource: secrets, webhooks, clients, oauth_clients, environments, api_keys, account, audit_logs, agents, crypto, pki, vaults, and dynamic_db.

Call routes through the proxy

client.call() proxies a request through a KnoxCall route to your upstream and returns the raw httpx.Response — the upstream’s HTTP status belongs to you; the SDK never turns it into an error. Reference routes by slug (write-once, rename-proof); UUIDs also work.

Bound routes

State the route (and optional defaults) once with client.route(), then use plain HTTP verbs:
Works identically on the async client (await printnode.get(...)). The handle holds no state beyond the defaults — retries, token refresh, and 401 re-mint behave exactly as on call().

Verify webhooks

construct_webhook_event verifies a delivery AND returns the parsed, typed event in one step. Pass the RAW request body (never re-serialized JSON):
format= matches the webhook’s configured hmac_format: "legacy" (default), "stripe", "github", "slack", "aws-sns", or "custom" (pass header_name=). tolerance_seconds (default 300) bounds replay; pass None to disable. Also available as client.webhooks.construct_event() on both facades.

Handle errors

403 maps to PermissionDeniedError. Transport failures map to APIConnectionError / APIConnectionTimeoutError. Every API error carries the server’s request_id — quote it when contacting support.

Retries and idempotency

Management requests retry automatically on 408/429/500/502/503/504 with exponential backoff + jitter (3 attempts by default; never 409; Retry-After honored on 429, capped at 30s). Mutating requests get an auto-generated ULID idempotency key so retries are safe. A 401 triggers one transparent token re-mint. Data-plane transport failures retry only when safe: connection-refused always, later failures (read timeout, keepalive reset) only for GET/HEAD — a mutating request is never replayed.

DPoP

The SDK generates an ES256 keypair, binds the access token via cnf.jkt, and signs a fresh proof on every request — both management calls and proxy call() requests. In the default "auto" mode it upgrades automatically when the OAuth client requires DPoP.

Full reference

The package README documents every resource method, the ephemeral proxy, Redis token store, request-body encoding (datetime / Decimal / UUID / set out of the box), thread-safety details, and credential-less signup() / signup_sync(): sdk/knoxcall-python/README.md in the monorepo.