> ## 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.

# React Native SDK

> Integrate the OTPless Headless SDK in React Native for the SNA-only flow — add the dependency, configure SNA, initialize, start with a requestId, and handle callbacks.

This page covers the **SNA-only** integration of the OTPless Headless SDK in React Native. The SDK accepts the `requestId` generated by the [Create API](/sna/create-api), performs the silent network handshake, and reports progress through callbacks. Your backend confirms the final result via the [Status Check API](/sna/status-check-api).

## Requirements

| Requirement         | Version |
| ------------------- | ------- |
| React Native        | 0.64+   |
| Android Minimum SDK | 21      |
| iOS                 | 13.0+   |

## Step 1: Add SDK dependency

Install the OTPLESS Headless SDK at the root of your React Native project:

```bash theme={null}
npm i otpless-headless-rn
```

For iOS, install the pods:

```bash theme={null}
cd ios && pod install
```

<Note>
  Check the latest version of the [SDK on npm](https://www.npmjs.com/package/otpless-headless-rn).
</Note>

## Step 2: Smart Authentication (SNA) setup

<Warning>
  Make sure **Silent Network Authentication** is enabled on the [OTPLESS dashboard](https://otpless.com/dashboard/customer/channels). For an SNA-only configuration, SNA must be the only channel enabled.
</Warning>

<Tabs>
  <Tab title="Android">
    Add the network security config inside `android/app/src/main/AndroidManifest.xml`, in your `<application>` tag:

    ```xml AndroidManifest.xml theme={null}
    android:networkSecurityConfig="@xml/otpless_network_security_config"
    ```
  </Tab>

  <Tab title="iOS">
    Add the following block to your `Info.plist`.

    * If the `NSAppTransportSecurity` key is **not** already present, add the entire block below.
    * If it **is** already present, add the listed domains one by one under `NSExceptionDomains`.

    ```xml Info.plist theme={null}
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>api-csp.airtel.in</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
            <key>v4-api-csp.airtel.in</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
            <key>in-vil.ipification.com</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
            <key>partnerapi.jio.com</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>
    ```
  </Tab>
</Tabs>

## Step 3: Initialize the SDK

Create a `OtplessHeadlessModule` instance, initialize it with your App ID, and register the response callback:

```typescript theme={null}
import { OtplessHeadlessModule } from 'otpless-headless-rn';

const headlessModule = new OtplessHeadlessModule();

useEffect(() => {
    headlessModule.initialize("YOUR_APP_ID");
    headlessModule.setResponseCallback(onHeadlessResponse);
    return () => {
        headlessModule.clearListener();
        headlessModule.cleanup();
    };
}, []);
```

<Note>
  Replace `YOUR_APP_ID` with your actual App ID from the [OTPLESS dashboard](https://dashboard.otpless.com/login).
</Note>

## Step 4: Start SNA with the requestId

Pass the `requestId` returned by the [Create API](/sna/create-api) to `start()`:

```typescript theme={null}
const headlessRequest = {
    requestId: "REQUEST_ID_FROM_API"
};

headlessModule.start(headlessRequest);
```

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

## Step 5: Handle callbacks

```typescript theme={null}
const onHeadlessResponse = (response: any) => {
    headlessModule.commitResponse(response);

    switch (response.responseType) {
        case "SDK_READY": {
            // SDK initialized successfully — enable your continue button
            // or proceed with user authentication.
            break;
        }
        case "FAILED": {
            // SDK initialization failed
            if (response.statusCode === 5003) {
                // Please try to initialize the SDK again.
            }
            break;
        }
        case "INITIATE": {
            // Authentication has been initiated
            if (response.statusCode !== 200) {
                handleInitiateError(response);
            } else if (response.response?.authType === "SILENT_AUTH") {
                // SNA is being attempted — show a loading state.
            }
            break;
        }
        case "VERIFY": {
            // Verification failed for the attempted authType.
            if (response.response?.authType === "SILENT_AUTH" && response.statusCode === 9106) {
                // SNA verification failed — treated as AUTH_TERMINATED.
            }
            break;
        }
        case "ONETAP": {
            // Final success response — returns token / idToken
            break;
        }
        case "AUTH_TERMINATED": {
            // SNA-only configuration: auth could not complete.
            // Emitted when pre-checks fail, or when SNA was attempted
            // and then failed. Treat as a terminal failure and rely on
            // the Status Check API for the exact error.
            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 you initialize the SDK (Step 3).

| 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()` (Step 4).

| Callback          | State                  | Meaning                                                                                                   |
| ----------------- | ---------------------- | --------------------------------------------------------------------------------------------------------- |
| `INITIATE`        | Non-terminal           | SNA is being attempted after pre-checks pass. `authType` is `SILENT_AUTH`.                                |
| `VERIFY`          | Non-terminal           | Verification failed for the attempted `authType` (e.g. `statusCode 9106` for `SILENT_AUTH`).              |
| `ONETAP`          | **Success — terminal** | SNA completed successfully (Silent Mobile Verification). Returns `token` / `idToken`.                     |
| `AUTH_TERMINATED` | **Failed — terminal**  | Emitted in two cases: (1) pre-checks failed → terminated directly; (2) SNA was initiated and then failed. |

<Warning>
  In the SNA-only configuration `AUTH_TERMINATED` is a terminal failure with no fallback. Always treat the [Status Check API](/sna/status-check-api) result as authoritative. See [Handling the AUTH\_TERMINATED callback](/knowledge-base/sna/auth-terminated-callback).
</Warning>

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

## Next step

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