Apply a configuration plan

POST /v1/config-plans/{plan_id}:apply · permission config:write, the read permissions of the plan and the write permission of each kind it changes

Applies a stored plan to the environment. Every change is written in one transaction: if one fails, none is kept. A plan can be applied once.

Request

Parameter Description
plan_id The plan id, cfgp_….

The body is optional.

Field Description
resolved_secrets Object of secret_ref name → value for every change with requires_secret: true (for example KEENAUTH_CONNECTION_GITHUB_CLIENT_SECRET). Values are at most 8 KiB. They are never stored by the plan, logged or returned.
confirm_deletions List of <kind>/<key> deletions you confirm, for example connection/legacy. The plan's deletion_requires_confirmation warnings list the deletions that need it.
sp_host The environment's service-provider host, for example login.example.com. Required only when the plan creates the OIDC material of an enterprise connection (the callback https://<sp_host>/sso/<connection id>/callback is fixed from it); a request that does not need it must not send it.

Response

200 OK with Cache-Control: no-store: the plan in the form of Get a configuration plan with status: applied and applied_at.

The configuration of the affected resources before the change is kept as a revision (the newest 50 per environment, at most 90 days). The apply writes one config.applied entry to the environment's management log with the counts of created, updated, deleted and unchanged resources; each changed resource also writes its own entry.

Errors

HTTP code When
400 malformed_request, unknown_field The body is not JSON or has a field other than resolved_secrets, confirm_deletions and sp_host.
401 unauthenticated The credential is missing, invalid or revoked.
403 insufficient_permissions The credential lacks a required permission; required_permissions lists all of them.
404 not_found The plan does not exist, belongs to another environment or was deleted.
409 config_conflict The target changed after the plan was made; the plan is now conflicted.
409 config_plan_not_applicable The plan was already applied or is conflicted, or another request is applying it now (plan_status: applying); plan_status gives its status.
409 deletion_not_confirmed A protected deletion is missing from confirm_deletions; unconfirmed_deletions lists them.
409 conflict Another resource already uses a unique value of a change (errors[].pointer is /changes/<i>/spec/<field>, code duplicate); the plan stays planned.
409 connection_in_use The connection to delete is still in use; the plan stays planned.
409 connection_test_required A change creates an enterprise connection active or activates one without a successful test sign-in (errors[].pointer is /changes/<i>/spec, code test_required); the plan stays planned.
410 config_plan_expired The plan's hour has passed; make a new plan.
413 config_document_too_large The changes, or the revision kept for them (at most 10 MiB), are too large to apply in one request; plan fewer kinds.
422 validation_failed See below.
422 policy_conflict The change conflicts with an environment policy; the plan stays planned.
429 rate_limited The config_plan rate limit (shared with plan creation) was exceeded, or too many plans are being computed or applied for this environment at once; the plan stays planned; retry after the Retry-After period.
501 not_implemented The plan needs the client secret of a social connection, which cannot be written yet.
503 service_unavailable A dependency (the directory or, for enterprise OIDC material, the federation service) is temporarily unavailable or plan capacity is temporarily full; nothing was written or, for the federation service, only the connection record was. Retry after the Retry-After period.
errors[].pointer errors[].code Meaning
/resolved_secrets/<NAME> secret_missing The plan needs this secret.
/resolved_secrets/<NAME> secret_unused The plan does not need this secret.
/resolved_secrets/<NAME> secret_invalid The value is empty, longer than 8 KiB or not text.
/resolved_secrets/<NAME> invalid The name does not have the KEENAUTH_… form (A-Z, 0-9, _).
/sp_host sp_host_required, sp_host_unused, invalid The plan creates OIDC material and no host was given, no host is needed, or the host is not a lowercase DNS name.
/changes/<i>/spec/oidc/... as in the connection OIDC API The federation service rejected the material at this position of the plan's changes.
/confirm_deletions/<i> duplicate, not_a_deletion The item is repeated or is not a deletion in the plan.
/confirm_deletions/<i> invalid The item does not have the <kind>/<key> form.
/resolved_secrets, /confirm_deletions too_many More than 5,000 entries.
/changes/<i>/spec/... as in the resource's own API The environment rejected the change at this position of the plan's changes.

Example

curl -X POST "https://api.eu.keenauth.com/v1/config-plans/cfgp_01m4qpqtywfs7930tb6kqn5rc5:apply" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"confirm_deletions": ["connection/legacy"]}'

keenauth config apply cfgp_01m4qpqtywfs7930tb6kqn5rc5 --confirm-deletion connection/legacy

keenauth config apply --secrets-from-env reads each secret the plan needs from the environment variable of the same name and never prints it.