Language support
What every SDK guarantees
The core SDKs are held to a single parity spec (sdk/PARITY.md in the monorepo), with test coverage required for each behavior:
- Automatic retries — HTTP 408, 429, 500, 502, 503, 504 retried with exponential half-jitter backoff;
Retry-Afterhonored on 429 (capped at 30s); 409 is never retried (a real conflict does not resolve by replaying). - Idempotency by default — every mutating request carries a ULID
X-Idempotency-Keygenerated once per logical request and stable across retries, so replays are safe. - Transparent 401 re-mint — a 401 purges the cached token and retries once with fresh credentials before surfacing an error. Long-lived processes never wedge on a revoked or rotated token.
- Token lifecycle — tokens cached per tenant + scope with single-flight refresh, refresh-ahead, and a stale-but-valid fallback when the token endpoint is briefly unreachable.
- DPoP sender-constrained tokens (RFC 9449) — every SDK auto-upgrades to DPoP when the OAuth client requires it (
dpop: "auto", the default) and supports"always": the SDK generates an ES256 keypair, binds the access token viacnf.jkt, and signs a fresh proof per request. - Shared CLI login — every SDK auto-detects the credentials file written by
knoxcall login(~/.knoxcall/credentials.json), with cross-process-safe rotation of the single-use refresh token. Sign in once; every language picks it up. - Secret redaction — client secrets, access tokens, and OIDC subject tokens never appear in debug output, logs, or error messages.
- Typed errors with request IDs — 401/403/404/409/422/429/5xx each map to a named error type carrying the server’s
request_id(quote it when contacting support). - Envelope + pagination — the server wraps JSON responses in
{data, meta}. Single-object methods returndataunwrapped; paginated lists takepage/per_page(default 20, cap 100) and return{data: [...], meta: {total, page, per_page, total_pages, request_id}}, with an iterator that walks every page for you. - Raw data plane — proxy calls (
call()/ bound routes /ephemeral()) return the raw HTTP response and never raise on the upstream’s status; legacytk_…/AKE…keys automatically travel asx-knoxcall-key. Mutating data-plane requests are never replayed after they may have reached the wire. - Webhook
constructEvent— verify the delivery’s HMAC-SHA256 signature and parse it into a typed event in one step, across all six signature formats (legacy,stripe,github,slack,aws-sns,custom), with constant-time comparison and replay protection. - Sandbox mode — a
sandboxconstructor option targets the isolated Test environment (sandbox.knoxcall.commanagement host,sandbox-{tenant}.knoxcall.comproxy host) with atk_test_key. - Credential-less
signup()— create an account headlessly with no constructed client (see AI agent onboarding).
Authentication quickstart
Every SDK resolves credentials the same way: explicit constructor options beat environment variables, and conflicting options fail at construction. On a developer machine, log in once with the CLI below and skip configuration entirely. For servers and CI, register an OAuth client (dashboard → Settings → Security → OAuth Clients), set the environment once, and construct with zero arguments:tenant (or setting KNOXCALL_TENANT) just skips the discovery lookup.
Legacy API keys still work everywhere: set
KNOXCALL_API_KEY to a long-lived key (tk_live_…, tk_test_…, AKE…) or a pre-acquired kc_… token instead of the client-credentials pair — or pass it to the constructor as apiKey / api_key. A pre-acquired key is sent as-is and never auto-renewed. Prefer knoxcall login or an OAuth client for new integrations — see Authentication.Log in once with the CLI
On a developer machine, skip credentials entirely. Every KnoxCall SDK package ships theknoxcall command via its own package manager (pip, npm, gem, Composer, go install) — same surface, same credentials file, so it doesn’t matter which one you install. Sign in once in your browser (authorization code + PKCE) and every script, notebook, and agent on the machine — in any of the five languages — picks the credential up automatically. No env vars, no keys in code:
~/.knoxcall/credentials.json (file mode 0600), and the stored tenant and base URL seed the client automatically — explicit constructor options and 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 its typed authentication error telling you to run knoxcall login again. Override the file path with KNOXCALL_CREDENTIALS_FILE; select a non-default profile with KNOXCALL_PROFILE.
Credential resolution order
With no explicit constructor credentials, every SDK resolves from the environment in priority order:KNOXCALL_ACCESS_TOKEN(orKNOXCALL_API_KEY) — a pre-acquired token- The credentials file written by
knoxcall login(~/.knoxcall/credentials.json) - Workload identity auto-detect — Node.js and Python only (GitHub Actions, GCP, AWS IRSA, Azure Managed Identity, Vercel, and other CI OIDC issuers); zero stored secrets in CI
KNOXCALL_CLIENT_ID+KNOXCALL_CLIENT_SECRET— client-credentials grant
Canonical environment variables
Pick your language
Node.js / TypeScript
@knoxcall/sdk — fully typed, DPoP, workload identity, token storesPython
knoxcall — one import, sync or async, thread- and fork-safeGo
knoxcall-go — stdlib only, context-first, goroutine-safePHP
knoxcall/knoxcall-php — PHP-FPM aware token handlingRuby
knoxcall gem — Mutex-safe for Puma and SidekiqTerraform
Routes, secrets, clients, and webhooks as code
Browser Elements
Seal PANs and PII in the page; reveal with single-use capability tokens