> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Swift Quickstart

Get started with Dynamic's Swift SDK to add embedded wallets, multi-chain support, and flexible authentication (email, social login, passkeys) to your iOS app in just a few lines.

<Tip>
  **📱 Complete Example App**: For a fully functional iOS app demonstrating all SDK
  features, check out our [Swift SDK Example App](https://github.com/dynamic-labs/swift-sdk-and-sample-app/tree/main/ExampleApp). It
  includes authentication flows (email/SMS OTP, social login, passkeys), wallet management, EVM/Solana transactions,
  MFA, and passkey examples with SwiftUI.
</Tip>

<Note>
  **Requirements:** iOS 15.5+, Swift 5.9+, Xcode 14.0+, and a Dynamic environment ID from the [Dynamic dashboard](https://app.dynamic.xyz/dashboard/developer/api).
</Note>

<Tabs>
  <Tab title="Agent-friendly">
    <Tip>
      Add the Dynamic docs MCP to your AI editor first — your agent can then query the docs directly. Instructions are on the [Welcome page](/overview/introduction/welcome).
    </Tip>

    Copy this prompt into your LLM (e.g. Claude, ChatGPT, Cursor) to implement Dynamic in your Swift app.

    <div data-llm-quickstart>
      ````markdown theme={"system"}
      # Swift SDK Quickstart

      ## Purpose and Usage

      This document provides structured quickstart information for the Dynamic Swift SDK. It is designed to be consumed by LLMs to generate accurate installation commands and code examples based on user requirements.

      **How to use this document:**

      **BEFORE WRITING ANY CODE**, ask the user which path they want:

      > "Would you like a **Quick start** (Xcode + SwiftUI, zero configuration — recommended if you're just getting started) or a **Custom setup** (choose your installation method and configuration)?"

      Do not proceed until the user has answered. Do not assume a path.

      - If the user chooses **Quick start**: follow the Quick Start Path section exactly. Do not ask any configuration questions — execute the happy path as written.
      - If the user chooses **Custom setup**: follow the Custom Setup Path section and ask all configuration questions before proceeding.

      ---

      ## Quick Start Path

      > Use this path when the user chooses Quick start. Execute every step in order. Do not skip steps. Do not ask configuration questions.

      **Stack:** Xcode + SwiftUI + Swift Package Manager

      ### Step 1 — Prerequisites

      Tell the user:
      - Xcode 14.0+ is required
      - iOS 15.5+ deployment target is required
      - A Dynamic environment ID is required — get one at https://app.dynamic.xyz/dashboard/developer/api

      Ask the user for their environment ID before proceeding.

      ### Step 2 — Install the SDK via Xcode

      1. Open your project in Xcode
      2. Go to **File → Add Package Dependencies**
      3. Enter the repository URL: `https://github.com/dynamic-labs/swift-sdk-and-sample-app.git`
      4. Select version `1.0.4` or later
      5. Add to your app target

      ### Step 3 — Configure URL scheme

      The SDK requires a URL scheme for authentication callbacks. Add the following to your `Info.plist`:

      ```xml
      <key>CFBundleURLTypes</key>
      <array>
          <dict>
              <key>CFBundleTypeRole</key>
              <string>Editor</string>
              <key>CFBundleURLName</key>
              <string>com.yourcompany.yourapp</string>
              <key>CFBundleURLSchemes</key>
              <array>
                  <string>yourapp</string>
              </array>
          </dict>
      </array>
      ```

      > Replace `yourapp` with your app's URL scheme (e.g. `myapp`). This must match the `redirectUrl` you set in Step 4.

      In the [Dynamic dashboard](https://app.dynamic.xyz), go to **Security → Whitelist Mobile Deeplink** and add the same deep link URL you will use as `redirectUrl` (e.g. `yourapp://`). Auth callbacks and social login can fail if this URL is not whitelisted.

      ### Step 4 — Initialize the SDK

      In your `@main` App struct, initialize the SDK in `init()` before any views are rendered:

      ```swift
      import SwiftUI
      import DynamicSDKSwift

      @main
      struct YourApp: App {
          init() {
              _ = DynamicSDK.initialize(
                  props: ClientProps(
                      environmentId: "YOUR_ENVIRONMENT_ID",
                      appLogoUrl: "https://demo.dynamic.xyz/favicon-32x32.png",
                      appName: "My App",
                      redirectUrl: "yourapp://",   // Must match your Info.plist URL scheme
                      appOrigin: "https://your-domain.com"
                  )
              )
          }

          var body: some Scene {
              WindowGroup {
                  ContentView()
              }
          }
      }
      ```

      > All five `ClientProps` fields are required. `redirectUrl` must match the URL scheme you configured in Step 3.

      ### Step 5 — Build the content view

      Replace the contents of `ContentView.swift`:

      ```swift
      import SwiftUI
      import DynamicSDKSwift
      import Combine

      @MainActor
      class AuthViewModel: ObservableObject {
          @Published var isAuthenticated = false
          @Published var walletAddress: String? = nil
          private let sdk = DynamicSDK.instance()
          private var cancellables = Set<AnyCancellable>()

          init() {
              isAuthenticated = sdk.auth.authenticatedUser != nil

              sdk.auth.authenticatedUserChanges
                  .receive(on: DispatchQueue.main)
                  .sink { [weak self] user in
                      self?.isAuthenticated = user != nil
                  }
                  .store(in: &cancellables)

              sdk.wallets.userWalletsChanges
                  .receive(on: DispatchQueue.main)
                  .sink { [weak self] wallets in
                      self?.walletAddress = wallets.first?.address
                  }
                  .store(in: &cancellables)
          }

          func signIn() { sdk.ui.showAuth() }
          func signOut() { Task { try await sdk.auth.logout() } }
      }

      struct ContentView: View {
          @StateObject private var vm = AuthViewModel()

          var body: some View {
              VStack(spacing: 20) {
                  if vm.isAuthenticated {
                      Text("Connected!")
                          .font(.headline)
                      if let address = vm.walletAddress {
                          Text(address)
                              .font(.caption)
                              .foregroundColor(.secondary)
                      }
                      Button("Disconnect") { vm.signOut() }
                          .foregroundColor(.red)
                  } else {
                      Button("Connect Wallet") { vm.signIn() }
                          .buttonStyle(.borderedProminent)
                  }
              }
              .padding()
          }
      }
      ```

      ### Step 6 — Run the app

      Build and run in Xcode (`Cmd + R`) or via terminal:

      ```bash
      xcodebuild -scheme YourApp -destination 'platform=iOS Simulator,name=iPhone 16' build
      ```

      You should see a **Connect Wallet** button. Tapping it opens the Dynamic auth UI.

      ### Step 7 — Dashboard configuration checklist

      Before testing auth, verify these settings in your Dynamic dashboard at https://app.dynamic.xyz:

      1. **Login method enabled** — go to **Sign-in Methods** and enable at least one (e.g. email OTP)
      2. **Embedded wallets enabled** — go to **Wallets** and enable embedded wallets
      3. **Chains enabled** — go to **Chains & Networks** and enable EVM
      4. **Mobile deep link whitelisted** — go to **Security → Whitelist Mobile Deeplink** and add the exact `redirectUrl` value (e.g. `yourapp://`). It must match `Info.plist` and `ClientProps`.

      ---

      ## Custom Setup Path

      > Use this path when the user chooses Custom setup. Ask ALL questions below before generating any code.

      **Questions to ask the user:**

      1. Which installation method do you prefer? (Xcode SPM — recommended, or Package.swift)
      2. Which chains do you want to support? (EVM, SVM/Solana — one or both)

      **Only after receiving answers**, use the sections below to generate the correct setup.

      ### Installation Methods

      **Xcode (recommended):**
      1. File → Add Package Dependencies
      2. URL: `https://github.com/dynamic-labs/swift-sdk-and-sample-app.git`
      3. Version: `1.0.4` or later

      **Package.swift:**
      ```swift
      dependencies: [
          .package(url: "https://github.com/dynamic-labs/swift-sdk-and-sample-app.git", from: "1.0.4")
      ]
      ```

      ### ClientProps — All Fields Required

      | Property | Description | Example |
      |---|---|---|
      | `environmentId` | Your Dynamic environment ID | `"abc123..."` |
      | `appLogoUrl` | URL to your app logo | `"https://your-app.com/logo.png"` |
      | `appName` | Your app's display name | `"My App"` |
      | `redirectUrl` | URL scheme for auth callbacks — must match `Info.plist` | `"yourapp://"` |
      | `appOrigin` | Your app's origin domain | `"https://your-app.com"` |
      | `reownProjectId` | Reown project ID for [WalletConnect dApp connectivity](/swift/wallets/global-wallets/walletconnect) (optional) | `"your-reown-project-id"` |

      **Dashboard:** In **Security → Whitelist Mobile Deeplink**, add the same value as `redirectUrl` (e.g. `yourapp://`).

      ### Documentation
      All docs for this SDK: https://docs.dynamic.xyz (paths starting with `/swift/`)
      Environment ID: https://app.dynamic.xyz/dashboard/developer/api

      ---

      ## Critical Reference

      | Correct | Incorrect | Notes |
      |---|---|---|
      | `DynamicSDK.initialize()` in `@main` App `init()` | Initializing inside a View | Must happen before any views are rendered |
      | `redirectUrl` matches `Info.plist` URL scheme | Mismatched URL scheme | Auth callbacks will silently fail if these don't match |
      | `redirectUrl` whitelisted under **Security → Whitelist Mobile Deeplink** | Deep link not whitelisted | OAuth and return-to-app flows can fail |
      | All 5 `ClientProps` fields set | Omitting `redirectUrl` or `appOrigin` | All fields are required |
      | Combine publishers for auth/wallet state | One-time checks | SDK state is async — always observe publishers |
      | `sdk.wallets.userWalletsChanges` for wallet updates | Reading wallets immediately after auth | Wallets are created asynchronously after authentication |

      ---

      ## Step-Up Authentication

      **Required before accepting the `2026_04_01` API version** — verify your
      minimum API version in [Dashboard > Developers > API & SDK Keys](https://app.dynamic.xyz/dashboard/developer/api).

      If using the Dynamic SDK's built-in UI, step-up prompts are handled
      automatically. **If building a headless integration, you must handle
      step-up authentication manually** using
      `sdk.stepUpAuth.isStepUpRequired(scope:)` and
      `sdk.stepUpAuth.promptStepUpAuth(requestedScopes:)`.

      See [Step-up authentication](/swift/step-up-auth) for the full implementation guide.

      ---

      ## Device Registration

      **Required before accepting the `2026_04_01` API version** — verify your
      minimum API version in [Dashboard > Developers > API & SDK Keys](https://app.dynamic.xyz/dashboard/developer/api).

      If using the Dynamic SDK's built-in UI, device registration is handled
      automatically. **If building a headless integration, you must manually
      check** `sdk.deviceRegistration.isDeviceRegistrationRequired` **and handle
      the completion event yourself.**

      Full guide: https://docs.dynamic.xyz/swift/device-registration

      ---

      ## Troubleshooting

      ### 1 — "Could not find module 'DynamicSDKSwift'"
      Make sure the package is added to your app target (not just the project). Try Product → Clean Build Folder, then rebuild. Restart Xcode if needed.

      ### 2 — Auth UI not appearing
      Verify `DynamicSDK.initialize()` is called in `@main` App `init()` before any views load. Do not call `DynamicSDK.instance()` before initialization.

      ### 3 — Auth callbacks not working / social login fails
      Verify your URL scheme is configured in `Info.plist` and matches `redirectUrl` in `ClientProps`. Whitelist your deeplink URL in the Dynamic dashboard under **Security → Whitelist Mobile Deeplink**.

      ### 4 — Wallets not appearing after login
      Wallets are created asynchronously — use `sdk.wallets.userWalletsChanges` publisher to observe updates. Verify embedded wallets are enabled in the dashboard.

      ### 5 — Session state not updating
      Use Combine publishers (`authenticatedUserChanges`, `userWalletsChanges`) with `@StateObject` / `@ObservedObject`. Do not read state once — always observe.

      If the issue persists, check https://docs.dynamic.xyz/overview/troubleshooting/general.
      ````
    </div>
  </Tab>

  <Tab title="Visual">
    <iframe frameBorder="0" width="100%" height="600px" src="https://documentation-quickstarts.vercel.app/swift?color-scheme=dark" allow="clipboard-write" className="rn-qs-dark">
      {" "}
    </iframe>

    <iframe frameBorder="0" width="100%" height="600px" src="https://documentation-quickstarts.vercel.app/swift?color-scheme=light" allow="clipboard-write" className="rn-qs-light">
      {" "}
    </iframe>

    ## Configure URL Scheme

    Add a URL scheme to your `Info.plist` for authentication callbacks:

    ```xml Info.plist theme={"system"}
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLName</key>
            <string>com.yourcompany.yourapp</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>yourapp</string>
            </array>
        </dict>
    </array>
    ```

    Use the same URL scheme string as the `redirectUrl` you pass to `ClientProps` (for example `yourapp://`).

    ## Whitelist your mobile deep link

    In the [Dynamic dashboard](https://app.dynamic.xyz), open your environment and go to **Security → Whitelist Mobile Deeplink**. Add your app's deep link URL—the same value as `redirectUrl` (e.g. `yourapp://`). Without this, authentication callbacks and social login may not return to your app correctly.

    ## Initialize the SDK

    The quickstart embed under **Install the SDK** shows package install and SDK initialization. Use the table below for the main `ClientProps` fields.

    ### Configuration Options

    | Property         | Description                                                                                             | Required |
    | ---------------- | ------------------------------------------------------------------------------------------------------- | -------- |
    | `environmentId`  | Your Dynamic environment ID from the dashboard                                                          | Yes      |
    | `appLogoUrl`     | URL to your app's logo (shown in auth UI)                                                               | Yes      |
    | `appName`        | Your app's display name                                                                                 | Yes      |
    | `redirectUrl`    | Deep link URL scheme for callbacks                                                                      | Yes      |
    | `appOrigin`      | Your app's origin URL                                                                                   | Yes      |
    | `reownProjectId` | Reown (WalletConnect) project ID for [connecting to dApps](/swift/wallets/global-wallets/walletconnect) | No       |
    | `logLevel`       | Logging level (`.debug`, `.info`, `.warn`, `.error`)                                                    | No       |
    | `debug`          | Debug options like `ClientDebugProps(webview: true)`                                                    | No       |

    ### Access the SDK

    After initialization, access the SDK singleton anywhere in your app:

    ```swift theme={"system"}
    let sdk = DynamicSDK.instance()
    ```

    ## Basic Usage

    ### Using Built-in Authentication UI

    The easiest way to add authentication is using the built-in UI:

    ```swift theme={"system"}
    import SwiftUI
    import DynamicSDKSwift

    struct ContentView: View {
        var body: some View {
            VStack {
                Button("Sign In") {
                    DynamicSDK.instance().ui.showAuth()
                }
            }
        }
    }
    ```

    ### Listening for Authentication State

    Use Combine publishers to react to authentication changes:

    ```swift theme={"system"}
    import SwiftUI
    import DynamicSDKSwift
    import Combine

    struct ContentView: View {
        @StateObject private var vm = ContentViewModel()

        var body: some View {
            Group {
                if vm.isAuthenticated {
                    HomeView()
                } else {
                    LoginView()
                }
            }
        }
    }

    @MainActor
    class ContentViewModel: ObservableObject {
        @Published var isAuthenticated = false
        private let sdk = DynamicSDK.instance()
        private var cancellables = Set<AnyCancellable>()

        init() {
            isAuthenticated = sdk.auth.authenticatedUser != nil

            sdk.auth.authenticatedUserChanges
                .receive(on: DispatchQueue.main)
                .sink { [weak self] user in
                    self?.isAuthenticated = user != nil
                }
                .store(in: &cancellables)
        }
    }
    ```

    ### Complete Example with Wallets

    ```swift theme={"system"}
    import SwiftUI
    import DynamicSDKSwift
    import Combine

    struct HomeView: View {
        @State private var wallets: [BaseWallet] = []
        @State private var cancellables = Set<AnyCancellable>()

        private let sdk = DynamicSDK.instance()

        var body: some View {
            VStack {
                Text("Welcome!")

                ForEach(wallets, id: \.address) { wallet in
                    Text("Wallet: \(wallet.address)")
                }

                Button("Show Profile") {
                    sdk.ui.showUserProfile()
                }

                Button("Logout") {
                    Task {
                        try await sdk.auth.logout()
                    }
                }
            }
            .onAppear {
                wallets = sdk.wallets.userWallets

                sdk.wallets.userWalletsChanges
                    .receive(on: DispatchQueue.main)
                    .sink { newWallets in
                        wallets = newWallets
                    }
                    .store(in: &cancellables)
            }
        }
    }
    ```

    ## Enable Features in Dashboard

    Before you can use authentication and wallet features, enable them in your Dynamic dashboard:

    1. Go to your [Dynamic Dashboard](https://app.dynamic.xyz/dashboard/overview)
    2. Select your project
    3. Go to **Authentication** and enable the methods you want to use:
       * Email OTP
       * SMS OTP
       * Social providers (Apple, Google, Farcaster)
       * Passkeys
    4. Go to **Wallets** and enable embedded wallets
    5. Go to **Chains** and enable the networks you want to support (EVM and/or Solana)
    6. Go to **Security → Whitelist Mobile Deeplink** and add your app's deep link URL (the same value as `redirectUrl`, e.g. `yourapp://`)

    <Tip>
      For testing, we recommend starting with Email OTP authentication and an EVM
      testnet like Base Sepolia. This gives you a complete setup without requiring
      real phone numbers or mainnet transactions.
    </Tip>

    ## Troubleshooting

    ### Common Issues

    * **Could not find module 'DynamicSDKSwift'**
      * Make sure you've added the package to your target
      * Try cleaning the build folder (Product → Clean Build Folder)
      * Restart Xcode

    * **SDK not initialized**
      * Ensure `DynamicSDK.initialize()` is called in your App's `init()` before any views access the SDK
      * Don't call `DynamicSDK.instance()` before initialization

    * **Authentication callbacks not working**
      * Verify your URL scheme is configured in `Info.plist`
      * Ensure the `redirectUrl` matches your URL scheme
      * Whitelist your deep link URL in the Dynamic dashboard under **Security → Whitelist Mobile Deeplink**

    * **Wallets not appearing after login**
      * Wallets are created asynchronously after authentication
      * Use `sdk.wallets.userWalletsChanges` publisher to listen for wallet updates
      * Check that embedded wallets are enabled in your dashboard

    * **Session state not updating**
      * Make sure you're observing the reactive Combine publishers (`authenticatedUserChanges`, `userWalletsChanges`, etc.)
      * Verify that your views are using `@StateObject` or `@ObservedObject` for view models that observe SDK state

    ## Next Steps

    <Warning>
      **Step-up authentication** and **device registration** are required
      before accepting the `2026_04_01` API version. If you have a headless
      integration, you must implement both manually.
      See the [upgrade guide](/overview/migrations/api/2026_04_01).
    </Warning>

    * [Step-up authentication](/swift/step-up-auth)
    * [Device registration](/swift/device-registration)

    Great! Your SDK is now configured and ready to use. Here's what you can do next:

    1. **[Authentication Guide](/swift/headless-authentication)** - Learn how to implement user authentication with email, SMS, and passkeys
    2. **[Social Authentication](/swift/social-authentication)** - Add social login options like Apple, Google, and Farcaster
    3. **[Wallet Operations](/swift/wallets/general/token-balances)** - Work with balances and sign messages
    4. **[Networks](/swift/wallets/general/network-management)** - Configure blockchain networks
    5. **[Connect to dApps](/swift/wallets/global-wallets/walletconnect)** - Use WalletConnect to connect your embedded wallet to any dApp

    <Info>
      Building without the Dynamic SDK's built-in UI? See the [Authentication screens](/swift/headless-authentication) for a full list of screens your app needs to handle.
    </Info>
  </Tab>
</Tabs>
