diff --git a/docs.json b/docs.json
index cf8cfc41..decf01b3 100644
--- a/docs.json
+++ b/docs.json
@@ -126,7 +126,7 @@
"pages": [
"sdks/react/landing",
"sdks/react-native",
- "sdks/flutter",
+ "sdks/flutter/landing",
"sdks/swift",
"sdks/typescript-frontend/landing",
"sdks/javascript-server"
@@ -408,7 +408,26 @@
"sdks/react-native/advanced-api-requests"
]
},
- "sdks/flutter",
+ {
+ "group": "Flutter",
+ "pages": [
+ "sdks/flutter/index",
+ "sdks/flutter/getting-started",
+ {
+ "group": "Authentication",
+ "pages": [
+ "sdks/flutter/authentication/overview",
+ "sdks/flutter/authentication/email-sms",
+ "sdks/flutter/authentication/passkey",
+ "sdks/flutter/authentication/social-logins"
+ ]
+ },
+ "sdks/flutter/sub-organization-customization",
+ "sdks/flutter/using-embedded-wallets",
+ "sdks/flutter/signing",
+ "sdks/flutter/advanced-api-requests"
+ ]
+ },
{
"group": "Swift",
"pages": [
diff --git a/sdks/flutter.mdx b/sdks/flutter.mdx
deleted file mode 100644
index c52a6fb5..00000000
--- a/sdks/flutter.mdx
+++ /dev/null
@@ -1,40 +0,0 @@
----
-title: "Flutter"
-description: "This documentation contains guides for using the Flutter SDK."
----
-
-We have created a set of Dart packages that can be used to interact with the Turnkey API. These can be combined to create a fully-featured Flutter app, powered by Turnkey.
-
-## Packages
-
-| Package Name | Description | Link |
-| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
-| turnkey_sdk_flutter | A Flutter package that simplifies the integration of the Turnkey API into Flutter applications. It provides secure session management, authentication, and cryptographic operations | [turnkey_sdk_flutter](https://pub.dev/packages/turnkey_sdk_flutter) |
-| turnkey_http | A lower-level, fully typed HTTP client for interacting with the Turnkey API. | [turnkey_http](https://pub.dev/packages/turnkey_http) |
-| turnkey_api_key_stamper | A Dart package for API stamping functionalities. It is meant to be used with Turnkey's HTTP package. | [turnkey_api_key_stamper](https://pub.dev/packages/turnkey_api_key_stamper) |
-| turnkey_flutter_passkey_stamper | A Flutter package for stamping payloads with passkeys. It is meant to be used with Turnkey's HTTP package. | [turnkey_flutter_passkey_stamper](https://pub.dev/packages/turnkey_flutter_passkey_stamper) |
-| turnkey_crypto | This package consolidates common cryptographic utilities used across our applications, particularly primitives related to keys, encryption, and decryption in a pure Dart implementation. | [turnkey_crypto](https://pub.dev/packages/turnkey_crypto) |
-| turnkey_encoding | This package contains decoding and encoding functions used by other Turnkey packages. | [turnkey_encoding](https://pub.dev/packages/turnkey_encoding) |
-
-You can visit [Turnkey's pub.dev publisher page](https://pub.dev/publishers/turnkey.com/packages) to see all all the packages we have published and install them in your Flutter project.
-
-## Getting Started
-
-The easiest way to build a Flutter app with Turnkey is to use our [Flutter demo app](https://github.com/tkhq/dart-sdk/tree/main/examples/flutter-demo-app) as a starter. This app is a fully-featured example that demonstrates how to use the Turnkey's Flutter SDK to authenticate users, create wallets, export wallets, sign messages, and more.
-
-The app includes a backend [JavaScript server](https://github.com/tkhq/dart-sdk/tree/main/examples/flutter-demo-app/api-server) which uses [@turnkey/sdk-server](https://www.npmjs.com/package/@turnkey/sdk-server) to make requests to Turnkey that must be signed by the parent organization. An example of a request that must be signed by the parent organization is creating a [sub-organization](/concepts/sub-organizations). [(code reference)](https://github.com/tkhq/dart-sdk/blob/51405520d721910961fa942ddc5f5a3030783b9b/examples/flutter-demo-app/api-server/src/controllers/turnkey-api.ts#L139-L178)
-
-Some requests made to Turnkey must be signed by the sub-organization. These are written in Dart and are ran by the app directly. You can find these requests in the app's [TurnkeyProvider](https://github.com/tkhq/dart-sdk/blob/main/examples/flutter-demo-app/lib/providers/turnkey.dart). An example of a request that must be signed by the sub-organization is creating a wallet. [(code reference)](https://github.com/tkhq/dart-sdk/blob/51405520d721910961fa942ddc5f5a3030783b9b/examples/flutter-demo-app/lib/providers/turnkey.dart#L531-L559)
-
-## Video
-
-
-
-
-
-#### Complete the installation and setup by following the instructions in the [README](https://github.com/tkhq/dart-sdk/blob/main/examples/flutter-demo-app/README.md) file.
diff --git a/sdks/flutter/advanced-api-requests.mdx b/sdks/flutter/advanced-api-requests.mdx
new file mode 100644
index 00000000..cef999b2
--- /dev/null
+++ b/sdks/flutter/advanced-api-requests.mdx
@@ -0,0 +1,112 @@
+---
+
+title: "Advanced API requests"
+description: "Learn how to make advanced API requests to Turnkey's infrastructure."
+sidebarTitle: "Advanced API requests"
+---
+
+## Overview
+
+Turnkey's Flutter SDK provides a wide variety of helper functions to abstract interactions with Turnkey's infrastructure.
+However, you can also make advanced API requests directly to Turnkey's endpoints if you need more control or want to implement custom features in your Flutter app.
+
+## The underlying client
+
+To make advanced API requests, use the `client` retrieved from the `TurnkeyProvider`.
+This client is tied to the active session, so stamping, authentication, and organization context are automatically handled for you.
+
+You can see the [API Reference](/api-reference/overview) for a complete list of available API endpoints and their parameters. All of these can be accessed through the `client`.
+
+Here's how you can use the `client` to make a `signRawPayload` request to Turnkey:
+
+```dart title=lib/widgets/sign_raw_payload_button.dart
+import 'dart:convert';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class SignRawPayloadButton extends StatelessWidget {
+ const SignRawPayloadButton({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ Future doSignRawPayload() async {
+ try {
+ final wallet = tk.wallets?.first;
+ final account = wallet?.accounts.first;
+ if (account == null) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text('No account available to sign with')),
+ );
+ return;
+ }
+
+ final message = 'Hello, Turnkey!';
+ final payload = utf8
+ .encode(message)
+ .fold('', (s, byte) => s + byte.toRadixString(16).padLeft(2, '0'));
+
+ final response = await tk.client.signRawPayload(
+ SignRawPayloadParams(
+ signWith: account.address,
+ payload: payload,
+ encoding: v1PayloadEncoding.payload_encoding_hexadecimal,
+ hashFunction: v1HashFunction.hash_function_not_applicable,
+ ),
+ );
+
+ debugPrint('Message signed: ${response.signature}');
+ } catch (error) {
+ debugPrint('Error signing message: $error');
+ }
+ }
+
+ return ElevatedButton(
+ onPressed: doSignRawPayload,
+ child: const Text('Sign Message'),
+ );
+ }
+}
+```
+
+## Viewing the activity
+
+When creating, modifying, or using resources within Turnkey, an activity is created. You can learn more about activities in the [Activities](/api-reference/activities/overview) section.
+
+If you use the `client`, you can view all the metadata of the activity you are performing.
+This includes the activity ID, status, and more.
+
+```dart
+final response = await tk.client.updateWallet(
+ UpdateWalletParams(
+ walletId: 'a-wallet-id-123',
+ walletName: 'New wallet name',
+ ),
+);
+
+final activity = response.activity;
+if (activity != null) {
+ debugPrint('Activity ID: ${activity.id}');
+ debugPrint('Status: ${activity.status}');
+}
+```
+
+
+## Stamping with a passkey
+
+You can create a client that uses a passkey for stamping instead of using securely stored api keys. Use the `createPasskeyClient` method from the `TurnkeyProvider` to create a new client instance configured for passkey stamping.
+
+An `rpId` is required to use passkey stamping; you can either pass it directly when creating the client or set it in the `TurnkeyProvider` config.
+
+```dart
+final passkeyClient = await tk.createPasskeyClient(
+ passkeyStamperConfig: PasskeyStamperConfig( // You can pass this into the TurnkeyProvider config instead
+ rpId: 'example.com',
+ ),
+);
+```
+
+To learn more about using passkeys in your Flutter app, check out the [Passkey Authentication](/sdks/flutter/authentication/passkey) guide.
+
diff --git a/sdks/flutter/authentication/email-sms.mdx b/sdks/flutter/authentication/email-sms.mdx
new file mode 100644
index 00000000..47779fd0
--- /dev/null
+++ b/sdks/flutter/authentication/email-sms.mdx
@@ -0,0 +1,172 @@
+---
+
+title: "Email and SMS OTP authentication"
+description: "Set up and implement email or SMS OTP authentication using Turnkey's Flutter SDK."
+sidebarTitle: "Email & SMS"
+---
+
+## Overview
+
+This guide shows how to implement OTP authentication using `turnkey_sdk_flutter`. You'll trigger an OTP to a user's email address (or phone number), navigate to a verification screen, and verify the 6-digit code.
+
+Before you begin:
+
+* Complete the provider setup from **Getting Started** and enable **Auth Proxy** with **Email OTP** and/or **SMS OTP** in the Turnkey Dashboard.
+* Ensure your `TurnkeyConfig` is pointing at the correct `authProxyConfigId` (OTP settings are controlled in the dashboard).
+
+## Request an OTP (email)
+
+Create or update your login screen to request an email OTP using `initOtp`. The snippet below navigates to an OTP screen with the returned `otpId` and the email address.
+
+```dart title=lib/screens/login.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+import 'otp.dart';
+
+class LoginScreen extends StatefulWidget {
+ const LoginScreen({super.key});
+
+ @override
+ State createState() => _LoginScreenState();
+}
+
+class _LoginScreenState extends State {
+ final _emailController = TextEditingController();
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ return Scaffold(
+ appBar: AppBar(title: const Text('Login')),
+ body: Padding(
+ padding: const EdgeInsets.all(16),
+ child: Column(
+ children: [
+ TextField(
+ controller: _emailController,
+ keyboardType: TextInputType.emailAddress,
+ decoration: const InputDecoration(hintText: 'you@example.com'),
+ ),
+ const SizedBox(height: 12),
+ ElevatedButton(
+ onPressed: () async {
+ final email = _emailController.text.trim();
+ if (email.isEmpty || !email.contains('@')) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text('Enter a valid email')),
+ );
+ return;
+ }
+
+ // Request OTP from Turnkey
+ final otpId = await tk.initOtp(
+ otpType: OtpType.Email,
+ contact: email,
+ );
+
+ if (!context.mounted) return;
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (_) => OTPScreen(
+ otpId: otpId,
+ contact: email,
+ otpType: OtpType.Email,
+ ),
+ ),
+ );
+ },
+ child: const Text('Continue with email'),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
+```
+
+## Verify the OTP code
+
+On the OTP screen, pass `contact` and `otpId` via the constructor and call `loginOrSignUpWithOtp` with the 6-digit code.
+
+```dart title=lib/screens/otp.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class OTPScreen extends StatefulWidget {
+ final String otpId;
+ final String contact; // email or phone number
+ final OtpType otpType; // OtpType.Email or OtpType.Sms
+
+ const OTPScreen({
+ super.key,
+ required this.otpId,
+ required this.contact,
+ required this.otpType,
+ });
+
+ @override
+ State createState() => _OTPScreenState();
+}
+
+class _OTPScreenState extends State {
+ final _otpController = TextEditingController();
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ return Scaffold(
+ appBar: AppBar(title: const Text('Verify code')),
+ body: Padding(
+ padding: const EdgeInsets.all(16),
+ child: Column(
+ children: [
+ TextField(
+ controller: _otpController,
+ keyboardType: TextInputType.number,
+ maxLength: 6, // default OTP length is 6
+ decoration: const InputDecoration(hintText: 'Enter 6-digit code', counterText: ''),
+ ),
+ const SizedBox(height: 12),
+ ElevatedButton(
+ onPressed: () async {
+ final code = _otpController.text.trim();
+ if (code.length != 6) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text('Enter the 6-digit code')),
+ );
+ return;
+ }
+
+ // Verify OTP and log in/sign up
+ await tk.loginOrSignUpWithOtp(
+ otpId: widget.otpId,
+ otpCode: code,
+ contact: widget.contact,
+ otpType: widget.otpType,
+ );
+
+ // Success will trigger onSessionSelected in your TurnkeyConfig
+ if (!mounted) return;
+ Navigator.pop(context);
+ },
+ child: const Text('Verify'),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
+```
+
+### Notes
+
+* The default OTP length is **6**; if you customized OTP settings in the dashboard, validate accordingly.
+* To resend a code, call `initOtp` again with the same contact.
+* For SMS, replace `OtpType.Email` with `OtpType.Sms` and pass a phone number in `contact`.
diff --git a/sdks/flutter/authentication/overview.mdx b/sdks/flutter/authentication/overview.mdx
new file mode 100644
index 00000000..9ec275e2
--- /dev/null
+++ b/sdks/flutter/authentication/overview.mdx
@@ -0,0 +1,156 @@
+---
+title: "Overview"
+description: "Learn how to set up, log in, or sign up easily in your Flutter app using Turnkey's Flutter SDK."
+sidebarTitle: "Overview"
+---
+
+Turnkey's Flutter SDK makes authentication simple. You can call specific login and signup functions (email/SMS OTP, passkeys, or social logins) to build your own UI and auth flow.
+
+## Authentication state
+
+In Flutter, you access auth state via the `TurnkeyProvider` (a `ChangeNotifier`). The presence of a `session` indicates the user is authenticated.
+
+```dart title=lib/widgets/auth_status.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class AuthStatus extends StatelessWidget {
+ const AuthStatus({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Consumer(
+ builder: (context, tk, _) {
+ final session = tk.session; // null when not authenticated
+ final user = tk.user; // may be null until fetched
+
+ if (session != null) {
+ return Text('Welcome back, ${user?.userName ?? 'user'}!');
+ }
+
+ return ElevatedButton(
+ onPressed: () {
+ // Navigate to your login screen or trigger your chosen auth flow
+ // e.g., email OTP, passkey, or social login
+ Navigator.of(context).pushNamed('/login');
+ },
+ child: const Text('Log in'),
+ );
+ },
+ );
+ }
+}
+```
+
+You can also set up an `onSessionSelected` callback in `TurnkeyConfig` to handle post-authentication logic, such as redirecting.
+
+```dart title=snippet (in main.dart where you construct TurnkeyProvider)
+final turnkeyProvider = TurnkeyProvider(
+ config: TurnkeyConfig(
+ // ... your existing config ...
+ onSessionSelected: (session) {
+ // User authenticated — perform navigation or data preloads
+ navigatorKey.currentState?.pushReplacementNamed('/dashboard');
+ },
+ ),
+);
+```
+
+## Listening to provider updates
+
+`TurnkeyProvider` is a `ChangeNotifier`, so you can attach listeners to respond to internal state changes (e.g., when wallets/users are fetched). This pattern is useful when you want to mirror provider data into local widget state.
+
+Below is an example (adapted from the [demo app](https://github.com/tkhq/dart-sdk/tree/main/examples/flutter-demo-app)) that keeps a local `selectedWallet`/`selectedAccount` in sync with the provider:
+
+```dart title=lib/screens/dashboard.dart (excerpt)
+class DashboardScreenState extends State {
+ Wallet? _selectedWallet;
+ v1WalletAccount? _selectedAccount;
+
+ late final TurnkeyProvider _turnkeyProvider;
+ late final VoidCallback _providerListener;
+
+ @override
+ void initState() {
+ super.initState();
+
+ // Capture provider once; no context in listener later.
+ _turnkeyProvider = Provider.of(context, listen: false);
+
+ _providerListener = _handleProviderUpdate;
+ _turnkeyProvider.addListener(_providerListener);
+
+ // Initialize local selections from provider.
+ _updateSelectedWalletFromProvider(_turnkeyProvider);
+ }
+
+ @override
+ void dispose() {
+ // Always remove listeners to avoid calling setState on a disposed widget.
+ _turnkeyProvider.removeListener(_providerListener);
+ super.dispose();
+ }
+
+ void _handleProviderUpdate() {
+ if (!context.mounted) return;
+ _updateSelectedWalletFromProvider(_turnkeyProvider);
+ }
+
+ void _updateSelectedWalletFromProvider(TurnkeyProvider provider) {
+ final wallets = provider.wallets;
+ final user = provider.user;
+
+ if (user == null || wallets == null || wallets.isEmpty) return;
+ if (wallets.first.accounts.isEmpty) return;
+
+ if (!context.mounted) return;
+ setState(() {
+ _selectedWallet = wallets.first;
+ _selectedAccount = wallets.first.accounts.first;
+ });
+ }
+}
+```
+
+> **Tips**
+>
+> * Use `addListener/removeListener` for one-off reactions to state changes.
+> * Use `Consumer`, `Selector`, or `context.select` when you want automatic rebuilds based on specific slices of provider state.
+> * Avoid calling `setState` inside your listener after the widget is disposed — always guard with `if (!mounted) return;` or `if (!context.mounted) return;`.
+
+## Customize sub-organization creation
+
+Need to configure default user names, passkey names, wallet creations or anything sub-org related? You can learn more about customizing the sub-orgs you create in the [Sub-Organization Customization](/sdks/flutter/sub-organization-customization).
+
+Follow the guides below to learn how to set up email and SMS authentication, passkey authentication, and social logins in your Flutter app.
+
+
+
+ Learn how to set up email and SMS authentication in your Flutter app.
+
+
+ Learn how to set up passkey authentication in your Flutter app.
+
+
+ Discover how to add social logins (Google, Apple, X, Discord) and handle wallet creation and account derivation.
+
+
\ No newline at end of file
diff --git a/sdks/flutter/authentication/passkey.mdx b/sdks/flutter/authentication/passkey.mdx
new file mode 100644
index 00000000..47f8e6cf
--- /dev/null
+++ b/sdks/flutter/authentication/passkey.mdx
@@ -0,0 +1,154 @@
+---
+
+title: "Passkey authentication"
+description: "Set up and implement passkey authentication using Turnkey's Flutter SDK."
+sidebarTitle: "Passkeys"
+---
+
+## Overview
+
+This guide shows how to implement passkey authentication in a Flutter app using `turnkey_sdk_flutter`.
+You'll add the necessary platform configuration, set up the provider with a proper `rpId`, and call `signUpWithPasskey` and `loginWithPasskey` from your UI.
+
+## Passkey setup (platform)
+
+Passkeys require an **Relying Party ID (rpId)** that matches a domain you control and a verified association between your app and that domain.
+
+### iOS — Associated Domains
+
+1. **Enable the entitlement** in Xcode for your iOS target:
+
+ * Select your app target → **Signing & Capabilities** → **+ Capability** → **Associated Domains**.
+ * Add an entry: `webcredentials:yourdomain.com` (replace with your domain).
+
+2. **Entitlements file** (if editing manually): `ios/Runner/Runner.entitlements`
+
+```xml title=ios/Runner/Runner.entitlements
+
+
+
+
+ com.apple.developer.associated-domains
+
+ webcredentials:yourdomain.com
+
+
+
+```
+
+> Ensure your provisioning profile includes **Associated Domains**. The domain must serve a valid **Apple App Site Association (AASA)** file.
+
+3. **AASA file** hosted by your domain at `https://yourdomain.com/.well-known/apple-app-site-association`.
+ The file should include your app's team/app identifiers. Refer to Apple's documentation for the exact structure.
+
+### Android — Digital Asset Links
+
+1. Host a **Digital Asset Links** statement at:
+ `https://yourdomain.com/.well-known/assetlinks.json`
+
+2. Include your app's package name and signing certificate SHA‑256 fingerprint.
+
+```json title=public/.well-known/assetlinks.json
+[
+ {
+ "relation": [
+ "delegate_permission/common.get_login_creds"
+ ],
+ "target": {
+ "namespace": "android_app",
+ "package_name": "com.example.myapp",
+ "sha256_cert_fingerprints": [
+ "AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90"
+ ]
+ }
+ }
+]
+```
+
+> Make sure the file is served with `Content-Type: application/json` and no redirects.
+
+## Provider configuration
+
+Set `passkeyConfig.rpId` to the domain you associated above (e.g., `yourdomain.com`). This must match the iOS/Android domain setup.
+
+```dart title=lib/main.dart (excerpt)
+final turnkeyProvider = TurnkeyProvider(
+ config: TurnkeyConfig(
+ // ... your existing config ...
+ passkeyConfig: PasskeyConfig(
+ rpId: 'yourdomain.com', // Note: You can also manually pass the rpId into the login/signUp methods
+ ),
+ ),
+);
+```
+
+## Usage
+
+Below are minimal examples to sign up and log in with passkeys.
+
+### Sign up with passkey
+
+```dart title=lib/screens/login.dart (excerpt)
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class LoginScreen extends StatelessWidget {
+ const LoginScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ ElevatedButton(
+ onPressed: () async {
+ await tk.signUpWithPasskey(); // rpId can be passed here optionally instead of in the TurnkeyProvider config
+ // onSessionSelected will handle navigation on success
+ },
+ child: const Text('Sign up with passkey'),
+ ),
+ ],
+ );
+ }
+}
+```
+
+### Log in with passkey
+
+```dart title=lib/screens/login.dart (excerpt)
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class LoginScreen extends StatelessWidget {
+ const LoginScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ ElevatedButton(
+ onPressed: () async {
+ await tk.loginWithPasskey(); // rpId can be passed here optionally instead of in the TurnkeyProvider config
+ // onSessionSelected will handle navigation on success
+ },
+ child: const Text('Log in with passkey'),
+ ),
+ ],
+ );
+ }
+}
+```
+
+## Tips
+
+* `rpId` **must** match the domain configured in your platform setup, otherwise passkey operations will fail.
+* iOS: confirm your build includes **Associated Domains** and the AASA file is reachable.
+* Android: confirm `assetlinks.json` is valid and your app's package name + signing certificate fingerprint are correct.
+* Consider setting a dynamic display name for passkeys on sign-up so users can identify authenticators later.
diff --git a/sdks/flutter/authentication/social-logins.mdx b/sdks/flutter/authentication/social-logins.mdx
new file mode 100644
index 00000000..77fa6ebd
--- /dev/null
+++ b/sdks/flutter/authentication/social-logins.mdx
@@ -0,0 +1,242 @@
+---
+
+title: "Social logins"
+description: "Configure and implement social logins in your Flutter app using `turnkey_sdk_flutter`."
+sidebarTitle: "Social logins"
+---
+
+## Configuring OAuth
+
+Using OAuth requires configuration in the Turnkey Dashboard and in your app.
+
+### Enabling OAuth
+
+Navigate to the **Wallet Kit** section in the [Turnkey Dashboard](https://app.turnkey.com/dashboard/walletKit) and enable **OAuth**. If you have not enabled the Auth Proxy, enable it first. See [Getting Started](/sdks/flutter/getting-started) for details.
+
+
+
+### Configuring OAuth providers
+
+Enable the providers you want to use under **Social logins**.
+
+
+
+#### Client IDs
+
+You can enter client IDs for each provider and the redirect URL directly in the dashboard:
+
+
+
+
+
+Or provide client IDs and the redirect URI through your app configuration and pass them to the `TurnkeyProvider`.
+
+
+ For OAuth 2.0 providers, you will need to upload the client ID and secret in the dashboard. See the **OAuth 2.0 providers** section below for details.
+
+
+#### Client configuration
+
+If you prefer configuring via code, provide your client IDs and optional redirect URI through `TurnkeyConfig.authConfig.oAuthConfig`, and set an `appScheme` to complete deep links.
+
+```dart title=lib/main.dart (excerpt)
+final turnkeyProvider = TurnkeyProvider(
+ config: TurnkeyConfig(
+ // ... your existing config ...
+ appScheme: 'myapp', // Required for OAuth deep link completion
+ authConfig: AuthConfig(
+ oAuthConfig: OAuthConfig(
+ // Note: If no redirect URI is provided, the default redirect URI will be used: https://oauth-redirect.turnkey.com. This url must be configured to redirect back to your app!
+ oauthRedirectUri: '', // Optional: e.g., "https://your-app.com/oauth-callback"
+
+ // Client IDs from your provider dashboards
+ googleClientId: '',
+ appleClientId: '',
+ facebookClientId: '',
+ xClientId: '',
+ discordClientId: '',
+ ),
+ ),
+ ),
+);
+```
+
+### App scheme configuration (deep links)
+
+Register your app scheme on each platform to complete the OAuth flow.
+
+#### iOS (Info.plist)
+
+```xml title=ios/Runner/Info.plist (excerpt)
+CFBundleURLTypes
+
+
+ CFBundleURLName
+ myapp
+ CFBundleURLSchemes
+
+ myapp
+
+
+
+```
+
+#### Android (AndroidManifest.xml)
+
+```xml title=android/app/src/main/AndroidManifest.xml (excerpt)
+
+
+
+
+
+
+```
+
+Replace `myapp` with your actual scheme and ensure it matches `appScheme` in `TurnkeyConfig`.
+
+## Usage
+
+Call the helper for each provider from your `TurnkeyProvider` instance: `handleGoogleOauth`, `handleAppleOauth`, `handleFacebookOauth`, `handleDiscordOauth`, and `handleXOauth`.
+
+```dart title=lib/screens/social_logins.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class SocialLoginButtons extends StatelessWidget {
+ const SocialLoginButtons({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ Future run(Future Function() fn) async {
+ try {
+ await fn();
+ // onSessionSelected in TurnkeyConfig can handle navigation on success
+ } catch (e) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(content: Text('Error: $e')),
+ );
+ }
+ }
+
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ ElevatedButton(
+ onPressed: () => run(tk.handleGoogleOauth),
+ child: const Text('Continue with Google'),
+ ),
+ ElevatedButton(
+ onPressed: () => run(tk.handleAppleOauth),
+ child: const Text('Continue with Apple'),
+ ),
+ ElevatedButton(
+ onPressed: () => run(tk.handleFacebookOauth),
+ child: const Text('Continue with Facebook'),
+ ),
+ ElevatedButton(
+ onPressed: () => run(tk.handleDiscordOauth),
+ child: const Text('Continue with Discord'),
+ ),
+ ElevatedButton(
+ onPressed: () => run(tk.handleXOauth),
+ child: const Text('Continue with X'),
+ ),
+ ],
+ );
+ }
+}
+```
+
+## Provider details
+
+### OAuth providers
+
+#### Google
+
+Requirements:
+
+* Dashboard: enable Google in Wallet Kit → Authentication.
+* Client ID: Web client ID from the Google developer console, set in the Dashboard or via `OAuthConfig`.
+
+Usage:
+
+```dart
+await context.read().handleGoogleOauth();
+```
+
+#### Apple
+
+Requirements:
+
+* Dashboard: enable Apple.
+* Client ID: Apple Services ID, set in the Dashboard or via `OAuthConfig`.
+* Redirect URI must match your configured value (e.g., `myapp://`).
+
+Usage:
+
+```dart
+await context.read().handleAppleOauth();
+```
+
+#### Facebook
+
+Requirements:
+
+* Dashboard: enable Facebook.
+* Client ID: set in the Dashboard or via `OAuthConfig`.
+* Redirect URI must match your configured value (e.g., `myapp://`).
+
+Usage:
+
+```dart
+await context.read().handleFacebookOauth();
+```
+
+### OAuth 2.0 providers
+
+For providers that use OAuth 2.0 (e.g., X, Discord), configure additional settings in the Turnkey Dashboard.
+
+In **Wallet Kit → Socials**, click **Add provider**.
+
+
+
+Select the provider and fill in the required fields from the provider console. Secrets are encrypted on upload.
+
+
+
+Then go to **Authentication** and enable the provider under **SDK Configuration**.
+
+
+
+Click **Select** to choose your newly added client ID, then **Save Settings**. Alternatively, enter the client ID through `OAuthConfig`.
+
+#### Discord
+
+Requirements:
+
+* Dashboard: enable Discord (OAuth 2.0).
+* Client ID: set in Dashboard or via `OAuthConfig`.
+* Redirect URI must match your configured value (e.g., `myapp://`).
+
+Usage:
+
+```dart
+await context.read().handleDiscordOauth();
+```
+
+#### X (Twitter)
+
+Requirements:
+
+* Dashboard: enable X (OAuth 2.0).
+* Client ID: set in Dashboard or via `OAuthConfig`.
+* Redirect URI must match your configured value (e.g., `myapp://`).
+
+Usage:
+
+```dart
+await context.read().handleXOauth();
+```
diff --git a/sdks/flutter/getting-started.mdx b/sdks/flutter/getting-started.mdx
new file mode 100644
index 00000000..59f22fd8
--- /dev/null
+++ b/sdks/flutter/getting-started.mdx
@@ -0,0 +1,179 @@
+---
+title: "Getting started with Turnkey's Flutter SDK"
+description: "Learn how to setup Turnkey's Flutter SDK into your application. This guide walks you through enabling Turnkey's Auth Proxy, installing the SDK, and configuring the provider."
+sidebarTitle: "Getting started"
+---
+
+## Turnkey organization setup
+
+To start, you must create a Turnkey organization via the [Turnkey dashboard](https://app.turnkey.com). The steps to do so are described in the [Account Setup](/getting-started/quickstart) section.
+
+For this setup, we will be using Turnkey's Auth Proxy to handle authentication. We can enable and configure this through the Turnkey dashboard.
+
+
+
+ Navigate to the **Wallet Kit** section in the Turnkey Dashboard and enable the
+ **Auth Proxy**.
+
+
+
+
+
+
+
+
+
+
+You can choose which auth methods to enable and customize various options from this screen. For this quickstart, let's enable **email OTP** and **passkeys**. When you're done, click **Save**.
+
+
+
+
+
+
+
+
+
+
+
+Once you're finished with the auth proxy setup, you can copy the **auth proxy config ID**
+
+
+
+and your **organization ID** from the dashboard.
+
+
+
+These will be used in the next steps to configure your app.
+
+
+
+
+
+## Installation
+
+You can use `turnkey_sdk_flutter` in any Flutter application.
+
+If you're starting fresh, create a new Flutter app:
+
+```bash
+flutter create my_turnkey_app
+cd my_turnkey_app
+```
+
+Add the Turnkey Flutter SDK and supporting packages:
+
+
+
+```bash dart
+flutter pub add turnkey_sdk_flutter provider flutter_inappwebview
+```
+
+
+
+
+## Provider
+
+Wrap your app with `ChangeNotifierProvider` and configure `TurnkeyProvider`.
+
+
+```dart lib/main.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+
+final GlobalKey navigatorKey = GlobalKey();
+
+void main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+
+ // Optional: define some callbacks
+ void onSessionSelected(Session session) {
+ // Do something when the user logs in, e.g. navigate to home screen
+ }
+
+ void onSessionCleared(Session session) {
+ // Do something when the user logs out, e.g. navigate to login screen
+ }
+
+ void onInitialized(Object? error) {
+ // Do something when the SDK is initialized
+ }
+
+ final turnkeyProvider = TurnkeyProvider(
+ config: TurnkeyConfig(
+ authProxyConfigId: "",
+ organizationId: "",
+
+ // Optional: attach some callbacks
+ onSessionSelected: onSessionSelected,
+ onSessionCleared: onSessionCleared,
+ onInitialized: onInitialized,
+ ),
+ );
+
+ runApp(
+ ChangeNotifierProvider(
+ create: (_) => turnkeyProvider,
+ child: const MyApp(),
+ ),
+ );
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ navigatorKey: navigatorKey,
+ title: 'My Turnkey App',
+ theme: ThemeData(useMaterial3: true),
+ home: const MyApp(), // Replace with your app's screen
+ );
+ }
+}
+```
+
+## Optional: Ready state & error surfacing
+
+You can await `turnkeyProvider.ready` during startup to surface initialization errors to the user:
+
+```dart
+turnkeyProvider.ready.then((_) {
+ debugPrint('Turnkey is ready');
+}).catchError((error) {
+ debugPrint('Error during Turnkey initialization: $error');
+ // Show a snackbar/toast after the current frame
+});
+```
+
+
+## Demo app
+
+You can check out a complete demo app that uses Turnkey's Flutter SDK on [GitHub](https://github.com/tkhq/dart-sdk/tree/main/examples/flutter-demo-app). Feel free to clone and modify it to get started quickly!
+
+
+
+
+## Next steps
+
+Ready to start building your app? Check out the **Authentication** guide to learn how to set up login/signup in your Flutter application.
diff --git a/sdks/flutter/index.mdx b/sdks/flutter/index.mdx
new file mode 100644
index 00000000..dbda184b
--- /dev/null
+++ b/sdks/flutter/index.mdx
@@ -0,0 +1,62 @@
+---
+title: "Overview"
+description: "Turnkey's Flutter SDK [`(turnkey_sdk_flutter)`](https://pub.dev/packages/turnkey_sdk_flutter) is the easiest way to integrate Turnkey's Embedded Wallets into your Flutter applications, no backend required. It provides a set of functions and utilities to interact with Turnkey's APIs, a powerful session management system, built-in stampers, and a raw HTTP client for advanced use cases."
+sidebarTitle: "Overview"
+---
+
+Find `turnkey_sdk_flutter` on [pub.dev](https://pub.dev/packages/turnkey_sdk_flutter) or view the source code on [GitHub](https://github.com/tkhq/dart-sdk)!
+
+
+
+
+ The initial setup guide for integrating Turnkey's Flutter SDK into your app.
+
+
+ Learn how to set up authentication that leverages Turnkey's Auth Proxy, enabling fast and secure user authentication in your Flutter app.
+
+
+ Discover how to create and manage embedded wallets in your Flutter
+ application, including wallet creation, account derivation, and more.
+
+
+
+ Learn how to sign transactions and messages in your Flutter app using
+ Turnkey's Embedded Wallets.
+
+
+
+ Learn how to customize the sub-organization settings in your Flutter app,
+ including wallet creation options and default usernames for different
+ authentication methods.
+
+
\ No newline at end of file
diff --git a/sdks/flutter/landing.mdx b/sdks/flutter/landing.mdx
new file mode 100644
index 00000000..1b316755
--- /dev/null
+++ b/sdks/flutter/landing.mdx
@@ -0,0 +1,7 @@
+---
+title: "Flutter"
+description: "Turnkey's Flutter SDK [`(turnkey_sdk_flutter)`](https://pub.dev/packages/turnkey_sdk_flutter) is the easiest way to integrate Turnkey's Embedded Wallets into your Flutter applications, no backend required. It provides a set of functions and utilities to interact with Turnkey's APIs, a powerful session management system, built-in stampers, and a raw HTTP client for advanced use cases."
+sidebarTitle: "Flutter"
+---
+
+Head over to the [Getting Started](/sdks/flutter/getting-started) guide to set up your Flutter app with Turnkey's Embedded Wallets.
diff --git a/sdks/flutter/signing.mdx b/sdks/flutter/signing.mdx
new file mode 100644
index 00000000..49f5f6e8
--- /dev/null
+++ b/sdks/flutter/signing.mdx
@@ -0,0 +1,95 @@
+---
+
+title: "Signing"
+description: "Learn how to sign messages and transactions in your Flutter app using Turnkey's Embedded Wallets."
+sidebarTitle: "Signing"
+---
+
+## Overview
+
+Turnkey's Flutter SDK makes it simple to sign messages and transactions using embedded wallets managed by the `TurnkeyProvider`.
+
+
+## Signing messages
+
+To sign a message, select a wallet account and call `signMessage` from the `TurnkeyProvider`. You can optionally pass in the payload's `encoding` and `hashFunction` if needed.
+
+```dart title=lib/widgets/sign_message_button.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class SignMessageButton extends StatelessWidget {
+ const SignMessageButton({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ Future doSignMessage() async {
+ try {
+ final wallet = tk.wallets?.first;
+ final account = wallet?.accounts.first;
+
+
+ final message = 'Hello, Turnkey!';
+ final signature = await tk.signMessage(
+ walletAccount: account,
+ message: message,
+ );
+
+ debugPrint('Message signature: $signature');
+ } catch (e) {
+ debugPrint('Sign message failed: $e');
+ }
+ }
+
+ return ElevatedButton(
+ onPressed: doSignMessage,
+ child: const Text('Sign Message'),
+ );
+ }
+}
+```
+
+## Signing transactions
+
+To sign transactions, use the `signTransaction` function. Select a wallet account's address, prepare an unsigned transaction, and specify a transaction type.
+
+```dart title=lib/widgets/sign_transaction_button.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class SignTransactionButton extends StatelessWidget {
+ const SignTransactionButton({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ Future doSignTransaction() async {
+ try {
+ final wallet = tk.wallets?.first;
+ final account = wallet?.accounts.first;
+
+ final unsignedTx = '0x...'; // unsigned transaction hex
+ final signature = await tk.signTransaction(
+ signWith: account.address, // use the address of the wallet account
+ unsignedTransaction: unsignedTx,
+ transactionType: v1TransactionType.transaction_type_ethereum,
+ );
+
+ debugPrint('Tx signature: $signature');
+ } catch (e) {
+ debugPrint('Sign transaction failed: $e');
+ }
+ }
+
+ return ElevatedButton(
+ onPressed: doSignTransaction,
+ child: const Text('Sign Transaction'),
+ );
+ }
+}
+```
diff --git a/sdks/flutter/sub-organization-customization.mdx b/sdks/flutter/sub-organization-customization.mdx
new file mode 100644
index 00000000..83ee7401
--- /dev/null
+++ b/sdks/flutter/sub-organization-customization.mdx
@@ -0,0 +1,99 @@
+---
+
+title: "Sub-organization customization"
+description: "Learn how to customize the sub-organization creation process in your Flutter app."
+sidebarTitle: "Sub-organization customization"
+---
+
+## Overview
+
+Turnkey's Flutter SDK allows you to customize the sub-organization creation process in your Flutter application. This is useful if you want to tailor the onboarding experience — such as automatically creating wallets, configuring authentication method-specific settings, setting default usernames, or naming passkeys.
+
+These customization options can be applied differently for each authentication method.
+
+## Customization
+
+You can customize sub-org creation through `authConfig.createSubOrgParams` inside your `TurnkeyConfig`.
+
+Each authentication method can have its own configuration. For example, you can assign a default username for users who sign up via email OTP and a separate wallet setup for passkey users.
+
+```dart title=lib/main.dart (excerpt)
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+final turnkeyProvider = TurnkeyProvider(
+ config: TurnkeyConfig(
+ // ... your existing configuration
+ authConfig: AuthConfig(
+ createSubOrgParams: MethodCreateSubOrgParams(
+ emailOtpAuth: CreateSubOrgParams(
+ userName: 'An email user',
+ customWallet: CustomWallet(
+ walletName: 'Email Wallet',
+ walletAccounts: [
+ v1WalletAccountParams(
+ curve: v1Curve.curve_secp256k1,
+ pathFormat: v1PathFormat.path_format_bip32,
+ path: "m/44'/60'/0'/0/0",
+ addressFormat: v1AddressFormat.address_format_ethereum,
+ ),
+ ],
+ ),
+ ),
+ passkeyAuth: CreateSubOrgParams(
+ userName: 'A passkey user',
+ customWallet: CustomWallet(
+ walletName: 'Passkey Wallet',
+ walletAccounts: [
+ v1WalletAccountParams(
+ curve: v1Curve.curve_ed25519,
+ pathFormat: v1PathFormat.path_format_bip32,
+ path: "m/44'/501'/0'/0'",
+ addressFormat: v1AddressFormat.address_format_solana,
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+);
+```
+
+You may also define a single set of parameters to apply across all authentication methods:
+
+```dart title=lib/main.dart (excerpt)
+final subOrgParams = CreateSubOrgParams(
+ userName: 'User-${DateTime.now().millisecondsSinceEpoch}',
+ customWallet: CustomWallet(
+ walletName: 'Wallet-${DateTime.now().millisecondsSinceEpoch}',
+ walletAccounts: [
+ v1WalletAccountParams(
+ curve: v1Curve.curve_secp256k1,
+ pathFormat: v1PathFormat.path_format_bip32,
+ path: "m/44'/60'/0'/0/0",
+ addressFormat: v1AddressFormat.address_format_ethereum,
+ ),
+ ],
+ ),
+);
+
+final turnkeyProvider = TurnkeyProvider(
+ config: TurnkeyConfig(
+ // ... your existing configuration
+ authConfig: AuthConfig(
+ createSubOrgParams: MethodCreateSubOrgParams(
+ emailOtpAuth: subOrgParams,
+ smsOtpAuth: subOrgParams,
+ oAuth: subOrgParams,
+ passkeyAuth: subOrgParams,
+ ),
+ ),
+ ),
+);
+```
+
+For a full list of parameters available, inspect the `CreateSubOrgParams` class in the Flutter SDK.
+
+## Next steps
+
+Now that you can customize sub-org creation in Flutter, check out the [Using Embedded Wallets](/sdks/flutter/using-embedded-wallets) guide next to learn how to create and manage wallets within your app!
diff --git a/sdks/flutter/using-embedded-wallets.mdx b/sdks/flutter/using-embedded-wallets.mdx
new file mode 100644
index 00000000..b9c31b76
--- /dev/null
+++ b/sdks/flutter/using-embedded-wallets.mdx
@@ -0,0 +1,256 @@
+---
+title: "Using embedded wallets"
+description: "Learn how to create and manage embedded wallets in your Flutter application using Turnkey's Embedded Wallet Kit."
+sidebarTitle: "Using embedded wallets"
+---
+
+## Overview
+
+Turnkey's Flutter SDK provides a straightforward way to create and manage embedded wallets in your Flutter application. You can create wallets, derive accounts, import wallets, and keep local UI state in sync with provider data.
+
+Before starting, review the concepts of **[Wallets](/concepts/wallets)** and **[Wallet Accounts](/concepts/wallets#accounts)**.
+
+## Creating an embedded wallet
+
+After the user authenticates (i.e., a `session` exists on `TurnkeyProvider`), you can create an embedded wallet and specify which accounts to create within it.
+
+```dart title=lib/widgets/create_wallet_button.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class CreateWalletButton extends StatelessWidget {
+ const CreateWalletButton({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ Future handleCreateWallet() async {
+ try {
+ final walletId = await tk.createWallet(
+ walletName: 'My New Wallet',
+ accounts: [
+ // One Ethereum account
+ v1WalletAccountParams(
+ curve: v1Curve.curve_secp256k1,
+ pathFormat: v1PathFormat.path_format_bip32,
+ path: "m/44'/60'/0'/0/0",
+ addressFormat: v1AddressFormat.address_format_ethereum,
+ ),
+ // One Solana account
+ v1WalletAccountParams(
+ curve: v1Curve.curve_ed25519,
+ pathFormat: v1PathFormat.path_format_bip32,
+ path: "m/44'/501'/0'/0'",
+ addressFormat: v1AddressFormat.address_format_solana,
+ ),
+ ],
+ );
+ debugPrint('Wallet created: $walletId');
+ } catch (e) {
+ debugPrint('Error creating wallet: $e');
+ }
+ }
+
+ return ElevatedButton(
+ onPressed: handleCreateWallet,
+ child: const Text('Create Wallet'),
+ );
+ }
+}
+```
+
+## Listing and refreshing wallets
+
+`TurnkeyProvider.wallets` contains all embedded wallets for the current sub-organization. It updates automatically when wallets change.
+
+```dart title=lib/widgets/wallet_list.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class WalletList extends StatelessWidget {
+ const WalletList({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Consumer(
+ builder: (_, tk, __) {
+ final wallets = tk.wallets ?? [];
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ for (final w in wallets)
+ Text('${w.name} — ${w.id}'),
+ ],
+ );
+ },
+ );
+ }
+}
+```
+
+To refresh explicitly:
+
+```dart title=lib/widgets/refresh_wallets_button.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class RefreshWalletsButton extends StatelessWidget {
+ const RefreshWalletsButton({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+ return ElevatedButton(
+ onPressed: () => tk.refreshWallets(),
+ child: const Text('Refresh Wallets'),
+ );
+ }
+}
+```
+
+## Creating wallet accounts (after wallet creation)
+
+To add accounts to an **existing** wallet, use the `createWalletAccounts` method from the underlying `client`.
+
+```dart title=lib/widgets/add_account_button.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class AddAccountButton extends StatelessWidget {
+ const AddAccountButton({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ Future handleAddAccount() async {
+ try {
+ final wallet = tk.wallets?.first;
+ if (wallet == null) return;
+
+ await tk.client.createWalletAccounts(
+ CreateWalletAccountsParams(
+ walletId: wallet.walletId,
+ accounts: [
+ v1WalletAccountParams(
+ curve: v1Curve.curve_secp256k1,
+ pathFormat: v1PathFormat.path_format_bip32,
+ path: "m/44'/60'/1'/0/0", // next index
+ addressFormat: v1AddressFormat.address_format_ethereum,
+ ),
+ ],
+ ),
+ );
+
+ debugPrint('Account created');
+ } catch (e) {
+ debugPrint('Error creating account: $e');
+ }
+ }
+
+ return ElevatedButton(
+ onPressed: handleAddAccount,
+ child: const Text('Add Ethereum Account'),
+ );
+ }
+}
+```
+
+## Importing wallets
+
+You can import a wallet from a mnemonic using the `importWallet` method and optionally specify accounts to pre-create.
+
+```dart title=lib/widgets/import_wallet_button.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class ImportWalletButton extends StatelessWidget {
+ const ImportWalletButton({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ Future handleImport() async {
+ try {
+ final walletId = await tk.importWallet(
+ mnemonic: '', // The user will enter this
+ walletName: 'Imported Wallet',
+ accounts: [
+ v1WalletAccountParams(
+ curve: v1Curve.curve_secp256k1,
+ pathFormat: v1PathFormat.path_format_bip32,
+ path: "m/44'/60'/0'/0/0",
+ addressFormat: v1AddressFormat.address_format_ethereum,
+ ),
+ ],
+ );
+ debugPrint('Imported wallet: $walletId');
+ } catch (e) {
+ debugPrint('Import failed: $e');
+ }
+ }
+
+ return ElevatedButton(
+ onPressed: handleImport,
+ child: const Text('Import Wallet (mnemonic)'),
+ );
+ }
+}
+```
+
+## Exporting wallets
+
+You can export a wallet's mnemonic using the `exportWallet` method. This method will automatically decrypt the mnemonic for you.
+
+```dart title=lib/widgets/export_wallet_button.dart
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'package:turnkey_sdk_flutter/turnkey_sdk_flutter.dart';
+
+class ExportWalletButton extends StatelessWidget {
+ const ExportWalletButton({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final tk = Provider.of(context, listen: false);
+
+ Future handleExport() async {
+ try {
+ final wallet = tk.wallets?.first;
+ if (wallet == null) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text('No wallet available to export')),
+ );
+ return;
+ }
+
+ // Default: returns decrypted mnemonic for development workflows
+ final mnemonic = await tk.exportWallet(walletId: wallet.walletId);
+ debugPrint('Wallet mnemonic: $mnemonic');
+
+ } catch (e) {
+ debugPrint('Export failed: $e');
+ }
+ }
+
+ return ElevatedButton(
+ onPressed: handleExport,
+ child: const Text('Export Wallet'),
+ );
+ }
+}
+```
+
+## Next steps
+
+Continue to **[Signing](/sdks/flutter/signing)** to learn how to sign messages and transactions with your embedded wallets.
+
+
+