# ABHA SDK Implementation

This guide provides everything you need to integrate the ABHA SDK into your application.

## Overview

The ABHA SDK allows you to integrate flows—such as Create ABHA, Login, Profile KYC, Consent Management, and Scan & Share—into your healthcare application, while offering customizable theme options. It provides:

- **Create ABHA**: Create a new ABHA using Mobile or Aadhaar.
- **Login with ABHA**: Login to your existing ABHA using PHR Address, ABHA number, Aadhaar number or Mobile number.
- **ABHA Consent Management**: Manage Consent requests raised by healthcare providers to share medical records securely.
- **ABHA Profile KYC**: Get your ABHA address KYC verified.
- **ABHA Scan & Share**: Get your Appointments Booked through ABHA.
- **Customizing the Theme**: Customize the ABHA SDK colors to match your application's branding.

## Installation

### Prerequisites

- A modern web browser.
- Your domain must be whitelisted with Eka Care to avoid CORS(Cross-Origin Resource Sharing) error.
  (Contact Eka Care to request API access and domain whitelisting.)
- A valid HTML container element where the SDK will mount.

### Setup

Add the following HTML and script tags to your webpage. For staging/dev, swap the npm package from `@eka-care/abha` → `@eka-care/abha-stg` (see [Release URLs](#release-urls) for all CDN and npm options).

```html
<!doctype html>
<html>
  <head>
    <title>ABHA SDK Integration</title>

    <!-- Include ABHA SDK CSS -->
    <link rel="stylesheet" href="https://unpkg.com/@eka-care/abha/dist/sdk/abha/css/abha.css" />
  </head>
  <body>
    <h1>ABHA SDK Demo</h1>

    <!-- Mount Button -->
    <button class="button" onclick="mountABHASDK()">Mount SDK</button>

    <!-- Container for ABHA SDK -->
    <div id="sdk_container"></div>

    <!-- Include ABHA SDK JS -->
    <script type="module" src="https://unpkg.com/@eka-care/abha/dist/sdk/abha/js/abha.js"></script>

    <script>
      function mountABHASDK() {
        window.initAbhaApp({
          containerId: 'sdk_container',
          clientId: 'ext',
          theme: {
            // if you want to customise sdk theme/colors
            // pass the colors of your organisation design system
          },
          // data object
          data: {
            // pass the required data as per the flow
          },

          // Success callback
          onSuccess: (params) => {
            console.log('ABHA Registration flow completed successfully:', params);
          },

          // KYC Success callback
          onKYCSuccess: (params) => {
            console.log('ABHA KYC Verified successfully:', params);
          },

          // Consent Success callback
          onConsentSuccess: (params) => {
            console.log('ABHA Consent flow completed successfully:', params);
          },

          // Scan & Share Success callback
          onAppointmentBookedSuccess: (params) => {
            console.log('Appointment Booked successfully:', params);
          },

          // Skip ABHA callback
          onSkipAbha: (params) => {
            console.log('ABHA flow SKIPPED:', params);
          },

          // Abha Close callback
          onAbhaClose: () => {
            console.log('ABHA SDK closed');
          },

          // Error callback
          onError: (params) => {
            console.error('ABHA SDK failed:', params);
          },
        });
      }
    </script>
  </body>
</html>
```

---

## Development

### Run locally

The dev server runs on HTTP at port 80. Use `sudo` to bind to port 80 and access via your named `.eka.care` subdomain.

```bash
# PROD 
sudo env "VITE_APP_ENV=PROD" yarn dev --scope=abha --include-dependencies

# DEV 
sudo env yarn dev --scope=abha --include-dependencies
```

> The host in `vite.config.ts` is set to `nishant.eka.care`. Change it to your own `.eka.care` subdomain if needed.

### Local Testing

There is no parent app locally — the SDK is auto-mounted via a DEBUG block in [src/main.tsx](src/main.tsx) when `VITE_APP_MODE=DEBUG` is set.

**Steps:**

1. Open [src/main.tsx](src/main.tsx) and locate the `DEBUG` block at the bottom of the file.
2. Set `accessToken` in the `data` object to a valid bearer token (without the `Bearer` prefix).
3. Set `clientId` to the platform you want to simulate (see table below).
4. Uncomment and set `flow` if you need a specific flow (e.g. `abha-kyc`, `consent`, `scan-share`).
5. Run the dev server with `VITE_APP_MODE=DEBUG`:

```bash
sudo env "VITE_APP_ENV=PROD" VITE_APP_MODE=DEBUG yarn dev --scope=abha --include-dependencies
```

6. Open `https://{yourname}.eka.care/` in your browser — the SDK mounts automatically into `#lofe_root`.

**`clientId` values and their internal mapping:**

| `clientId`                                               | Internal client | Use case                              |
| -------------------------------------------------------- | --------------- | ------------------------------------- |
| `doc-web`, `ext`, `androiddoc`, `doctor-app-ios`, `doctor-ipad-ios` | `doctor`  | Doctor-facing flows (KYC, consent, etc) and ext is for external clients    |
| `androidp`, `patient-app-ios`                           | `phr`           | Patient app flows                     |
| `www-eka`                                               | `eka-web`       | Eka web flows (default for local dev) |

**`flow` values:**

| `flow`               | Description                                     |
| -------------------- | ----------------------------------------------- |
| _(omitted)_          | Default login / create ABHA screen              |
| `abha-kyc`           | ABHA address KYC verification                   |
| `consent`            | Consent management (requires `consent_id`)      |
| `scan-share`         | Scan & Share for appointment booking            |
| `scan-share-kiosk`   | Kiosk mode Scan & Share (requires `counter_id`) |
| `abha-registration`   | Flow for registration of abha's through campaigns  (requires `id i.e. campaign id`) |

**Testing scenarios:**

| Scenario                      | How to trigger                                                                                 |
| ----------------------------- | ---------------------------------------------------------------------------------------------- |
| Default login / create ABHA   | Leave `flow` unset — login-or-create screen appears                                            |
| KYC flow                      | Set `flow: 'abha-kyc'` and pass a valid `accessToken` + `oid`                                  |
| Consent flow                  | Set `flow: 'consent'` and pass `accessToken`, `oid`, and `consent_id`                          |
| Scan & Share                  | Set `flow: 'scan-share'`, `hipId`, and optionally `counter_id`                                 |
| Kiosk Scan & Share            | Set `flow: 'scan-share-kiosk'`, `hipId`, `counter_id`, `facilityName`                          |
| ABHA Registration          | Set `flow: 'abha-registration'`, `regJourneyId`, `identifier`, if needed `successRedirect`                          |
| Pre-fill identifier           | Set `identifier` to a mobile / ABHA number and optionally `identifier_type`                    |
| Skip ABHA button              | Set `skipABHAEnable: true` — a "Skip" option appears on the login screen                       |
| Theme customisation           | Uncomment the `theme` block in the DEBUG call and adjust color tokens                          |
| `onSuccess` fires             | Complete any flow — check browser console for `onSuccessParams` log                            |
| `onError` fires               | Pass an invalid `accessToken` or trigger a network error — check console for `onErrorParams`   |


### Web URLs

Each flow is available as a dedicated URL (website/mWeb) on production and staging. Swap `www.eka.care` → `curio.dev.eka.care` for staging.

| Flow                | Prod URL                                                                                                                                               |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| ABHA KYC            | `https://www.eka.care/ayushman-bharatabha-kyc?abha=[non-kyc-abha@abdm]`                                                                               |
| Consent             | `https://www.eka.care/ayushman-bharat/consent?abha=[abha-address@abdm]&id=[consent-id]`                                                               |
| Scan & Share        | `https://www.eka.care/ayushman-bharat/share-profile?hip-id=[hip-id]&counter-id=[counter-id]`                                                          |
| Scan & Share Kiosk  | `https://www.eka.care/ayushman-bharat/abha-kiosk-setup?hip-id=[hip-id]&counter-id=[counter-id]&name=[clinic-name]`                                    |
| ABHA Registration   | `https://www.eka.care/ayushman-bharat/abha-registration?id=[campaign-id]&identifier=[abha-address@abdm / mobile / aadhaar / abha_number]`                                                 |

**Staging:** replace `www.eka.care` with `curio.dev.eka.care` — e.g. `https://curio.dev.eka.care/ayushman-bharat/consent?...`

---

### Build

Run from repo root:

```bash
# Staging
sudo yarn build-abha:stg

# Production
sudo yarn build-abha:prod
```

Build output: `dist/sdk/abha/js/abha.js` and `dist/sdk/abha/css/abha.css`. Deployed to S3 and published as the `@eka-care/abha` npm package.

---

## Core Functions

### 1. initAbhaApp

Initializes and renders the ABHA SDK in your specified container.

**Parameters:**

| Parameter                    | Type                                      | Required    | Description                                                             |
| ---------------------------- | ----------------------------------------- | ----------- | ----------------------------------------------------------------------- |
| `containerId`                | `string`                                  | ✅          | HTML element ID where the SDK will mount.                               |
| `clientId`                   | `string`                                  | ✅          | Platform identifier. Use `ext` for external integrations.               |
| `data`                       | `object`                                  | ⚙️ Optional | Flow configuration — see `data` fields table below.                     |
| `theme`                      | `object`                                  | ⚙️ Optional | Color token overrides. All keys optional — only supply what you change. |
| `onSuccess`                  | `(params: TOnAbhaSuccessParams) => void`  | ✅          | Fired when the user successfully creates or logs in to ABHA.            |
| `onKYCSuccess`               | `(params: TOnAbhaKycSuccessParams) => void` | ⚙️ Optional | Fired when KYC verification completes.                                  |
| `onConsentSuccess`           | `(params: TOnAbhaConsentSuccessParams) => void` | ⚙️ Optional | Fired when the consent flow completes.                             |
| `onAppointmentBookedSuccess` | `(params: TOnAbhaSnSAppointmentSuccessParams) => void` | ✅ | Fired when an appointment is booked via Scan & Share.          |
| `onSkipAbha`                 | `(params: TOnSkipABHA) => void`           | ⚙️ Optional | Fired if the user skips the ABHA flow.                                  |
| `onAbhaClose`                | `() => void`                              | ✅          | Fired when the SDK closes.                                              |
| `onError`                    | `(params: TOnAbhaFailureParams) => void`  | ✅          | Fired when an error occurs during the ABHA flow.                        |

**`data` object fields:**

| Field               | Type      | Required    | Description                                                                                                       |
| ------------------- | --------- | ----------- | ----------------------------------------------------------------------------------------------------------------- |
| `accessToken`       | `string`  | ✅          | Bearer token from [Connect Login](https://developer.eka.care/api-reference/authorization/client-login) — omit the `Bearer` prefix. |
| `flow`              | `string`  | ⚙️ Optional | Flow to launch: `abha-kyc`, `consent`, `scan-share`, `scan-share-kiosk`. Omit for default login/create screen.   |
| `hipId`             | `string`  | ⚙️ Optional | HFR ID of the facility. Required for Scan & Share flows.                                                          |
| `oid`               | `string`  | ⚙️ Optional | Patient OID. Required for `abha-kyc` and `consent` flows.                                                        |
| `consent_id`        | `string`  | ⚙️ Optional | Consent request ID. Required for `consent` flow.                                                                  |
| `counter_id`        | `string`  | ⚙️ Optional | HIP counter/facility code. Required for `scan-share-kiosk`.                                                       |
| `facilityName`      | `string`  | ⚙️ Optional | Display name of the clinic. Used in `scan-share-kiosk`.                                                           |
| `identifier`        | `string`  | ⚙️ Optional | Pre-fill login identifier — mobile, Aadhaar, ABHA number, or PHR address.                                         |
| `identifier_type`   | `string`  | ⚙️ Optional | Type of `identifier`: `mobile`, `aadhaar_number`, `abha_number`, `phr_address`. Auto-detected if omitted.         |
| `mobile`            | `string`  | ⚙️ Optional | Pre-fill the mobile number field (10 digits).                                                                     |
| `skipABHAEnable`    | `boolean` | ⚙️ Optional | Show a “Skip” button on the login screen.                                                                         |
| `orgIconUrl`        | `string`  | ⚙️ Optional | Public CDN URL of your organisation's logo (must start with `https://`).                                          |
| `linkToOrgIcon`     | `string`  | ⚙️ Optional | Public CDN URL of the “Link ABHA to your org” icon (must start with `https://`).                                  |
| `successRedirect`   | `string`  | ⚙️ Optional | Redirect target after success (e.g. `abha-card`).                                                                 |
| `regJourneyId`      | `string`  | ⚙️ Optional | Registration journey ID for tracked onboarding campaigns.                                                         |

## Callback Parameters

### onSuccess Callback

The onSuccess callback is triggered when the ABHA flow completes successfully.
It returns verified user details and tokens, which can be used to log in or continue the user’s session.

**Callback Signature:**

```typescript
onSuccess: (params: TOnAbhaSuccessParams) => void;
```

**Type Definitions**

```typescript
type TOnAbhaSuccessParams = {
  response: TAuthVerifyV2Response;
};

type TAuthVerifyV2Response = {
  skip_state: number;
  method: AUTH_METHOD;
  data?: {
    tokens: {
      sess: string;
      refresh: string;
    };
    profile: TProfileRecord;
  };
  txn_id: string;
  error?: {
    code: number;
    message: string;
  };
};

enum AUTH_METHOD {
  EMAIL = 1,
  MOBILE = 2,
  ABHA = 7,
}

type TProfileRecord = {
  fln: string;
  fn: string;
  mn?: string;
  ln?: string;
  gen?: 'M' | 'F' | 'O' | 'U' | undefined; // 'male' | 'female' | 'other' | 'unknown'
  dob?: string;
  mobile?: string;
  email?: string;
  uuid?: string;
  bloodgroup?: '' | 'A+' | 'A-' | 'B+' | 'B-' | 'O+' | 'O-' | 'AB+' | 'AB-';
  pic?: string;
  as?: string;
  'dob-valid'?: boolean;
  'is-d'?: boolean;
  'is-d-s'?: boolean;
  'is-p'?: boolean;
  oid: string;
  at: string;
  type?: 1 | 2 | 3 | 4 | 5 | 6;
  'health-ids'?: Array<string>;
  abha_number?: string;
  kyc_verified?: boolean;
};
```

**Parameters**

| Key        | Type                    | Description                                                                                               |
| ---------- | ----------------------- | --------------------------------------------------------------------------------------------------------- |
| `response` | `TAuthVerifyV2Response` | The complete ABHA verification response, containing session tokens, user profile, and transaction details. |

**Example:**

```javascript
const onSuccess = (params) => {
  console.log('ABHA Success:', params.response);

  const abhaNumber = params.response.data?.profile?.abha_number;
  const userName = params.response.data?.profile?.name;

  alert(`Welcome ${userName}! Your ABHA Number: ${abhaNumber}`);

  // Optionally pass data to native bridge if available
  if (window.EkaAbha) {
    window.EkaAbha.onAbhaSuccess(JSON.stringify(params));
  }
};
```

### onKYCSuccess Callback

The onKYCSuccess callback is triggered when the ABHA KYC flow completes successfully.
It returns a confirmation message indicating that the KYC has been verified.

**Callback Signature:**

```typescript
onKYCSuccess: (params: TOnAbhaKycSuccessParams) => void;
```

**Type Definitions**

```typescript
type TOnAbhaKycSuccess = string;
```

**Parameters**

| Key | Type | Description |
| ------------------- | -------- | ----------------------------------------------------- |
| `TOnAbhaKycSuccess` | `string` | A confirmation message from SDK post KYC verification |

**Example:**

```javascript
const onKYCSuccess = (params) => {
  console.log('KYC verification Success:', params);

  alert('KYC was verified successfully!');

  // Optionally pass data to native bridge if available
  if (window.EkaAbha) {
    window.EkaAbha.onAbhaKYCSuccess(params);
  }
};
```

### onConsentSuccess Callback

The onConsentSuccess callback is triggered when the ABHA Consent flow completes successfully.
It returns a confirmation message indicating that the Consent flow ended successfully.

**Callback Signature:**

```typescript
onConsentSuccess: (params: TOnAbhaConsentSuccessParams) => void;
```

**Type Definitions**

```typescript
type TOnAbhaConsentSuccessParams = string;
```

**Parameters**

| Key                           | Type     | Description                                                  |
| ----------------------------- | -------- | ------------------------------------------------------------ |
| `TOnAbhaConsentSuccessParams` | `string` | A confirmation message from SDK post Consent flow completion |

**Example:**

```javascript
const onConsentSuccess = (params) => {
  console.log('Consent Flow completed:', params);

  alert('Consent flow completed successfully!');

  // Optionally pass data to native bridge if available
  if (window.EkaAbha) {
    window.EkaAbha.onAbhaConsentSuccess(params);
  }
};


```
### onAppointmentBookedSuccess Callback

The onAppointmentBookedSuccess callback is triggered when the appointment is booked and token gets generated successfully.
It returns a confirmation message indicating that the Appointment is booked.

**Callback Signature:**

```typescript
onAppointmentBookedSuccess: (params: TOnAbhaSnSAppointmentSuccessParams) => void;
```

**Type Definitions**

```typescript
type TOnAbhaSnSAppointmentSuccess = string;
```

**Parameters**

| Key                          | Type     | Description                                               |
| ---------------------------- | -------- | --------------------------------------------------------- |
| `onAppointmentBookedSuccess` | `string` | Confirmation message from SDK post appointment token generation. |

**Example:**

```javascript
const onAppointmentBookedSuccess = (params) => {
  console.log("Appointment Booked successfully!:", params);

  alert("Appointment Booked successfully!");

  // Optionally pass data to native bridge if available
  if (window.EkaAbha) {
    window.EkaAbha.onAppointmentBookedSuccess(params);
  }
};
```

### onSkipAbha Callback

The onSkipAbha callback is triggered when the ABHA SDK flow is skipped. The callback is functional when skipABHAEnable is set to true in the data parameter while initializing the SDK.

**Callback Signature:**

```typescript
onSkipAbha: (params: TOnSkipABHA) => void;
```

**Example:**

```javascript
const onSkipAbha = (params) => {
  console.log("ABHA SDK Skipped:", params);
};
```

**Type Definitions**

```typescript
type IdentifierType =
  | "mobile"
  | "aadhaar_number"
  | "abha_number"
  | "phr_address";

type TOnSkipABHA = {
  identifier?: string;
  identifier_type?: IdentifierType[]; // No default value here
};
```

**Parameters**

| Key               | Type                | Description                                    |
| ----------------- | ------------------- | ---------------------------------------------- |
| `identifier`      | `string?`           | Login identifier value filled by the user.     |
| `identifier_type` | `IdentifierType[]?` | Type of the login identifier.                  |

### onAbhaClose Callback

The onAbhaClose callback is triggered when the ABHA SDK flow gets closed.

**Callback Signature:**

```typescript
onAbhaClose: () => void;
```

**Example:**

```javascript
const onAbhaClose = () => {
  console.log("ABHA SDK Closed");
};
```

### onError Callback

The onError callback is triggered whenever an ABHA flow fails or is interrupted.
It provides details about the failure through structured parameters, allowing you to handle or forward the error appropriately (for example, to native apps or monitoring tools).

**Callback Signature:**

```typescript
onError: (params: TOnAbhaFailureParams) => void;
```

**Type Definitions**

```typescript
type TOnAbhaFailureParams = {
  error?: string;
  response?: TAuthVerifyV2Response;
};

type TAuthVerifyV2Response = {
  skip_state: number;
  method: AUTH_METHOD;
  data?: {
    tokens: {
      sess: string;
      refresh: string;
    };
    profile: TProfileRecord;
  };
  txn_id: string;
  error?: {
    code: number;
    message: string;
  };
};

enum AUTH_METHOD {
  EMAIL = 1,
  MOBILE = 2,
  ABHA = 7,
}

type TProfileRecord = {
  fln: string;
  fn: string;
  mn?: string;
  ln?: string;
  gen?: "M" | "F" | "O" | "U" | undefined; // 'male' | 'female' | 'other' | 'unknown'
  dob?: string;
  mobile?: string;
  email?: string;
  uuid?: string;
  bloodgroup?: "" | "A+" | "A-" | "B+" | "B-" | "O+" | "O-" | "AB+" | "AB-";
  pic?: string;
  as?: string;
  "dob-valid"?: boolean;
  "is-d"?: boolean;
  "is-d-s"?: boolean;
  "is-p"?: boolean;
  oid: string;
  at: string;
  type?: 1 | 2 | 3 | 4 | 5 | 6;
  "health-ids"?: Array<string>;
  abha_number?: string;
  kyc_verified?: boolean;
};
```

**Parameters**

| Key        | Type                     | Description                                                      |
| ---------- | ------------------------ | ---------------------------------------------------------------- |
| `error`    | `string?`                | Short description of the failure or error message.               |
| `response` | `TAuthVerifyV2Response?` | Partial or full API response object returned from ABHA services. |

**Example:**

```javascript
const onError = (params) => {
  console.error("ABHA Error:", params);

  if (params.response?.error?.code === 1001) {
    alert("Authentication failed. Please try again.");
  } else if (params.error === "NETWORK_ERROR") {
    alert("Please check your internet connection.");
  } else {
    alert("Something went wrong. Please retry.");
  }

  // Forward the error to native handler if available
  if (window.EkaAbha) {
    window.EkaAbha.onAbhaFailure(JSON.stringify(params));
  }
};
```

**Suggested Handling**

- Always log the full error response (`params`) for debugging.
- Display friendly error messages for known `error.code` values.
- If `params.response` is present, inspect `response.error.message` for more detail.
- If integrating with native apps, forward the serialized error object:

```javascript
window.EkaAbha.onAbhaFailure(JSON.stringify(params));
```

## Customizing the Theme

The ABHA SDK supports full color-token overriding. You can pass a theme object during initialization to match your application's branding.

### Default Theme Colors

If no theme is provided, the SDK uses the following default values:

```typescript
const defaultAbhaColors = {
  semantic: {
    error: '#BD0F0F',
    warning: '#FCB069',
    success: '#27B961',
  },
  primary: {
    brand: '#6B5CE0', // Main buttons, radios, and active states
  },
  surface: {
    base: '#FFFFFF', // Background of pages
    subtle: '#F2F4F7', // Card backgrounds
    muted: '#E4E7EC', // Dividers and borders
    strong: '#BEC5D0',
    success: '#D5F6E2', // Success background alerts
    neutral: '#0000000D',
    danger: '#DD3F3F',
    abhaCard: '#232477', // Specific background for the ABHA ID card
  },
  content: {
    primary: '#111B31', // Heading and main text
    secondary: '#4B596D', // Subtext
    muted: '#9EA8B8', // Disabled or placeholder text
    success: '#1B7E43', // Success text
    enabled: '#ffffff', // enabled button text color
  },
  qrCodeColors: {
    fgColor: '#000000', // Color of the QR code dots
    bgColor: '#FFFFFF', // Background of the QR code
  },
};
```

### Overriding the theme

To customize the look, add the `theme` key to your `initAbhaApp` configuration:

```typescript
window.initAbhaApp({
  containerId: 'sdk_container',
  clientId: 'ext',
  theme: {
    primary: {
      brand: '<your_org_primary_color>', // brand color
    },
    semantic: {
      error: '<your_semantic_error_color>',
      warning: '<your_semantic_warning_color>',
      success: '<your_semantic_success_color>',
    },
    surface: {
      base: '<your_base_color>', // Background of pages
      subtle: '<your_subtle_color>', // Card backgrounds
      muted: '<your_muted_color>', // Dividers and borders
      strong: '<your_strong_color>',
      success: '<your_success_color>', // Success background alerts
      neutral: '<your_neutral_color>',
      danger: '<your_danger_color>',
      abhaCard: '<your_abhaCard_color>', // Specific background for the ABHA ID card
    },
    content: {
      primary: '<your_content_primary_color>', // Heading and main text
      secondary: '<your_content_secondary_color>', // Subtext
      muted: '<your_content_muted_color>', // Disabled or placeholder text
      success: '<your_content_success_color>', // Success text
      enabled: '<enabled_button_text_color>', // enabled button text color
    },
    qrCodeColors: {
      fgColor: '<your_qrcode_dot_color>', // Color of the QR code dots
      bgColor: '<your_qrcode_bg_color>', // Background of the QR code
    },
  },
  data: {
    orgIconUrl: 'https://your-domain.com/logo.png',
    // ... rest of your data
  },
  onSuccess: (params) => {
    /* ... */
  },
  onError: (params) => {
    /* ... */
  },
  // ... other methods of initAbhaApp fn
});
```

## Container Styling

Ensure your container has sufficient space:

```html
<div id="sdk_container" style="width: 100%; height: 600px; border: 1px solid #ddd;"></div>
```

## Troubleshooting

### Common Issues

#### 1. SDK Not Rendering

**Problem**: Nothing appears in the container.

**Solution**:

- Ensure containerId matches an existing HTML element.
- Verify the SDK JS and CSS are correctly loaded.
- Check browser console for errors.

#### 2. APIs Not Being Called

**Problem**: API requests are not triggered after the SDK is mounted.

**Solution**:

- Ensure that the accessToken is passed correctly (do not include the Bearer prefix) and that the token has not expired.
- To prevent CORS-related issues, ensure that your domain is whitelisted.

#### 3. Callback Not Triggered

**Problem**: onSuccess, onError, onKYCSuccess, onConsentSuccess, onAbhaClose isn’t firing.

**Solution**:

- Make sure callbacks are passed as valid functions.
- Avoid race conditions (e.g., calling before SDK fully loads).

#### 4. Styling Issues

**Problem**: SDK content appears misaligned or clipped.

**Solution**:

- Give your container a fixed height (e.g., 600px).
- Ensure no parent element uses `overflow: hidden`.

### Common Theming Issues

#### 1. Button Not Visible or Hard to See

**Problem**: A button appears invisible, blends into the background, or is difficult to read.

**Cause**: This typically happens when `primary.brand` and `content.enabled` are too similar (e.g., both set to white or both dark), making the button label invisible against its background.

**Solution**:
- Ensure `primary.brand` (button background) and `content.enabled` (button text) have sufficient contrast.
- A dark `primary.brand` should pair with a light `content.enabled` (e.g., `#ffffff`), and vice versa.

```typescript
theme: {
  primary: {
    brand: ‘#1A237E’,   // Dark button background
  },
  content: {
    enabled: ‘#FFFFFF’, // Light text on button — must contrast with brand
  },
}
```

#### 2. Color Discrepancy — Overrides Not Taking Effect

**Problem**: You passed a theme but some colors still appear as defaults.

**Cause**: Token keys may be misspelled, nested incorrectly, or using the wrong casing.

**Solution**:
- Double-check that your token keys exactly match the structure in [Default Theme Colors](#default-theme-colors). The SDK performs a shallow merge — missing or misnamed keys fall back to defaults silently.
- Verify nesting: tokens like `surface.base` must be passed as `surface: { base: ‘...’ }`, not as a flat key.

```typescript
// ❌ Wrong — flat key, will be ignored
theme: {
  ‘surface.base’: ‘#F9FAFB’,
}

// ✅ Correct — nested object
theme: {
  surface: {
    base: ‘#F9FAFB’,
  },
}
```

#### 3. Success / Error States Look Off

**Problem**: Success alerts, error messages, or validation states are visually inconsistent or unreadable.

**Cause**: Overriding only `semantic.success` without also updating `surface.success` and `content.success` (or vice versa) breaks the foreground/background pairing for state banners.

**Solution**: Always override semantic state colors as a group — the background surface token, the text content token, and the semantic indicator token together.

| State   | Tokens to keep in sync                                          |
| ------- | --------------------------------------------------------------- |
| Success | `semantic.success`, `surface.success`, `content.success`        |
| Error   | `semantic.error`, `surface.danger`                              |
| Warning | `semantic.warning`                                              |

#### 4. ABHA Card Color Not Changing

**Problem**: The ABHA ID card background color is not updating despite passing a theme.

**Solution**: The card background is controlled by `surface.abhaCard`, not `surface.base` or `primary.brand`. Pass it explicitly:

```typescript
theme: {
  surface: {
    abhaCard: ‘#1A237E’, // Override the ABHA card background
  },
}
```

#### 5. QR Code Invisible or Unreadable

**Problem**: The QR code is not scannable or appears blank.

**Cause**: `qrCodeColors.fgColor` and `qrCodeColors.bgColor` may have been set to the same or similar colors.

**Solution**: Maintain high contrast between the QR dot color and background — black on white is the most reliable combination for scanner compatibility.

```typescript
theme: {
  qrCodeColors: {
    fgColor: ‘#000000’, // QR dots — keep dark
    bgColor: ‘#FFFFFF’, // QR background — keep light
  },
}
```


