openapi: 3.2.0 info: title: KnoxCall Client Management Secrets API version: '1.0' description: 'The KnoxCall Client Management API provides programmatic access to manage your API gateway resources including routes, secrets, clients, environments, webhooks, and API keys. ## Authentication All requests must include an OAuth 2.1 access token **or** a legacy API key. The recommended path for new integrations is the first-party SDKs, which mint, cache, and refresh OAuth tokens for you (start with `knoxcall login` on a developer machine, or `KNOXCALL_CLIENT_ID` / `KNOXCALL_CLIENT_SECRET` in CI). You can authenticate using any of: - **Authorization header (OAuth 2.1 bearer token — recommended)**: `Authorization: Bearer ` - **Authorization header (legacy API key)**: `Authorization: Bearer tk_xxx_yyy` - **x-api-key header (legacy API key)**: `x-api-key: tk_xxx_yyy` OAuth 2.1 access tokens (`kc_` prefix) are minted at the root-host token endpoint `https://api.knoxcall.com/oauth/token` (not under `/v1`) using the `client_credentials` or `authorization_code` grant. See the `OAuth2` security scheme and the `/oauth/*` endpoints. Some resources that are managed exclusively through OAuth reject API-key auth with a `403 use_oauth` error. Long-lived API keys remain fully supported. They come in three types: - **Standard keys** (`tk_` prefix) are used on the production API (`api.knoxcall.com`). - **Test keys** (`tk_` prefix, type=test) are used on the sandbox API (`sandbox.knoxcall.com`). - **Enterprise Access Keys** (`AKE` prefix) follow the format `AKE[16chars]:[40chars]`. Using a test key on the production API (or vice versa) will return a `403 wrong_key_type` error. ## Request IDs Every response — success or error — includes an `X-Request-Id` response header (a UUID). Its value is identical to the `request_id` field in the response body (`meta.request_id` on success, `error.request_id` on error). Quote it when contacting support. ## API Versioning The API is versioned on two axes: - **Major version — the `/v1` path prefix.** Breaking changes ship under a new major (`/v2`). `/v1` never receives a breaking change. - **Minor version — the `KnoxCall-Version` header (dated, `YYYY-MM-DD`).** Send `KnoxCall-Version: 2026-08-05` to pin the behaviour of a specific dated release. Omit the header to get the newest minor version. Every response echoes the resolved version back in a `KnoxCall-Version` response header. Within a major version, **additive changes are not breaking** and may appear without a new dated version: new endpoints, new optional request fields, new response fields, new `error.type` values, and new enum members. Clients must tolerate unknown response fields and unknown `error.type` values (see the `ErrorResponse` schema). An **unknown or malformed** `KnoxCall-Version` value returns `400` with `error.type: invalid_api_version`. ## Rate Limiting API keys can have optional rate limits configured. When a limit is configured, the following headers are emitted on **every** response (not only `429`s): - `X-RateLimit-Limit` -- maximum requests allowed per window - `X-RateLimit-Remaining` -- remaining requests in the current window - `X-RateLimit-Reset` -- epoch seconds at which the window resets When the limit is exceeded the API returns `429` (`rate_limit_exceeded` / `rate_limited`) and additionally sets `Retry-After` (seconds until the window resets). ## DPoP sender-constrained tokens, and the server nonce A token minted with a `cnf.jkt` binding (DPoP, RFC 9449) requires a `DPoP` proof header on every request, signed over the request''s method and canonical public URL. **Every response to a request that carried a `DPoP` header also carries a `DPoP-Nonce` response header** -- mints, refusals and successful calls alike, on `POST /oauth/token`, `/v1`, the tenant data plane, the self-hosted proxy and the AI gateway. The value is stateless and changes every minute; the server accepts the current and the previous minute''s, so a nonce is good for 60-120 seconds.' contact: name: KnoxCall Support url: https://knoxcall.com email: support@knoxcall.com license: name: Proprietary url: https://knoxcall.com/terms servers: - url: https://api.knoxcall.com/v1 description: Production - url: https://sandbox.knoxcall.com/v1 description: Sandbox (test keys only) security: - OAuth2: [] - BearerAuth: [] - ApiKeyAuth: [] tags: - name: Secrets description: Manage encrypted secrets injected into route headers and bodies. paths: /secrets: get: operationId: listSecrets summary: List secrets description: Returns a paginated list of secret metadata. Secret values are never returned by the API. tags: - Secrets parameters: - $ref: '#/components/parameters/PageParam' - $ref: '#/components/parameters/PerPageParam' - name: sort in: query schema: type: string enum: - created_at - name - base_environment default: name description: Field to sort by. - $ref: '#/components/parameters/OrderParam' responses: '200': description: A paginated list of secrets. content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Secret' meta: $ref: '#/components/schemas/PaginationMeta' '401': $ref: '#/components/responses/Unauthorized' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' post: operationId: createSecret summary: Create a secret description: 'Creates a new encrypted secret. Pass `secret_type` to choose the secret variant: | `secret_type` | Use case | |---|---| | `string` (default) | Any static value — API keys, tokens, passwords | | `oauth2` | OAuth2 connection with automatic token refresh | | `certificate` | TLS/mTLS certificate + optional private key | For `oauth2` secrets, see the field reference under **POST /secrets/oauth2**. For `certificate` secrets, see **POST /secrets/certificate**. String secrets require only `name` and `value`.' tags: - Secrets parameters: - $ref: '#/components/parameters/IdempotencyKeyParam' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateSecretRequest' examples: string: summary: String secret value: name: STRIPE_SECRET_KEY value: REDACTED_STRIPE_KEY_abc123def456 oauth2: summary: OAuth2 secret (Google) value: secret_type: oauth2 name: GOOGLE_OAUTH provider: google client_id: 1234567890.apps.googleusercontent.com client_secret: GOCSPX-abc123 scopes: - openid - email - profile certificate: summary: Certificate secret (PEM) value: secret_type: certificate name: MY_TLS_CERT certificate_type: pem certificate_content: '-----BEGIN CERTIFICATE----- ...' private_key: REDACTED_PRIVATE_KEY_EXAMPLE pem_only: summary: PEM certificate only (no private key) value: name: CA_CERT certificate_type: pem certificate_content: '-----BEGIN CERTIFICATE----- MIID...== -----END CERTIFICATE-----' responses: '200': description: Certificate secret created. content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/CertificateSecretCreated' meta: $ref: '#/components/schemas/RequestMeta' '400': $ref: '#/components/responses/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '402': $ref: '#/components/responses/PlanLimit' '409': $ref: '#/components/responses/Conflict' '422': $ref: '#/components/responses/IdempotencyKeyReuse' '429': $ref: '#/components/responses/RateLimited' '500': $ref: '#/components/responses/InternalError' components: schemas: RequestMeta: type: object description: Metadata included with every API response. properties: request_id: type: string format: uuid description: Unique identifier for this API request, useful for support and debugging. example: 550e8400-e29b-41d4-a716-446655440000 required: - request_id CreateOAuth2SecretRequest: type: object required: - name - provider - client_id properties: secret_type: type: string enum: - oauth2 description: Must be `oauth2` when using this schema via `POST /secrets`. name: type: string description: Secret name. Spaces are replaced with underscores. example: GOOGLE_OAUTH provider: type: string enum: - google - github - salesforce - microsoft - slack - custom description: 'OAuth2 provider. Use `custom` for any provider not listed — you must then supply `auth_url` and `token_url`. ' example: google client_id: type: string description: OAuth2 client ID (from your provider's developer console). example: 1234567890.apps.googleusercontent.com client_secret: type: string description: 'OAuth2 client secret. Required unless using `mtls_certificate_id` for mTLS auth or `grant_type: implicit`. ' example: GOCSPX-abc123 grant_type: type: string enum: - authorization_code - client_credentials - password - implicit default: authorization_code description: 'OAuth2 grant type: - `authorization_code` (default) — redirects user to `redirect_uri` for consent - `client_credentials` — server-to-server; tokens fetched immediately - `password` — ROPC flow; requires `username` and `password` - `implicit` — legacy browser flow (not recommended) ' scopes: type: array items: type: string description: OAuth2 scopes to request. Defaults to the provider's recommended scopes. example: - openid - email - profile auth_url: type: string format: uri description: 'Authorization endpoint URL. Accepted only when `provider` is `custom` — for every other provider the platform''s known default is used and this field is ignored. Must be an absolute `https://` URL with no embedded credentials and no `#` fragment; anything else is rejected with `validation_error`. A query string is allowed (Azure AD B2C''s `?p=`) and is preserved. ' example: https://accounts.google.com/o/oauth2/v2/auth token_url: type: string format: uri description: 'Token endpoint URL. Accepted only when `provider` is `custom` — for every other provider the platform''s known default is used and this field is ignored. Must be an absolute `https://` URL with no embedded credentials and no `#` fragment; `http://` is rejected because this endpoint receives the client secret. ' example: https://oauth2.googleapis.com/token username: type: string description: Username for `password` grant type. password: type: string description: Password for `password` grant type. mtls_certificate_id: type: string format: uuid description: 'ID of a `certificate`-type secret to use for mTLS authentication to the token endpoint instead of `client_secret`. ' collection_id: type: string format: uuid description: Assign this secret to a collection. Secret: type: object description: 'Secret metadata. Secret values are never returned by the API. Reference secrets in route injection configs using `{{SECRET_NAME}}` syntax. ' properties: id: type: string format: uuid example: a7c1d8f3-2e4b-4c6a-8d9e-1f3b5a7c9d2e name: type: string description: The secret name (spaces normalized to underscores). example: STRIPE_SECRET_KEY shortcode_name: type: string description: Short name used in template references. example: STRIPE_SECRET_KEY base_environment: type: string description: Default environment for this secret. example: production secret_type: type: string enum: - string - oauth2 - certificate description: The type of secret. example: string environment_count: type: integer description: Number of environments this secret has values configured in. example: 2 collection_id: type: - string - 'null' format: uuid description: Collection this secret belongs to, if any. expires_at: type: - string - 'null' format: date-time description: When the secret expires. Null for no expiry. On write, must be within 20 years of now — far-future sentinels like 9999-12-31 are rejected with 400. strict_expiry_enforcement: type: boolean description: When true, the proxy refuses to inject the secret after it expires. created_at: type: string format: date-time example: '2025-03-15T10:30:00.000Z' PaginationMeta: type: object description: Pagination metadata for list endpoints. properties: total: type: integer description: Total number of records matching the query. example: 42 page: type: integer description: Current page number. example: 1 per_page: type: integer description: Number of records per page. example: 20 total_pages: type: integer description: Total number of pages, capped at the deepest page the 100,000-row offset ceiling allows -- `min(ceil(total / per_page), floor(100000 / per_page) + 1)`. When it is below `ceil(total / per_page)` the result set is larger than pagination can reach; narrow it with a filter. example: 3 request_id: type: string format: uuid description: Unique identifier for this API request. example: 550e8400-e29b-41d4-a716-446655440000 required: - total - page - per_page - total_pages - request_id ErrorResponse: type: object description: Standard error response envelope. properties: error: type: object properties: type: type: string description: 'Machine-readable error type. The set is OPEN — endpoints define specific types beyond the common ones below, so clients should branch on the types they know and fall back to the HTTP status class for anything unrecognized. Common values: authentication_required, invalid_api_key, wrong_key_type, subscription_inactive, rate_limit_exceeded, validation_error, forbidden, not_found, method_not_allowed (405, carries Allow), conflict, in_use, plan_limit, plan_feature, internal_error, dependency_unavailable (503, carries Retry-After), invalid_request, invalid_definition, not_cancellable, invalid_idempotency_key, idempotency_key_reuse, request_in_progress, system_client_protected, use_oauth, use_dpop_nonce (401 on /v1 and the data plane, 400 on POST /oauth/token; see "DPoP sender-constrained tokens").' example: validation_error message: type: string description: Human-readable error message. example: name and target_base_url are required. request_id: type: string format: uuid description: Unique identifier for this request. example: 550e8400-e29b-41d4-a716-446655440000 required: - type - message - request_id required: - error CreateSecretRequest: description: 'Creates a secret. Set `secret_type` to choose the variant: - `string` (default) — requires `name` and `value` - `oauth2` — requires OAuth2 fields (see `CreateOAuth2SecretRequest`) - `certificate` — requires certificate fields (see `CreateCertificateSecretRequest`) ' oneOf: - title: String secret type: object required: - name - value properties: secret_type: type: string enum: - string default: string description: Omit or set to `string` for a static value secret. name: type: string description: Secret name. Spaces are replaced with underscores. example: STRIPE_SECRET_KEY value: type: string description: The secret value to encrypt and store. example: REDACTED_STRIPE_KEY_abc123def456 collection_id: type: string format: uuid description: Assign this secret to a collection. expires_at: type: - string - 'null' format: date-time description: Optional expiry timestamp (ISO-8601). strict_expiry_enforcement: type: boolean default: false description: When true, the proxy refuses to inject the secret after it expires. - $ref: '#/components/schemas/CreateOAuth2SecretRequest' - $ref: '#/components/schemas/CreateCertificateSecretRequest' CreateCertificateSecretRequest: type: object required: - name - certificate_content properties: secret_type: type: string enum: - certificate description: Must be `certificate` when using this schema via `POST /secrets`. name: type: string description: Secret name. Spaces are replaced with underscores. example: MY_TLS_CERT certificate_content: type: string description: 'The certificate in PEM, PKCS#7, CRT/CER format, or as a base64-encoded DER/PFX/P12 blob. For PEM, include the full `-----BEGIN CERTIFICATE-----` block. ' example: '-----BEGIN CERTIFICATE----- MIID...== -----END CERTIFICATE-----' private_key: type: string description: 'Optional PEM-encoded private key. If provided, it is combined with the certificate content before encryption. ' example: REDACTED_PRIVATE_KEY_EXAMPLE passphrase: type: string description: 'Optional passphrase to decrypt the private key. Encrypted and stored separately from the certificate. ' certificate_type: type: string enum: - pem - pfx - p12 - crt - cer - key - pkcs7 - p7b - p7c default: pem description: 'Format of the certificate content: - `pem` / `crt` / `cer` — PEM-encoded X.509 certificate (metadata auto-extracted) - `pkcs7` / `p7b` / `p7c` — PKCS#7 certificate bundle (metadata auto-extracted) - `pfx` / `p12` — Binary PKCS#12 bundle (pass as base64) - `key` — Standalone private key ' example: pem collection_id: type: string format: uuid description: Assign this secret to a collection. CertificateSecretCreated: type: object description: Response after creating a certificate secret. properties: id: type: string format: uuid description: The new secret's ID. example: b9e3f0a5-4c6d-5e8f-0f1a-3b5d7e9f1a3b name: type: string description: Normalized secret name. example: MY_TLS_CERT secret_type: type: string enum: - certificate example: certificate certificate_type: type: string example: pem base_environment: type: string example: production collection_id: type: - string - 'null' format: uuid metadata: type: object description: 'Parsed certificate metadata (for PEM, CRT, CER, PKCS#7 formats). Null fields indicate the value could not be extracted from the certificate. ' properties: subject: type: - string - 'null' description: Certificate subject distinguished name. example: CN=example.com, O=Example Inc, C=US issuer: type: - string - 'null' description: Certificate issuer distinguished name. example: CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US expires_at: type: - string - 'null' format: date-time description: Certificate expiry date/time. example: '2026-03-15T12:00:00.000Z' has_private_key: type: boolean description: Whether a private key was stored alongside the certificate. example: true has_passphrase: type: boolean description: Whether a passphrase was stored for the private key. The platform never returns the passphrase itself; this boolean is the only confirmation that one was received and stored. example: true responses: PlanLimit: description: 'Payment Required. The action exceeds your plan''s limits. Two `error.type` values share this status: `plan_limit` when a COUNTED resource quota was reached (routes, secrets, AI agents, MCP servers), and `plan_feature` when the CAPABILITY itself is not on your tier (custom PII redaction policies, compliance packs, custom prompt-firewall policies). Both mean "upgrade to proceed"; branch on `type` only if you want to distinguish "you have used your allowance" from "buy a bigger plan". Neither ever revokes something you already have: a plan downgrade leaves existing agents, policies and installed packs in place and keeps working. ' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' KnoxCall-Version: $ref: '#/components/headers/KnoxCall-Version' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: type: plan_limit message: Route limit reached (10). Upgrade your plan to add more. request_id: 550e8400-e29b-41d4-a716-446655440000 Conflict: description: A resource with the same unique identifier already exists, or the resource is in use. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' KnoxCall-Version: $ref: '#/components/headers/KnoxCall-Version' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: type: conflict message: A route with this name already exists. request_id: 550e8400-e29b-41d4-a716-446655440000 InternalError: description: An unexpected server error occurred. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' KnoxCall-Version: $ref: '#/components/headers/KnoxCall-Version' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: type: internal_error message: An unexpected error occurred. request_id: 550e8400-e29b-41d4-a716-446655440000 Unauthorized: description: Authentication is required or the provided API key is invalid. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' KnoxCall-Version: $ref: '#/components/headers/KnoxCall-Version' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' examples: missing_key: summary: No API key provided value: error: type: authentication_required message: 'API key is required. Use Authorization: Bearer or x-api-key header.' request_id: 550e8400-e29b-41d4-a716-446655440000 invalid_key: summary: Invalid API key value: error: type: invalid_api_key message: Invalid API key. request_id: 550e8400-e29b-41d4-a716-446655440000 IdempotencyKeyReuse: description: 'The supplied idempotency key was already used for a request with a different body. Idempotency keys may only be reused with an identical request. ' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' KnoxCall-Version: $ref: '#/components/headers/KnoxCall-Version' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: type: idempotency_key_reuse message: This idempotency key was already used with a different request body. request_id: 550e8400-e29b-41d4-a716-446655440000 ValidationError: description: The request failed validation (always `400 validation_error`). A malformed idempotency key returns `400 invalid_idempotency_key`. headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' KnoxCall-Version: $ref: '#/components/headers/KnoxCall-Version' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' examples: validation_error: summary: Request body failed validation value: error: type: validation_error message: name and target_base_url are required. request_id: 550e8400-e29b-41d4-a716-446655440000 invalid_idempotency_key: summary: Malformed idempotency key value: error: type: invalid_idempotency_key message: X-Idempotency-Key must be a non-empty string of at most 255 characters. request_id: 550e8400-e29b-41d4-a716-446655440000 RateLimited: description: 'Too many requests. Retry after the indicated time. The `X-RateLimit-*` headers are also present on non-429 responses whenever a limit is configured. ' headers: X-Request-Id: $ref: '#/components/headers/X-Request-Id' KnoxCall-Version: $ref: '#/components/headers/KnoxCall-Version' X-RateLimit-Limit: $ref: '#/components/headers/X-RateLimit-Limit' X-RateLimit-Remaining: $ref: '#/components/headers/X-RateLimit-Remaining' X-RateLimit-Reset: $ref: '#/components/headers/X-RateLimit-Reset' Retry-After: $ref: '#/components/headers/Retry-After' content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' example: error: type: rate_limit_exceeded message: API rate limit exceeded. Please retry later. request_id: 550e8400-e29b-41d4-a716-446655440000 headers: X-RateLimit-Remaining: description: 'Remaining requests in the current window. Emitted on every response whenever a rate limit is configured for the authenticated key. ' schema: type: integer example: 999 KnoxCall-Version: description: 'The dated API version (`YYYY-MM-DD`) that served this response. Equals the value of the `KnoxCall-Version` request header when supplied, otherwise the newest version. ' schema: type: string pattern: ^\d{4}-\d{2}-\d{2}$ example: '2026-08-05' X-Request-Id: description: 'Unique identifier for this request (UUID). Present on **every** response and equal to the `request_id` field in the response body. Quote it when contacting support. ' schema: type: string format: uuid example: 550e8400-e29b-41d4-a716-446655440000 Retry-After: description: Seconds to wait before retrying. Set on `429` responses. schema: type: integer example: 30 X-RateLimit-Reset: description: 'Epoch seconds at which the current rate-limit window resets. Emitted on every response whenever a rate limit is configured for the authenticated key. ' schema: type: integer example: 1735689600 X-RateLimit-Limit: description: 'Maximum requests allowed per window. Emitted on every response whenever a rate limit is configured for the authenticated key. ' schema: type: integer example: 1000 parameters: OrderParam: name: order in: query schema: type: string enum: - asc - desc default: desc description: Sort direction. PageParam: name: page in: query schema: type: integer minimum: 1 default: 1 description: Page number for pagination. Clamped server-side so the derived offset never exceeds 100,000 rows -- the effective maximum is `floor(100000 / per_page) + 1`, i.e. 1,001 at `per_page=100`. A larger value returns that last page, and `meta.page` reports it. PerPageParam: name: per_page in: query schema: type: integer minimum: 1 maximum: 100 default: 20 description: Number of items per page (max 100). IdempotencyKeyParam: name: X-Idempotency-Key in: header required: false schema: type: string maxLength: 255 description: 'Optional idempotency key so a retried mutating request is executed at most once. The standard `Idempotency-Key` spelling is also accepted. Replaying a completed request with the same key returns the original stored response with an `X-Idempotent-Replay: true` header. A key still in progress returns `409 request_in_progress`; the same key with a different body returns `422 idempotency_key_reuse`; a malformed key returns `400 invalid_idempotency_key`. ' example: 3f6c9b2e-1a4d-4c8e-9b0a-7d2e5f1c3a8b securitySchemes: OAuth2: type: oauth2 description: 'OAuth 2.1 authentication — recommended for new integrations. Access tokens (`kc_` prefix) are minted at the root-host token endpoint `https://api.knoxcall.com/oauth/token` and passed as `Authorization: Bearer `. Public clients must use PKCE with the `authorization_code` grant; confidential clients may use `client_credentials`. The first-party SDKs and the `knoxcall login` CLI handle token minting, caching, refresh, and DPoP for you. ' flows: clientCredentials: tokenUrl: https://api.knoxcall.com/oauth/token refreshUrl: https://api.knoxcall.com/oauth/token scopes: routes:read: Read routes. routes:write: Create, update, and delete routes. secrets:read: Read secret metadata. Does NOT include retrieving a live OAuth2 access token. secrets:oauth_token: Retrieve a live upstream OAuth2 access token (GET /v1/secrets/{id}/oauth2/token). Distinct from secrets:read because the call refreshes the credential at the provider. secrets:write: Create, update, and delete secrets. vaults:detokenize: Turn a vault token back into its original value. Required by GET /v1/vaults/{vault}/tokens/{token}, by a token template reference in a /v1/proxy body, and by creating a `detokenize` route action. Distinct from vaults:read, which lists vaults and token metadata and never returns a value. transit:decrypt: Open a portable `kc:` ciphertext with a tenant transit key. Required by creating a `decrypt` route action, which stores a standing instruction to open every matching field on every later request through that route. It is the same capability name the policy engine uses for POST /v1/decrypt. No routes scope satisfies it — managing a route is not permission to open the data flowing through it. proxy:invoke: Call the one-shot ephemeral proxy (any method on /v1/proxy). Required for EVERY verb — the proxy is one capability behind one handler, and a bodyless GET spends an escrowed credential exactly as a POST does. Neither proxy:read nor proxy:write satisfies it. clients:read: Read clients. clients:write: Manage clients. webhooks:write: Manage webhooks. workflows:write: Manage and execute workflows. '*:*': Full access (all scopes). authorizationCode: authorizationUrl: https://api.knoxcall.com/oauth/authorize tokenUrl: https://api.knoxcall.com/oauth/token refreshUrl: https://api.knoxcall.com/oauth/token scopes: routes:read: Read routes. routes:write: Create, update, and delete routes. secrets:read: Read secret metadata. Does NOT include retrieving a live OAuth2 access token. secrets:oauth_token: Retrieve a live upstream OAuth2 access token (GET /v1/secrets/{id}/oauth2/token). Distinct from secrets:read because the call refreshes the credential at the provider. secrets:write: Create, update, and delete secrets. vaults:detokenize: Turn a vault token back into its original value. Required by GET /v1/vaults/{vault}/tokens/{token}, by a token template reference in a /v1/proxy body, and by creating a `detokenize` route action. Distinct from vaults:read, which lists vaults and token metadata and never returns a value. transit:decrypt: Open a portable `kc:` ciphertext with a tenant transit key. Required by creating a `decrypt` route action, which stores a standing instruction to open every matching field on every later request through that route. It is the same capability name the policy engine uses for POST /v1/decrypt. No routes scope satisfies it — managing a route is not permission to open the data flowing through it. proxy:invoke: Call the one-shot ephemeral proxy (any method on /v1/proxy). Required for EVERY verb — the proxy is one capability behind one handler, and a bodyless GET spends an escrowed credential exactly as a POST does. Neither proxy:read nor proxy:write satisfies it. clients:read: Read clients. clients:write: Manage clients. webhooks:write: Manage webhooks. workflows:write: Manage and execute workflows. '*:*': Full access (all scopes). PhantomToken: type: http scheme: bearer description: "The AI **data plane** credential — a `kp_`-prefixed capability token, not a\nManagement API credential. It is minted per agent (or per MCP resource) at\n`POST /v1/ai-gateway/agents/{agentId}/tokens`, or exchanged from a CI workload's\nOIDC token at `POST /v1/oauth/token`, and it is the ONLY credential `/v1/ai/*`\naccepts: an OAuth `kc_` access token or a `tk_` API key is refused there, and a\n`kp_` token is refused on `api.knoxcall.com`.\n\nThree header spellings are accepted, so an existing provider SDK can be pointed at\nthe agent URL without rewriting its auth:\n\n Authorization: Bearer kp_live_a_...\n x-api-key: kp_live_a_...\n x-knox-ai-key: kp_live_a_...\n\n`kp_live_` is refused on the sandbox host and `kp_test_` on the Live host — the env\nsegment is enforced, not cosmetic. DPoP-bound tokens additionally require a valid\n`DPoP` proof header on every request, signed over the canonical public URL rather\nthan a rewritten `Host`.\n\nA rejected credential answers `401`/`403` in the data-plane error envelope with the\ncause in `code` and in the `X-Auth-Failure` response header.\n" BearerAuth: type: http scheme: bearer description: 'Legacy long-lived API key authentication via the Authorization header. Pass your API key as: `Authorization: Bearer tk_xxx_yyy`. Standard keys (`tk_` prefix) are accepted on `api.knoxcall.com`. Test keys (type=test) are accepted on `sandbox.knoxcall.com`. Enterprise Access Keys (`AKE` prefix) are accepted on both. Fully supported, but prefer the `OAuth2` scheme (or the SDKs, which handle OAuth for you) for new integrations. ' ApiKeyAuth: type: apiKey in: header name: x-api-key description: 'Legacy API key authentication via the `x-api-key` header. This is an alternative to Bearer token authentication for clients that cannot set the `Authorization` header. Prefer the `OAuth2` scheme for new integrations. ' CapabilityTokenAuth: type: http scheme: bearer description: 'Single-use client capability token (`kct_` prefix), passed as `Authorization: Bearer kct_...`. Minted server-side via `POST /client-tokens` and bound either to one exact payload + action (`decrypt`, `detokenize`) or to one vault + a closed set of page origins (`tokenize`). This is NOT an API key — it authenticates only the `POST /client/decrypt`, `POST /client/detokenize` and `POST /client/tokenize` consume endpoints and is invalidated after its first use. '