---
name: freshdesk-react-native-integration
description: Integrate, debug, verify, and answer questions about the Freshdesk React Native SDK (@freshworks/react-native-freshdesk-sdk) in a host React Native app for Android and iOS. Use for greenfield integration, integration Q&A (knowledge base), diagnostics-driven debugging, FreshdeskSDK.initialize/openSupport/openKnowledgeBase, JWT, push notifications, ContentConfiguration, or any customer question about wiring the SDK.
---

# Freshdesk React Native SDK Integration

This skill teaches an AI agent how to integrate, debug, verify, and **answer integration questions** for the Freshdesk React Native SDK in a host app.

**Three modes:**

- **Mode A — Greenfield integration**: SDK not yet in the app. Follow the phased workflow below.
- **Mode B — Diagnostics-driven debugging**: SDK already integrated. Use `FreshdeskSDK.runDiagnostics()` as source of truth and apply each check's `fixHint`.
- **Mode C — Integration Q&A (knowledge base)**: Customer asks a question about integration (setup, APIs, push, JWT, errors, platform differences). **Read [integration-knowledge-base.md](integration-knowledge-base.md) first**, answer directly from it, and cite [platform-apis.md](platform-apis.md) when platforms differ. Escalate to Mode A (full wiring) or Mode B (diagnostics) only when the question requires it.

> **Consumer apps only.** Do not edit `sdk_src` or files inside `node_modules/@freshworks/react-native-freshdesk-sdk`. Only change the target app's files.

**References:**
- [integration-faq.md](integration-faq.md) — prerequisites, app changes, post-integration checklist
- [integration-knowledge-base.md](integration-knowledge-base.md) — Q&A for any integration question
- [platform-apis.md](platform-apis.md) — Android vs iOS API and native differences
- [examples.md](examples.md) — worked scenarios

## When to use

Apply when integrating, auditing, debugging, or **answering questions about** `@freshworks/react-native-freshdesk-sdk` in a React Native app.

Examples of Mode C questions:
- "How do I open the knowledge base?"
- "Do I need Firebase for chat?"
- "What's the difference between Android and iOS push setup?"
- "Why does openSupport show a spinner?"
- "Where do I put my Freshdesk token?"

Do NOT use for Freshdesk web/dashboard config unrelated to the mobile SDK, generic RN questions with no Freshdesk involvement, or SDK wrapper maintenance.

## Prerequisites

- React Native **0.75.0+**. Backward-compatible with both the New Architecture
  (TurboModule) and the classic bridge — no consumer-facing choice to make;
  `runDiagnostics()` reports which one is active (`architecture: 'old'|'new'`).
  On **React Native 0.79+** (Kotlin 2.1.x toolchain) use wrapper **2.0.1+** —
  earlier builds fail to compile `FreshdeskModule.kt` against RN 0.79's nullable
  `ReadableMap.toHashMap()` (see [troubleshooting.md](troubleshooting.md), Issue 5).
- iOS deployment target **15.0+**. The native SDK ships as a vendored,
  statically-linked `FreshdeskSDK.xcframework` — **no `use_frameworks!`,
  Swift Package Manager, or `FRESHDESK_IOS_USE_VENDORED` env var required**
  (2.0.0+; older 1.4.x used an SPM path that needed those — see
  [troubleshooting.md](troubleshooting.md) if the target app is still on 1.4.x).
- Android `minSdkVersion 26+`. The wrapper reads `compileSdkVersion`/`targetSdkVersion` from your
  app's own root `build.gradle` `ext` block if set; otherwise it falls back to **35**, which
  requires AGP **8.6+**. Apps that set `compileSdkVersion 36` (Android 16) in their own `ext`
  block should use AGP **8.9.1+** (9.x recommended).
- CocoaPods **1.12+** (iOS).
- Freshdesk portal access: **Admin Settings → Mobile Chat SDK**.

---

## Step 0 — Detect mode

1. Search `package.json` for `@freshworks/react-native-freshdesk-sdk`.
2. Search source for `FreshdeskSDK.initialize(` or imports from the package.
3. Classify the user's request:

| Request type | Mode |
|--------------|------|
| Question about integration (how-to, what-if, error meaning, API usage) | **Mode C** → [integration-knowledge-base.md](integration-knowledge-base.md) |
| "Integrate Freshdesk" / greenfield / SDK not in app | **Mode A** → Phase 1 |
| Bug report / something broken / verify existing integration | **Mode B** → Step B1 |
| Question + broken symptom | **Mode C** answer first, then **Mode B** if needed |

If unsure between A and B, ask: "Is the Freshdesk React Native SDK already in your app, or is this a new integration?"

---

## Mode C — Integration Q&A (knowledge base)

**When the customer asks any integration question**, act as a knowledgeable support agent:

1. **Search** [integration-knowledge-base.md](integration-knowledge-base.md) for the topic (credentials, init, push, JWT, APIs, errors, platform differences).
2. **Answer directly** — concise, accurate, with code snippets when they help. Do not start a full greenfield workflow unless they ask to integrate.
3. **Platform-specific?** Cross-check [platform-apis.md](platform-apis.md) and state Android vs iOS differences explicitly.
4. **Symptom / bug?** After answering, suggest `runDiagnostics()` and offer Mode B triage if they share the report.
5. **Full integration requested?** Hand off to Mode A.

### Mode C response format

1. Direct answer to the question (2–5 sentences or a short code block).
2. Related gotchas (platform differences, common mistakes) — only if relevant.
3. Optional: "If you want me to wire this into your app, say so and I'll integrate it."

Never invent credentials. Never paste secrets in chat.

---

## Mode A — Greenfield integration (phased workflow)

### Phase 1 — Interactive setup (host & language)

**Ask the user directly** (do not invent values):

1. **Host** — Freshdesk instance URL from Admin → Mobile Chat SDK. Accepts **either** `yourcompany.freshdesk.com` **or** `https://yourcompany.freshdesk.com` — the SDK auto-prefixes `https://` when omitted.
2. **Language / locale** — BCP-47 code for widget UI (default `en` if unspecified).

Record answers for use in `.env`, `initialize({ locale })`, and native credential files.

Also confirm in one batch:

| Question | Why |
|----------|-----|
| Target platforms (Android, iOS, both)? | Scopes native work |
| Android `applicationId` / iOS bundle id? | Push portal setup |
| Is JWT enforced on the widget? | JWT wiring vs `setUserProperties` |
| Push notifications needed? | Native init mandatory |

### Phase 2 — Secrets via file paths (never paste in chat)

**Do not ask the user to paste token, SDK ID, or JWT in the chat.**

Discover paths in the host app, then tell the user exactly which files to edit:

#### 2a — Create or update `.env` (app root, gitignored)

```bash
FRESHDESK_HOST=<value from Phase 1>
FRESHDESK_LOCALE=<value from Phase 1>
FRESHDESK_TOKEN=          # ← user fills from portal App Keys
FRESHDESK_SDK_ID=         # ← user fills from portal
FRESHDESK_JWT=            # ← user fills if JWT enforced; leave empty otherwise
```

If the app uses `react-native-dotenv` / `@env`, ensure `babel.config.js` includes the plugin and `src/types/env.d.ts` declares the keys.

#### 2b — Android native credentials (required when push is enabled)

Point to `android/app/build.gradle` → `defaultConfig`:

```gradle
buildConfigField "String", "FRESHDESK_TOKEN", "\"...\""
buildConfigField "String", "FRESHDESK_HOST", "\"...\""
buildConfigField "String", "FRESHDESK_SDK_ID", "\"...\""
buildConfigField "String", "FRESHDESK_JWT", "\"...\""
buildConfigField "String", "FRESHDESK_LOCALE", "\"en\""
```

Prefer reading from `.env` via a helper (see SDK sample app `freshdeskEnvValue()`).

#### 2c — iOS native credentials (required when push is enabled)

Point to `ios/<AppName>/Info.plist`:

```xml
<key>FreshdeskHost</key><string>...</string>
<key>FreshdeskLocale</key><string>en</string>
<key>FreshdeskToken</key><string>...</string>
<key>FreshdeskSdkId</key><string>...</string>
<key>FreshdeskJwt</key><string>...</string>  <!-- if JWT enforced -->
```

**Stop and wait** until the user confirms credentials are filled. Do not proceed with init testing while placeholders remain.

### Phase 3 — Install package

```bash
npm install @freshworks/react-native-freshdesk-sdk
```

Autolinking handles native linking (RN 0.60+).

### Phase 4 — Integration inventory (existing code vs agent creates)

For **each area below**, ask: **"Do you already have code for this in your app?"**

- **Yes** → show the exposed API(s), inspect their file(s), wire SDK calls into their existing code.
- **No** → agent implements the integration from scratch (minimal, idiomatic to their app structure).

Process areas in this order:

#### 4.1 SDK initialization

**API:**

```typescript
await FreshdeskSDK.initialize({
  token, host, sdkId,
  locale: FRESHDESK_LOCALE || 'en',
  jwt: FRESHDESK_JWT,      // JWT-enforced only
  debugMode: __DEV__,      // Android Logcat only
});
```

**If no existing code:** create a `FreshdeskProvider` (or init in root `App.tsx` / `useEffect`) that:
- Reads credentials from `@env` or config module.
- Calls `initialize()` once on mount.
- Sets `isInitialized` state; guards all SDK calls until true.
- On failure: log error, do not silently continue.

**If existing code:** merge init params (host, locale from Phase 1); ensure single init, awaited before other calls.

#### 4.2 Support entry points

**APIs:**

| Method | Purpose |
|--------|---------|
| `openSupport()` | Support home / chat |
| `openKnowledgeBase()` | FAQ / KB directly |
| `openTopic({ topicName, topicId? })` | Specific topic |

**If no existing code:** add a support button (settings, profile, or tab) calling `openSupport()` with try/catch and init guard.

**If existing code:** connect their button/navigation handler to the appropriate API.

#### 4.3 User identity

**JWT enforced** (from Phase 1):

| API | When |
|-----|------|
| `initialize({ jwt })` | At startup |
| `authenticateAndUpdate(jwt)` | After token refresh |
| `addUserStateListener(cb)` | Handle `authExpired`, `notAuthenticated` |
| `resetUser()` | On logout |

Do **not** call `setUserProperties` for identity when JWT is enforced.

**Non-JWT:**

| API | When |
|-----|------|
| `setUserProperties({ name, email, phone, ... })` | After login |
| `resetUser()` | On logout |

**If no existing code:** add listener in provider; hook login/logout flows if auth exists in app.

#### 4.4 Push notifications (native — per platform)

**No JS push API.** Ask if they have existing FCM/APNs wiring.

**If yes:** integrate Freshdesk into their existing `FirebaseMessagingService` (Android) and `AppDelegate` push handlers (iOS). See [platform-apis.md](platform-apis.md).

**If no:** create native wiring mirroring SDK sample app:

| Platform | Files to create/modify |
|----------|------------------------|
| Android | `FreshdeskMessagingService.kt` (headless init), `AndroidManifest.xml`, `google-services.json`, `build.gradle` |
| iOS | `AppDelegate.mm`/`.swift`, `FreshdeskPush.swift` (if needed), `Info.plist`, Xcode Push + Background Modes |

> **Critical (Android):** Do **not** call native `FreshdeskSDK.initialize()` in `MainApplication.onCreate()` — it conflicts with JS init and breaks `openSupport()`. Use JS init for in-app support; native init **only** inside `FirebaseMessagingService` for headless push.

Android headless init (inside `FreshdeskMessagingService`, via `FreshdeskInitializer` pattern — not `MainApplication`):

```kotlin
FreshdeskInitializer.ensureInitializedBlocking(applicationContext)
FreshdeskSDK.handleFCMNotification(data)
```

iOS native init (in `AppDelegate` early, before RN bridge):

```objc
[FreshdeskNativeModuleBridge initializeSDKWithToken:... host:... sdkId:... locale:... jwt:...];
```

Forward tokens and handle all three iOS notification delivery paths.

#### 4.5 Content configuration & localization

**API:**

```typescript
await FreshdeskSDK.setContentConfiguration({
  headers: { chat: '...', faq: '...' },
  placeholders: { replyField: '...', searchField: '...' },
  actions: { tabChat: '...' },
  privacyPolicySetting: { ... },
});
```

Pass `{}` to reset to widget defaults.

**If no existing code:** call after successful init with strings matching Phase 1 locale if custom copy is needed.

#### 4.6 Event listeners

| API | Platform | Purpose |
|-----|----------|---------|
| `addUnreadCountListener(cb)` | Both | Badge / tab count |
| `addUserStateListener(cb)` | Both | JWT auth state |
| `addUserCreatedListener(cb)` | **iOS only** | New anonymous user |
| `setLinkHandler(cb)` | Both | Custom in-widget URLs |

**If no existing code:** register in provider; `.remove()` on unmount; call `removeAllListeners()` in cleanup.

#### 4.7 Analytics (optional)

**API:** `trackEvent(name, properties?)`

Wire only if user requests or already has analytics hooks.

### Phase 5 — Platform native baseline

Apply even when push is disabled:

**Android (all apps):**
- `mavenCentral()` in repositories.
- `minSdkVersion 26`. Set `compileSdkVersion`/`targetSdkVersion` explicitly in the app's own `ext`
  block — the wrapper falls back to **35** (AGP 8.6+) if unset, so apps targeting **36**
  (Android 16) should set it explicitly and use AGP **8.9.1+**.
- JDK 17–21 for Gradle.
- Apply `android/freshdesk-consumer.gradle` from the npm package (Kotlin metadata fix — see [troubleshooting.md](troubleshooting.md)).
- Set `kotlinOptions { freeCompilerArgs += ["-Xskip-metadata-version-check"] }` on the app module.
- RN 0.79+ (Kotlin 2.1.x): keep the wrapper at **2.0.1+**. Older wrapper builds do not compile
  against RN 0.79's nullable `ReadableMap.toHashMap()` ([troubleshooting.md](troubleshooting.md), Issue 5).

**iOS (all apps, 2.0.0+):**

Nothing Freshdesk-specific to add beyond the deployment target — the native SDK
is a vendored static xcframework, so it does not force `use_frameworks!` and
needs no `post_install` hook of its own:

```ruby
platform :ios, '15.0'
```

```bash
cd ios && pod install
```

Keep `use_frameworks!` only if some *other* dependency in the app needs it —
prefer `:linkage => :static` if so. If the target app's `package.json` still
pins `@freshworks/react-native-freshdesk-sdk@~1.4.x`, it needs the older SPM
path instead — see [troubleshooting.md](troubleshooting.md).

### Phase 6 — Verify initialization & debug failures

**Mandatory before declaring success:**

1. Build and run each targeted platform.
2. Confirm init completes (no `FRESHDESK_INVALID_CONFIG` / `FRESHDESK_INIT_ERROR` in logs).
3. Open support entry point once.
4. Run diagnostics:

```typescript
await FreshdeskSDK.enableDebugLogs(true);
const report = await FreshdeskSDK.runDiagnostics();
console.log(report.prettyPrinted);
```

5. Triage any non-`pass` check — apply `fixHint` verbatim (hand off to Mode B).
6. Confirm `runtime.sdkInitialized: pass`.
7. **Output the Integration Summary** and link [integration-faq.md](integration-faq.md) (see Output format).

**Android extra signal:** `debugMode: true` in `initialize()` + Logcat tag `Freshdesk`.

**iOS extra signal:** full native report with masked secrets — safe to share.

**iOS `initialize()` normally takes ≥2 seconds — this is expected, not a bug.**
The native SDK has no readiness signal of its own, so the wrapper holds
`initialize()`'s promise until a fixed settle delay has passed (see
[platform-apis.md](platform-apis.md)). Do not "fix" a 2+ second `initialize()`
call on iOS; do flag it as a real bug if `openSupport()`/`trackEvent()`/
`setUserProperties()` fail or no-op **after** `initialize()` has resolved —
that combination means either an SDK version without this fix (check
`CHANGELOG.md` for the "iOS `initialize()` settle delay" entry), or a
genuine credentials/network problem worth diagnostics.

Do not declare integration complete until diagnostics and the user's symptom both confirm success.

---

## Mode B — Diagnostics-driven debugging

### Step B1 — Run diagnostics first

```typescript
await FreshdeskSDK.enableDebugLogs(true);
const report = await FreshdeskSDK.runDiagnostics();
console.log(report.prettyPrinted);
```

Do not change code without a diagnostic signal.

Each check: `id`, `status` (`pass|warn|fail|skipped`), `details`, `fixHint`.

### Step B2 — Triage (priority order)

1. `fail` — fix first.
2. `warn` — likely symptom cause.
3. `skipped` — informational (Android `runtime.diagnostics` until native parity).

| Check / symptom | Action |
|-----------------|--------|
| `config.token` empty | User must fill `.env` / native files (Phase 2) |
| `network.configEndpoint` 401/403/404 | Wrong token, host, or sdkId |
| `config.hostScheme` warn (Android) | Bare domain — auto-normalized on 1.2.2+; prefer `https://` in `.env` |
| `runtime.doubleInit` warn (Android) | Remove `MainApplication.onCreate()` native init; use JS init |
| `runtime.sdkInitialized` fail | Ensure `initialize()` awaited before other calls |
| `runtime.nativeModule` fail | `pod install`, Gradle clean, rebuild native app |
| `push.sdkToken` not set (iOS) | Native init + APNs forwarding |
| `push.messagingService` warn (Android) | Register FCM messaging service |
| Init throws `FRESHDESK_INVALID_CONFIG` | Empty token/host/sdkId in env wiring |
| iOS: `openSupport()`/`trackEvent()`/`setUserProperties()` silently no-op or fail right after `initialize()` resolves | Confirm the SDK version includes the `initialize()` settle-delay fix (see `CHANGELOG.md` / [platform-apis.md](platform-apis.md)). On a version without it, add a short delay after `initialize()` resolves before the first other call, or upgrade. |

Always cite exact `fixHint` from the report.

### Step B3 — JWT troubleshooting

If `jwt.*` fails or `UserState` not `authenticated`/`identifierUpdated`:

1. Check `remoteConfig.jwtEnforced` in iOS report.
2. Pass `jwt` at init; refresh with `authenticateAndUpdate(jwt)`.
3. `addUserStateListener` for `authExpired`.
4. Verify server signing key matches widget encryption key.

Reference: https://support.freshdesk.com/en/support/solutions/articles/50000011580-enable-jwt-authentication

### Step B4 — Validate fix

Re-run diagnostics after each change. Confirm previously failing checks are `pass` and symptom resolved.

---

## Output format

### Mode C must include

1. Direct answer sourced from [integration-knowledge-base.md](integration-knowledge-base.md) or [integration-faq.md](integration-faq.md).
2. Platform callouts when Android and iOS differ.
3. Code snippet only when it clarifies the answer.
4. Diagnostics suggestion if the question implies a failure.
5. For "what do I need before integrating?" questions → point to [integration-faq.md](integration-faq.md) **Before you integrate** section.

### Mode A must include

1. Mode confirmation (greenfield).
2. Host + locale collected; credential file paths listed with placeholders for token/sdkId/jwt.
3. Integration inventory results (existing vs created per area).
4. **Integration Summary** — mandatory section at the end (see template below).
5. Link to **[integration-faq.md](integration-faq.md)** for post-integration checklist and common questions.
6. Diagnostics hand-off: build, run, open support, share report.

#### Integration Summary template (required output)

After all code changes, output this section so the customer knows exactly what changed:

```markdown
## Freshdesk integration summary

### Credentials — you update manually
- List each file path (`.env`, `build.gradle`, `Info.plist`) and which keys need portal values

### Files changed
| Area | File | What changed |
|------|------|--------------|
| npm | package.json | Added @freshworks/react-native-freshdesk-sdk |
| JS | ... | Init provider, support button, listeners |
| Android | ... | (list each file or "none") |
| iOS | ... | (list each file or "none") |
| Push | ... | (if applicable) |
| JWT | ... | (if applicable) |

### APIs wired
- List each FreshdeskSDK method integrated (initialize, openSupport, listeners, push, JWT, etc.)

### Manual steps for you
1. Fill credentials in listed files
2. pod install / rebuild commands
3. Test: open support, run diagnostics

### Docs & FAQ
- [Integration FAQ](ai/skills/freshdesk-react-native-integration/integration-faq.md) — prerequisites, what changed, post-integration checklist
- [Knowledge base](ai/skills/freshdesk-react-native-integration/integration-knowledge-base.md) — answer any follow-up questions
- [Platform APIs](ai/skills/freshdesk-react-native-integration/platform-apis.md) — Android vs iOS differences
```

Populate every row with **actual files touched** in the host app — do not leave generic placeholders.

### Mode B must include

1. `overallStatus` + first non-pass check (`id`, `details`, `fixHint`).
2. Minimal fix per check using `fixHint` verbatim.
3. Re-run diagnostics verification step.
4. If files were modified: brief **Integration Summary** (files changed + what was fixed) and link [integration-faq.md](integration-faq.md).

Never invent token, host, sdkId, or JWT. Never ask users to paste secrets in chat.

---

## Reference links

- [integration-faq.md](integration-faq.md) — prerequisites, what changes in your app, post-integration checklist
- [integration-knowledge-base.md](integration-knowledge-base.md) — Q&A knowledge base for any integration question
- [platform-apis.md](platform-apis.md) — Android vs iOS differences
- [troubleshooting.md](troubleshooting.md) — Kotlin metadata mismatch, iOS FreshdeskSDK embed, common build/launch fixes
- [examples.md](examples.md) — worked scenarios
- `PLATFORM_DIFFERENCES.md` (ships in the npm package root) — every method whose
  runtime behavior, not just error surface, differs by platform: `resetUser()`,
  `enableDebugLogs()`, `getUnreadCount()`, `trackEvent()`, and the iOS
  `initialize()` settle delay.
- Installation: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/installation.md
- Initialization: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/initialization.md
- API reference: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/api_reference.md
- Troubleshooting: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/troubleshooting.md

## Do not

- Do not edit `sdk_src` or `node_modules/@freshworks/react-native-freshdesk-sdk` in consumer apps.
- Do not commit `.env`, `google-services.json`, APNs keys, or real credentials.
- Do not use JS-only init for push.
- Do not set iOS deployment target below `15.0` or Android `minSdkVersion` below `26`.
- Do not invent credentials or paste secrets into chat.
