Operation details
GET /v1/security-jwt-key-sets
List JWT key sets
- operationId
listSecurityJWTKeySets- Auth
- API key: header Authorization: CdncaKey <key_id>.<secret>. Effective permissions are the key scopes intersected with the owner’s current permissions.
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Requires security_policies.read. Tenant identities only. key_count counts the keys of an allowed algorithm (what the nodes get); reference_count the tenant's live policies naming the set.
Responses
listSecurityJWTKeySets Responses| Status | Description |
|---|
200 | Sets by name. Fields:items: array<SecurityJWTKeySet> |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
POST /v1/security-jwt-key-sets
Create a JWT key set
- operationId
createSecurityJWTKeySet- Auth
- API key: header Authorization: CdncaKey <key_id>.<secret>. Effective permissions are the key scopes intersected with the owner’s current permissions.
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Requires security_policies.manage; tenant only. A remote set is fetched once (https, public addresses only, checked after DNS); a failed fetch still creates it with fetch_state failing and no keys, except a URL resolving to a non-public address (validation_error jwks_url blocked_address). A static set takes a JWK Set in jwks: public keys only (a private member refuses it: jwks contains_private_key), RSA 2048-8192 / EC P-256 / Ed25519, at least one of an allowed algorithm (jwks no_usable_key). Other field reasons: jwks_url not_https, jwks invalid_json / too_many_keys. At most 50 live sets per tenant (422 jwt_key_set_limit). Audit security.jwt_key_set.create.
Parameters
createSecurityJWTKeySet Parameters| Name | In | Type | Required | Description |
|---|
Idempotency-Key | header | string | Yes | — |
|---|
Request body
application/json · Required:Yes
createSecurityJWTKeySet Request body| Name | Type | Required | Description |
|---|
name | string | Yes | — |
|---|
description | string | No | — |
|---|
source | string: remote / static | Yes | Fixed at creation. |
|---|
jwks_url | string(uri) | No | remote only; https, public address. |
|---|
refresh_seconds | integer | No | remote only. |
|---|
jwks | object | No | static only; a JWK Set ({keys: [...]}), public keys only, at most 256 KiB. |
|---|
algorithms | array<string: RS256 / ES256 / EdDSA> | Yes | — |
|---|
token_sources | array<SecurityJWTTokenSource> | Yes | The node takes the first token found |
|---|
issuer | string | No | Empty skips the iss check. |
|---|
audiences | array<string> | No | Empty skips the aud check. |
|---|
require_exp | boolean | No | — |
|---|
clock_skew_seconds | integer | No | — |
|---|
failure_status | integer: 403 / 401 | No | What a blocking jwt_invalid rule answers: 403 the block page, 401 with WWW-Authenticate: Bearer. |
|---|
Responses
createSecurityJWTKeySet Responses| Status | Description |
|---|
201 | Created, or an identical request replayed. Fields:id: string(uuid) name: string description: string source: string: remote / static jwks_url?: string refresh_seconds?: integer algorithms: array<string> token_sources: array<SecurityJWTTokenSource> issuer?: string audiences: array<string> require_exp: boolean clock_skew_seconds: integer failure_status: integer: 403 / 401 keys: array<SecurityJWTKey> ignored_keys: array<object> key_count: integer keys_revision: integer fetch_state: string: none / ok / failing fetch_failures: integer fetch_error?: string: dns / blocked_address / tls / http_status / too_large / content_type / invalid_json / contains_private_key / no_usable_key / network fetched_at?: string(date-time) next_fetch_at?: string(date-time) refresh_available_at?: string(date-time) reference_count: integer revision: integer updated_at: string(date-time) |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
409 | The requested state conflicts with an existing resource or idempotency fact. |
|---|
422 | The request is well formed but breaks a business rule (error.code names it). |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
GET /v1/security-jwt-key-sets/{set_id}
Get a JWT key set
- operationId
getSecurityJWTKeySet- Auth
- API key: header Authorization: CdncaKey <key_id>.<secret>. Effective permissions are the key scopes intersected with the owner’s current permissions.
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Requires security_policies.read. The set with its normalized public keys and the keys the last JWKS left out.
Parameters
getSecurityJWTKeySet Parameters| Name | In | Type | Required | Description |
|---|
set_id | path | string(uuid) | Yes | — |
|---|
Responses
getSecurityJWTKeySet Responses| Status | Description |
|---|
200 | The set. Fields:id: string(uuid) name: string description: string source: string: remote / static jwks_url?: string refresh_seconds?: integer algorithms: array<string> token_sources: array<SecurityJWTTokenSource> issuer?: string audiences: array<string> require_exp: boolean clock_skew_seconds: integer failure_status: integer: 403 / 401 keys: array<SecurityJWTKey> ignored_keys: array<object> key_count: integer keys_revision: integer fetch_state: string: none / ok / failing fetch_failures: integer fetch_error?: string: dns / blocked_address / tls / http_status / too_large / content_type / invalid_json / contains_private_key / no_usable_key / network fetched_at?: string(date-time) next_fetch_at?: string(date-time) refresh_available_at?: string(date-time) reference_count: integer revision: integer updated_at: string(date-time) |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
PUT /v1/security-jwt-key-sets/{set_id}
Replace a JWT key set
- operationId
updateSecurityJWTKeySet- Auth
- API key: header Authorization: CdncaKey <key_id>.<secret>. Effective permissions are the key scopes intersected with the owner’s current permissions.
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Requires security_policies.manage and the current revision. source cannot change. A static set sent without jwks keeps its keys. A remote set whose jwks_url changes is fetched first and refused when that fetch fails (validation_error jwks_url fetch_<category>, or blocked_address). Algorithms leaving no key are refused (algorithms no_usable_key). Every tenant whose bound WAF policy names the set is republished (system trigger jwt_key_set). Audit security.jwt_key_set.update.
Parameters
updateSecurityJWTKeySet Parameters| Name | In | Type | Required | Description |
|---|
Idempotency-Key | header | string | Yes | — |
|---|
set_id | path | string(uuid) | Yes | — |
|---|
Request body
application/json · Required:Yes
updateSecurityJWTKeySet Request body| Name | Type | Required | Description |
|---|
name | string | Yes | — |
|---|
description | string | No | — |
|---|
source | string: remote / static | Yes | Fixed at creation. |
|---|
jwks_url | string(uri) | No | remote only; https, public address. |
|---|
refresh_seconds | integer | No | remote only. |
|---|
jwks | object | No | static only; a JWK Set ({keys: [...]}), public keys only, at most 256 KiB. |
|---|
algorithms | array<string: RS256 / ES256 / EdDSA> | Yes | — |
|---|
token_sources | array<SecurityJWTTokenSource> | Yes | The node takes the first token found |
|---|
issuer | string | No | Empty skips the iss check. |
|---|
audiences | array<string> | No | Empty skips the aud check. |
|---|
require_exp | boolean | No | — |
|---|
clock_skew_seconds | integer | No | — |
|---|
failure_status | integer: 403 / 401 | No | What a blocking jwt_invalid rule answers: 403 the block page, 401 with WWW-Authenticate: Bearer. |
|---|
expected_revision | integer | Yes | — |
|---|
Responses
updateSecurityJWTKeySet Responses| Status | Description |
|---|
200 | Replaced (revision + 1), or an identical request replayed. Fields:id: string(uuid) name: string description: string source: string: remote / static jwks_url?: string refresh_seconds?: integer algorithms: array<string> token_sources: array<SecurityJWTTokenSource> issuer?: string audiences: array<string> require_exp: boolean clock_skew_seconds: integer failure_status: integer: 403 / 401 keys: array<SecurityJWTKey> ignored_keys: array<object> key_count: integer keys_revision: integer fetch_state: string: none / ok / failing fetch_failures: integer fetch_error?: string: dns / blocked_address / tls / http_status / too_large / content_type / invalid_json / contains_private_key / no_usable_key / network fetched_at?: string(date-time) next_fetch_at?: string(date-time) refresh_available_at?: string(date-time) reference_count: integer revision: integer updated_at: string(date-time) |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
409 | The requested state conflicts with an existing resource or idempotency fact. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
DELETE /v1/security-jwt-key-sets/{set_id}
Delete a JWT key set
- operationId
deleteSecurityJWTKeySet- Auth
- API key: header Authorization: CdncaKey <key_id>.<secret>. Effective permissions are the key scopes intersected with the owner’s current permissions.
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Requires security_policies.manage and the current revision. A set any live policy version names is refused (409 jwt_key_set_in_use). Audit security.jwt_key_set.delete.
Parameters
deleteSecurityJWTKeySet Parameters| Name | In | Type | Required | Description |
|---|
Idempotency-Key | header | string | Yes | — |
|---|
set_id | path | string(uuid) | Yes | — |
|---|
expected_revision | query | integer | Yes | — |
|---|
Responses
deleteSecurityJWTKeySet Responses| Status | Description |
|---|
204 | Deleted. |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
409 | The requested state conflicts with an existing resource or idempotency fact. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
GET /v1/security-jwt-key-sets/{set_id}/references
List the policies naming a JWT key set
- operationId
listSecurityJWTKeySetReferences- Auth
- API key: header Authorization: CdncaKey <key_id>.<secret>. Effective permissions are the key scopes intersected with the owner’s current permissions.
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Requires security_policies.read. The tenant's live policies with a version naming the set; rule_count is from the latest such version.
Parameters
listSecurityJWTKeySetReferences Parameters| Name | In | Type | Required | Description |
|---|
set_id | path | string(uuid) | Yes | — |
|---|
Responses
listSecurityJWTKeySetReferences Responses| Status | Description |
|---|
200 | Policies by name. Fields:items: array<SecurityStringSetReference> |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
POST /v1/security-jwt-key-sets/{set_id}/refresh
Fetch a JWT key set's JWKS now
- operationId
refreshSecurityJWTKeySet- Auth
- API key: header Authorization: CdncaKey <key_id>.<secret>. Effective permissions are the key scopes intersected with the owner’s current permissions.
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Requires security_policies.manage. Remote sets only (409 jwt_key_set_not_remote); once a minute per set (429 refresh_too_frequent, refresh_available_at says when). A failed fetch keeps the last good keys and is returned in fetch_state / fetch_error, not as an error. New keys republish the tenants naming the set. Audit security.jwt_key_set.refresh.
Parameters
refreshSecurityJWTKeySet Parameters| Name | In | Type | Required | Description |
|---|
set_id | path | string(uuid) | Yes | — |
|---|
Responses
refreshSecurityJWTKeySet Responses| Status | Description |
|---|
200 | The set after the fetch. Fields:id: string(uuid) name: string description: string source: string: remote / static jwks_url?: string refresh_seconds?: integer algorithms: array<string> token_sources: array<SecurityJWTTokenSource> issuer?: string audiences: array<string> require_exp: boolean clock_skew_seconds: integer failure_status: integer: 403 / 401 keys: array<SecurityJWTKey> ignored_keys: array<object> key_count: integer keys_revision: integer fetch_state: string: none / ok / failing fetch_failures: integer fetch_error?: string: dns / blocked_address / tls / http_status / too_large / content_type / invalid_json / contains_private_key / no_usable_key / network fetched_at?: string(date-time) next_fetch_at?: string(date-time) refresh_available_at?: string(date-time) reference_count: integer revision: integer updated_at: string(date-time) |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
409 | The requested state conflicts with an existing resource or idempotency fact. |
|---|
429 | refresh_too_frequent. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.409 Read the current state first; a retry of the same operation keeps the original Idempotency-Key and body.429 Rate limited: wait, then retry with lower concurrency.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list
POST /v1/security-jwt-key-sets/{set_id}/test-token
Check a token against a JWT key set
- operationId
testSecurityJWTToken- Auth
- API key: header Authorization: CdncaKey <key_id>.<secret>. Effective permissions are the key scopes intersected with the owner’s current permissions.
- Session: the Bearer session of a signed-in control plane user, used by the customer in their own control plane; a plugin must never ask for it.
- Required permissions
The contract has no separate permission annotation; see the description below and the 403 response.
Description (from the contract)
Requires security_policies.read. Verifies the token as the nodes would (same algorithms, keys, issuer, audiences, exp / nbf and skew). The token is not stored, audited or logged.
Parameters
testSecurityJWTToken Parameters| Name | In | Type | Required | Description |
|---|
set_id | path | string(uuid) | Yes | — |
|---|
Request body
application/json · Required:Yes
testSecurityJWTToken Request body| Name | Type | Required | Description |
|---|
token | string | Yes | — |
|---|
Responses
testSecurityJWTToken Responses| Status | Description |
|---|
200 | The result. Fields:valid: boolean reason?: string: missing / malformed / alg_not_allowed / key_not_found / bad_signature / expired / exp_required / not_yet_valid / issuer_mismatch / audience_mismatch header?: object claims?: object |
|---|
400 | The request body or parameters are invalid. |
|---|
401 | Authentication failed or the session is invalid. |
|---|
403 | The authenticated principal is not allowed to perform the action. |
|---|
404 | The requested resource was not found. |
|---|
500 | The request could not be completed because of an internal failure. |
|---|
What to do on failure
400 Fix the parameters or body per the field list; do not retry unchanged.401 Check the credential format and whether it expired or was rotated.403 Check the key scopes, the owner’s current permissions and the tenant scope; never switch to a more privileged account.404 The resource does not exist or belongs to another tenant.500 Outcome unknown: read back by ID or list first, then decide whether to retry with the original Idempotency-Key.
↑ Back to list