Skip to main content
knoxcall-go is the official KnoxCall client for Go — stdlib only, context-first, goroutine-safe (the token store uses single-flight refresh).

Install

Not yet published — install from the monorepo path with a replace directive in your go.mod, or via a git checkout.

Create a client

Set Sandbox: true to target the isolated Test data plane (sandbox.knoxcall.com management host, sandbox-{tenant}.knoxcall.com proxy host) with a tk_test_ key. Passing conflicting credential options (e.g. APIKey and ClientID) is a construction error; explicit options always beat the environment. With no explicit credentials, the SDK resolves 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), then KNOXCALL_CLIENT_ID + KNOXCALL_CLIENT_SECRET. Legacy API keys — a pre-acquired key or token still works everywhere: knoxcall.New(knoxcall.Options{APIKey: os.Getenv("KNOXCALL_API_KEY")}) 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

On a developer machine, run knoxcall login once (this module ships it: go install github.com/knoxcall/knoxcall-go/cmd/knoxcall@latest — every KnoxCall SDK ships the same command). It signs you in via your browser and stores the credential in ~/.knoxcall/credentials.json — Go programs using this SDK pick the file up automatically, including the stored tenant and base URL, and handle refresh (cross-process safe, atomic rotation of the single-use refresh token). Select a profile with KNOXCALL_PROFILE (or Credentials: knoxcall.StoredCredentials{Profile: "staging"}).

Manage resources

Create a route, then list with pagination — single-object methods return the unwrapped object; paginated lists return a typed Page[T]; ListAll walks every page:
The same pattern covers every resource: Secrets, Webhooks, Clients, OAuthClients, Environments, APIKeys, Account, AuditLogs, Agents, Crypto, PKI, Vaults, and DynamicDB. All methods take a context.Context first.

Call routes through the proxy

client.Call() proxies a request through a KnoxCall route to your upstream and returns the raw *http.Response — the upstream’s status belongs to you; the SDK never turns it into an error. Reference routes by slug (write-once, rename-proof); UUIDs also work.
For a per-call timeout, pass a context with a deadline (context.WithTimeout).

Bound routes

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

Verify webhooks

ConstructWebhookEvent (also available as client.Webhooks.ConstructEvent) verifies the delivery’s HMAC-SHA256 signature and parses it into a typed event in one step. Pass the raw body bytes — never re-serialized JSON:
Formats beyond the default legacy header (stripe, github, slack, aws-sns, custom) are selected with &knoxcall.ConstructEventOptions{Format: "stripe"}; the replay window defaults to 300s; custom requires HeaderName.

Handle errors

All API failures are typed and unwrap to *APIError (status, machine-readable type, human message, RequestID for support):
Hierarchy: AuthenticationError (401), PermissionDeniedError (403), NotFoundError (404), ConflictError (409), ValidationError (422), RateLimitError (429), ServerError (5xx), plus SignupError, WebhookSignatureVerificationError, and ConnectionError / ConnectionTimeoutError for transport failures.

Retries and idempotency

Management requests retry automatically on transport errors and HTTP 408/429/500/502/503/504 (never 409), with exponential half-jitter backoff and Retry-After honored up to 30s. Every mutating request carries a ULID X-Idempotency-Key that stays stable across retries. A 401 purges the cached token and retries once with fresh credentials. Tune with Options{RetryMaxAttempts, RetryBaseDelay, RetryMaxDelay}.

DPoP

For higher-security tenants, enable sender-constrained tokens (RFC 9449) — the SDK generates an ES256 keypair, binds the access token via cnf.jkt, and signs a fresh proof per request:
In the default "auto" mode the SDK starts with plain Bearer tokens and upgrades to DPoP automatically when the OAuth client record requires it (require_dpop): the token endpoint answers invalid_dpop_proof, the SDK generates a keypair, retries once, and operates as DPoP from then on. "never" opts out — if the server issues a DPoP-bound token anyway, the SDK returns a clear error rather than 401-looping.

Full reference

The package README documents every resource method, the ephemeral proxy, field-actions, crypto/PKI/vault operations, and credential-less Signup(): sdk/knoxcall-go/README.md in the monorepo.