# Komo React Native SDK

Embed Komo content in your React Native applications.

## Installation

```sh
pnpm add @komo-tech/react-native
```

NOTE: This package has a peer dependency on [react-native-webview](https://github.com/react-native-webview/react-native-webview), and recommends the latest major version, `13.x`.

## Basic Usage

- The quickest way to get started with embedding Komo content in react native is by using the [`KomoCard`](#komocard-props) component.
- This component combines metadata fetching, card cover display, and modal handling for the card content (i.e. experience).
- The only required prop is `embedMetaUrl`. To find this in the Komo portal:
  - Navigate to the settings of the card to be embedded.
  - Select the `Embed` tab and click on `React Native code` in the right sidebar.
  - Copy the `Card embed meta URL` and use it as the value of the `embedMetaUrl` prop.

```js
import { KomoCard } from '@komo-tech/react-native';

// ...

<KomoCard
  embedMetaUrl={KomoCardNativeEmbedUrl}
  containerStyle={{ maxWidth: '80%' }}
/>;
```

### Provider Auth

Use `KomoClientProvider` when your app should share one authenticated Komo session across all `KomoCard` and direct `KomoExperienceModal` usage beneath it.

```tsx
import { KomoCard, KomoClientProvider } from '@komo-tech/react-native';

<KomoClientProvider
  appId="au1_app-guid"
  getIdentityToken={async () => ({
    type: 'jwt',
    token: await getHostJwt()
  })}
>
  <KomoCard embedMetaUrl={KomoCardNativeEmbedUrl} />
</KomoClientProvider>;
```

`getIdentityToken` is required. It must return the identity payload used by Komo session exchange.

Authentication failures are reported as `KomoAuthError`. Use `onAuthError` for global logging/UI and catch `identify()` for user-triggered retry flows.

```tsx
import { isKomoAuthError } from '@komo-tech/react-native';

<KomoClientProvider
  appId="au1_app-guid"
  getIdentityToken={async () => {
    const token = await getHostJwt();
    return token ? { type: 'jwt', token } : { type: 'none' };
  }}
  onAuthError={(error) => {
    switch (error.code) {
      case 'identity_provider_failed':
        showAuthServiceUnavailableMessage();
        break;
      case 'invalid_identity':
        reportSdkConfigurationError(error.message);
        break;
      case 'token_invalid':
        promptUserToSignInAgain();
        break;
      default:
        logAuthError(error.code, error.message, error.retryable);
        break;
    }
  }}
>
  <KomoCard embedMetaUrl={KomoCardNativeEmbedUrl} />
</KomoClientProvider>;

const retryIdentify = async () => {
  try {
    await komo.identify();
  } catch (error) {
    if (isKomoAuthError(error) && error.retryable) {
      showRetryPrompt();
    }
  }
};
```

`KomoAuthError.code` values:

| Code                        | Source | Meaning                                                                          |
| --------------------------- | ------ | -------------------------------------------------------------------------------- |
| `identity_provider_failed`  | `app`  | `getIdentityToken` threw or rejected                                             |
| `invalid_identity`          | `sdk`  | Identity payload missed required fields, for example empty JWT token             |
| `network_error`             | `sdk`  | SDK could not reach Komo auth endpoints                                          |
| `session_request_failed`    | `komo` | Komo request failed without a known structured reason                            |
| `app_not_found`             | `komo` | Workspace app was not found, active, or available                                |
| `origin_not_permitted`      | `komo` | Request origin is not permitted for this workspace app                           |
| `type_not_permitted`        | `komo` | Identity type or custom provider is not permitted for this workspace app         |
| `token_invalid`             | `komo` | Host JWT is expired, malformed, tampered, wrong-signature, or has invalid claims |
| `attendee_not_found`        | `komo` | Eventbase or Thuzi custom provider attendee was not found                        |
| `upstream_unavailable`      | `komo` | Eventbase, Thuzi, or Rainfocus custom provider service was unavailable           |
| `oauth2_not_supported`      | `komo` | OAuth2 SDK exchange is not supported                                             |
| `contact_resolution_failed` | `komo` | Komo could not resolve the authenticated contact                                 |
| `handoff_invalid`           | `komo` | Handoff token is invalid                                                         |
| `handoff_expired`           | `komo` | Handoff token is expired                                                         |
| `handoff_consumed`          | `komo` | Handoff token was already used                                                   |
| `sdk_instance_mismatch`     | `komo` | Handoff token was issued to another SDK instance                                 |
| `unknown`                   | `sdk`  | Failure did not match a known error shape                                        |

Host JWT expiry maps to `token_invalid`.

Provider mode appends `komo_session` to embedded experience URLs. It does not use legacy per-open `embedAuthUrl` or `authPassthroughParams` flows. If those props are supplied under `KomoClientProvider`, they are ignored and a development-only warning is logged.

Apps that do not use `KomoClientProvider` keep existing behavior, including Auth0 session transfer with `embedAuthUrl` and `authPassthroughParams`.

### Prefilling form details

- You can pass information through to the Komo experience that will be pre-filled in any forms that the user may encounter.
- Pass a plain `Record<string,string>` object of keys and values through to the `formPrefillValues` prop on [`KomoCard`](#komocard-props) or [`KomoExperienceModal`](#komoexperiencemodal-props).
- The object keys must match the Unique ID of the form field or contact property from the Komo Platform that you want to prefill.

```js
<KomoCard
  embedMetaUrl={KomoCardNativeEmbedUrl}
  containerStyle={{ maxWidth: '80%' }}
  formPrefillValues={{
    email: 'email@domain.com',
    first_name: 'Person',
    last_name: 'Doe'
  }}
/>
```

## Advanced usage

### Metadata fetching

- The first step to using embedded Komo content involves fetching the card metadata.
- Use the [`useCardMetadataQuery`](#usecardmetadataquery) hook and the `Native embed URL` copied from the platform to fetch the [CardEmbedMetadata](#cardembedmetadata).
- The [CardEmbedMetadata](#cardembedmetadata) has the information required to render the cover image (`imageUrl`) and the URL (`embedUrl`) that the [KomoExperienceModal](#komoexperiencemodal-props) needs to render the embedded experience.
- Note: you can use your own data-fetching patterns if you require more advanced data fetching handling. So long as it produces a [CardEmbedMetadata](#cardembedmetadata), you can pass that to the other components that you want to use.

```js
import { useCardMetadataQuery } from '@komo-tech/react-native';

// ... rest of your component

const { data, isLoading, isError } = useCardMetadataQuery({
  embedMetaUrl: KomoCardNativeEmbedUrl
});

// ... use the data.
```

### Render a Card Cover

- The [`KomoCardCover`](#komocardcover-props) component is used to display the cover image of a Komo card.
- It handles loading states, error states, and button display.
- The component requires an `onClick` handler and `isLoading` state.
- The `imageUrl` and `imageAspectRatio` props are typically obtained from the [CardEmbedMetadata](#cardembedmetadata).

```js
import { KomoCardCover } from '@komo-tech/react-native';

// ... rest of your component

<KomoCardCover
  imageUrl={metadata?.imageUrl}
  imageAspectRatio={metadata?.imageAspectRatio}
  isLoading={isLoading}
  isError={isError}
  onClick={() => doSomethingOnCoverClicked()}
  metaButtonStyle={metadata?.buttonStyle}
  containerStyle={{ borderRadius: 8 }}
/>;
```

### Using the Experience Modal

- The [`KomoExperienceModal`](#komoexperiencemodal-props) component is used to display the full Komo experience in a modal overlay.
- It handles loading states, error states, and communication with the embedded experience.
- The component requires an `isOpen` state and `onClose` handler.
- A valid `embedUrl` prop is required for the experience modal to function, and this is typically obtained from the [CardEmbedMetadata](#cardembedmetadata).
- If you have forced OAuth enabled and are not using `KomoClientProvider`, you also need to pass through the `embedAuthUrl` from [CardEmbedMetadata](#cardembedmetadata).

```js
import { KomoExperienceModal } from '@komo-tech/react-native';

// ... rest of your component

<KomoExperienceModal
  isOpen={isModalOpen}
  onClose={() => setIsModalOpen(false)}
  embedUrl={metadata?.embedUrl}
  embedAuthUrl={metadata?.embedAuthUrl}
  loadingTimeoutMs={15000} // Optional: customize loading timeout
  appId="my-app" // Optional: identify where the content is embedded
/>;
```

### Experience Modal example without Card Cover

- You can use whichever components you want to build your desired experience.
- For example, you can trigger the [`KomoExperienceModal`](#komoexperiencemodal-props) without rendering our KomoCardCover.

```js
// ... rest of your component
const { data, isLoading } = useCardMetadataQuery({
  isEnabled,
  embedMetaUrl: EmbedMetaUrlFromKomoPortal
});
const [modalOpen, setModalOpen] = useState(false);

// other code, e.g. some element that calls setModalOpen(true) after isLoading returns false

<KomoExperienceModal
  isOpen={modalOpen}
  onClose={() => {
    setModalOpen(false);
  }}
  embedUrl={data?.embedUrl}
/>;
```

### Listening for events from the embedded experience

- You can listen for events from the embedded experience by using the `onWindowMessage` or `onKomoEvent` props on the [`KomoExperienceModal`](#komoexperiencemodal-props) or [`KomoCard`](#komocard-props).
- The `onWindowMessage` prop exposes any `window.postMessage` events from the embedded experience.
- The `onKomoEvent` prop exposes any [User Interaction Events](https://developers.komo.tech/user-interaction-events) from the embedded experience.
  - Note: User Interaction Events will also appear in the `onWindowMessage` callback. `onKomoEvent` is a more convenient way to listen for Komo User Interaction Events from the embedded experience.

```js
<KomoExperienceModal
  isOpen={modalOpen}
  onClose={() => {
    setModalOpen(false);
  }}
  embedUrl={data?.embedUrl}
  onKomoEvent={(event) => {
    console.log('Komo event received:', event);
  }}
  onWindowMessage={(event) => {
    console.log('Window message received:', event);
  }}
/>
```

### Extension Data

- The [`KomoExperienceModal`](#komoexperiencemodal-props) and [`KomoCard`](#komocard-props) components allow you to set [extension data](https://developers.komo.tech/user-interaction-events/extension-data) on the user interaction events.
- The `extensionDataValues` prop is a plain `Record<string, string | number | boolean | object>` object.
- Make sure PII is not passed in as extension data, as it is passed directly to your tag manager integrations.

```js
<KomoCard
  embedMetaUrl={KomoCardNativeEmbedUrl}
  extensionDataValues={{
    custom_unique_id: 'ABC123',
    custom_object: {
      some_id: 'ABC123',
      some_measure: 123456
    }
  }}
/>
```

### Query Parameters

Pass custom query parameters (like UTM tracking parameters) to the embedded experience URL using the `queryParams` prop.

#### Usage

```js
import { KomoCard } from '@komo-tech/react-native';

<KomoCard
  embedMetaUrl={KomoCardNativeEmbedUrl}
  queryParams={{
    utm_source: 'mobile-app',
    utm_medium: 'widget',
    utm_campaign: 'summer-2024',
    utm_content: 'hero-banner'
  }}
/>;
```

#### Common Use Cases

**UTM Tracking:**

```js
<KomoCard
  embedMetaUrl={embedUrl}
  queryParams={{
    utm_source: 'instagram',
    utm_medium: 'social',
    utm_campaign: 'product-launch',
    utm_term: 'keyword',
    utm_content: 'story-swipe-up'
  }}
/>
```

**Dynamic Campaign Tracking:**

```js
import { KomoCard } from '@komo-tech/react-native';
import { useRoute } from '@react-navigation/native';

function CampaignScreen() {
  const route = useRoute();
  const { campaignId, source } = route.params;

  return (
    <KomoCard
      embedMetaUrl={embedUrl}
      queryParams={{
        utm_campaign: campaignId,
        utm_source: source,
        utm_medium: 'app'
      }}
    />
  );
}
```

**User Segment Tracking:**

```js
import { KomoCard } from '@komo-tech/react-native';
import { useUser } from './hooks/useUser';

function ContestScreen() {
  const { userSegment, subscriptionTier } = useUser();

  return (
    <KomoCard
      embedMetaUrl={embedUrl}
      queryParams={{
        utm_source: 'app',
        utm_content: userSegment,
        user_tier: subscriptionTier
      }}
    />
  );
}
```

#### Combining with Other Props

Query parameters work alongside form prefill and extension data:

```js
<KomoCard
  embedMetaUrl={embedUrl}
  // Prefill form fields
  formPrefillValues={{
    email: user.email,
    first_name: user.firstName
  }}
  // Add analytics data
  extensionDataValues={{
    user_id: user.id,
    account_type: user.accountType
  }}
  // Track campaign source
  queryParams={{
    utm_source: 'app',
    utm_medium: 'home-screen',
    utm_campaign: 'welcome-flow'
  }}
/>
```

#### Using with KomoExperienceModal

The `KomoExperienceModal` component also supports `queryParams`:

```js
import { KomoExperienceModal } from '@komo-tech/react-native';

function CustomModal() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <Button title="Open Contest" onPress={() => setIsOpen(true)} />

      <KomoExperienceModal
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        embedUrl={metadata?.embedUrl}
        queryParams={{
          utm_source: 'custom-modal',
          utm_medium: 'app'
        }}
      />
    </>
  );
}
```

#### Technical Details

- Query parameters are added directly to the webview URL (no prefix)
- All values must be strings
- Parameters are available to analytics tools in the embedded experience
- Can be combined with `formPrefillValues` and `extensionDataValues`
- Supports standard UTM parameters and custom parameters

### Auth0 Session Transfer

- The [`KomoCard`](#komocard-props) component supports Auth0 authentication through the `authPassthroughParams` prop.
- The [`KomoExperienceModal`](#komoexperiencemodal-props) component supports Auth0 authentication through the `embedAuthUrl` and `authPassthroughParams` props.
  - The `embedAuthUrl` is typically obtained from [CardEmbedMetadata](#cardembedmetadata).
- Auth0 session transfer applies only when no `KomoClientProvider` is active. Under `KomoClientProvider`, `embedAuthUrl` and `authPassthroughParams` are ignored because provider session-token URL auth is used instead.
- Pre-requisites:
  - Auth0 SSO must be configured on the Komo Hub, and "Force Embed Auth" must be enabled under Embed SDK settings on the hub.
  - Pass a fresh session transfer token to the `authPassthroughParams` prop, e.g. `session_transfer_token: 'ABC123'`.
- With this setup, the user will be redirected to Auth0 to authenticate when the experience modal is opened, before being redirected back to the embedded experience.
- The session transfer token must be obtained immediately before opening the experience modal, since it has a short 60 second lifespan.
- **Recommended:** Specify `webViewProps={{ incognito: true }}` to ensure user session state is cleared correctly when changing between different authenticated users.

```js
<KomoCard
    embedMetaUrl={KomoCardNativeEmbedUrl}
    authPassthroughParams={new URLSearchParams({
        session_transfer_token: 'ABC123'
    })}
    webViewProps={{ incognito: true }}
/>
// or if using the KomoExperienceModal directly
<KomoExperienceModal
    isOpen={isModalOpen}
    onClose={() => setIsModalOpen(false)}
    embedUrl={metadata?.embedUrl}
    embedAuthUrl={metadata?.embedAuthUrl}
    authPassthroughParams={new URLSearchParams({
        session_transfer_token: 'ABC123'
    })}
    webViewProps={{ incognito: true }}
/>
```

#### Error handling

- If the `session_transfer_token` passed to Auth0 is used, invalid, or expired, then the users will end up being shown the KomoExperienceModal `errorDisplay`, which includes a built-in retry button.
- If you don't provide an `errorDisplay` override, the retry function will just attempt to reload the experience with the current parameters and will most likely fail again.
- We recommend that you provide a custom `errorDisplay` so that you can handle `session_transfer_token` regeneration before trying to load the content again.

## Troubleshooting

### Debug Mode

The SDK includes a `debugMode` prop that enables comprehensive logging throughout the component lifecycle. This is extremely helpful for diagnosing issues with form prefill values, loading states, and platform-specific behavior.

#### How to Enable Debug Mode

Add `debugMode={true}` to either `KomoCard` or `KomoExperienceModal`:

```js
<KomoCard
  embedMetaUrl={KomoCardNativeEmbedUrl}
  formPrefillValues={{
    email: 'user@example.com',
    first_name: 'John',
  }}
  debugMode={true}
/>

// Or with KomoExperienceModal directly:
<KomoExperienceModal
  isOpen={isModalOpen}
  onClose={() => setIsModalOpen(false)}
  embedUrl={metadata?.embedUrl}
  formPrefillValues={{
    email: 'user@example.com',
  }}
  debugMode={true}
/>
```

#### What Debug Mode Shows

When `debugMode` is enabled, the SDK will log detailed information to the console:

1. **Modal State Changes**
   - Modal open/close events
   - Loading states
   - Error states
   - Available form prefill values and their keys

2. **URL Construction**
   - Input data availability (form prefill, extension data, query params)
   - Each parameter being added to the URL
   - Warnings for empty values that are skipped
   - Final constructed URL (embedded content and auth URLs)

3. **WebView Lifecycle**
   - WebView load completion
   - HTTP errors
   - Network errors

4. **Message Handshake**
   - RequestInit received from embedded content
   - Init response sent to embedded content
   - Experience state changes (loading → ready → complete)
   - Platform-specific messaging methods used (iOS postMessage, Android injectJavaScript, web iframe postMessage)

5. **Platform-Specific Details**
   - Current platform (iOS, Android, web)
   - iOS: webviewRef existence and postMessage availability
   - Android: injectJavaScript usage
   - Web: iframe postMessage usage

#### Example Debug Output

```
[KomoExperienceModal] State changed: {
  isOpen: true,
  isLoading: true,
  hasFormPrefillValues: true,
  formPrefillKeys: ['email', 'first_name'],
  platform: 'ios'
}

[KomoWebView] Calculating iframe URL with inputs: {
  hasEmbedUrl: true,
  hasFormPrefill: true,
  formPrefillKeys: ['email', 'first_name'],
  platform: 'ios'
}

[urlResolution] Added form prefill: email = user@example.com
[urlResolution] Added form prefill: first_name = John
[urlResolution] Final embedded content URL: https://...?komo_f:email=user@example.com&komo_f:first_name=John

[KomoWebView] Final constructed URL: https://...?komo_f:email=user@example.com&komo_f:first_name=John

[KomoWebView] WebView load finished

[EmbedMessageHandler] Received RequestInit, sending Init response
[EmbedMessageHandler] Platform: iOS, using webview postMessage
[EmbedMessageHandler] webviewRef exists: true
[EmbedMessageHandler] postMessage method exists: true
[EmbedMessageHandler] iOS postMessage sent

[EmbedMessageHandler] Experience state changed to: ready
```

#### When to Use Debug Mode

Use debug mode when:

- **Verifying form prefill values** - Ensure values are being passed correctly and appear in the URL
- **Diagnosing loading state issues** - See if the experience is stuck loading or timing out
- **Understanding message flow** - Verify the handshake between your app and the embedded experience
- **Identifying platform differences** - See which code paths are taken on iOS vs Android vs web
- **Troubleshooting network errors** - Check if WebView is loading correctly
- **Testing Auth0 integration** - Verify auth URL construction and parameters
- **Testing provider auth** - Verify `komo_session` is added and legacy auth props are ignored under `KomoClientProvider`

#### Common Issues Debugged with Debug Mode

**Form Prefill Not Working:**

- Check debug logs to verify values are in the final URL
- Look for "Skipping empty form prefill value" warnings
- Verify the keys match your Komo form field Unique IDs

**Modal Stuck Loading:**

- Check if "WebView load finished" appears
- Look for WebView error messages
- Verify "Experience state changed to: ready" is logged

**iOS postMessage Issues:**

- Check "webviewRef exists" and "postMessage method exists" logs
- Verify "iOS postMessage sent" appears
- Look for any error messages in the console

**Auth URL Issues:**

- Verify "Building auth URL with returnTo parameter" appears
- Check the final auth URL includes session transfer token
- Ensure embedded content URL is properly encoded in returnTo

#### Production Note

**⚠️ Important:** Debug mode should only be used during development and troubleshooting. Always disable it in production builds:

```js
const isDevelopment = __DEV__; // React Native's development flag

<KomoCard embedMetaUrl={KomoCardNativeEmbedUrl} debugMode={isDevelopment} />;
```

Debug logs may expose sensitive information and can impact performance, so it's important to disable debug mode in production environments.

## Metadata model

### CardEmbedMetadata

| Property           | Type         | Description                                                       |
| ------------------ | ------------ | ----------------------------------------------------------------- |
| `title`            | string?      | The title of the card                                             |
| `imageUrl`         | string?      | URL of the card's cover image                                     |
| `imageHeight`      | number?      | Height of the cover image in pixels                               |
| `imageWidth`       | number?      | Width of the cover image in pixels                                |
| `imageAspectRatio` | number?      | Aspect ratio of the cover image                                   |
| `embedUrl`         | string?      | URL for the embedded experience                                   |
| `embedAuthUrl`     | string?      | URL used to OAuth the user before showing the embedded experience |
| `buttonStyle`      | ButtonStyle? | Styling for the card's button                                     |

### ButtonStyle

| Property          | Type    | Description                    |
| ----------------- | ------- | ------------------------------ |
| `text`            | string? | Text to display on the button  |
| `backgroundColor` | string? | Background color of the button |
| `color`           | string? | Text color of the button       |

## Hooks

### useKomoSession

Reads the active provider session. Must be called under `KomoClientProvider`.
Derive readiness from `session.state`; `AUTHENTICATING` means a session exchange is in flight.

| Property            | Type                          | Description                                                                                                |
| ------------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `session`           | CurrentSession                | Latest provider session snapshot                                                                           |
| `getSessionToken`   | () => Promise<string \| null> | Returns the current bearer token and refreshes state snapshot                                              |
| `getCurrentSession` | () => CurrentSession          | Imperative current session snapshot read                                                                   |
| `identify`          | () => Promise<CurrentSession> | Forces identity exchange using the latest `getIdentityToken`; rejects with `KomoAuthError` on auth failure |
| `logout`            | () => void                    | Logs out the current Komo session and updates provider state                                               |

### KomoAuthError

`KomoAuthError` is the stable error contract for provider authentication failures.

| Property        | Type                       | Description                                                      |
| --------------- | -------------------------- | ---------------------------------------------------------------- |
| `name`          | `'KomoAuthError'`          | Error type discriminator                                         |
| `code`          | `KomoAuthErrorCode`        | Stable machine-readable reason. Switch on this for app behavior. |
| `source`        | `'app' \| 'komo' \| 'sdk'` | Origin of the failure                                            |
| `retryable`     | boolean                    | Whether retrying the auth operation may succeed                  |
| `status`        | number?                    | HTTP status when Komo returned one                               |
| `failureReason` | ExchangeFailureReason?     | Raw Komo auth failure reason when returned by Komo               |
| `message`       | string                     | Human-readable diagnostic message                                |

### useOptionalKomoSession

Internal/provider-aware hook that returns the active provider session or `null` when no provider exists.

### useCardMetadataQuery

A hook for fetching card metadata from the Komo platform.

#### Options

| Property       | Type             | Required | Description                                                                   |
| -------------- | ---------------- | -------- | ----------------------------------------------------------------------------- |
| `embedMetaUrl` | string           | Yes      | The URL of the embed metadata for the card, copied from the Komo Portal       |
| `isEnabled`    | boolean          | No       | Whether the embed metadata query is enabled. Defaults to true                 |
| `onError`      | (e: any) => void | No       | Callback for when an error occurs during querying the embed metadata endpoint |

#### Result

| Property       | Type                | Description                                |
| -------------- | ------------------- | ------------------------------------------ |
| `data`         | CardEmbedMetadata?  | The embed metadata for the card            |
| `isLoading`    | boolean             | Whether the embed metadata is loading      |
| `isError`      | boolean             | Whether the embed metadata query failed    |
| `isSuccess`    | boolean             | Whether the embed metadata query succeeded |
| `refetchAsync` | () => Promise<void> | Function to refetch the embed metadata     |

## Components

### KomoClientProvider Props

| Property           | Type                                                          | Required | Description                                                                              |
| ------------------ | ------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------- |
| `appId`            | string                                                        | Yes      | Workspace app ID copied from Komo Portal, including region prefix, e.g. `au1_<app-guid>` |
| `getIdentityToken` | () => Promise<IdentityResult> \| IdentityResult               | Yes      | Returns identity used for session exchange                                               |
| `siteId`           | string                                                        | No       | Deprecated and obsolete. No longer used and will be removed.                             |
| `fetch`            | PortableFetch \| RuntimeFetch                                 | No       | Custom fetch implementation. Defaults to `globalThis.fetch`                              |
| `logger`           | Pick<EmbedCoreLogger, 'debug' \| 'info' \| 'warn' \| 'error'> | No       | Optional logger passed to the session manager                                            |
| `onAuthenticated`  | ({ contactId, trustLevel }) => void                           | No       | Called when provider session authenticates                                               |
| `onSessionExpired` | ({ reason }) => void                                          | No       | Called when provider session expires, refresh fails, or user logs out                    |
| `onAuthError`      | (error: KomoAuthError) => void                                | No       | Called when provider authentication, refresh, or handoff fails                           |
| `children`         | ReactNode                                                     | Yes      | Components that should share the provider session                                        |

### KomoCardCover Props

| Property                  | Type                   | Required | Description                                                |
| ------------------------- | ---------------------- | -------- | ---------------------------------------------------------- |
| `onClick`                 | () => void             | Yes      | The callback for when the cover is clicked                 |
| `isLoading`               | boolean                | Yes      | Whether the cover is loading                               |
| `isError`                 | boolean?               | No       | Whether the cover is in an error state                     |
| `loader`                  | ReactNode?             | No       | Override the default skeleton loader                       |
| `errorDisplay`            | ReactNode?             | No       | Override the default error display                         |
| `metaButtonStyle`         | ButtonStyle?           | No       | The button style returned from the embed metadata endpoint |
| `overrideButtonStyle`     | StyleProp<ViewStyle>?  | No       | Override the button style                                  |
| `overrideButtonTextStyle` | StyleProp<TextStyle>?  | No       | Override the button text style                             |
| `containerStyle`          | StyleProp<ViewStyle>?  | No       | Override the container style                               |
| `coverImageStyle`         | StyleProp<ImageStyle>? | No       | Override the cover image style                             |
| `hideCoverButton`         | boolean?               | No       | Whether to hide the cover button                           |
| `imageUrl`                | string?                | No       | The url of the cover image                                 |
| `imageAspectRatio`        | number?                | No       | The aspect ratio of the cover image                        |

### KomoExperienceModal Props

| Property                | Type                                                  | Required | Description                                                                                                                                                                      |
| ----------------------- | ----------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `isOpen`                | boolean                                               | Yes      | Whether the modal is open                                                                                                                                                        |
| `onClose`               | () => void                                            | Yes      | Callback for when close is requested                                                                                                                                             |
| `embedUrl`              | string                                                | Yes      | The URL of the embedded card experience                                                                                                                                          |
| `modalHeader`           | ReactNode                                             | No       | Override the default modal header                                                                                                                                                |
| `shareClickUrl`         | string                                                | No       | Override the url that redirects a user when clicking on a share link                                                                                                             |
| `appId`                 | string                                                | No       | An identifier for the embedded Komo content                                                                                                                                      |
| `formPrefillValues`     | Record<string, string>                                | No       | Prefill values for the form within the experience                                                                                                                                |
| `loadingIndicator`      | ReactNode                                             | No       | Override the default loading indicator                                                                                                                                           |
| `modalProps`            | ModalProps                                            | No       | Override the default modal props                                                                                                                                                 |
| `loadingTimeoutMs`      | number                                                | No       | Timeout in milliseconds before showing error state. Defaults to 15000ms                                                                                                          |
| `errorDisplay`          | ({ onRetry }: { onRetry: () => void }) => ReactNode   | No       | Override the default error display                                                                                                                                               |
| `onFileDownload`        | WebViewProps['onFileDownload']                        | No       | Callback for when a file download is requested. Only applies to iOS. See react-native-webview docs for more details                                                              |
| `onKomoEvent`           | (eventData: KomoEvent) => void                        | No       | Callback for when a komo-event is raised in the embedded experience                                                                                                              |
| `onWindowMessage`       | (eventData: any) => void                              | No       | Callback for when a window message is raised in the embedded experience. Note that komo-events are also window messages, so this callback will be called for komo-events as well |
| `extensionDataValues`   | Record<string, string \| number \| boolean \| object> | No       | Extension data to be included with user interaction events. Avoid including PII as this data is passed directly to tag manager integrations.                                     |
| `queryParams`           | Record<string, string>                                | No       | Query parameters to add to the iframe URL. Common use case is UTM tracking parameters.                                                                                           |
| `embedAuthUrl`          | string                                                | No       | The URL of the authorization endpoint. If provided, the experience modal will first load the auth URL, then redirect to the embed URL. Typically obtained from CardEmbedMetadata |
| `authPassthroughParams` | URLSearchParams                                       | No       | Passthrough parameters to add to the auth URL as query parameters. For example, an Auth0 session transfer token can be added to the auth URL.                                    |
| `webViewProps`          | WebViewProps                                          | No       | Additional props for the react-native-webview component. Only applies if the platform is not web.                                                                                |
| `iframeProps`           | IframeProps                                           | No       | Additional props for the iframe component. Only applies if the platform is web.                                                                                                  |
| `debugMode`             | boolean                                               | No       | Enable debug mode to log component lifecycle, URL construction, and message handling. Only use during development/troubleshooting.                                               |

### KomoCard Props

| Property                | Type                                                  | Required | Description                                                                                                                                                                      |
| ----------------------- | ----------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `embedMetaUrl`          | string                                                | Yes      | The URL of the embed metadata for the card, copied from the Komo Portal                                                                                                          |
| `appId`                 | string                                                | No       | An identifier for the embedded Komo content                                                                                                                                      |
| `containerStyle`        | StyleProp<ViewStyle>                                  | No       | Override the container style                                                                                                                                                     |
| `coverImageStyle`       | StyleProp<ImageStyle>                                 | No       | Override the cover image style                                                                                                                                                   |
| `buttonStyle`           | StyleProp<ViewStyle>                                  | No       | Override the button style                                                                                                                                                        |
| `buttonTextStyle`       | StyleProp<TextStyle>                                  | No       | Override the button text style                                                                                                                                                   |
| `coverLoader`           | ReactNode                                             | No       | Override the default loader for the cover                                                                                                                                        |
| `coverErrorDisplay`     | ReactNode                                             | No       | Override the default error display for the cover                                                                                                                                 |
| `hideCoverButton`       | boolean                                               | No       | Whether to hide the cover button. Defaults to false                                                                                                                              |
| `modalHeader`           | ReactNode                                             | No       | Override the default modal header                                                                                                                                                |
| `onError`               | (e: any) => void                                      | No       | Callback for when an error occurs during querying the embed metadata endpoint                                                                                                    |
| `onModalClose`          | () => void                                            | No       | Callback for when the modal is closed                                                                                                                                            |
| `onModalOpen`           | () => void                                            | No       | Callback for when the modal is opened                                                                                                                                            |
| `shareClickUrl`         | string                                                | No       | Override the url that redirects a user when clicking on a share link                                                                                                             |
| `formPrefillValues`     | Record<string, string>                                | No       | Prefill values for the form within the experience                                                                                                                                |
| `onFileDownload`        | WebViewProps['onFileDownload']                        | No       | Callback for when a file download is requested. Only applies to iOS. See react-native-webview docs for more details                                                              |
| `onKomoEvent`           | (eventData: KomoEvent) => void                        | No       | Callback for when a komo-event is raised in the embedded experience                                                                                                              |
| `onWindowMessage`       | (eventData: any) => void                              | No       | Callback for when a window message is raised in the embedded experience. Note that komo-events are also window messages, so this callback will be called for komo-events as well |
| `extensionDataValues`   | Record<string, string \| number \| boolean \| object> | No       | Extension data to be included with user interaction events. Avoid including PII as this data is passed directly to tag manager integrations.                                     |
| `queryParams`           | Record<string, string>                                | No       | Query parameters to add to the iframe URL. Common use case is UTM tracking parameters.                                                                                           |
| `authPassthroughParams` | URLSearchParams                                       | No       | Passthrough parameters to add to the auth URL as query parameters. For example, an Auth0 session transfer token can be added to the auth URL.                                    |
| `loadingTimeoutMs`      | number                                                | No       | Timeout in milliseconds before showing error state in the modal. Defaults to 15000ms                                                                                             |
| `modalErrorDisplay`     | ({ onRetry }: { onRetry: () => void }) => ReactNode   | No       | Override the default error display for the modal                                                                                                                                 |
| `webViewProps`          | WebViewProps                                          | No       | Additional props for the react-native-webview component. Only applies if the platform is not web.                                                                                |
| `iframeProps`           | IframeProps                                           | No       | Additional props for the iframe component. Only applies if the platform is web.                                                                                                  |
| `debugMode`             | boolean                                               | No       | Enable debug mode to log component lifecycle, URL construction, and message handling. Only use during development/troubleshooting.                                               |

Existing integrations that pass `region` separately remain supported temporarily, but new integrations should use the prefixed App ID from Komo Portal.

## Other models

### KomoEvent

| Property        | Type                                                  | Description                                    |
| --------------- | ----------------------------------------------------- | ---------------------------------------------- |
| `eventName`     | string                                                | The name of the Komo event                     |
| `eventData`     | any                                                   | The data associated with the Komo event        |
| `extensionData` | Record<string, string \| number \| boolean \| object> | The extension data raised along with the event |
