github.com/knoxcall/sdk-go is the official KnoxCall client for Go — stdlib only, context-first, goroutine-safe (the token store uses single-flight refresh).
Install
knoxcall, imported as github.com/knoxcall/sdk-go/knoxcall. Module: github.com/knoxcall/sdk-go on pkg.go.dev. Source: github.com/KnoxCall/sdk-go.
Create a client
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, runknoxcall login once (this module ships it: go install github.com/knoxcall/sdk-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 typedPage[T]; ListAll walks every page:
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.
path is the upstream path. On a KnoxCall cloud tenant host the data plane is served under /api (https://{tenant}.knoxcall.com/api/<path>); the SDK adds that prefix itself whenever the proxy base is a cloud tenant host with no path of its own, and uses any other base verbatim (self-hosted, or an override that already carries a path). So /api/v2/tickets reaches an upstream path that itself begins with /api.
For a per-call timeout, pass a context with a deadline (context.WithTimeout).
Bound routes
State the route (and optional defaults) once withclient.Route(), then use plain HTTP verbs:
Call().
Route-aware interception (preview)
Send an untouched third-party SDK’s traffic through the Route that covers it — and through the ephemeral proxy where no Route does — with no per-SDK wiring. Turn the Route’s Intercept toggle on and it takes effect on the next poll (60 s) or the next refusal, with no code change. The full decision order, what is and is not reached, and the hooks are on Route-aware interception.Intercept swaps http.DefaultTransport for a route-aware RoundTripper wrapping the previous one; Stop() restores it. Reached: http.DefaultClient and any *http.Client with a nil Transport (most SDK defaults). Not reached: a client built with its own Transport — hand those client.Wrap.RoundTripper(knoxcall.WithRoutes()), which makes the same decisions on an explicit transport (Ready(), Refresh(ctx), Manifest(), Stop()). Per-host options: knoxcall.WithHost("api.resend.com", knoxcall.HostEscrow("resend-key")) (escrow) or knoxcall.HostUnavailableDirect() (transit only); knoxcall.WithRequireContext() limits interception to requests whose context descends from client.Wrap.Routed(ctx). KNOXCALL_INTERCEPT=off is the kill switch.
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:
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):
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 andRetry-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 viacnf.jkt, and signs a fresh proof per request:
"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-lessSignup(): github.com/KnoxCall/sdk-go.