# Recover via Email / SMS

Recover your Safe account using [Candide Guardian](https://docs.candide.dev/wallet/recovery/auth-api.md) when you've lost access to your owner keys. This guide covers the complete recovery process using email and SMS verification.

info

The Recovery Service requires access credentials. [Request access here](https://app.formbricks.com/s/brdzlw0t897cz3mxl3ausfb5).

> If you haven't set up Candide Guardian yet, see the [Add Candide Guardian](https://docs.candide.dev/wallet/plugins/add-candide-guardian.md) guide first.

## What You'll Need[​](#what-youll-need "Direct link to What You'll Need")

Before starting recovery, ensure you have:

* **Access to registered recovery methods** (email or SMS)
* **Safe account address** to recover
* **New private key** to replace the lost key
* **Recovery service access** (Candide Guardian enabled)

## Recovery Overview[​](#recovery-overview "Direct link to Recovery Overview")

The recovery process consists of five key steps:

1. **Generate New Owner Key** - Create a replacement for the lost key
2. **Request Guardian Signature** - Initiate recovery through the Guardian service
3. **Verify All Channels** - Confirm identity through ALL registered methods
4. **Execute Recovery** - Submit the recovery transaction
5. **Finalize Recovery** - Complete ownership transfer after the grace period

## Quickstart[​](#quickstart "Direct link to Quickstart")

> You can also [fork the complete code](https://github.com/candidelabs/safe-recovery-service-sdk/blob/main/examples/03-recovery-flow/index.ts) and follow along.

### Installation[​](#installation "Direct link to Installation")

* npm
* yarn

```
npm i abstractionkit safe-recovery-service-sdk viem
```

```
yarn add abstractionkit safe-recovery-service-sdk viem
```

### Configure Environment[​](#configure-environment "Direct link to Configure Environment")

* .env

```
# Network Configuration

CHAIN_ID=11155111

BUNDLER_URL=https://api.candide.dev/public/v3/11155111

NODE_URL=https://ethereum-sepolia-rpc.publicnode.com



# Recovery Service URL

# Get access here: https://app.formbricks.com/s/brdzlw0t897cz3mxl3ausfb5

RECOVERY_SERVICE_URL= 
```

## Step 1: Initialize Recovery Service[​](#step-1-initialize-recovery-service "Direct link to Step 1: Initialize Recovery Service")

```
import { RecoveryByCustodialGuardian } from "safe-recovery-service-sdk";

import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts';



const chainId = BigInt(process.env.CHAIN_ID as string);

const serviceUrl = process.env.RECOVERY_SERVICE_URL as string;



// Initialize recovery service

const custodialGuardianService = new RecoveryByCustodialGuardian(serviceUrl, chainId);



// Generate new owner key to replace the lost one

const newOwnerPrivateKey = generatePrivateKey();

const newOwner = privateKeyToAccount(newOwnerPrivateKey);
```

## Step 2: Request Guardian Signature Challenge[​](#step-2-request-guardian-signature-challenge "Direct link to Step 2: Request Guardian Signature Challenge")

Request a recovery signature from Candide Guardian:

```
// Request Candide Guardian signature for recovery

const signatureRequest = await custodialGuardianService.requestCustodialGuardianSignatureChallenge(

    safeAccountAddress,

    [newOwner.address], // New owner array

    1 // New threshold

);
```

## Step 3: Verify All Recovery Channels[​](#step-3-verify-all-recovery-channels "Direct link to Step 3: Verify All Recovery Channels")

You must verify **ALL** registered channels to complete recovery. Submit the OTP codes received:

* Email Verification
* SMS Verification
* Verify All Channels

```
// Find the email authentication challenge

const emailAuth = signatureRequest.auths.find(auth => auth.channel === 'email');



// Enter OTP from email

const emailOtp = "123456"; // Replace with actual OTP



const verificationResult = await custodialGuardianService.submitCustodialGuardianSignatureChallenge(

    signatureRequest.requestId,

    emailAuth.challengeId,

    emailOtp

);
```

```
// Find the SMS authentication challenge

const smsAuth = signatureRequest.auths.find(auth => auth.channel === 'sms');



// Enter OTP from SMS

const smsOtp = "654321"; // Replace with actual OTP



const verificationResult = await custodialGuardianService.submitCustodialGuardianSignatureChallenge(

    signatureRequest.requestId,

    smsAuth.challengeId,

    smsOtp

);
```

```
// Verify ALL registered channels (required for recovery)

let verificationResult;



for (const auth of signatureRequest.auths) {

    // Enter OTP for current channel

    const recoveryOtpCode = "123456"; // Replace with actual OTP from respective channel

    

    verificationResult = await custodialGuardianService.submitCustodialGuardianSignatureChallenge(

        signatureRequest.requestId,

        auth.challengeId,

        recoveryOtpCode

    );

}
```

## Step 4: Execute Recovery Transaction[​](#step-4-execute-recovery-transaction "Direct link to Step 4: Execute Recovery Transaction")

After verifying all channels, execute the recovery with the obtained guardian signature:

```
// Execute recovery using the service

const recoveryRequest = await custodialGuardianService.createAndExecuteRecoveryRequest(

    safeAccountAddress,

    [newOwner.address], // New owner array

    1, // New threshold

    verificationResult.custodianGuardianAddress as string,

    verificationResult.custodianGuardianSignature as string

);
```

## Step 5: Finalize Recovery After Grace Period[​](#step-5-finalize-recovery-after-grace-period "Direct link to Step 5: Finalize Recovery After Grace Period")

Wait for the grace period to expire, then finalize the recovery:

```
import { SocialRecoveryModuleGracePeriodSelector } from "abstractionkit";

import { RecoveryByGuardian } from "safe-recovery-service-sdk";



// Wait for grace period (3 minutes)

await new Promise(resolve => setTimeout(resolve, 3 * 60 * 1000));



// Initialize recovery service for finalization

const recoveryService = new RecoveryByGuardian(

    serviceUrl,

    chainId,

    SocialRecoveryModuleGracePeriodSelector.After3Minutes

);



// Finalize the recovery

const finalizationResult = await recoveryService.finalizeRecoveryRequest(recoveryRequest.id);
```

## Complete Working Example[​](#complete-working-example "Direct link to Complete Working Example")

Full Recovery Flow Example

examples/03-recovery-flow/index.ts

```
loading...
```

[See full example on GitHub](<https://github.com/candidelabs/safe-recovery-service-sdk/blob/main/examples/03-recovery-flow/index.ts&#xA;>)

## What's Next[​](#whats-next "Direct link to What's Next")

* [Recovery Alerts Guide](https://docs.candide.dev/wallet/plugins/recovery-alerts-guide.md): set up email and SMS notifications so account owners are alerted if a recovery is ever initiated
