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.
Before you start
Section titled “Before you start”- 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.
1. Issue the new credential
Section titled “1. Issue the new credential”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 /apiauthContent-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.
5. Revoke the old credential
Section titled “5. Revoke the old credential”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.
Verify the outcome
Section titled “Verify the outcome”- 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.
Failure modes
Section titled “Failure modes”| 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.

