
Replace credentials without an abrupt cutover
Integrations need time to adopt a replacement secret. Wildo can keep the previous API key or OAuth client secret valid during a declared overlap window, then reject it after the deadline.
Rotation, regeneration and revocation have different purposes. A timed rotation supports a planned handover; revocation stops access. The authentication path checks the credential’s status and expiry as well as the previous secret’s window.
Example — Move an integration to its replacement key
An administrator rotates a credential with a handover deadline. The integration is updated while both secrets are accepted. After the deadline, requests using the previous secret fail while the new secret continues to work, provided the credential remains active and unexpired.
For engineers
Choose the right administration operation
| Operation | Meaning for the previous secret |
|---|---|
| Rotate | A declared invalidation date bounds its acceptance |
| Regenerate | Open-ended overlap until the next reissue |
| Revoke | The inactive status prevents authentication, including the previous secret |
| Extend expiry | Changes the credential lifetime; it is distinct from the previous-secret deadline |
Regeneration is not a response to a compromised secret. Choose revocation or a rotation deadline appropriate to the incident, and arrange how the legitimate consumer obtains its replacement through the authorized credential flow.
Perform a deliberate API-key handover
For an organization API key, use its declared ROTATE operation as an authorized organization administrator (or the administrator variant). This operation requires step-up authentication. The request and response fields below are selected from that operation’s schema:
requestDto: z.object({
oldKeyInvalidationDate: z.date().min(new Date(), 'Invalidation date must be in the future or now').default(() => new Date()),
}),
customResponseDto: ApiKeyOrganizationSchema.extend({
plainKey: z.string().min(1).isEphemeral(),
oldKeyId: z.string(),
oldKeyInvalidationDate: z.date(),
}),
Supply an explicit future oldKeyInvalidationDate when invoking the operation through the application’s administration interface or generated client. Omitting it means immediate cutover, not a default handover period. The schema fragment is a contract excerpt, not code to copy into an application or a guessed endpoint URL.
| Step | What to do and observe |
|---|---|
| Prepare | Select an active, unexpired key, choose a deadline and complete the required step-up |
| Rotate | Submit the chosen deadline and capture the response’s one-time plainKey into the consumer’s secret store |
| Switch | Update the integration; verify the new secret works and the previous secret still works before the deadline |
| Finish | Verify the previous secret is rejected after the deadline while the new one remains accepted |
There is one previous-secret slot. Rotating again replaces that slot even if its earlier deadline has not passed. Finish one handover before beginning the next; never assume a chain of older secrets remains accepted. The returned plaintext is ephemeral and must not be logged or treated as a field that can be retrieved later.
This workflow concerns API-key records. Framework-managed platform secrets use coordinated provisioning and distribution, not this record’s overlap window.
Keep the two clocks distinct
These are the actual shared predicates used by machine authentication. The first checks the previous-secret slot; the second checks the lifetime of the credential itself.
export function isRotationGraceWindowOpen(invalidationDate?: Date | null): boolean {
if (invalidationDate === null || invalidationDate === undefined) return true;
return new Date(invalidationDate).getTime() > Date.now();
}
export function isCredentialExpired(expiresAt?: Date | null): boolean {
if (expiresAt === null || expiresAt === undefined) return false;
return new Date(expiresAt).getTime() <= Date.now();
}
The callers also require an active record. An open overlap cannot revive a revoked credential, and a delayed administrative status update cannot extend an expired credential’s actual access.
Follow persistence and authentication together
Reissue handlers write the previous-secret and grace fields through the repository’s server-managed field allow-list. The API-key request handlers, OAuth client handlers and OAuth token exchange use the shared date rules. The integration test for rotation persistence specifically checks that strict schema parsing preserves authorized injected fields.
A nightly expiry sweep now updates expired records through their expire operation. That bookkeeping can lag the clock, so authentication still checks expiresAt on every use. For a handover check, exercise both secrets before the deadline and the old secret after it; also check revocation independently. A single successful request with the new key does not establish the overlap behavior.