# IBEx Wallet API > Advanced self-custody wallet API. Build gasless, passwordless dApps using FIDO2 passkeys + Safe Global wallet or EOA with account abstraction EIP-7702. > Base URL: https://passkeys-productionv2.ibex.fi ## Machine-Readable Resources - [OpenAPI 3.0 Spec (JSON)](https://passkeys-productionv2.ibex.fi/openapi.json): Full specification with schemas, parameters, and response types - [AI Skills File](https://passkeys-productionv2.ibex.fi/skills.md): Structured skill file — boundaries, architecture, workflows, reference - [Full API Docs (Markdown)](https://passkeys-productionv2.ibex.fi/docs/llms-full.txt): Complete endpoint documentation in a single file - [MCP Server](https://passkeys-productionv2.ibex.fi/docs/guides/integration/mcp): Connect AI coding tools (Cursor, Windsurf, Claude) directly to these docs ## Authentication All authenticated endpoints require a JWT Bearer token: ``` Authorization: Bearer ``` Obtain a token via the sign-up or sign-in flow. The `access_token` expires in ~1h; refresh it with `POST /v1.2/auth/refresh`. ### Token lifecycle & refresh strategy - **Access token (`access_token`)**: expires after **3600 seconds (1 hour)**, as indicated by the `expires_in` field in every auth response. - **Refresh token (`refresh_token`)**: valid for **24 hours**, but is **single-use** — once consumed by `POST /v1.2/auth/refresh` it is immediately revoked and a new one is returned. - **Recommended refresh cadence**: proactively call `POST /v1.2/auth/refresh` **5–10 minutes before** the access token expires (i.e. ~50–55 min after issuance). This avoids race conditions where in-flight requests hit a just-expired token. - **Late refresh**: if the access token has already expired but the refresh token is still valid (< 24 h), the refresh endpoint still succeeds and returns a fresh token pair. - **Expired refresh token**: after 24 h the refresh token is no longer valid → `401 Unauthorized`. The user must re-authenticate (sign-in / sign-up). - **One-time use**: each `refresh_token` can only be used **once**. Always store the latest `refresh_token` returned by the most recent call. Replaying an already-consumed token returns `401`. - **AI agent tip**: schedule a refresh timer based on `expires_in` (e.g. `setTimeout(refresh, (expires_in - 300) * 1000)`). On WebSocket connections, listen for `error_code: TOKEN_EXPIRED` to trigger an immediate refresh. Optional headers: - `x-api-key: ` — required if the tenant domain enforces API key auth - `X-Blockchain-Id: ` — select chain (defaults to configured chain) ### Balance response structure — `GET /v1.2/users/me/balances` **Query params:** `walletAddress`, `iban`, `blockchainId`, `includeZero`, `includeEmpty`, `includePrices`, `page`, `limit`. **Chain behavior in aggregated mode** (no `walletAddress` / no `iban`): - **No explicit `blockchainId`** (neither header nor query): returns balances across **all chains** for the user. The platform `DEFAULT_CHAIN_ID` is **not** applied as a filter. - **Explicit `blockchainId`** (header `X-Blockchain-Id` or query `?blockchainId=100`): returns balances for that chain only. **Empty wallet filtering:** By default (`includeEmpty=false`), wallets with no tokens and chains containing only empty wallets are stripped. Set `includeEmpty=true` to include them. Aggregated mode response — `crypto` is an object keyed by chain ID, each chain contains wallets keyed by address: ```json { "timestamp": "2026-05-14T19:07:41.697Z", "crypto": { "100": { "0x67b3a55a...": { "tokens": [ { "tokenAddress": "0x420c...", "symbol": "EURe", "decimals": 18, "balance": "2.0", "price_usd": 1.18, "price_eur": 1, "value_usd": "2.36", "value_eur": "2.00", "price_source": "coinbase" } ], "pending": [] } }, "421614": { "0x391ff36...": { "tokens": [ { "symbol": "ETH-IBEX", "balance": "0.005", "..." : "..." } ], "pending": [] } } }, "fiat": {}, "totals": { "crypto_total_value_eur": "720.75", "grand_total_value_eur": "720.75", "conversion_rate_eur_usd": 1.1797 }, "prices_available": true } ``` - Access tokens via `response.crypto[""][""].tokens[]`. - `totals` provides aggregated values across all chains. - Token rows include `price_usd`, `price_eur`, `value_usd`, `value_eur`, `balance`, `symbol`, `decimals`, `price_source`. - When `includeZero=true`: zero-balance tokens may appear. ### Transactions — `GET /v1.2/users/me/transactions` - `scope` query parameter controls returned classes: `mixed` (default), `crypto`, `fiat`. - `scope=mixed` returns both sections: `crypto` and `fiat`. - `scope=crypto` returns only `crypto`; `scope=fiat` returns only `fiat`. - In aggregated mode (no `walletAddress`/`iban`): explicit `blockchainId` (query) or `X-Blockchain-Id` scopes to one chain; without explicit selector, aggregation runs across all user chains. Aggregated mode response — `crypto.transactions` is an object keyed by chain ID, each chain has its own pagination: ```json { "type": "mixed", "crypto": { "timestamp": "...", "transactions": { "100": { "total": 1, "page": 1, "limit": 50, "totalPages": 1, "data": [ { "transactionHash": "0x...", "from": "0x...", "to": "0x...", "tokenSymbol": "EURe", "valueFormatted": 2, "direction": "IN", "watchedAddress": "0x67b3...", "blockchainId": "100" } ] }, "421614": { "total": 117, "page": 1, "limit": 50, "totalPages": 3, "data": [ "..." ] } }, "prices_available": true }, "fiat": { "ibans": [], "total": 0, "data": [], "filters": { "startDate": "2025-01-01", "endDate": "2026-12-31" } } } ``` - Access transactions via `response.crypto.transactions[""].data[]`. - Each transaction includes: `transactionHash`, `from`, `to`, `tokenAddress`, `tokenSymbol`, `tokenType`, `value`, `valueFormatted`, `direction` (`IN`/`OUT`), `watchedAddress`, `blockchainId`, `price_usd`, `price_eur`, `value_usd`, `value_eur`. - Optional query parameter: `walletAddress` to target a specific user wallet (must belong to JWT user; otherwise `400`). - Optional query parameter: `iban` to target one IBAN only. ### Handling "address not yet indexed" (404) on balance/transaction/pool endpoints - `GET /v1.2/users/me/balances`, `GET /v1.2/users/me/transactions`, `GET /v1.2/users/me/pools` may return `404` if the wallet address is not yet indexed. - Blockchain data is indexed asynchronously. The API automatically triggers indexing and retries the request before returning `404`. - If you still get `404`, wait 5–10 seconds and retry once — the blockchain indexer may need a few seconds to process the address. ### Wallet address endpoint — signer filtering, multi-chain & modules - `GET /v1.2/users/me/address` returns wallets for **the signer that authenticated the JWT**, not all signers of the user. - The JWT contains a `sid` (signer ID) claim added at authentication time. Only safes belonging to that signer are returned. - Each wallet is listed once with a `chainIds` array containing **all chain IDs** the safe is deployed on, sorted numerically. - If the JWT was issued before `sid` support (legacy tokens without this claim), the endpoint falls back to returning all signers' wallets. - Returns `204 No Content` if the signer has no wallets. - **Safe modules per chain**: the `chains` array provides per-chain details. If a Safe module is activated on a chain, it appears in the `modules` object: - `recovery` — social recovery module (guardians can recover the wallet). Fields: `enabled`, `moduleAddress`. - `automation` — allowance/automation module (scheduled transfers, DCA, etc.). - Core fields: `enabled`, `moduleAddress`, `targetAddress`, `transferMode`, `frequency`, `tokenAddress`. - Transfer policy: `percentage` (mode `PERCENT_OF_RECEIVED`) or `fixedAmount` + optional `maxWalletPercentage` (mode `FIXED_AMOUNT`). - Rate/limits: `minIntervalMinutes`, `periodCapAmount`, `periodCapMinutes`. - Modules are **only included** when activated — if no modules exist on a chain, the `modules` field is omitted. - **AI agent tip**: after sign-up, the wallet may take a few seconds to appear. If you receive `204`, retry after 2–3 seconds. - **AI agent tip**: check the `chains[].modules` object to determine which Safe features are enabled before attempting module-specific operations (e.g. don't call recovery endpoints if `recovery` is not present). ### Automatic multi-chain Safe expansion on sign-in - When a user signs in (passkey or KDF mode, `walletMode=SAFE_4337`), the API automatically creates Safe wallet records on **all active chains** that support Safe wallets. - This is **asynchronous** — the sign-in response (JWT) is returned immediately; expansion runs in the background. - Only applies to `PASSKEY` signers with `SAFE_4337` wallet mode. EOA/EIP-7702 wallets are excluded. - The Safe address is **deterministic** (counterfactual) — the same passkey produces the same Safe address on every chain. - New Safe addresses are automatically registered for blockchain balance/transaction monitoring. - **AI agent tip**: after sign-in, call `GET /v1.2/users/me/address` to get the full list. If some chains are missing, retry after 2–3 seconds — the background expansion may still be running. - The JWT now includes a `sid` claim (signer ID) for per-signer wallet filtering. ### Aggregated profile payload — `GET /v1.2/users/me` - Returns a **compact** top-level payload: `addresses`, `balances`, `ibans`, `signers`, `transactions`, `kycStatus`, `addressbook`. - Successful sections are returned directly (no `{ status, data }` wrapper). - When one or more sections fail, an optional `errors` object is added: `errors.
= { status, message }`. - Failed sections are omitted from top-level keys and represented only in `errors`. Section formats: - `addresses`: `{ rpId, externalUserId, signerId, count, wallets[] }`. Each wallet has `safeAddress`, `chainIds[]`, `chains[]`, `primary`, `derived.global.eoaAddresses[]`. - `balances`: same format as `GET /v1.2/users/me/balances` — `{ timestamp, crypto: { "": { "": { tokens[], pending[] } } }, fiat, totals, prices_available }`. Empty wallets/chains are stripped by default. - `transactions`: hybrid format — `crypto` has both a flat `data[]` (with pagination: `total`, `page`, `limit`, `totalPages`) and a grouped `chains[].wallets[]` view. Each transaction in `data[]` includes a `walletAddress` field added by the aggregator. `fiat` has `ibans[]`, `data[]`, `filters`. - `signers`: `{ count, signers[] }`. Each signer has `id`, `type` (`PASSKEY`/`EOA`/`EMAIL_TOKEN`), `walletMode`, `keyName`, `keyDisplayName`, `safesCount`. - `ibans`: `{ count, ibans[] }`. - `kycStatus`: `{ externalUserId, kycLevel, status, verified }`. - `addressbook`: `{ success, data[] }`. ## Guides - [Quick Start](https://passkeys-productionv2.ibex.fi/docs/guides/quick-start): Get started in 5 minutes - [Authentication Concepts](https://passkeys-productionv2.ibex.fi/docs/guides/auth-concepts): The 4 authentication modes (passkey, KDF, email, EOA+7702) - [Key Derivation (KDF)](https://passkeys-productionv2.ibex.fi/docs/guides/kdf): Deterministic wallet derivation - [EOA + EIP-7702](https://passkeys-productionv2.ibex.fi/docs/guides/eip-7702): Upgrade an existing EOA to a Smart Account - [Passkey Integration](https://passkeys-productionv2.ibex.fi/docs/guides/integration/passkey-integration): WebAuthn / FIDO2 integration guide - [WebSocket Events](https://passkeys-productionv2.ibex.fi/docs/guides/integration/websocket): Real-time operation tracking - [SDK](https://passkeys-productionv2.ibex.fi/docs/guides/integration/sdk): JavaScript SDK reference - [cURL Examples](https://passkeys-productionv2.ibex.fi/docs/guides/integration/curl-examples): Copy-paste examples - [MCP Server](https://passkeys-productionv2.ibex.fi/docs/guides/integration/mcp): AI tool integration via MCP ## API Reference — Authentication - [GET /v1.2/auth/sign-in/data/{dataRequestId}](https://passkeys-productionv2.ibex.fi/docs/api-reference/authentication/data/get): Poll asynchronous sign-in include data - [EOA](https://passkeys-productionv2.ibex.fi/docs/api-reference/authentication/morewallet/eoa) - [Safe](https://passkeys-productionv2.ibex.fi/docs/api-reference/authentication/morewallet/safe) - [POST /v1.2/auth/refresh](https://passkeys-productionv2.ibex.fi/docs/api-reference/authentication/refresh): Refresh Session - [POST /v1.2/auth/sign-in/safe-provision](https://passkeys-productionv2.ibex.fi/docs/api-reference/authentication/safe-provision/post): Register additional counterfactual Safe (same passkey signer) - [GET /v1.2/auth/sign-in](https://passkeys-productionv2.ibex.fi/docs/api-reference/authentication/sign-in/get): Sign-in with passkey 1/2 - [POST /v1.2/auth/sign-in](https://passkeys-productionv2.ibex.fi/docs/api-reference/authentication/sign-in/post): Sign-in with passkey 2/2 - [POST /v1.2/auth/email/recover](https://passkeys-productionv2.ibex.fi/docs/api-reference/authentication/sign-in/recover): Recover encrypted wallet backup (wallet=email) - [GET /v1.2/auth/sign-up](https://passkeys-productionv2.ibex.fi/docs/api-reference/authentication/sign-up/get): Sign-up with passkey 1/2 - [POST /v1.2/auth/sign-up](https://passkeys-productionv2.ibex.fi/docs/api-reference/authentication/sign-up/post): Sign-up with passkey 2/2 ## API Reference — Blockchain Operations - [Aave Lending](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/aave) - [PUT /v1.2/safes/{safeAddress}/automation-module/config](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/automation/config): Update automation module configuration for a Safe - [POST /v1.2/safes/bitcoin/tx/broadcast](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/bitcoin/broadcast): Broadcast signed raw transaction (hex) - [POST /v1.2/safes/bitcoin/psbt/build](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/bitcoin/build): Build PSBT (placeholder) - [GET /v1.2/safes/bitcoin/fees](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/bitcoin/fees): Bitcoin fee rates (sat/vB) - [GET /v1.2/safes/bitcoin/info](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/bitcoin/info): Bitcoin network info - [POST /v1.2/safes/bitcoin/send/prepare](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/bitcoin/prepare): Prepare a simple Bitcoin send (no signing) - [GET /v1.2/safes/bitcoin/utxos](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/bitcoin/utxos): List UTXOs for an address - [GET /v1.2/chains/](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/chains): Chains - [Hyperliquid Vaults](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/hyperliquid) - [Morpho Vaults](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/morpho) - [Multisig Operations](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/multisig) - [DeFi Positions](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/pools) - [Sign Message](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/sign-message) - [Solana](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/solana) - [Swap Tokens](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/swap) - [GET /v1.2/safes/swap/quote](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/swap/quote): Get swap quote from COWSWAP, 1INCH or both (uses your first Safe as receiver) - [Transfer Tokens](https://passkeys-productionv2.ibex.fi/docs/api-reference/blockchain-operations/transfer) ## API Reference — User Data & Privacy - [POST /v1.2/auth/enroll](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/kyc/enroll): KYB enrollment - [POST /v1.2/auth/iframe](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/kyc/iframe): Get an iframe URL - [GET /v1.2/users/kyc/status](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/kyc/status): KYC verification status - [GET /v1.2/users/me/address](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/me/address): User's wallet addresses - [GET /v1.2/users/me/addressbook](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/me/addressbook): Address Book - [GET /v1.2/users/me/balances](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/me/balances): User's balances - [GET /v1.2/domain/chainid](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/me/chainid): Tenant chains and wallets - [GET /v1.2/users/me/ibans](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/me/ibans): User's IBANs - [User's data](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/me) - [GET /v1.2/users/me/lending](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/me/lending): Available lending pools - [GET /v1.2/users/me/pools](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/me/pools): User's pool positions - [GET /v1.2/users/me/signers](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/me/signers): User's signers - [GET /v1.2/users/me/tokens](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/me/tokens): List monitored tokens - [GET /v1.2/users/me/transactions](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/me/transactions): User's transactions - [POST /v1.2/users/me/validate-email](https://passkeys-productionv2.ibex.fi/docs/api-reference/privacy/validate-email): Validate email ## API Reference — Admin & Chain Info - [Domains — DNS verification & create](https://passkeys-productionv2.ibex.fi/docs/api-reference/admin/domains) - [DELETE /api/admin/billing/pricing](https://passkeys-productionv2.ibex.fi/docs/api-reference/admin/pricing/delete): Delete pricing rule - [GET /api/admin/billing/pricing](https://passkeys-productionv2.ibex.fi/docs/api-reference/admin/pricing/get): List pricing rules - [PUT /api/admin/billing/pricing](https://passkeys-productionv2.ibex.fi/docs/api-reference/admin/pricing/put): Upsert pricing rule - [GET /api/admin/billing/transactions](https://passkeys-productionv2.ibex.fi/docs/api-reference/admin/transactions/get): List billing transactions - [GET /v1.2/domain/users/{id}](https://passkeys-productionv2.ibex.fi/docs/api-reference/admin/users): Tenant user by externalUserId - [WebSockets](https://passkeys-productionv2.ibex.fi/docs/api-reference/admin/websockets) ## MCP Server Integration Connect AI coding assistants (Cursor, Windsurf, Claude) directly to this documentation: ```bash npx -y @chr33s/mcpdoc https://passkeys-productionv2.ibex.fi/docs/llms.txt ```