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

# Quickstart

> How to quickly get up and running with the Stytch iOS SDK

# iOS Quickstart

<Note>This guide is for our new Kotlin Multiplatform SDK which is in **Public beta**. If you are instead looking for the stable version, please see [stytch-ios](https://github.com/stytchauth/stytch-ios) and the usage docs [here](https://stytchauth.github.io/stytch-ios/latest/StytchCore/documentation/stytchcore/).</Note>

This guide walks you through adding Stytch authentication to an iOS app using `StytchConsumerSDK` or `StytchB2BSDK`. Both are distributed as a Swift Package from [`stytchauth/stytch-ios-sdk`](https://github.com/stytchauth/stytch-ios-sdk) and require **iOS 15.0+**.

***

## 1. Install the SDK

**In Xcode:**

1. Go to **File → Add Package Dependencies...**
2. Enter: `https://github.com/stytchauth/stytch-ios-sdk`
3. Select version **1.0.0** or later
4. Add the product that matches your project type:
   * `StytchConsumerSDK` — Consumer (B2C) apps
   * `StytchB2BSDK` — B2B apps (organizations/members)

**In `Package.swift`:**

```swift theme={null}
dependencies: [
    .package(url: "https://github.com/stytchauth/stytch-ios-sdk", from: "1.0.0"),
],
targets: [
    .target(
        name: "YourTarget",
        dependencies: [
            .product(name: "StytchConsumerSDK", package: "stytch-ios-sdk"),
            // or: .product(name: "StytchB2BSDK", package: "stytch-ios-sdk"),
        ]
    ),
]
```

**Required linker flag:** In your target's **Build Settings**, add `-ObjC` to **Other Linker Flags**.

***

## 2. Initialize the Client

Create the client once — at app startup or at the entry point of your auth flow. The client is a singleton; calling `createStytchConsumer` again returns the same instance.

```swift theme={null}
import StytchConsumerSDK

// Create once and store — e.g., in your App or a top-level singleton
let stytch = createStytchConsumer(
    configuration: .init(
        publicToken: "public-token-live-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    )
)
```

For B2B apps, import `StytchB2BSDK` and use `createStytchB2B(configuration:)` instead.

Your public token is in the [Stytch Dashboard](https://stytch.com/dashboard/api-keys). Make sure you've also enabled the auth methods you want to use under **SDK Configuration**.

***

## 3. Observe Authentication State

The SDK exposes an `authenticationStateFlow` — an async sequence that emits whenever authentication state changes. Use `for await` to observe it:

```swift theme={null}
Task {
    for await state in stytch.authenticationStateFlow {
        switch onEnum(of: state) {
        case .authenticated(let s):
            let user = s.user
            let session = s.session
            let sessionToken = s.sessionToken
            // Navigate to your authenticated UI
        case .unauthenticated:
            // Show your login UI
        case .loading:
            // SDK is restoring a persisted session — show a splash screen
        }
    }
}
```

To read the current state synchronously (e.g., during a navigation check), use `stytch.authenticationStateFlow.value`.

***

## 4. Auth Methods

All SDK methods are `async throws`. Call them from a `Task` or an `async` context and handle errors with `do/catch`. Errors are thrown as `StytchError`.

### SMS OTP Example

```swift theme={null}
import StytchConsumerSDK

// Step 1: Send OTP
var methodId: String = ""

Task {
    do {
        let params: OTPsSMSLoginOrCreateParameters = .init(phoneNumber: "+15551234567")
        let response = try await stytch.otp.sms.loginOrCreate(request: params)
        methodId = response.methodId
    } catch {
        // Handle error
    }
}

// Step 2: Verify the code
Task {
    do {
        let params: OTPsAuthenticateParameters = .init(
            token: userEnteredCode,
            methodId: methodId,
            sessionDurationMinutes: 30
        )
        try await stytch.otp.authenticate(request: params)
    } catch {
        // Handle error
    }
}
```

***

## 5. Handle Deeplinks

Magic links and password reset emails redirect back to your app via a URL scheme.

**1. Register a redirect URL** in the [Stytch Dashboard](https://stytch.com/dashboard/redirect-urls). Use a scheme like `myapp://auth`.

**2. Add a URL scheme** to your target in Xcode: go to your target's **Info** tab, expand **URL Types**, click **+**, and enter your scheme (e.g., `myapp`) in the **URL Schemes** field.

**3. Receive the URL** in SwiftUI or UIKit:

```swift theme={null}
// SwiftUI — add to your root view
.onOpenURL { url in
    handleDeeplink(url: url)
}

// UIKit — in your SceneDelegate
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let url = URLContexts.first?.url else { return }
    handleDeeplink(url: url)
}
```

**4. Authenticate the deeplink:**

```swift theme={null}
func handleDeeplink(url: URL) {
    Task {
        do {
            let result = try await stytch.authenticate(url: url.absoluteString, sessionDurationMinutes: 30)
            switch onEnum(of: result) {
            case .authenticated:
                // User is now logged in
                break
            case .manualHandlingRequired(let status):
                // Password reset token — prompt for a new password,
                // then call stytch.passwords.resetByEmail(...)
                let resetToken = status.token
            case .unknownDeeplink:
                // Not a Stytch deeplink
                break
            }
        } catch {
            // Handle error
        }
    }
}
```

***

## 6. Session Management

Sessions are automatically persisted across app launches and validated on startup.

```swift theme={null}
// Manually validate the current session (optionally extend it)
let params: SessionsAuthenticateParameters = .init(sessionDurationMinutes: 30)
try await stytch.session.authenticate(request: params)

// Hydrate a client with a session token received out-of-band
try await stytch.hydrate("existing-session-token")

// Sign out
try await stytch.session.revoke()
```
