POST /v1/admin/org/{org_id}/force-rotate

Manual key rotation for compromise response (master-key auth; admin-worker only).

What this is

Manual key rotation initiated by the admin-dashboard for compromise response (e.g., key leaked in a customer’s git repo, employee offboarding without org-side rotation, security incident). Mints a NEW key and returns it ONCE; the previous key is permanently revoked.

Phase 2.2.5 placeholder state: scoring-api returns 501 on auth-success until admin-dashboard plan PR ships. Auth gate active.

Authentication

X-API-Key: $MASTER_ADMIN_KEY_ORG_FORCE_ROTATE — admin-worker only.

Idempotency

Idempotency-Key required. Replays return prefix-only — plaintext NEVER cached.

⚠️ Plaintext key returned ONCE

The new_api_key field in the 200 response is the only place the plaintext appears. NEVER persisted. The previous key is permanently revoked at this point. The admin-worker handler does NOT inspect the response body — it forwards the scoring-api response directly. Plaintext keys NEVER appear in admin-worker’s admin_audit_log (Codex P0-7 / Q10 P0-3) — only the new prefix + version diff.

Rate limiting

Request

curl -X POST https://api.cohesionauth.com/v1/admin/org/org_acme_2026_example/force-rotate \
  -H "X-API-Key: $MASTER_ADMIN_KEY_ORG_FORCE_ROTATE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: example-force-rotate-key" \
  -d '{
    "confirm_org_id": "org_acme_2026_example",
    "idempotency_key": "example-force-rotate-key"
  }'

Response (post-implementation)

{
  "rotated": true,
  "org_id": "org_acme_2026_example",
  "new_api_key": "TEST_FIXTURE_NOT_A_REAL_KEY_FORCE_ROTATE",
  "prefix": "TESTFIXT",
  "rotated_at": "2026-05-03T04:00:00.000Z",
  "warning": "This API key is shown ONCE. The previous key was permanently revoked.",
  "request_id": "req_01H...",
  "timestamp": "2026-05-03T04:00:00.000Z"
}

Errors

StatusMeaning
401Master-key missing or wrong scope
422confirm_org_id mismatches URL path
501Handler pending admin-dashboard plan PR
502upstream_protocol_violation — scoring-api returned 200 without new_api_key (audit-logged as protocol_violation; admin-app surfaces this as a clear error rather than a silent success)