IBExWalletAPI
AuthenticationSign up

Sign-up with passkey 1/2

Enhanced signup endpoint (v1.2) supporting 4 authentication methods.

rpId (tenant identification):

The rpId (Relying Party Identifier) is a domain string that scopes users, wallets, and credentials to your application. Each rpId is an isolated namespace — users created under one rpId are invisible to another. It also serves as the WebAuthn rpId, so the browser enforces that it matches your page origin.

Your rpId must be registered with IBEx. Pass it via:

  • Query parameter: ?rpId=yourdomain.com
  • Header: X-RpId: yourdomain.com
  • Automatically via Origin header (browser requests)

If missing or unregistered, returns 400 Unknown domain/rpId.

For local development, localhost is automatically recognized.

See the full [rpId guide](/docs/guides/integration/rpid) for production setup, WebAuthn constraints, and common errors.

---

Query parameters reference:

| Parameter | Type | Required for |

|-----------|------|-------------|

| wallet | string | All modes (passkeys default, kdf, email, 7702) |

| email | string | wallet=email only |

| address | string | wallet=7702 only (0x-prefixed, 42 chars) |

| chainId | number | wallet=7702 (optional, defaults to project chain) |

| user.name / userName | string | wallet=passkeys (optional, WebAuthn override) |

| user.displayname / userDisplayName | string | wallet=passkeys (optional, WebAuthn override) |

| keyName / keyDisplayName | string | wallet=passkeys (optional, display labels) |

| passkeys | string | ⚠️ Deprecated — use wallet instead |

| flow | string | ⚠️ Deprecated — use wallet=kdf instead |

---

### 1. Passkeys Safe wallet (wallet=passkeys, default)

What it means?

Creates a new user account backed by a WebAuthn passkey (biometric / security key). The browser generates a cryptographic key pair; the public key is registered as the signer for a new Safe Smart Contract Wallet (ERC-4337). This is the most secure mode — the private key never leaves the device.

Next step: POST the credential returned by navigator.credentials.create() to POST /sign-up.

---

### 2. KDF Safe wallet (wallet=kdf)

What it means?

Creates a user account where the signer key is derived client-side from a user-chosen PIN/password using Argon2id. The server never sees the PIN — it only provides the salt and KDF parameters. A server-signed challenge prevents replay attacks. Ideal for devices without biometric/passkey support.

Next step: Derive the key from PIN + salt, sign the canonical message, and call POST /sign-up with the signature proof.

---

### 3. Email Safe wallet (wallet=email, requires email)

What it means?

Creates an account where a one-shot email OTP (30 seconds) verifies the user's email address. The client generates a key pair locally and encrypts the private key with a user passphrase before sending it to the server as a backup. The server stores only the encrypted blob — it can never access the real key. Useful for email-first onboarding.

Next step: Verify the OTP via POST /email/recover, then call POST /sign-up with the signature proof.

---

### 4. EOA + EIP-7702 (wallet=7702, requires address)

What it means?

Registers an existing Externally Owned Account (EOA) and turns it into a Smart Account via EIP-7702 delegation to SafeEIP7702Proxy. The user signs a SIWE-like challenge with their wallet (MetaMask, WalletConnect, etc.). After sign-up, the backend creates a PENDING delegation record — the client must broadcast the EIP-7702 authorization transaction on-chain to activate Smart Account features (modules, batching, recovery).

Next step: Sign challenge with the wallet and call POST /sign-up with { wallet: "7702", address, signature, nonce }.

GET
/v1.2/auth/sign-up

Query Parameters

walletstring

Authentication mode: passkeys (default), kdf, email, or 7702

Value in: "passkeys" | "kdf" | "email" | "7702"
passkeysDeprecatedstring

[Deprecated] Use wallet=passkeys or wallet=kdf instead

Value in: "TRUE" | "FALSE"
flowDeprecatedstring

[Deprecated] Use wallet=kdf instead

Value in: "pin-kdf"
emailstring

[Email mode only] Email address to receive OTP

addressstring

[7702 mode only] EOA address (0x-prefixed, 42 chars)

chainIdnumber

[7702 mode only] Target blockchain chain ID

user.namestring

[Passkeys mode] Override WebAuthn user.name

user.displaynamestring

[Passkeys mode] Override WebAuthn user.displayName

userNamestring

[Passkeys mode] Alias for user.name

userDisplayNamestring

[Passkeys mode] Alias for user.displayname

keyNamestring

[Passkeys mode] Passkey display name stored server-side

keyDisplayNamestring

[Passkeys mode] Passkey display label stored server-side

curl -X GET "https://passkeys-testnet.ibex.fi/v1.2/auth/sign-up?wallet=passkeys&passkeys=TRUE&flow=pin-kdf&email=%3Cstring%3E&address=%3Cstring%3E&chainId=0&user.name=%3Cstring%3E&user.displayname=%3Cstring%3E&userName=%3Cstring%3E&userDisplayName=%3Cstring%3E&keyName=%3Cstring%3E&keyDisplayName=%3Cstring%3E"

Signup challenge (format depends on wallet mode)

{
  "summary": "wallet=passkeys (default)",
  "value": {
    "credentialRequestOptions": {
      "rp": {
        "id": "passkeys-prat1.ibex.fi",
        "name": "IBEx Wallet"
      },
      "user": {
        "id": "base64url-user-id",
        "name": "user@example.com",
        "displayName": "User"
      },
      "challenge": "base64url-challenge",
      "pubKeyCredParams": [
        {
          "type": "public-key",
          "alg": -7
        }
      ],
      "timeout": 60000,
      "attestation": "none",
      "authenticatorSelection": {
        "authenticatorAttachment": "platform",
        "residentKey": "required",
        "userVerification": "required"
      }
    }
  }
}