This guide walks you through the setup of Para in a Flutter application. You’ll learn how to install the SDK, configure iOS/Android for passkey-based logins, implement user authentication flows, and generate wallets.

If you haven’t already created your Flutter app, follow the official Flutter docs to set up a new project.

Prerequisites

To use Para, you need an API key. This key authenticates your requests to Para services and is essential for integration.

Don’t have an API key yet? Request access to the Developer Portal to create API keys, manage billing, teams, and more.

Installation

Start by installing the Para SDK:

flutter pub add para

Project Setup

To set up associated domains for passkey functionality in your Flutter project, you need to configure both iOS and Android platforms:

To enable passkeys on iOS, you need to set up associated domains in your Xcode project:

  1. Open your Flutter project’s iOS folder in Xcode
  2. Select your target and go to “Signing & Capabilities”
  3. Click ”+ Capability” and add “Associated Domains”
  4. Add the following domains:
    • webcredentials:app.beta.usecapsule.com
    • webcredentials:app.usecapsule.com

For more details, see the Apple Developer documentation.

Important: You must register your TeamId and BundleId with Para via the Developer Portal to use associated domains. This is required by Apple for passkey security. Allow up to 24 hours for domain propagation.

Initializing Para

To use Para’s features, you’ll need to initialize a Para client instance that can be accessed throughout your app. This client handles all interactions with Para’s services, including authentication, wallet management, and transaction signing.

Create a file (e.g., lib/services/para_client.dart) to initialize your Para client:

import 'package:para/para.dart';

// Initialize a global Para client instance
final para = Para(
  environment: Environment.beta, // Use Environment.prod for production
  apiKey: 'YOUR_PARA_API_KEY',
);

You can access para from anywhere in your app by importing the file where you initialized it. This singleton pattern ensures consistent state management across your application.

Para offers two hosted environments: Environment.BETA (alias Environment.DEVELOPMENT) for testing, and Environment.PROD (alias Environment.PRODUCTION) for live use. Select the environment that matches your current development phase.

Using the Para SDK

The Para SDK provides multiple authentication methods including email and phone. Here’s how to implement these methods in your Flutter application.

Beta Testing Credentials In the BETA Environment, you can use any email ending in @test.getpara.com (like dev@test.getpara.com) or US phone numbers (+1) in the format (area code)-555-xxxx (like (425)-555-1234). Any OTP code will work for verification with these test credentials. These credentials are for beta testing only. You can delete test users anytime in the beta developer console to free up user slots.

Create a User with Email

Follow these steps to register a new user with email verification:

Future<void> registerUser(String email) async {
  // Check if user exists
  if (await para.checkIfUserExists(email)) {
    // User exists, handle login flow
    return;
  }
  
  // Create a new user account - this sends a verification code
  await para.createUser(email);
  
  // Next step: Verify the email with the code
}

Future<void> verifyAndCreateWallet(String email, String verificationCode) async {
  // Verify the code to get biometricsId
  final biometricsId = await para.verifyEmail(verificationCode);
  
  // Generate a passkey for this device
  await para.generatePasskey(email, biometricsId);
  
  // Create a wallet for the user
  final result = await para.createWallet(skipDistribute: false);
  
  // Store the recovery share securely
  final recoveryShare = result.recoveryShare;
}

Login with Email

To authenticate an existing user with their email:

Future<void> loginUser() async {
  // This triggers the platform's native passkey selection UI
  final wallet = await para.login();
  
  // User is now logged in
  // You can access their wallet address
  final address = wallet.address;
}

You can also check if a user is already logged in:

Future<void> checkLoginStatus() async {
  final isLoggedIn = await para.isFullyLoggedIn();
  
  if (isLoggedIn) {
    // User is logged in, get their wallets
    final wallets = await para.getWallets();
    
    // Access the first wallet
    if (wallets.isNotEmpty) {
      final wallet = wallets.values.first;
      final address = wallet.address;
    }
  }
}

When createWallet is called with skipDistribute: false, Para automatically handles the distribution of backup shares. Make sure to securely store and display the recovery secret to the user in your app as it’s essential for account recovery.

Working with Wallets

Once a user is authenticated, you can access and manage their wallets:

// Get all wallets for the current user
Future<void> getUserWallets() async {
  try {
    final wallets = await para.getWallets();
    
    // Access wallet information
    for (final wallet in wallets) {
      print('Wallet type: ${wallet.type}');
      print('Wallet address: ${wallet.address}');
    }
  } catch (e) {
    // Handle errors
  }
}

Examples

For practical implementations of the Para SDK in Flutter environments, check out our GitHub repository:

Troubleshooting

If you encounter issues during the integration or usage of the Para SDK in your Flutter application, here are some common problems and their solutions:

Next Steps

After integrating Para into your Flutter app, you can explore other features and integrations to enhance your Para experience.