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

# iOS SDK

> Integrate the OTPless Headless SDK on iOS for the authentication flow — add the dependency, start with a requestId, and handle callbacks.

This page covers the integration of the OTPless Headless SDK on iOS. The SDK accepts the `requestId` generated by the [Create API](/docs/server-initiated-auth/create-api), performs the authentication, and reports progress through callbacks. Your backend confirms the final result via the [Status Check API](/docs/server-initiated-auth/status-check-api).

## Requirements

| Requirement | Version |
| - | - |
| iOS | 13.0+ |
| Xcode | 12.0+ |
| Swift | 5.5+ |

## Step 1: Add SDK dependency

The SDK can be installed via **CocoaPods** or **Swift Package Manager**. Find the latest version of the [SDK here](https://cocoapods.org/pods/OtplessBM).

<CodeGroup>
  ```ruby CocoaPods theme={null}
  # Add to your Podfile's dependencies section
  pod 'OtplessBM/Core', 'latest_version'
  ```

  ```text Swift Package Manager theme={null}
  1. In Xcode, click File > Swift Packages > Add Package Dependency.
  2. Enter the repository URL:
     https://github.com/otpless-tech/otpless-headless-iOS-sdk.git
  3. Select the dependency rule as "exact version" and use the latest version.
  ```
</CodeGroup>

For CocoaPods, run the following in your root folder to fetch the dependency:

```bash theme={null}
pod repo update
pod install
```

<Warning>
  Make sure your authentication channel is enabled on the [OTPLESS dashboard](https://dashboard.otpless.com/login).
</Warning>

## Step 2: Start authentication with the requestId

Pass the `requestId` returned by the [Create API](/docs/server-initiated-auth/create-api) to `start()`:

```swift theme={null}
otplessTask?.cancel() // Cancel any ongoing tasks to prevent request duplication

let request = OtplessRequest()
otplessRequest.set(fromBackend: "REQUEST_ID_FROM_API")

otplessTask = Task(priority: .userInitiated) {
    await Otpless.shared.start(withRequest: request)
}
```

<Note>
  Start polling the [Status Check API](/docs/server-initiated-auth/status-check-api) from your backend immediately after calling `start()`. The SDK callback and the server status run in parallel.
</Note>

## Step 3: Handle callbacks

```swift theme={null}
func onResponse(_ response: OtplessBM.OtplessResponse) {
    Otpless.shared.commitOtplessResponse(response)

    switch response.responseType {
    case .SDK_READY:
        // SDK initialized successfully — enable your continue button
        // or proceed with user authentication.
        print("SDK has been initialized successfully.")

    case .FAILED:
        // SDK initialization failed
        if response.statusCode == 5003 {
            print("SDK initialization failed, please try to initialize the SDK again")
        }

    case .INITIATE:
        // Authentication has been initiated
        if response.statusCode == 200 {
            // Authentication is in progress — show a loading state.
        } else {
            handleInitiateError(response)
        }

    case .ONETAP:
        // Final success response with token / idToken
        if response.statusCode == 200 {
            if let data = response.response?["data"] as? [String: Any] {
                if let idToken = data["idToken"] as? String, !idToken.isEmpty {
                    // Process idToken and verify it on your backend.
                }
                if let token = data["token"] as? String, !token.isEmpty {
                    // Process token and verify it on your backend.
                }
            } else {
                print("Token not received")
            }
        } else {
            print("Token verification failed")
        }

    case .AUTH_TERMINATED:
        // Auth could not complete. Emitted when pre-checks fail,
        // or when authentication was attempted and then failed/expired.
        // Treat as a terminal failure and rely on the Status Check API
        // for the final outcome.
        break
    }
}
```

## Callback reference

The SDK works in two steps — initialization and `start()` — and each step has its own set of callbacks.

#### Step 1: Initialization callbacks

Emitted when the SDK initializes.

| Callback | Meaning |
| - | - |
| `SDK_READY` | SDK initialization completed. |
| `FAILED` | SDK failed to initialize (e.g. `statusCode 5003`). |

#### Step 2: Start callbacks

Emitted after you invoke `start()` to begin authentication.

| Callback | State | Meaning |
| - | - | - |
| `INITIATE` | Non-terminal | Authentication is in progress after pre-checks pass. |
| `ONETAP` | **Success — terminal** | Authentication completed successfully. Returns `token` / `idToken`. |
| `AUTH_TERMINATED` | **Failed — terminal** | Emitted in two cases: (1) pre-checks failed → terminated directly; (2) authentication was initiated and then failed/expired. |

<Note>
  For the `errorCode` / `statusCode` values surfaced in SDK callbacks, see [SDK Error Codes](/docs/server-initiated-auth/sdk-error-codes).
</Note>

## Next step

<Card title="Status Check API" icon="circle-check" href="/docs/server-initiated-auth/status-check-api">
  Confirm the authoritative auth status from your server.
</Card>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.