Skip to main content

API Changelog

Notable changes to the KnoxCall Management API (/v1) and the first-party SDKs. Newest first. Backwards-compatible additions (new fields, new endpoints, new error types) ship without a version bump; we call out anything that changes existing behavior.
An authorization or device request that names no scope now mints the client's allowed_scopes, not an unnarrowed token
Breaking for OAuth clients that omit scope. client_credentials has always minted a narrowed client’s whole allowed_scopes list when the request named no scope. The authorization_code and device grants did not: a request that named no scope produced a token with an empty scope grant, and an empty grant is read as unnarrowed — it reached every /v1 endpoint, ignoring the client’s allowed_scopes entirely.All three grants now behave the same way:The same resolution runs when the token is minted, so an authorization code or device code issued before the client’s allowed_scopes was narrowed no longer mints the wider set. If the narrowing leaves nothing the credential can carry, the exchange is refused with 400 invalid_scope rather than minting an empty (unnarrowed) grant; re-authorize to obtain a code within the client’s current list.Who is affected. OAuth clients with an explicit allowed_scopes list whose integration omits the scope parameter at GET /oauth/authorize or POST /oauth/device_authorization. Those calls previously produced an unrestricted token; they now produce exactly what the client is configured to allow. API keys, key-mirrored clients and knoxcall login (the CLI client) carry no allow-list to resolve against and are unchanged.What to do. Nothing, if the client’s allowed_scopes already lists what your integration uses. If a call starts returning 403 insufficient_scope, the header and body name the exact scope to add to the client and re-mint. The consent screen now lists those permissions instead of “No specific permissions requested”.
Two GET endpoints that return decrypted material now require their own scope
Breaking for narrowed OAuth tokens. Two /v1 GET endpoints hand back decrypted material rather than a description of it, and until now both were satisfied by the ordinary read scope for their resource family. They now require a scope that names the capability:The first returns a live upstream OAuth2 access token, refreshing it at the provider when it is stale — so it mints a credential rather than reading one. The second returns the cleartext value behind a vault token. Neither is a read of the resource, and granting secrets:read (“Read secret metadata”) or vaults:read (“Read vaults”) was never intended to carry them.Who is affected. Only tokens that were deliberately narrowed. If you authenticate with an API key (tk_/AKE), or with an OAuth client that KnoxCall mirrors from an API key, nothing changes — those callers carry no scope grant to narrow. You are affected if your OAuth client has an explicit allowed_scopes list, because a client_credentials request that names no scope is minted with that whole list.What to do. Add secrets:oauth_token (and/or vaults:detokenize) to the client’s allowed_scopes, then re-mint. A refused call returns 403 insufficient_scope and names the exact scope to request in both the WWW-Authenticate header and the response body:
Universal grants (secrets:*, vaults:*, *:*, *) continue to reach both endpoints.
Unified error envelope, request correlation, cross-worker rate-limit headers, dual idempotency-key header, typed secret creation in SDKs
Unified error envelope + X-Request-Id. Every failure on /v1 now returns one canonical shape — { "error": { "type", "message", "request_id" } } — with a bare-UUID request_id (no req_ prefix). The same ID is now returned on every response, success or error, in the new X-Request-Id header, so you can correlate a request even without parsing the body. Added the forbidden type (403) for RBAC denials. See the new Errors reference.Cross-worker rate-limit headers. Management API rate limits are enforced per API key across all workers. Responses now carry X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (epoch seconds) whenever a limit is configured — not only on 429s — plus Retry-After on a 429. See the new Rate limits reference.Dual idempotency-key header. Mutating requests accept an idempotency key as either X-Idempotency-Key or the standard Idempotency-Key spelling. A retry replays the stored response with X-Idempotent-Replay: true; reuse with a different body returns 422 (idempotency_key_reuse); a still-in-progress request returns 409 (request_in_progress). See the new Idempotency reference.Typed OAuth2 / certificate secret creation in SDKs. The first-party SDKs gained typed helpers for creating OAuth2 and mTLS-certificate secrets, matching the dedicated create OAuth2 secret and create certificate secret endpoints.