# WebView integration

The WebView integration renders the Footprint onboarding flow inside a native sheet that you control: a page sheet on iOS, a bottom sheet on Android, with your own back button, close button, and toolbar styling. `onboarding.initialize`, by contrast, launches the flow in an in-app browser.

The WebView integration requires `@onefootprint/footprint-expo` version 3.4.0 or higher.

## Camera permissions

If your onboarding flow includes identity document verification, declare camera permissions in your app's `app.json` (or `app.config.js`). The WebView runs inside your app, so your app's manifest and `Info.plist` gate the camera prompt, not a system browser.

```json
{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSCameraUsageDescription": "We use the camera to verify your identity documents."
      }
    },
    "android": {
      "permissions": ["android.permission.CAMERA"]
    }
  }
}
```

## Start an onboarding

1. **Wrap your app in `FootprintWebViewProvider`.** The provider mounts the native sheet that hosts the Footprint WebView. It must be an ancestor of every component that calls `useFootprintWebView()`.

```javascript
import { FootprintWebViewProvider } from "@onefootprint/footprint-expo";

export default function App() {
  return (
    <FootprintWebViewProvider>
      {/* The rest of your app */}
    </FootprintWebViewProvider>
  );
}
```

2. **Create an onboarding session.** Call [POST /onboardings](/articles/guide/definitive-integration-guide#the-end-to-end-integration-step-4-run-the-playbook) and keep the onboarding session token it returns, such as `obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH`.
3. **Launch the flow with the `useFootprintWebView` hook.** When the user taps a button, for example, call `initialize` with the `onboardingSessionToken` and an `onComplete` callback.

```javascript
import { useFootprintWebView } from "@onefootprint/footprint-expo";
import { View, Button } from "react-native";

const Screen = () => {
  const { initialize } = useFootprintWebView();

  const launch = () => {
    initialize({
      onboardingSessionToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
      onComplete: (validationToken) => {
        console.log(validationToken);
      },
    });
  };

  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Button onPress={launch} title="Launch Footprint" />
    </View>
  );
};
```

## Handle the result

When the user completes the flow, `onComplete` receives a `validationToken`. Post it to your backend for further processing.

The SDK also reports errors, cancellation, and closing. Pass `onError`, `onCancel`, and `onClose` to `initialize`:

```typescript
initialize({
  onboardingSessionToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
  onComplete: (validationToken) => {
    console.log(validationToken);
  },
  onError: (error) => {
    console.log(error);
  },
  onCancel: () => {
    console.log("User canceled the flow");
  },
  onClose: () => {
    console.log("User closed the flow");
  },
});
```

`onCancel` fires when the user taps the close button in the toolbar, swipes the sheet down, or taps the backdrop (Android).

## Customize the appearance

Pass an `appearance` object to `initialize` to change the look of the flow:

```typescript
initialize({
  onboardingSessionToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
  onComplete: (validationToken) => {
    console.log(validationToken);
  },
  appearance: {
    variables: {
      borderRadius: "8px",
      colorSuccess: "#10b981",
      colorError: "#F87171",
      buttonPrimaryBg: "#5550e9",
    },
  },
});
```

The [customization guide](/articles/integrate/customization) lists every variable.

## Style the sheet and toolbar

Beyond the in-flow `appearance`, you can style the native sheet and the toolbar that wraps it. The toolbar shows the Footprint domain, a close button, and, when relevant, a back button.

```typescript
initialize({
  onboardingSessionToken: "obtok_UxM6Vbvk2Rcy1gzcSuXgk3sj3L9I0pAnNH",
  onComplete: (validationToken) => {
    console.log(validationToken);
  },
  sheetStyle: {
    backgroundColor: "#ffffff",
  },
  toolbarStyle: {
    backgroundColor: "#ffffff",
    buttonColor: "#000000",
    textColor: "#000000",
    separatorColor: "#c8c8cc",
  },
  options: {
    hideFootprintUrl: false,
  },
});
```

## Available props

| Variable                 | Description                                                                                                                                                                                          |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onboardingSessionToken` | The onboarding session token you created.                                                                                                                                                            |
| `onComplete`             | Triggered after the user completes the onboarding flow. You receive a `validationToken` that your backend can exchange with Footprint to see the `fp_id`, the login method used, and the KYC status. |
| `onError`                | Optional. Called when there was an unrecoverable error while initializing the onboarding flow. It receives an error string with more details.                                                        |
| `onCancel`               | Triggered when the user abandons the flow: tapping the close button in the toolbar, swiping the sheet down, or tapping the backdrop.                                                                 |
| `onClose`                | Triggered when the user closes the flow, whether completed or canceled.                                                                                                                              |
| `appearance`             | Optional. A `FootprintAppearance` object that customizes the look of your integration.                                                                                                               |
| `l10n`                   | Optional. The desired localization. See [Localization configuration](/articles/integrate/customization#localization-configuration).                                                                  |
| `redirectUri`            | Optional. The URI scheme of your app, used to redirect back to your app from any external steps inside the flow.                                                                                     |
| `sheetStyle`             | Optional. `{ backgroundColor }`. Controls the background color of the sheet that contains the WebView.                                                                                               |
| `toolbarStyle`           | Optional. `{ backgroundColor, buttonColor, textColor, separatorColor }`. Controls the appearance of the toolbar at the top of the sheet.                                                             |
| `options`                | Optional. `{ hideFootprintUrl }`. When `true`, hides the Footprint domain from the toolbar.                                                                                                          |

## Next steps

* [Handle the decision](/articles/guide/definitive-integration-guide#the-end-to-end-integration-step-5-handle-the-decision) validates the token on your backend and reads the onboarding status.
* [Changelog](/articles/sdks/expo-changelog) lists notable releases of `@onefootprint/footprint-expo`.