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
- Layer 1: enforced.
- Layer 2: bypassed.
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
| Status | Meaning |
|---|---|
401 | Master-key missing or wrong scope |
422 | confirm_org_id mismatches URL path |
501 | Handler pending admin-dashboard plan PR |
502 | upstream_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) |