Safe Modules & Operations
IBEX Safe Modules & Operations — External API Reference
This document provides a comprehensive reference for all Safe (Gnosis Safe) modules, options, and operations exposed through the IBEX-FI API. It is intended for external integrators building on top of the IBEX-FI platform.
Table of Contents
- Overview: Safe Modules & Options
- Module: Recovery
- Module: Multisig (Owners & Threshold)
- Module: Automation / Allowance
- Operations Endpoint Reference
- Automation Trigger & Callback Endpoints
- Automation Config Update Endpoint
- Database Impact
1. Overview: Safe Modules & Options
Every Safe wallet managed by IBEX supports the following features, all accessible through the unified batch operations API (POST /v1.2/safes/operations/batch-intent → PUT /v1.2/safes/operations/batch-execute).
| Category | Operation Type(s) | Description |
|---|---|---|
| Recovery | ENABLE_RECOVERY, CANCEL_RECOVERY | Social recovery module — lets a guardian recover the Safe if the owner loses access. |
| Multisig / Owners | ADD_OWNER, REMOVE_OWNER, CHANGE_THRESHOLD | Add/remove co-signers and change the approval threshold (M-of-N). |
| Allowance (Automation) | ENABLE_AUTOMATION_MODULE | Enable the Safe Allowance Module and configure automatic percentage-based token transfers triggered on deposit. |
| Token Transfers | TRANSFER_EURe, TRANSFER_TOKEN | Send ERC-20 tokens (EURe or any token) from the Safe. |
| Message Signing | SIGN_MESSAGE | EIP-191 / EIP-712 off-chain message signing. |
| DeFi | AAVE_SUPPLY, AAVE_WITHDRAW, SWAP_FROM_QUOTE | Aave lending and CoW Swap token swaps. |
All operations use ERC-4337 (Account Abstraction) with WebAuthn (passkey) authentication. Gas is sponsored by IBEX (paymaster), so the end-user never pays gas.
Batch support: Multiple heterogeneous operations can be grouped into a single atomic transaction via MultiSend, requiring only one WebAuthn signature.
2. Module: Recovery
Allows a trusted guardian to recover the Safe by replacing the owner key.
ENABLE_RECOVERY
Activates the on-chain recovery module on the Safe.
Operation payload:
| Field | Type | Required | Description |
|---|---|---|---|
type | string | ✅ | Must be "ENABLE_RECOVERY" |
firstName | string | ✅ | Guardian's first name |
lastName | string | ✅ | Guardian's last name |
birthDate | string | ✅ | Guardian's birth date (YYYY-MM-DD) |
birthCity | string | ✅ | Guardian's birth city |
birthCountry | string | ✅ | Guardian's birth country (ISO 3166-1 alpha-2) |
On-chain effect: Calls enableModule(recoveryModuleAddress) on the Safe.
Database effect: Sets hasRecovery = true and stores recoveryModuleAddress on the Safe record.
CANCEL_RECOVERY
Cancels a pending recovery procedure.
3. Module: Multisig (Owners & Threshold)
These operations manage the Safe's signer list and the required approval threshold.
ADD_OWNER
Adds a new co-signer (owner) to the Safe and sets the new threshold.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | ✅ | Must be "ADD_OWNER" |
owner | string | ✅ | EVM address of the new owner (0x...) |
threshold | number | ✅ | New signature threshold (≥ 1) |
On-chain effect: Calls addOwnerWithThreshold(owner, threshold) on the Safe.
REMOVE_OWNER
Removes an existing owner from the Safe and sets the new threshold.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | ✅ | Must be "REMOVE_OWNER" |
owner | string | ✅ | EVM address of the owner to remove (0x...) |
threshold | number | ✅ | New signature threshold after removal (≥ 1) |
On-chain effect: Calls removeOwner(prevOwner, owner, threshold) on the Safe. The prevOwner is resolved automatically from the Safe's on-chain owner linked list.
CHANGE_THRESHOLD
Changes the approval threshold without modifying owners.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | ✅ | Must be "CHANGE_THRESHOLD" |
threshold | number | ✅ | New signature threshold (≥ 1, ≤ number of owners) |
On-chain effect: Calls changeThreshold(threshold) on the Safe.
4. Module: Automation / Allowance
The Automation Module leverages the Safe Allowance Module (a standard Gnosis Safe module) to enable automatic percentage-based token transfers when tokens are deposited into the Safe.
Architecture
Key concepts:
- Single Global Module: One Allowance Module contract is deployed per chain (stored in the
Chainstable). No per-user contract deployment needed. - Delegate (Worker): A backend-managed EOA (the "worker") is registered as a delegate on the Allowance Module. This delegate can call
executeAllowanceTransferwithout owner signatures. - Percentage-based: The module is configured with a percentage (0–100). When tokens arrive on the Safe, the backend triggers an automatic transfer of that percentage to the configured target address.
- Counterfactual Safe: If the Safe is not yet deployed on-chain, the
ENABLE_AUTOMATION_MODULEoperation will include theinitCodefor Safe deployment in the UserOperation (exactly likeENABLE_RECOVERY).
ENABLE_AUTOMATION_MODULE
Activates the Allowance Module on the Safe and sets up the allowance configuration. This is a single atomic on-chain transaction (via MultiSend) that performs three actions:
enableModule(allowanceModuleAddress)— Registers the module on the SafeaddDelegate(workerAddress)— Registers the backend worker as a delegatesetAllowance(delegate, token, amount, resetTimeMin, resetBaseMin)— Sets the token allowance
Operation payload:
| Field | Type | Required | Description |
|---|---|---|---|
type | string | ✅ | Must be "ENABLE_AUTOMATION_MODULE" |
targetAddress | string | ✅ | Destination address for automatic transfers |
percentage | number | ✅ | Percentage to transfer on each deposit (0–100) |
frequency | string | ✅ | Frequency constraint: "DAILY", "WEEKLY", "90_DAYS", or "NONE" |
tokenAddress | string | ✅ | ERC-20 token address (0x0...0 for all tokens) |
workerAddress | string | ❌ | Override for the delegate address (defaults to server-configured AUTOMATION_MODULE_WORKER_ADDRESS) |
Frequency values and their reset periods:
| Frequency | Reset Period (on-chain resetTimeMin) | Description |
|---|---|---|
NONE | 0 | No rate limit — can trigger at any time |
DAILY | 1440 min (24 h) | Once per day |
WEEKLY | 10080 min (7 d) | Once per week |
90_DAYS | 129600 min (90 d) | Once per 90 days |
On-chain effect: Calls MultiSend with enableModule + addDelegate + setAllowance in a single UserOperation.
Error conditions:
- Returns
409 Conflictif the automation module is already enabled on the Safe.
How Automatic Transfers Work (Post-Activation)
Once the module is activated, the transfer flow is:
- Deposit detected: BCReader (blockchain reader) detects an ERC-20 transfer to the Safe address.
- Callback: BCReader sends an
erc20_receivedevent to the IBEX backend (via WebSocket or HTTP callback). - Calculation: The backend computes
transferAmount = receivedAmount × percentage / 100. - Execution: The backend worker calls
executeAllowanceTransfer(safe, token, to, amount, ...)on the Allowance Module contract using its delegate private key. - Confirmation: The transfer transaction is confirmed on-chain.
This flow requires no user interaction — it is fully automated once the module is enabled.
5. Operations Endpoint Reference
All Safe operations follow a two-step flow: intent (prepare) then execute (sign & submit).
Step 1 — POST /v1.2/safes/operations/batch-intent
Prepares a batch of one or more operations and returns WebAuthn challenge data.
Authentication: JWT (Bearer token)
Request headers:
| Header | Required | Description |
|---|---|---|
Authorization | ✅ | Bearer <jwt>`` |
X-Blockchain-Id | ❌ | Chain ID (defaults to server DEFAULT_CHAIN_ID) |
Content-Type | ✅ | application/json |
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
safeAddress | string | ✅ | Safe wallet address |
chainId | number | ❌ | Target blockchain ID (e.g. 100 for Gnosis) |
idempotencyKey | string | ❌ | Client-provided key to avoid duplicate batches |
options.atomic | boolean | ❌ | If true (default), all operations must succeed or all revert |
options.autoApprove | boolean | ❌ | Auto-insert ERC-20 approvals before transfers (default true) |
options.ttlSec | number | ❌ | Intent TTL in seconds (default 300, range 60–3600) |
operations | array | ✅ | Array of operation objects (min 1) |
200 Response:
| Field | Type | Description |
|---|---|---|
batchId | string | Unique batch identifier (pass to batch-execute) |
expiresAt | string | ISO 8601 expiration timestamp |
operationCount | number | Number of operations in the batch |
credentialRequestOptions | object | WebAuthn PublicKeyCredentialRequestOptions — use to sign with the passkey |
Step 2 — PUT /v1.2/safes/operations/batch-execute
Submits the signed WebAuthn credential to execute the batch on-chain.
Authentication: JWT (Bearer token)
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
batchId | string | ✅ | The batchId returned by batch-intent |
credential | object | ✅ | Signed WebAuthn credential (from navigator.credentials.get()) |
200 Response:
| Field | Type | Description |
|---|---|---|
userOpHash | string | ERC-4337 UserOperation hash — can be used to track execution status |
Tracking Execution — GET /v1.2/safes/operations/\{userOpHash\}/status
Poll this endpoint to check the on-chain status.
200 Response:
Status lifecycle:
| Status | Description |
|---|---|
CREATED | Operation prepared but not yet signed |
SIGNED | WebAuthn signature attached |
EXECUTED | Submitted to the bundler / on-chain |
CONFIRMED | Confirmed with sufficient block confirmations |
FAILED | Execution reverted or timed out |
6. Automation Trigger & Callback Endpoints
These system-level endpoints are used by the IBEX infrastructure (BCReader / cron) but are documented here for completeness.
POST /system/automation-module/on-token-received
HTTP callback endpoint called by BCReader when an ERC-20 token is received on a watched Safe. Triggers the automatic allowance transfer if the automation module is active.
Authentication: API Key (x-api-key header)
Request body:
200 Response (transfer executed):
200 Response (transfer skipped):
Possible reason values when skipped:
| Reason | Description |
|---|---|
worker_private_key_not_configured | Backend worker key not set |
safe_not_found_or_automation_disabled | Safe not found or hasAutomationModule = false or moduleEnabled = false |
no_module_address | No automationModuleAddress in DB |
no_target_address | No moduleTargetAddress in DB |
token_mismatch | Received token doesn't match configured token |
zero_transfer_amount | Calculated transfer amount is 0 |
POST /system/automation-module/trigger
Cron endpoint that finds all eligible Safes and triggers reclaim operations based on frequency rules.
Authentication: API Key (x-api-key header)
Query parameters:
| Param | Type | Default | Description |
|---|---|---|---|
chainId | number | all chains | Filter by chain ID |
limit | number | 10 | Max number of Safes to process |
200 Response:
7. Automation Config Update Endpoint
PUT /v1.2/safes/\{safeAddress\}/automation-module/config
Updates the automation module configuration for a Safe (off-chain parameters only — does not modify on-chain state).
Authentication: JWT (Bearer token)
Path parameters:
| Param | Type | Description |
|---|---|---|
safeAddress | string | Safe wallet address |
Request body (all fields optional):
| Field | Type | Description |
|---|---|---|
targetAddress | string | New destination address for auto-transfers |
percentage | number | New percentage (0–100) |
frequency | string | "DAILY", "WEEKLY", "90_DAYS", or "NONE" |
tokenAddress | string | ERC-20 token filter (0x0...0 for any token) |
enabled | boolean | Enable/disable the module without removing it |
200 Response:
8. Database Impact
Safe Table
When the automation module is enabled or configured, the following columns are affected:
| Column | Type | Set When | Description |
|---|---|---|---|
hasAutomationModule | Boolean | After on-chain batch-execute confirmation | true once the module is activated on-chain |
automationModuleAddress | String | During batch-intent (pre-execution) | Address of the global Allowance Module contract |
moduleTargetAddress | String | During batch-intent | Destination address for auto-transfers |
modulePercentage | Int | During batch-intent | Percentage (0–100) to auto-transfer |
moduleFrequency | String | During batch-intent | "DAILY", "WEEKLY", "90_DAYS", or "NONE" |
moduleCreationDate | DateTime | On activation | Timestamp of module activation |
moduleEnabled | Boolean | Default true, toggleable via config endpoint | Soft enable/disable switch |
moduleTokenAddress | String | During batch-intent | ERC-20 token address for allowance (0x0...0 = any) |
moduleMaxAllowance | String | During batch-intent | Max allowance amount (string representation of BigInt) |
moduleResetTimeMin | String | During batch-intent | On-chain resetTimeMin (minutes between resets) |
moduleResetBaseMin | String | During batch-intent | On-chain resetBaseMin (always "0") |
moduleLastTriggeredAt | DateTime | After each auto-transfer or cron trigger | Timestamp of the last automatic transfer execution |
Write sequence during ENABLE_AUTOMATION_MODULE:
batch-intent(Step 1): Pre-storesautomationModuleAddress,moduleTargetAddress,modulePercentage,moduleFrequency,moduleTokenAddress,moduleMaxAllowance,moduleResetTimeMin,moduleResetBaseMinon theSaferecord.hasAutomationModuleremainsfalse.batch-execute(Step 2): After on-chain confirmation, setshasAutomationModule = true.on-token-received(auto-transfer): UpdatesmoduleLastTriggeredAtto the current timestamp.
Chains Table
| Column | Type | Description |
|---|---|---|
automationModuleAddress | String | Global Allowance Module contract address for this chain (set during seed/migration) |
SafeOperation Table
Each batch-intent + batch-execute creates one SafeOperation record:
| Column | Type | Description |
|---|---|---|
userOpHash | String (PK) | ERC-4337 UserOperation hash |
safeAddress | String | Associated Safe |
blockchainId | Int | Chain ID |
status | Enum | CREATED → SIGNED → EXECUTED → CONFIRMED (or FAILED) |
transactionHash | String? | On-chain transaction hash (set after execution) |
paymaster | Enum | Always SPONSORED |
Operation Table
Each individual operation within a batch creates one Operation record:
| Column | Type | Description |
|---|---|---|
type | Enum (OperationType) | e.g. ENABLE_AUTOMATION_MODULE, ADD_OWNER, ENABLE_RECOVERY |
index | Int | Position within the batch (0-based) |
data | JSON | Contains params (original request) and encoded (on-chain tx data: to, data, operation, value) |
Recovery-Specific Database Impact
Column (on Safe) | Type | Set When | Description |
|---|---|---|---|
hasRecovery | Boolean | After on-chain confirmation of ENABLE_RECOVERY | true once recovery module is active |
recoveryModuleAddress | String | After on-chain confirmation | Address of the recovery module contract |
Note: Personal data (
firstName,lastName, etc.) submitted withENABLE_RECOVERYis stored temporarily in theOperation.dataJSON during processing, then purged (set to\{\}) after the recovery is registered with the IBEX Safe service.
Full Example: Enable Automation Module (End-to-End)
1. Prepare the operation
Response:
2. Sign with WebAuthn and execute
Response:
3. Poll status until confirmed
Response:
4. Automatic transfer triggers on deposit
When someone sends tokens to the Safe, the backend automatically transfers 50% to the configured targetAddress:
5. Batch example: Multiple operations in one transaction
All three operations are bundled into a single MultiSend transaction requiring only one WebAuthn signature.