Skip to main content

POST /admin/tenant-kms/unseal

Force an immediate unseal attempt after restoring KMS access. This is not idempotent — once the tenant is unsealed, calling it again returns 409 not_sealed. Auth: served on the admin host with a session Authorization: Bearer <jwt> plus the X-Tenant-ID header (owner/admin role). This action also requires a recent step-up verification within a 2-minute window — enforced server-side against the authenticated user. No step-up header or token is sent on this request; instead the signed-in user must have re-authenticated shortly beforehand via POST /auth/2fa/verify-step-up (TOTP), POST /auth/passkey/verify-step-up (passkey), or the email fallback (POST /auth/step-up/email-challenge then POST /auth/step-up/verify-email). If no recent verification exists, the endpoint returns 403 { "error": "Recent step-up verification required for this action", "requires_step_up": true, "max_age_minutes": 2 }. Omitting X-Tenant-ID returns 400. Manual unseal forces immediate recovery rather than waiting for the next BYOK bundle-renewal cycle.

Response

{ "unsealed": true }

Error codes

StatusCodeMeaning
404no_kms_configNo customer KMS configured for this tenant
409not_sealedTenant is not currently sealed
502unseal_failedUnseal attempt failed — KMS still unreachable or access still denied
unseal_failed includes a reason field: "access_denied" (IAM grant still missing) or "unreachable" (network issue).
curl -X POST https://admin.knoxcall.com/admin/tenant-kms/unseal \
  -H "Authorization: Bearer $KC_ADMIN_JWT" \
  -H "X-Tenant-ID: $KC_TENANT_ID"
resp = requests.post(
    "https://admin.knoxcall.com/admin/tenant-kms/unseal",
    headers={
        "Authorization": f"Bearer {KC_ADMIN_JWT}",
        "X-Tenant-ID": KC_TENANT_ID,
    },
)
resp.raise_for_status()
assert resp.json()["unsealed"] is True
const resp = await fetch("https://admin.knoxcall.com/admin/tenant-kms/unseal", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${KC_ADMIN_JWT}`,
    "X-Tenant-ID": KC_TENANT_ID,
  },
});
const { unsealed } = await resp.json();