Skip to content

Rotate API credentials without downtime

By the end of this guide you will have replaced your API app’s client credentials without a single failed request.

The mechanism that makes this possible is the overlap: an API app can hold two active credentials at once. Rotation is therefore not a cutover but a handover — you add the new credential, move your callers onto it, and only then remove the old one. Nothing has to stop.

  • Access to the Developer Console for the API app in question. Secrets are issued and revoked there, not through this API.
  • Somewhere your running integration reads its client id and secret from that you can change without a redeploy — a secret store, an environment variable, a configuration record. If either is baked into a build artefact, sort that out first; it is what turns a rotation into an outage.
  • A note of when your current access token expires. Tokens issued before the rotation stay valid for their full lifetime.

In the Developer Console, add a second credential to the existing API app. It comes back as a client id and a secret, along with the date it expires. Copy both immediately — the secret is shown once.

Do not delete the old one yet. Both are now live, and your integration is still authenticating with the old one perfectly happily. This overlap is the entire safety margin, so do not shorten it out of tidiness.

2. Put the new credential where your integration reads it

Section titled “2. Put the new credential where your integration reads it”

Update your secret store, environment variable or configuration record — the client id as well as the secret. If you run several instances, update them all before moving on.

Nothing changes yet: your integration is still holding a valid access token minted from the old secret, and it will keep using it until that token expires.

3. Prove the new secret works before you rely on it

Section titled “3. Prove the new secret works before you rely on it”

Exchange it for a token explicitly, rather than waiting to find out during the next scheduled run:

POST /apiauth
Content-Type: application/json
{ "clientId": "…the new client id…", "clientSecret": "…the new secret…", "grantType": "client_credentials" }

A 200 with an accessToken means the new secret is good. A 401 means it is not — and because the old secret is still live, you can stop here and investigate with nothing broken.

This step is the reason rotation is safe. Skip it and you find out the new secret is wrong at the moment the old one stops working.

4. Let the old token expire, or force the handover

Section titled “4. Let the old token expire, or force the handover”

Access tokens are unaffected by a secret change: one minted from the old secret keeps working until it expires. You have two ways to finish.

Let it drain. Do nothing. When the current token expires your integration requests a new one, using the new credential it picked up in step 2. This is the least eventful option, and the wait is bounded by the token lifetime — read expiresIn rather than assuming a value.

Force it. Restart your integration, or clear its cached token, so it authenticates again immediately. Choose this when you want the rotation finished on a schedule rather than whenever the token happens to lapse.

Only now, and only once you have confirmed every instance is authenticating with the new credential, remove the old one in the Developer Console.

Leaving it in place indefinitely defeats the purpose of rotating. Revoke it deliberately as the last step, rather than leaving it as a fallback you never remove.

  • A fresh token exchange with the new client id and secret returns 200.
  • A token exchange with the old client id and secret returns 401 — proof the revocation took effect.
  • Your integration completes a full cycle of normal work without a 401.
What you see Why What to do
401 exchanging the new credential in step 3 The secret was mistyped or truncated on copy, or the new secret was paired with the old client id The old credential is still live. Check both values, re-copy, or issue another credential
401 across the integration after step 5 An instance was still holding the old credential Re-add a credential, complete step 2 for every instance, and revoke again
Everything works, then fails hours later An instance caches its token and only re-authenticated after the old secret was revoked Force the handover in step 4 rather than letting it drain
401 from a caller outside the office The API app’s IP allow-list, not the secret Rotation does not change the allow-list; check it separately

Security — how to hold these credentials once they are rotated.