API key lifecycle and rotation
An Orbit API key moves through three states — active, grace-rotated, and revoked or expired — and two rotation modes move it across the boundaries. This page defines the states, the difference between grace and immediate rotation, how the cutoff on the old key is computed, and when to rotate versus revoke. For the credential classes and resolution rule, start with the authentication and session model.Section 1 — The lifecycle at a glance
Every API key is born in one of two states and ends in one of two states:- Active. The key authenticates requests.
activeis true and neither a grace window nor a scheduled cutoff constrains it. - Grace-rotated. A rotation ran with the default grace mode: a replacement key was minted and the old key keeps authenticating until its computed cutoff (
old_key_expires_at). Both keys are valid simultaneously during this window. - Revoked / expired. The key no longer authenticates — either because an immediate rotation or an explicit revoke killed it, or because its expiry instant (
expires_atorold_key_expires_at) passed.
POST /api/v1/settings/api-keys/:id/revoke, a scheduled revocation cutoff (revoke_at), or a customer-set expires_at all terminate it directly.
Section 2 — The two rotation modes
POST /api/v1/settings/api-keys/:id/rotate mints a replacement key and retires the old one. The mode field picks which retirement path the old key takes:
Two properties of the mode resolution are worth knowing:
- Grace is the floor for routine rotations. Omitting
mode, sendingmode: "grace", or sending an unrecognized value all resolve to the grace path. The grace window is never zero — it is clamped to a minimum of 1 hour — so a routine rotation cannot become an accidental panic-revoke through a typo. - Immediate is an explicit, separate action. It is not “grace with zero hours”; the grace path enforces the 1-hour minimum precisely so the dual-validity guarantee holds for routine rotations. Sending
mode: "immediate"is the only way the old key dies in the same transaction, and on that pathgrace_period_hoursis ignored.
api_key.rotated entry, immediate rotation writes api_key.revoked_immediate, so a compliance review can separate routine rotations from panic-revokes without reading request payloads.
Section 3 — The dual-key grace window
In grace mode the old and new keys validate at the same time untilold_key_expires_at. That overlap is the entire point: you rotate, update every integration to the new key on its own schedule, and the old key keeps answering requests until the window closes.
This is deliberately not a “grace = 0” behavior. The 1-hour floor preserves the overlap for every routine rotation — a zero-length window is only reachable through the explicit immediate mode, which exists for keys that must die now.
Plan the cutover against the cutoff returned in the rotation response. If the window ends before you finish migrating, every request still carrying the old key starts failing 401 at that instant.
Section 4 — How old_key_expires_at is computed
Rotation never silently extends the life of the old key. The cutoff is the earlier of two instants:
- The old key’s pre-existing
expires_at, if one was set at creation. - The new grace window (rotation time plus
grace_period_hours).
immediate mode the cutoff is the rotation instant itself. The resolved cutoff comes back as old_key_expires_at in the response so the dashboard (and your runbook) can show “old key valid until …” without a second call.
Section 5 — Provenance and audit capture
Every rotation records the old-to-new pair without ever writing the secret to the audit log:- The old key’s
lastFourCharssuffix is captured before the rotation runs — after the rotation, the key list shows the new suffix, so without this look-back the “rotated from …1234 to …5678” provenance would be lost. - The audit entry carries the key id, the replacement key id, the key label, both suffixes, the resolved mode, and (for grace) the requested window. The plaintext of the new key never appears there.
key field — its plaintext — is returned exactly once, in the rotation response, with Cache-Control: no-store. Store it in your secret manager immediately; later reads only ever show the masked prefix and suffix.
Section 6 — Rotate versus revoke
One billing note for the leak case: revoking a leaked key stops the meter at the revoke timestamp — usage billed into your account ends there regardless of what the leaked key does afterward, so revoking is always the right first move even before you investigate.
Section 7 — A guided cutover
- List keys first so you target the right id:
GET /api/v1/settings/api-keysreturns labels, prefixes, suffixes, and expiry metadata — secrets are never listed. - Rotate with grace.
- Copy
keyinto your secret manager now — this response is the only place the plaintext ever appears. - Deploy the new key to every integration. The old key keeps working against the same scopes until
oldKeyExpiresAt, so you can roll service by service. - Confirm the cutover. After
oldKeyExpiresAtpasses, any request still carrying the old key fails401— grep your access logs for the old suffix (…5b7d) ahead of the cutoff if you want zero surprises.
"mode": "immediate" mints the replacement and revokes the old key in one transaction — do the copy step before you send it.