Skip to main content

Safe Recovery UX API

Benefits

FeatureDescription
Alerts and NotificationsAccount owners subscribe to receive notifications via email or SMS when a recovery request is initiated on-chain.
Guardians Sign OnceOff-chain signature collection eliminating the need for guardians to share links with one another.
Privacy GuaranteedGuardians sign only off-chain and do not need to maintain a balance in their accounts, allowing them to preserve their pseudonymity with fresh accounts.
Social Engineering ProtectionA communication system using emojis that allows guardians to verify and approve legitimate recovery requests from their rightful owners.
Auto Finalization After Grace PeriodA built-in relayer automatically submits signed transactions on behalf of guardians for confirmation and finalization once the grace period has elapsed.
info

To get started, request access here.

Authentication

All API requests require a Bearer token in the Authorization header:

curl -X POST \
https://yourcompany.recovery.candide.dev/recoveries/create \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
-d '{...}'

/recoveries

  • /recoveries/create
    • POST: Creates a new recovery request
  • /recoveries/fetchByAddress
    • GET: Fetches recovery requests
  • /recoveries/listByAddress
    • GET: Lists all recovery requests with filtering and pagination
  • /recoveries/fetchById
    • GET: Fetch a recovery request by ID
  • /recoveries/sign
    • POST: Collects a guardian signature
  • /recoveries/execute
    • POST: Execute a recovery request by ID
  • /recoveries/finalize
    • POST: Finalize a recovery request by ID

/alerts

  • /alerts/subscribe
    • POST: Creates an inactive alerts subscription for an account
  • /alerts/activate
    • POST: Activate subscription to recovery requests
  • /alerts/subscriptions
    • GET: Fetches active alerts subscriptions for an account.
  • /alerts/unsubscribe
    • POST: Unsubscribes from an active alerts subscription.

Recoveries

Create Recovery Request

Creates a new recovery request by a guardian with a lost signer of a Safe account. Can only be initiated by guardians of the account.

POST /recoveries/create

curl -X POST \
https://yourcompany.recovery.candide.dev/create \
-H 'Content-Type: application/json' \
-d '{
"account": "0xD422B9d638a7BA4eBeF9e33Af9456007eAB4ccba",
"newOwners": ["0x41153290c995c8c4410d50f95D87ee86A1B07eeC", "0xB97A1C3993A551f0Febf030539630ACb77E6832D"],
"newThreshold": 2,
"chainId": 1,
"signer": "0x795B9cD1E5419C54B07768d4AD09809407dfAF5b",
"signature": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
}'

Fetch recovery by address

Fetches a recovery request by Safe account address and nonce. Requires account, chainId, and nonce parameters.

GET /recoveries/fetchByAddress

curl -G "https://yourcompany.recovery.candide.dev/fetchByAddress" \
--data-urlencode "account=0xD422B9d638a7BA4eBeF9e33Af9456007eAB4ccba" \
--data-urlencode "chainId=11155111" \
--data-urlencode "nonce=0x1"

List all recoveries by address

Lists all recovery requests for a Safe account with advanced filtering, pagination, and ordering. The executed and finalized filters are cross-checked with indexed on-chain data for accuracy.

GET /recoveries/listByAddress

curl -G "https://yourcompany.recovery.candide.dev/recoveries/listByAddress" \
--data-urlencode "account=0xD422B9d638a7BA4eBeF9e33Af9456007eAB4ccba" \
--data-urlencode "chainId=11155111" \
When to use fetchByAddress vs listByAddress
  • /recoveries/fetchByAddress: Use when you know the exact nonce. Ideal for checking a specific pending request or looking up the current recovery state.
  • /recoveries/listByAddress: Use when you need to query multiple requests with filtering, pagination, or sorting. Better for dashboard UIs showing recovery history.

Fetch recovery by ID

Fetch a recovery request by ID

GET /recoveries/fetchById

curl -G "https://yourcompany.recovery.candide.dev/fetchById" \
--data-urlencode "id=0x123"

Collect a guardian signature

Collects a guardian signature to store for later confirmation and finalization

POST /recoveries/sign

curl -X POST \
https://yourcompany.recovery.candide.dev/sign \
-H 'Content-Type: application/json' \
-d '{
"id": "123456789",
"signer": "0x795B9cD1E5419C54B07768d4AD09809407dfAF5b",
"signature": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
}'

Execute a recovery by ID

POST /recoveries/execute

Execute a recovery request by ID

curl -X POST \
https://yourcompany.recovery.candide.dev/execute \
-H 'Content-Type: application/json' \
-d '{
"id": 123456789
}'

Finalize recovery by ID

POST /recoveries/finalize

Finalize a recovery request by ID

curl -X POST \
https://yourcompany.recovery.candide.dev/finalize \
-H 'Content-Type: application/json' \
-d '{
"id": 123456789
}'

Alerts

Alerts: Subscribe to recovery requests

POST /alerts/subscribe

Creates an inactive alerts subscription for an account, both onchain and offchain. It then needs to be activated through challenge submission using POST /alerts/activate.

curl -X POST \
https://yourcompany.recovery.candide.dev/alerts/subscribe \
-H 'Content-Type: application/json' \
-d '{
"account": "0x...",
"chainId": 1,
"channel": "email",
"target": "user@example.com",
"message": "siwe(chainId, statement(channel, target))",
"signature": "sign(message)"
}'
  • account: The smart account address requesting registration.
  • chainId: The chain id in which the account resides (this is used to verify the signature field only, the alert will trigger for any action for this account across any chain)
  • channel: Either "email" or "sms" (defines the delivery channel).
  • target: The email or phone number for authentication.
  • message: SIWE (EIP-4361) message statement. Statement:
I agree to receive Social Recovery Module alert notifications for my account address on all supported chains sent to {{target}}
  • signature: signature proving the request is initiated from the account

See example guide how to construct the message and signature using Sign in With Ethereum (SIWE)

Alerts: Activate subscription to recovery requests

POST /alerts/activate

Verifies submitted challenge and activates alerts subscription.

curl -X POST \
https://yourcompany.recovery.candide.dev/alerts/activate \
-H 'Content-Type: application/json' \
-d '{
"subscriptionId": "unique-subscription-id",
"challenge": "123456"
}'
  • subscriptionId: The unique ID received in the subscription response.
  • challenge: The code received via email/SMS.

Alerts: Get active subscription

Fetches active alerts subscriptions for an account.

GET /alerts/subscriptions

curl -G "https://yourcompany.recovery.candide.dev/alerts/subscriptions" \
--data-urlencode "account=0x...",
--data-urlencode "chainId=0x1",
--data-urlencode "message=siwe(chainId, statement)",
--data-urlencode "signature=sign(message)"
  • account: The smart account address.
  • chainId: The chain id in which the account resides (this is used to verify the signature field only, the alerts are global for this account accross all supported chains that have alerts enabled)
  • message: SIWE (EIP-4361) message statement. Statement:
I request to retrieve all Social Recovery Module alert subscriptions linked to my account
  • signature: signature proving the request is initiated from the account

See example guide how to construct the message and signature using Sign in With Ethereum (SIWE)

Alerts: Unsubscribe

Unsubscribes from an active alerts subscription.

POST /alerts/unsubscribe

curl -X POST \
https://yourcompany.recovery.candide.dev/alerts/unsubscribe \
-H 'Content-Type: application/json' \
-d '{
"subscriptionId": "unique-subscription-id"
}'
  • subscriptionId: The unique ID received in the subscription response.

Error Handling

The API uses standard HTTP status codes to indicate the success or failure of a request. Error responses include a JSON object with the following structure:

{
"error": {
"code": 404,
"message": "Recovery request not found"
}
}

HTTP Status Codes

CodeDescription
200Success
400Bad Request - Invalid parameters or missing required fields
401Unauthorized - Invalid or missing Bearer token
404Not Found - Resource not found
429Too Many Requests - Rate limit exceeded
500Internal Server Error - Something went wrong on the server

Common Error Messages

MessageDescription
Recovery request not foundThe requested recovery ID does not exist
Invalid signatureThe signature verification failed
Guardian not foundThe signer is not a registered guardian
Insufficient signaturesNot enough guardian signatures collected
Rate limit exceededToo many requests, please try again later