If there is a suspicion that private keys were compromised, lock the existing user and create a replacement user with new keys. You cannot replace a user's publicKey with v0_UpdateUser.
Before you refresh the user key, decide what kind of replacement user you need:
- UI human user: The user creates a new profile with the Ripple Custody authenticator app and shares the new public key. The replacement user should receive the original human-facing alias and
loginIds. - API or bot user: Generate a new API key pair for the client or bot, then use the new public key when you create the replacement user. Store the new private key in your secrets manager.
Retrieve the existing user's id, metadata.revision, alias, roles, and loginIds. Also prepare:
- A new UUID for the replacement user.
- A retired alias for the old user, such as
operator-retired-20260618@example.com. - Retired
loginIdsfor the old user. Do not setloginIdstonull; when present,loginIdsmust be an array of valid login ID objects.
For more information, see:
- Ripple Custody API > Generate a key pair and share the public key
- Ripple Custody UI > Create a profile
These steps describe how to refresh a user key with the API.
To refresh a user key:
Get the current user details. For more information, see Manage users and roles.
Create a
v0_UpdateUserintent for the existing user that changes the old user'saliasandloginIdsto retired values. This releases the original alias and login IDs for the replacement user.{ "payload": { "reference": { "id": "61aaa805-f9b8-11eb-b158-dcfb48cfb3cb", "revision": 2 }, "alias": "operator-retired-20260618@example.com", "roles": ["transaction-operator"], "loginIds": [ { "id": "operator-retired-20260618@example.com", "providerId": "harmonize" } ], "description": "Retired user record after key refresh", "customProperties": { "keyRefreshStatus": "retired" }, "type": "v0_UpdateUser" } }If the user has multiple login providers, provide a retired
loginIdsentry for each provider. Do not usenullforloginIds.Create a
v0_LockUserintent to lock the existing user.{ "payload": { "reference": { "id": "61aaa805-f9b8-11eb-b158-dcfb48cfb3cb", "revision": 3 }, "type": "v0_LockUser" } }Create a replacement user with a new user
id, the original alias andloginIds, the required roles, and the newly generated public key.{ "payload": { "id": "4d8c6240-3261-4991-9aa9-59e66f089d76", "alias": "operator@example.com", "publicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...", "roles": ["transaction-operator"], "loginIds": [ { "id": "operator@example.com", "providerId": "harmonize" } ], "lock": "Unlocked", "description": "Replacement user after key refresh", "customProperties": { "replacesUserId": "61aaa805-f9b8-11eb-b158-dcfb48cfb3cb" }, "type": "v0_CreateUser" } }For a UI human user, use the public key from the user's new authenticator profile. For an API or bot user, use the public key from the newly generated API key pair.
After the intents execute, confirm that the old user is locked and that the replacement user can authenticate and perform the expected read-only operation before allowing state mutation work.
For more information about submitting update, lock, and create-user intents, see Manage intents and approvals and Manage users and roles.