Layers
Partner APIAPI referenceOrganizationsChild API keys

POST /v1/organizations/:orgId/api-keys/:keyId/rotate

Zero-downtime rotation of a child key - new secret now, old secret lives for 24 hours.

View as Markdown
POST/v1/organizations/{orgId}/api-keys/{keyId}/rotate
Phase 1stableidempotent
Auth
Bearer
Scope
org:admin

To roll a customer's credential without an outage, rotate the child key. You call this with your parent (org:admin) key. Rotation mints a brand-new key (new id, new secret) carrying the same scopes, env, and tier as the old one - and the old secret keeps working for a 24-hour grace window. That overlap is the point: deploy the new secret across the customer's fleet at your own pace, and the old one stops automatically when the window closes.

This is distinct from rotating your own parent key, which replaces the secret in place and kills the old one instantly. Child rotation is dual-secret by design.

A key can be rotated once. Once you rotate a key it's superseded by its replacement, and rotating that same (superseded) key again returns 409 CONFLICT - rotate the current key instead. The chain rolls forward cleanly: K → K2 → K3, each link rotating the live key, never a retired one.

The new plaintext secret is returned once, in this response. Store it before you do anything else.

Path
  • orgId
    string (org_…)required
    The child organization that owns the key. Must be a direct child of your org.
  • keyId
    string (key_…)required
    The key to rotate. Must belong to this child org, must be active (not revoked or killed), and must be the current key - not one that has already been rotated.
Headers
  • Idempotency-Key
    string (UUID)optional
    Strongly recommended. A replay returns the SAME new secret - without it, a retry mints a second replacement and your first secret goes stale.

Example

NEW_SECRET=$(curl -s -X POST \
  https://api.layers.com/v1/organizations/org_d4e5f6a7-8b9c-4d0e-9f2a-3b4c5d6e7f80/api-keys/key_c2037bb9.../rotate \
  -H "Authorization: Bearer $LAYERS_PARENT_KEY" \
  -H "Idempotency-Key: $(uuidgen)" | jq -r .secret)

# Deploy NEW_SECRET to the customer's services within 24h.
# The old secret keeps working until then, so there's no flap.
200OK - new key minted, secret returned once
{
  "apiKey": {
    "id": "key_9a44e1f0-...",
    "organizationId": "org_d4e5f6a7-8b9c-4d0e-9f2a-3b4c5d6e7f80",
    "name": "acme-content-sync",
    "prefix": "lp_live_TUVWXYZ23456789",
    "env": "live",
    "scopes": ["content:read", "content:write"],
    "rateLimitTier": "standard",
    "status": "active",
    "createdAt": "2026-06-03T20:31:10.552Z",
    "lastUsedAt": null,
    "rotatedAt": null,
    "revokedAt": null,
    "graceUntil": null,
    "supersededBy": null
  },
  "secret": "lp_live_...",
  "warning": "Store this secret now. It cannot be retrieved again. Rotate the key if it's lost."
}

The response is the new key - the customer's go-forward credential. To observe the old key's grace window, list the child's keys: the old row now carries graceUntil (when its secret stops) and supersededBy (the new key's id).

Rotation runbook

Rotate with a fresh Idempotency-Key. Grab secret from the response - the new credential.
Deploy the new secret to every service the customer runs, within 24 hours. The old secret is still live, so callers don't flap during the rollout.
Verify with GET /v1/whoami using the new secret. A 200 confirms it end-to-end.
Let the old secret expire. At graceUntil it stops on its own - no second call needed. To cut it off sooner, delete the old key.

The grace window never overrides a kill switch. If you or the customer's org is suspended or archived, the old (and new) secret is rejected with 503 KILL_SWITCH regardless of graceUntil. Grace only postpones the old secret's normal expiry - it never resurrects access that ops has cut.

Errors

StatusCodeWhen
404NOT_FOUND:orgId isn't your child, OR :keyId isn't that child's key, OR the key is already revoked / killed (terminal state stays un-confirmable).
409CONFLICTThe key has already been rotated (it's superseded by a newer key). Rotate the current key instead.
422VALIDATIONMalformed :orgId or :keyId.
409IDEMPOTENCY_CONFLICTIdempotency-Key reused with a different body.
503KILL_SWITCHYour key or org is suspended; or the child org is suspended/archived.

See also

On this page