> ## Documentation Index
> Fetch the complete documentation index at: https://docs.crossmint.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage Recovery Methods

> Add or remove recovery methods on an existing wallet, and choose which recovery method authorizes signer changes.

Recovery methods are set when a wallet is created, but they are not fixed. You can add a recovery method to an existing wallet — for example a backup phone number or a new server key — and remove one the user no longer controls. Every change is approved by one of the wallet's existing recovery methods, and that approval is enforced onchain.

Adding and removing recovery methods is supported on **Solana** and **Stellar**. EVM is coming soon; contact support if you would like early access. See [Recovery Methods](/wallets/concepts/recovery) for the concept, and [Configure Wallet Recovery](/wallets/guides/recovery/configure-recovery) for setting recovery methods at creation time.

## Prerequisites

* **Wallet:** An existing Solana or Stellar wallet with at least one recovery method.
* **API key:** An API key with `wallets.create` and `wallets:transactions.create` scopes. In staging, all scopes are included by default.

## How It Works

Adding or removing a recovery method creates a transaction that one of the wallet's existing recovery methods must approve. With the SDK, `addRecoveryMethod()` and `removeRecoveryMethod()` handle the approval for you: an email or phone method prompts the user for a one-time code, a server method signs with its secret, and an external wallet signs through its `onSign` callback. Once the transaction confirms, `wallet.recoveryMethods` reflects the change. With the REST API, you submit the change and then approve the returned transaction yourself.

<Accordion title="Rules enforced by the API">
  * A wallet always keeps at least one recovery method: removing the last one is rejected.
  * A recovery method whose add transaction has not confirmed yet cannot be removed. Adding the same method again returns the in-flight transaction, or starts a new one once it has expired.
  * Only a recovery method can authorize these changes. Operational signers added with `addSigner()` cannot.
  * On Solana, only Crossmint smart wallets support these operations. On Stellar, removing a recovery method requires the wallet to run the latest contract version.
</Accordion>

## Select the Authorizing Recovery Method

When a wallet has a single recovery method, the SDK uses it to authorize `addSigner()`, `removeSigner()`, `addRecoveryMethod()`, and `removeRecoveryMethod()`. When a wallet has several, select the one to authorize with first by calling `useRecoveryMethod()` with one of the entries in `wallet.recoveryMethods`; otherwise the operation throws `SignerRequiredError`. Here, the phone recovery method authorizes adding an email signer:

```typescript theme={null}
await wallet.useRecoveryMethod({ type: "phone", phone: "+12223334444" });

await wallet.addSigner({ type: "email", email: "user@example.com" });
```

Pass the full config when the method needs it to sign: the `secret` for a server method, or the `onSign` callback for an external wallet.

```typescript theme={null}
await wallet.useRecoveryMethod({
    type: "server",
    secret: process.env.CROSSMINT_SIGNER_SECRET,
});
```

Passing a config that does not match any entry in `wallet.recoveryMethods` throws `InvalidRecoveryConfigError`.

<Note>
  `useRecoveryMethod()` is experimental and may change in a future release.
</Note>

## Add a Recovery Method

The new method accepts the same configuration objects as `recoveryMethods` at wallet creation — `email`, `phone`, `external-wallet`, or `server`. Phone numbers use E.164 format.

<Tabs>
  <Tab title="React">
    ```typescript theme={null}
    import { useWallet } from "@crossmint/client-sdk-react-ui";

    const { wallet } = useWallet();

    const result = await wallet.addRecoveryMethod({
        type: "phone",
        phone: "+12223334444",
    });

    console.log("Recovery method added:", result.transactionId);
    console.log(wallet.recoveryMethods.map((method) => method.type));
    ```

    For a wallet with a single email recovery method, the user enters the email one-time code to approve the change, and the last line logs `["email", "phone"]`. With several recovery methods, call `useRecoveryMethod()` first.
  </Tab>

  <Tab title="Node.js">
    ```typescript theme={null}
    import {
        createCrossmint,
        CrossmintWallets,
    } from "@crossmint/wallets-sdk";

    const crossmint = createCrossmint({
        apiKey: "YOUR_SERVER_API_KEY",
    });
    const crossmintWallets = CrossmintWallets.from(crossmint);

    const wallet = await crossmintWallets.getWallet(
        "<wallet-address>",
        {
            chain: "solana",
            signer: {
                type: "server",
                secret: process.env.CROSSMINT_SIGNER_SECRET,
            },
        }
    );

    const result = await wallet.addRecoveryMethod({
        type: "external-wallet",
        address: "GbA2NZfpAnRVM2G2BG29qooqsYbdV5c2WVFymJ8MMir7",
    });

    console.log("Recovery method added:", result.transactionId);
    ```

    Here the server signer is the wallet's recovery method, so it approves the change without user interaction. Only the `address` is needed to register an external wallet; the `onSign` callback is required later, when that recovery method is used to authorize an operation.
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    import { useWallet } from "@crossmint/client-sdk-react-native-ui";

    const { wallet } = useWallet();

    const result = await wallet.addRecoveryMethod({
        type: "phone",
        phone: "+12223334444",
    });

    console.log("Recovery method added:", result.transactionId);
    ```
  </Tab>

  <Tab title="REST">
    When using the REST API, the change must be approved by one of the wallet's recovery methods. You must [approve the transaction](/api-reference/wallets/approve-transaction) to complete it.

    <Steps>
      <Step title="Add the recovery method">
        Call the [add recovery method](/api-reference/wallets/add-recovery-method) endpoint. The `recoveryMethods` field takes one recovery method per request, as a signer object or a signer locator. Set `approver` to the locator of the recovery method that authorizes the change. Omit `chain` for Solana and Stellar wallets.

        <CodeGroup>
          ```bash cURL theme={null}
          curl --request POST \
              --url https://staging.crossmint.com/api/2025-06-09/wallets/email:user@example.com:solana/recovery-methods \
              --header 'Content-Type: application/json' \
              --header 'X-API-KEY: <x-api-key>' \
              --data '{
                  "recoveryMethods": {
                      "type": "external-wallet",
                      "address": "GbA2NZfpAnRVM2G2BG29qooqsYbdV5c2WVFymJ8MMir7"
                  },
                  "approver": "email:user@example.com"
              }'
          ```

          ```js Node.js theme={null}
          const url = 'https://staging.crossmint.com/api/2025-06-09/wallets/email:user@example.com:solana/recovery-methods';

          const payload = {
              recoveryMethods: {
                  type: "external-wallet",
                  address: "GbA2NZfpAnRVM2G2BG29qooqsYbdV5c2WVFymJ8MMir7"
              },
              approver: "email:user@example.com"
          };

          const options = {
              method: 'POST',
              headers: {
                  'X-API-KEY': '<x-api-key>',
                  'Content-Type': 'application/json'
              },
              body: JSON.stringify(payload)
          };

          try {
              const response = await fetch(url, options);
              const data = await response.json();
              console.log(data);
          } catch (error) {
              console.error(error);
          }
          ```

          ```python Python theme={null}
          import requests

          url = "https://staging.crossmint.com/api/2025-06-09/wallets/email:user@example.com:solana/recovery-methods"

          payload = {
              "recoveryMethods": {
                  "type": "external-wallet",
                  "address": "GbA2NZfpAnRVM2G2BG29qooqsYbdV5c2WVFymJ8MMir7"
              },
              "approver": "email:user@example.com"
          }
          headers = {
              "X-API-KEY": "<x-api-key>",
              "Content-Type": "application/json"
          }

          response = requests.post(url, json=payload, headers=headers)

          print(response.json())
          ```
        </CodeGroup>

        The response contains the registered method under `recoveryMethods` and the pending transaction under `tx`.
      </Step>

      <Step title="Sign and approve the transaction">
        Sign the approval message returned inside `tx.approvals` with the recovery method named in `approver`, then submit the signature to the [approve transaction](/api-reference/wallets/approve-transaction) endpoint using the transaction ID from `tx.id`. Once the transaction succeeds, the new method appears in the wallet's `config.recoveryMethods`.
      </Step>
    </Steps>
  </Tab>
</Tabs>

## Remove a Recovery Method

Identify the method to remove with the same configuration object you would pass to `useRecoveryMethod()`. Any of the wallet's recovery methods can authorize the removal, as long as at least one method remains afterwards. In the React and React Native examples below, the email method authorizes removing the phone method.

<Tabs>
  <Tab title="React">
    ```typescript theme={null}
    import { useWallet } from "@crossmint/client-sdk-react-ui";

    const { wallet } = useWallet();

    await wallet.useRecoveryMethod({ type: "email", email: "user@example.com" });

    const result = await wallet.removeRecoveryMethod({
        type: "phone",
        phone: "+12223334444",
    });

    console.log("Recovery method removed:", result.transactionId);
    ```
  </Tab>

  <Tab title="Node.js">
    ```typescript theme={null}
    import {
        createCrossmint,
        CrossmintWallets,
    } from "@crossmint/wallets-sdk";

    const crossmint = createCrossmint({
        apiKey: "YOUR_SERVER_API_KEY",
    });
    const crossmintWallets = CrossmintWallets.from(crossmint);

    const wallet = await crossmintWallets.getWallet(
        "<wallet-address>",
        {
            chain: "solana",
            signer: {
                type: "server",
                secret: process.env.CROSSMINT_SIGNER_SECRET,
            },
        }
    );

    const result = await wallet.removeRecoveryMethod({
        type: "external-wallet",
        address: "GbA2NZfpAnRVM2G2BG29qooqsYbdV5c2WVFymJ8MMir7",
    });

    console.log("Recovery method removed:", result.transactionId);
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    import { useWallet } from "@crossmint/client-sdk-react-native-ui";

    const { wallet } = useWallet();

    await wallet.useRecoveryMethod({ type: "email", email: "user@example.com" });

    const result = await wallet.removeRecoveryMethod({
        type: "phone",
        phone: "+12223334444",
    });

    console.log("Recovery method removed:", result.transactionId);
    ```
  </Tab>

  <Tab title="REST">
    <Steps>
      <Step title="Remove the recovery method">
        Call the [remove recovery method](/api-reference/wallets/remove-recovery-method) endpoint with the locator of the method to remove in the path, and the locator of the authorizing method in the `approver` query parameter. Omit `chain` for Solana and Stellar wallets.

        <Tip>
          Recovery method locators (for example `phone:+12223334444` or `external-wallet:GbA2NZfpAnRVM2G2BG29qooqsYbdV5c2WVFymJ8MMir7`) are listed under `config.recoveryMethods` when you [get the wallet](/api-reference/wallets/get-wallet-by-locator).
        </Tip>

        <CodeGroup>
          ```bash cURL theme={null}
          curl --request DELETE \
              --url 'https://staging.crossmint.com/api/2025-06-09/wallets/email:user@example.com:solana/recovery-methods/external-wallet:GbA2NZfpAnRVM2G2BG29qooqsYbdV5c2WVFymJ8MMir7?approver=email:user@example.com' \
              --header 'X-API-KEY: <x-api-key>'
          ```

          ```js Node.js theme={null}
          const url = 'https://staging.crossmint.com/api/2025-06-09/wallets/email:user@example.com:solana/recovery-methods/external-wallet:GbA2NZfpAnRVM2G2BG29qooqsYbdV5c2WVFymJ8MMir7?approver=email:user@example.com';

          const options = {
              method: 'DELETE',
              headers: {
                  'X-API-KEY': '<x-api-key>'
              }
          };

          try {
              const response = await fetch(url, options);
              const data = await response.json();
              console.log(data);
          } catch (error) {
              console.error(error);
          }
          ```

          ```python Python theme={null}
          import requests

          url = "https://staging.crossmint.com/api/2025-06-09/wallets/email:user@example.com:solana/recovery-methods/external-wallet:GbA2NZfpAnRVM2G2BG29qooqsYbdV5c2WVFymJ8MMir7?approver=email:user@example.com"

          headers = {"X-API-KEY": "<x-api-key>"}

          response = requests.delete(url, headers=headers)

          print(response.json())
          ```
        </CodeGroup>

        The response is the pending removal transaction, in the same shape as the [get transaction](/api-reference/wallets/get-transaction) endpoint.
      </Step>

      <Step title="Sign and approve the transaction">
        Sign the approval message returned inside `approvals` with the recovery method named in `approver`, then submit the signature to the [approve transaction](/api-reference/wallets/approve-transaction) endpoint. The method is removed from `config.recoveryMethods` once the transaction succeeds.
      </Step>
    </Steps>
  </Tab>
</Tabs>

## Next Steps

<CardGroup cols={3}>
  <Card title="Configure Recovery" icon="shield-halved" href="/wallets/guides/recovery/configure-recovery">
    Set recovery methods when creating a wallet
  </Card>

  <Card title="List Signers" icon="list" href="/wallets/guides/signers/list-signers">
    Inspect the wallet's signers and recovery methods
  </Card>

  <Card title="Recover a Wallet" icon="rotate" href="/wallets/guides/recovery/wallet-recovery">
    Regain access from a new device with a recovery method
  </Card>
</CardGroup>
