POST /v1/admin/billing/org/{org_id}/rotate
Mint a NEW key on subscription reactivation (master-key auth; payment-worker only).
What this is
Mints a new API key for the target org and atomically sets active = 1. Called by payment-worker on invoice.paid after a suspended-class state (past_due, unpaid, paused). The previously-suspended key was permanently revoked at suspension; this endpoint replaces it.
Authentication
X-API-Key: $MASTER_ADMIN_KEY_BILLING_ROTATE — scope-specific secret. payment-worker only.
Idempotency
Idempotency-Key required. Replays return cached envelope without the plaintext key — original caller had ONE chance on first response.
⚠️ Plaintext key returned ONCE
The new_api_key field in the 200 response is the only place the plaintext appears. NEVER persisted in D1, audit logs, or the idempotency cache. The previous key is permanently revoked at this point — operators who lost the new key on the original response must either rotate again (mints a third key) or contact support.
Rate limiting
- Layer 1: enforced.
- Layer 2: bypassed.
Request
curl -X POST https://api.cohesionauth.com/v1/admin/billing/org/org_acme_2026_example/rotate \
-H "X-API-Key: $MASTER_ADMIN_KEY_BILLING_ROTATE" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: example-billing-rotate-key" \
-d '{}'
Response
{
"rotated": true,
"org_id": "org_acme_2026_example",
"new_api_key": "TEST_FIXTURE_NOT_A_REAL_KEY_BILLING_ROTATE",
"prefix": "TESTFIXT",
"rotated_at": "2026-05-02T20:00:00.000Z",
"warning": "This API key is shown ONCE. The previous key was permanently revoked.",
"request_id": "req_01H...",
"timestamp": "2026-05-02T20:00:00.000Z"
}
Errors
| Status | Meaning |
|---|---|
401 | Master-key missing or wrong scope |
404 | Org not found |
500 | Server misconfigured (pepper missing) |