Safe Recovery UX API
Use the Recovery UX API to collect guardian signatures, submit recovery transactions, track requests, and manage email/SMS alerts for Safe accounts. It works with the Social Recovery Module.
For email/SMS verification that produces a guardian signature, use the Email/SMS Recovery API. For an explanation of the full recovery process, see the service overview.
Before You Start
- Enable the Social Recovery Module and configure guardians and a recovery threshold on the Safe account.
- Request service access to obtain your service URL and Bearer token.
- Use the Recovery Flow Guide for a TypeScript integration example.
Authentication
Include Authorization: Bearer YOUR_BEARER_TOKEN in every request. Replace https://yourcompany.recovery.candide.dev with your service URL.
Requests that create or approve a recovery also require a guardian signature over the recovery data. Alert subscription management requires an owner-signed SIWE message. These signatures authorize the account action; the Bearer token authenticates access to the API.
Examples use placeholder addresses, IDs, messages, and signatures. Replace them with values from your integration. Expressions such as siwe(...) and sign(message) describe values to generate in your application; they are not literal API inputs.
Recovery Workflow
- Create: Submit a request with the first guardian's signature using
/recoveries/create. - Approve: Other guardians check the request's emoji sequence with the account owner through a trusted channel, then submit signatures using
/recoveries/sign. - Execute: Once the guardian threshold is met, call
/recoveries/executeto submit the request on-chain and start the grace period. - Finalize: After the grace period, call
/recoveries/finalizeto apply the new owners and signing threshold. The current owner can cancel the recovery during the grace period.
The service sponsors gas for execution and finalization when configured, but it does not submit them on its own: your application must call both endpoints. Guardians can submit signatures off-chain without holding funds. Use the lookup endpoints to monitor progress; a successful submission does not by itself mean ownership has changed. See request states.
newThreshold is the signing threshold for the new Safe owners after recovery. The existing guardian threshold determines how many guardians must approve the recovery.
Endpoints
| Method | Endpoint | Purpose |
|---|---|---|
| POST | /recoveries/create | Create a request with a guardian signature. |
| POST | /recoveries/sign | Add another guardian's signature. |
| POST | /recoveries/execute | Submit execution once the guardian threshold is met. |
| POST | /recoveries/finalize | Submit finalization after the grace period. |
| GET | /recoveries/fetchById | Fetch one request by its service ID. |
| GET | /recoveries/fetchByAddress | Fetch requests for an account, chain, and recovery nonce. |
| GET | /recoveries/listByAddress | List requests with filters, sorting, and pagination. |
| POST | /alerts/subscribe | Create an inactive alert subscription and send a verification code. |
| POST | /alerts/activate | Verify the code and activate the subscription. |
| GET | /alerts/subscriptions | List active subscriptions for an account and owner. |
| POST | /alerts/unsubscribe | Remove a subscription. |
Recoveries
Create Recovery Request
Create a request proposing new owners and their signing threshold. The signer must be a guardian of the Safe account, and signature must approve the recovery data. The service stores this first signature with the request.
POST /recoveries/create
- Example Request
- Example Response
- Request Body
- Response Body
curl -X POST \
https://yourcompany.recovery.candide.dev/recoveries/create \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"account": "0xD422B9d638a7BA4eBeF9e33Af9456007eAB4ccba",
"newOwners": ["0x41153290c995c8c4410d50f95D87ee86A1B07eeC", "0xB97A1C3993A551f0Febf030539630ACb77E6832D"],
"newThreshold": 2,
"chainId": 1,
"signer": "0x795B9cD1E5419C54B07768d4AD09809407dfAF5b",
"signature": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
}'
{
"id": "123456789",
"emoji": "🤖😅🥵👻🖖",
"account": "0xD422B9d638a7BA4eBeF9e33Af9456007eAB4ccba",
"chainId": 1,
"newOwners": [
"0x41153290c995c8c4410d50f95D87ee86A1B07eeC",
"0xB97A1C3993A551f0Febf030539630ACb77E6832D"
],
"newThreshold": 2,
"nonce": "0x1",
"signatures": [
[
"0x795B9cD1E5419C54B07768d4AD09809407dfAF5b",
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
]
],
"executeData": {
"sponsored": false,
"transactionHash": ""
},
"finalizeData": {
"sponsored": false,
"transactionHash": ""
},
"status": "PENDING",
"discoverable": true,
"createdAt": "2023-04-18T12:34:56.789Z",
"updatedAt": "2023-04-18T12:34:56.789Z"
}
| key | type | description |
|---|---|---|
account | string | The Safe account address that the owner wants to recover. Must be a valid Ethereum address |
newOwners | string[] | The new owners to the Safe account. Must be a valid Ethereum addresses |
newThreshold | number | The signing threshold for the new Safe owners after recovery; not the guardian approval threshold |
chainId | number | The chainId of the network where the Safe account resides |
signer | string | The guardian public address initiating the recovery request |
signature | string | A signature from the guardian for a message containing the address of the safe, new owners of the Safe, chainId, module address, and a nonce |
| key | type | description |
|---|---|---|
id | string | The ID associated with the Recovery Request |
emoji | string | The emojis associated with the recovery request |
account | string | The Safe account address that the owner wants to recover. Must be a valid Ethereum address |
chainId | number | The chainId of the network where the Safe account resides |
newOwners | string[] | The new owners for the Safe account |
newThreshold | number | The signing threshold for the new Safe owners after recovery; not the guardian approval threshold |
nonce | string | Recovery module nonce serialized as a hexadecimal string in JSON responses |
signatures | json | The signatures for the recovery request |
executeData | object | Execution transaction details |
executeData.sponsored | boolean | If the recovery execution tx is gas-sponsored or not |
executeData.transactionHash | string | The transaction hash of the recovery execution |
finalizeData | object | Finalization transaction details |
finalizeData.sponsored | boolean | If the recovery finalization tx after the grace period ends is gas-sponsored or not |
finalizeData.transactionHash | string | The transaction hash of the finalization execution |
status | string | The status of the recovery request: PENDING | EXECUTION-IN-PROGRESS | EXECUTED | FINALIZATION-IN-PROGRESS | FINALIZED |
discoverable | boolean | Whether the recovery request is discoverable |
createdAt | datetime | The date the recovery request was created |
updatedAt | datetime | The date and time the recovery request was last updated |
Collect a guardian signature
Add a guardian signature to an existing recovery request. The signature must approve the same recovery data as the request.
POST /recoveries/sign
- Example Request
- Example Response
- Request Body
- Response
curl -X POST \
https://yourcompany.recovery.candide.dev/recoveries/sign \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"id": "123456789",
"signer": "0x795B9cD1E5419C54B07768d4AD09809407dfAF5b",
"signature": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
}'
{
"success": true
}
| key | type | description |
|---|---|---|
id | string | Recovery request ID |
signer | string | The guardian public address |
signature | string | The signature for the message hash of the guardian confirmation of recovery |
| key | type | description |
|---|---|---|
success | boolean | True when the guardian signature has been accepted |
Execute a recovery by ID
Submit the execution transaction for a request that has met the guardian threshold. Execution starts the grace period; it does not change ownership.
POST /recoveries/execute
- Example Request
- Example Response
- Request Body
- Response
curl -X POST \
https://yourcompany.recovery.candide.dev/recoveries/execute \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"id": "123456789"
}'
{
"success": true
}
| key | type | description |
|---|---|---|
id | string | Recovery request ID |
| key | type | description |
|---|---|---|
success | boolean | True when the execution request succeeds; use the recovery status to track on-chain progress |
Finalize recovery by ID
Submit the finalization transaction after the grace period has ended. Once finalized on-chain, the new owners and signing threshold take effect.
POST /recoveries/finalize
- Example Request
- Example Response
- Request Body
- Response
curl -X POST \
https://yourcompany.recovery.candide.dev/recoveries/finalize \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"id": "123456789"
}'
{
"success": true
}
| key | type | description |
|---|---|---|
id | string | Recovery request ID |
| key | type | description |
|---|---|---|
success | boolean | True when the finalization request succeeds; use the recovery status to confirm completion |
Fetch recovery by address
Fetch all discoverable requests matching a Safe account, chain, and recovery module nonce. The response is an array, which can be empty. Supply nonce as a hexadecimal string.
GET /recoveries/fetchByAddress
- Example Request
- Example Response
- Query Parameters
- Response
curl -G "https://yourcompany.recovery.candide.dev/recoveries/fetchByAddress" \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
--data-urlencode "account=0xD422B9d638a7BA4eBeF9e33Af9456007eAB4ccba" \
--data-urlencode "chainId=1" \
--data-urlencode "nonce=0x1"
[
{
"id": "123456789",
"emoji": "🤖😅🥵👻🖖",
"account": "0xD422B9d638a7BA4eBeF9e33Af9456007eAB4ccba",
"chainId": 1,
"newOwners": [
"0x41153290c995c8c4410d50f95D87ee86A1B07eeC",
"0xB97A1C3993A551f0Febf030539630ACb77E6832D"
],
"newThreshold": 2,
"nonce": "0x1",
"signatures": [
[
"0x795B9cD1E5419C54B07768d4AD09809407dfAF5b",
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
]
],
"executeData": {
"sponsored": false,
"transactionHash": ""
},
"finalizeData": {
"sponsored": false,
"transactionHash": ""
},
"status": "PENDING",
"discoverable": true,
"createdAt": "2023-04-18T12:34:56.789Z",
"updatedAt": "2023-04-18T12:34:56.789Z"
},
{
"id": "72682373",
"emoji": "💳📿🪣📥📹",
"account": "0xD422B9d638a7BA4eBeF9e33Af9456007eAB4ccba",
"chainId": 1,
"newOwners": [
"0x73f7b1184B5cD361cC0f7654998953E2a251dd58",
"0x7Cb027917b27BCb5963C548657a008BF45b25BDc"
],
"newThreshold": 2,
"nonce": "0x1",
"signatures": [
[
"0x795B9cD1E5419C54B07768d4AD09809407dfAF5b",
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
]
],
"executeData": {
"sponsored": false,
"transactionHash": ""
},
"finalizeData": {
"sponsored": false,
"transactionHash": ""
},
"status": "PENDING",
"discoverable": true,
"createdAt": "2023-04-18T12:34:56.789Z",
"updatedAt": "2023-04-18T12:34:56.789Z"
}
]
| key | type | description |
|---|---|---|
account | string | The Safe account address that the owner wants to recover. Must be a valid Ethereum address |
chainId | number | The chainId of the network where the Safe account resides |
nonce | string | Recovery module contract nonce as a hexadecimal string, such as 0x1 |
| key | type | description |
|---|---|---|
RecoveryRequest[] | object | A list of ongoing Recovery Requests for a Safe account address |
RecoveryRequest[].id | string | The ID associated with the Recovery Request |
RecoveryRequest[].emoji | string | The emojis associated with the recovery request |
RecoveryRequest[].account | string | The Safe account address that the owner wants to recover. Must be a valid Ethereum address |
RecoveryRequest[].chainId | number | The chainId of the network where the Safe account resides |
RecoveryRequest[].newOwners | string[] | The new owners for the Safe account |
RecoveryRequest[].newThreshold | number | The signing threshold for the new Safe owners after recovery; not the guardian approval threshold |
RecoveryRequest[].nonce | string | Recovery module nonce serialized as a hexadecimal string in JSON responses |
RecoveryRequest[].signatures | json | The signatures for the recovery request |
RecoveryRequest[].executeData | object | Execution transaction details |
RecoveryRequest[].executeData.sponsored | boolean | If the recovery execution tx is gas-sponsored or not |
RecoveryRequest[].executeData.transactionHash | string | The transaction hash of the recovery execution |
RecoveryRequest[].finalizeData | object | Finalization transaction details |
RecoveryRequest[].finalizeData.sponsored | boolean | If the recovery finalization tx after the grace period ends is gas-sponsored or not |
RecoveryRequest[].finalizeData.transactionHash | string | The transaction hash of the finalization execution |
RecoveryRequest[].status | string | The status of the recovery request: PENDING | EXECUTION-IN-PROGRESS | EXECUTED | FINALIZATION-IN-PROGRESS | FINALIZED |
RecoveryRequest[].discoverable | boolean | Whether the recovery request is discoverable |
RecoveryRequest[].createdAt | datetime | The date the recovery request was created |
RecoveryRequest[].updatedAt | datetime | The date and time the recovery request was last updated |
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
- Example Request
- Example Response
- Query Parameters
- Response
curl -G "https://yourcompany.recovery.candide.dev/recoveries/listByAddress" \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
--data-urlencode "account=0xD422B9d638a7BA4eBeF9e33Af9456007eAB4ccba" \
--data-urlencode "chainId=1" \
--data-urlencode "limit=20" \
--data-urlencode "offset=0"
[
{
"id": "123456789",
"emoji": "🤖😅🥵👻🖖",
"account": "0xD422B9d638a7BA4eBeF9e33Af9456007eAB4ccba",
"chainId": 1,
"newOwners": [
"0x41153290c995c8c4410d50f95D87ee86A1B07eeC",
"0xB97A1C3993A551f0Febf030539630ACb77E6832D"
],
"newThreshold": 2,
"nonce": "0x1",
"signatures": [
[
"0x795B9cD1E5419C54B07768d4AD09809407dfAF5b",
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
]
],
"executeData": {
"sponsored": false,
"transactionHash": ""
},
"finalizeData": {
"sponsored": false,
"transactionHash": ""
},
"status": "PENDING",
"discoverable": true,
"createdAt": "2023-04-18T12:34:56.789Z",
"updatedAt": "2023-04-18T12:34:56.789Z"
}
]
The response is a plain array with no total count. Request each next page by increasing offset by limit.
For queries without the executed and finalized filters, stop when fewer than limit items are returned. These two filters are applied after pagination, so queries using either filter can return a short or empty page even when later pages contain matching requests. For those queries, response length does not reliably indicate the end of the results.
| key | type | description |
|---|---|---|
account | string | The Safe account address. Must be a valid Ethereum address |
chainId | number | The chainId of the network where the Safe account resides |
status | string | (Optional) Filter by status: PENDING, EXECUTED, FINALIZED, EXECUTION-IN-PROGRESS, FINALIZATION-IN-PROGRESS |
executed | boolean | (Optional) Filter by executed status. Cross-checked with indexed data |
finalized | boolean | (Optional) Filter by finalized status. Cross-checked with indexed data |
nonce | string | (Optional) Filter by recovery nonce as a hex string. Use nonce__lt, nonce__gt, nonce__lte, or nonce__gte for range comparisons |
createdAt | string | (Optional) Filter by creation time as an ISO 8601 date. Use createdAt__lt, createdAt__gt, createdAt__lte, or createdAt__gte for range comparisons |
orderBy | string | (Optional) Field to order by: 'createdAt' or 'nonce' |
order | string | (Optional) Order direction: 'asc' or 'desc'. Defaults to 'desc' |
limit | number | (Optional) Maximum number of requests to return, between 1 and 50. Defaults to 20 |
offset | number | (Optional) Number of requests to skip for pagination. Defaults to 0 |
| key | type | description |
|---|---|---|
RecoveryRequest[] | object | A list of Recovery Requests matching the filters, as a plain array |
RecoveryRequest[].id | string | The ID associated with the Recovery Request |
RecoveryRequest[].emoji | string | The emojis associated with the recovery request |
RecoveryRequest[].account | string | The Safe account address that the owner wants to recover. Must be a valid Ethereum address |
RecoveryRequest[].chainId | number | The chainId of the network where the Safe account resides |
RecoveryRequest[].newOwners | string[] | The new owners for the Safe account |
RecoveryRequest[].newThreshold | number | The signing threshold for the new Safe owners after recovery; not the guardian approval threshold |
RecoveryRequest[].nonce | string | Recovery module nonce serialized as a hexadecimal string in JSON responses |
RecoveryRequest[].signatures | json | The signatures for the recovery request |
RecoveryRequest[].executeData | object | Execution transaction details |
RecoveryRequest[].executeData.sponsored | boolean | If the recovery execution tx is gas-sponsored or not |
RecoveryRequest[].executeData.transactionHash | string | The transaction hash of the recovery execution |
RecoveryRequest[].finalizeData | object | Finalization transaction details |
RecoveryRequest[].finalizeData.sponsored | boolean | If the recovery finalization tx after the grace period ends is gas-sponsored or not |
RecoveryRequest[].finalizeData.transactionHash | string | The transaction hash of the finalization execution |
RecoveryRequest[].status | string | The status of the recovery request: PENDING | EXECUTION-IN-PROGRESS | EXECUTED | FINALIZATION-IN-PROGRESS | FINALIZED |
RecoveryRequest[].discoverable | boolean | Whether the recovery request is discoverable |
RecoveryRequest[].createdAt | datetime | The date the recovery request was created |
RecoveryRequest[].updatedAt | datetime | The date and time the recovery request was last updated |
/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 one request using the id returned when it was created.
GET /recoveries/fetchById
- Example Request
- Example Response
- Query Parameters
- Response Body
curl -G "https://yourcompany.recovery.candide.dev/recoveries/fetchById" \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
--data-urlencode "id=123456789"
{
"id": "123456789",
"emoji": "🤖😅🥵👻🖖",
"account": "0xD422B9d638a7BA4eBeF9e33Af9456007eAB4ccba",
"chainId": 1,
"newOwners": [
"0x41153290c995c8c4410d50f95D87ee86A1B07eeC",
"0xB97A1C3993A551f0Febf030539630ACb77E6832D"
],
"newThreshold": 2,
"nonce": "0x1",
"signatures": [
[
"0x795B9cD1E5419C54B07768d4AD09809407dfAF5b",
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
]
],
"executeData": {
"sponsored": false,
"transactionHash": ""
},
"finalizeData": {
"sponsored": false,
"transactionHash": ""
},
"status": "PENDING",
"discoverable": true,
"createdAt": "2023-04-18T12:34:56.789Z",
"updatedAt": "2023-04-18T12:34:56.789Z"
}
| key | type | description |
|---|---|---|
id | string | Recovery request ID |
| key | type | description |
|---|---|---|
id | string | The ID associated with the Recovery Request |
emoji | string | The emojis associated with the recovery request |
account | string | The Safe account address that the owner wants to recover. Must be a valid Ethereum address |
chainId | number | The chainId of the network where the Safe account resides |
newOwners | string[] | The new owners for the Safe account |
newThreshold | number | The signing threshold for the new Safe owners after recovery; not the guardian approval threshold |
nonce | string | Recovery module nonce serialized as a hexadecimal string in JSON responses |
signatures | json | The signatures for the recovery request |
executeData | object | Execution transaction details |
executeData.sponsored | boolean | If the recovery execution tx is gas-sponsored or not |
executeData.transactionHash | string | The transaction hash of the recovery execution |
finalizeData | object | Finalization transaction details |
finalizeData.sponsored | boolean | If the recovery finalization tx after the grace period ends is gas-sponsored or not |
finalizeData.transactionHash | string | The transaction hash of the finalization execution |
status | string | The status of the recovery request: PENDING | EXECUTION-IN-PROGRESS | EXECUTED | FINALIZATION-IN-PROGRESS | FINALIZED |
discoverable | boolean | Whether the recovery request is discoverable |
createdAt | datetime | The date the recovery request was created |
updatedAt | datetime | The date and time the recovery request was last updated |
Alerts
Alert subscriptions are separate from email/SMS recovery registrations. Subscribing to alerts does not add a guardian or enable email/SMS recovery.
Create a subscription, then activate it with the code sent to the selected channel. Subscriptions monitor the Safe account across supported chains with alerts enabled. The chainId identifies the network used to verify the signing owner; subscription creation also checks that this owner belongs to the Safe on that chain.
The owner signs the SIWE message for subscription creation, lookup, and removal. See SIWE signing and the Recovery Alerts Guide.
Create an Alert Subscription
POST /alerts/subscribe
Create an inactive subscription and send a verification code to the target email address or phone number. Save the returned subscriptionId and activate it using /alerts/activate.
- Example Request
- Example Response
curl -X POST \
https://yourcompany.recovery.candide.dev/alerts/subscribe \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"account": "0x...",
"owner": "0x...",
"chainId": 1,
"channel": "email",
"target": "user@example.com",
"message": "siwe(chainId, statement(account, channel, target))",
"signature": "sign(message)"
}'
{
"subscriptionId": "unique-subscription-id"
}
account: The Safe account to monitor.owner: The Safe owner authorizing the subscription and signing the SIWE message.chainId: The supported chain used to verify the owner and signature. Subscriptions cover all supported chains with alerts enabled.channel: Either"email"or"sms"(defines the delivery channel).target: The email address or phone number that receives alerts.signature: The signature fromownerover the complete SIWE message.message: The complete SIWE message containing this exact statement:
I agree to receive Social Recovery Module alert notifications for {{account}} on all supported chains sent to {{target}} (via {{channel}})
Replace {{account}} with the lowercase Safe address, {{target}} with the destination, and {{channel}} with email or sms.
See SIWE signing to construct the message and signature.
Activate an Alert Subscription
POST /alerts/activate
Submit the verification code sent during subscription creation. Alerts begin after activation.
- Example Request
- Example Response
curl -X POST \
https://yourcompany.recovery.candide.dev/alerts/activate \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"subscriptionId": "unique-subscription-id",
"challenge": "123456"
}'
{
"success": true
}
subscriptionId: The unique ID received in the subscription response.challenge: The code received via email/SMS.
List Active Alert Subscriptions
Fetch active subscriptions for the specified Safe account and signing owner.
GET /alerts/subscriptions
- Example Request
- Example Response
curl -G "https://yourcompany.recovery.candide.dev/alerts/subscriptions" \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
--data-urlencode "account=0x..." \
--data-urlencode "owner=0x..." \
--data-urlencode "chainId=1" \
--data-urlencode "message=siwe(chainId, statement)" \
--data-urlencode "signature=sign(message)"
{
"subscriptions": [
{
"id": "unique-subscription-id",
"channel": "email",
"target": "user@example.com"
}
]
}
account: The Safe account being monitored.owner: The owner whose subscriptions to retrieve and who signs the SIWE message.chainId: The supported chain used to verify the owner and signature. Subscriptions cover all supported chains with alerts enabled.signature: The signature fromownerover the complete SIWE message.message: The complete SIWE message containing this exact statement:
I request to retrieve all Social Recovery Module alert subscriptions linked to my account
See SIWE signing to construct the message and signature.
Remove an Alert Subscription
Remove the subscription identified by subscriptionId. Include the owner's SIWE message and signature.
POST /alerts/unsubscribe
- Example Request
- Example Response
curl -X POST \
https://yourcompany.recovery.candide.dev/alerts/unsubscribe \
-H 'Authorization: Bearer YOUR_BEARER_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"subscriptionId": "unique-subscription-id",
"owner": "0x...",
"chainId": 1,
"message": "siwe(chainId, statement)",
"signature": "sign(message)"
}'
{
"success": true
}
subscriptionId: The subscription to remove.owner: The owner signing the request.chainId: The supported chain used to verify the signature.message: The complete SIWE message containing the statement below.signature: The signature fromownerover that message.
I request to unsubscribe from all Social Recovery Module alert subscriptions linked to my account
Use this exact statement even when removing one subscription. The subscriptionId selects the subscription to remove.
Error Handling
Use the HTTP status to determine whether a request succeeded. Service errors contain top-level code and message fields. For example:
{
"code": 404,
"message": "Recovery request not found"
}
HTTP Status Codes
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - Invalid parameters, missing required fields, or an invalid guardian signature |
| 401 | Unauthorized - Invalid or missing Bearer token |
| 403 | Forbidden - SIWE signature verification failed, challenge invalid or expired, sponsorship not enabled for the network, or the request is not ready to execute (wrong nonce or insufficient signatures) |
| 404 | Not Found - Resource not found |
| 409 | Conflict - The alert subscription already exists |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error - Something went wrong on the server |
Troubleshooting
- Invalid signature: Check the signing address, chain ID, and exact message or recovery data. SIWE messages must use the statement for the requested action.
- Invalid or expired code: Verify that the code matches the challenge ID. If it has expired, create a new alert subscription and verify its new code.
- Missing resource: Use the ID returned by the corresponding creation endpoint.
- Rate limit: Wait before retrying the request.