Skip to content
Crixaa
← All posts

API keys that survive a rotation

The Crixaa team4 min read

Most teams know they should rotate API credentials. Far fewer actually do it, and the reason is almost always the same: rotation means a flag day. Generate the new key, update every service that holds the old one, deploy them all together, and hope you found them all. That is a change nobody schedules for a Tuesday afternoon.

So the key stays where it is. It ends up in a CI variable, a colleague's .env, a Slack thread from 2024, and it outlives the person who created it.

Rotation with a grace period

A Crixaa key can be rotated with an overlap. You issue a successor, and the old key keeps working for a grace period you choose — anywhere from 1 to 30 days.

That single change removes the flag day. The sequence becomes:

  1. Rotate, with a grace period long enough to cover your deploy cadence.
  2. Roll the new secret out wherever it lives, at whatever pace is safe.
  3. Watch the old key's last used timestamp go quiet.
  4. Let it lapse — or revoke it early once you are confident.

Step 3 is the one that changes how rotation feels. You are not guessing whether you found every consumer; you are watching a timestamp. If something you forgot is still calling with the old key, it tells you before the credential stops working rather than after.

When you genuinely need a key dead this second — a secret in a public repository, a laptop gone missing — revoke instead. That takes effect immediately, with no overlap. Rotation is for hygiene; revocation is for incidents. It is worth keeping the two verbs distinct in your own runbook, because under pressure people reach for whichever one is closest.

Scope keys to the job

A key that can do everything is a key whose blast radius is everything. Crixaa keys carry explicit scopes:

ScopeGrants
documents:generateGenerate documents from a template
documents:readRead document metadata and download files
templates:readRead templates and their versions
webhooks:readList webhooks and their deliveries
webhooks:writeCreate and revoke webhooks

The useful habit is one key per consumer, scoped to what that consumer does. Your invoice service almost certainly needs documents:generate and nothing else. When a key is scoped that tightly, revoking it is a small decision — you know exactly what stops working — and "can we just rotate this?" stops being a question that needs a meeting.

Keys are also workspace-scoped. One workspace's key can never reach another's data, so a compromised key from a sandbox workspace cannot read production documents.

Limits are per key, not per account

Every key carries its own requests-per-minute ceiling, 120 by default, and the workspace has a daily ceiling on top of that.

Per-key limits matter more than they look. If a batch job goes into a retry loop, a shared account-wide limit means it takes down your interactive traffic with it. Give the batch job its own key with its own ceiling, and the blast radius of that loop is the batch job.

When a limit is hit you get a 429 with a Retry-After header. Honour it — retrying immediately just burns the next window too. Two other codes are worth handling distinctly:

  • 401 — the key is missing, revoked, expired, or simply wrong. Retrying will not help.
  • 403 — the key is valid but lacks the scope, or the resource belongs to another workspace. Also not worth retrying.
  • 402 — the workspace's billing needs attention. A human has to act.

Treating all four as "the API is unhappy" and retrying is how a scope typo becomes an outage that lasts until someone reads the logs.

Pin a key to your infrastructure

Two optional constraints, both worth setting on anything that runs from a fixed place:

An IP allowlist, per key. If your integration runs from a known egress range, a key that only works from that range is dramatically less useful to anyone who steals it.

An expiry date, per key. A key that expires is a key that cannot quietly outlive the project it was created for. We email ahead of the date so it lapses on purpose rather than at 3am — but do set a calendar reminder too, because an expiry you forgot about is an outage with a very confusing error message.

The habit worth building

Rotate on a schedule you pick, not on the day you discover you have to. A quarterly rotation with a 14-day grace period is close to free once your keys are scoped and their last-used timestamps tell you who is still holding one.

The point of the grace period is not really convenience. It is that a rotation which cannot break anything is a rotation you will actually perform.

Try it on your own document

Design a template in the browser and generate a real PDF — free, no card.