> ## Documentation Index
> Fetch the complete documentation index at: https://woku.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native SDK

> Capture woku ratings and NPS (text and audio) from your React Native app, with an offline buffer and quarantine-aware delivery

<Info>
  **Available on every plan, including the free one.** woku's official SDKs are enabled for every account. [See the plans](https://woku.app/pricing).
</Info>

The **`@wokuapp/react-native`** SDK lets you capture feedback from your
mobile app: **woku** ratings (1 to 5) and **NPS** (0 to 10), with a text
or audio comment. It includes an **offline buffer** (captures are queued and
retried when there is a connection) and respects the company's **quarantine**
rules.

<Note>
  Beyond native capture, the SDK also lets you **share or embed
  the [woku web widget](/docs/en/integrations/widget-js)** inside your app (for
  example, in a WebView), reusing the same woku/NPS capture experience in
  hybrid channels.
</Note>

## Installation

```bash theme={null}
npm install @wokuapp/react-native
```

`react` and `react-native` are peer dependencies (already present in your app).

## Initialization

Create a `WokuSdk` instance once and reuse it. Pass a **storage**
adapter so the offline queue persists across sessions (AsyncStorage or MMKV
work directly).

```ts theme={null}
import AsyncStorage from '@react-native-async-storage/async-storage';
import { WokuSdk } from '@wokuapp/react-native';

export const woku = new WokuSdk({
  apiUrl: 'https://clientapi.woku.app',
  companyId: 'tu_company_id',
  publicKey: 'tu_public_key', // per-company public capture key
  storage: AsyncStorage,       // persists the offline queue
});
```

| Option | Required | Description |
| - | - | - |
| `apiUrl` | yes | Base URL of the woku API. |
| `companyId` | yes | Company the captures belong to. |
| `publicKey` | yes | Public capture key issued per company. |
| `storage` | recommended | Persistence adapter for the offline queue. |
| `http` | no | HTTP transport; defaults to `fetch`. |
| `logger` | no | Optional logger. |
| `maxQueueAttempts` | no | Retains a failed capture after N attempts for inspection. |

## Capture a woku rating

```ts theme={null}
const result = await woku.captureWoku({
  wokuId: 'woku_123',
  rating: 5, // integer 1..5
  comment: 'Excellent service',
  respondent: { email: 'ana@example.com' }, // optional
});
```

## Capture an NPS

```ts theme={null}
await woku.captureNps({
  npsId: 'nps_1',
  score: 9, // integer 0..10
  comment: 'I would recommend it',
});
```

### Audio comment

Both captures accept an audio attachment instead of (or in addition to) text:

```ts theme={null}
await woku.captureWoku({
  wokuId: 'woku_123',
  rating: 4,
  audio: { uri: 'file:///path/grabacion.m4a', mimeType: 'audio/m4a' },
});
```

### Identify the respondent

Feedback is **anonymous** unless you send an identifier. Any of
these fields is optional:

```ts theme={null}
respondent: {
  email: 'ana@example.com',
  phone: '+56911111111',
  externalId: 'crm_4821', // external id controlled by your app
}
```

## Result of a capture

Each capture returns a `SubmissionResult` with its status:

| `status` | Meaning |
| - | - |
| `sent` | Delivered to the server. |
| `queued` | No connection: left in the queue to retry. |
| `quarantined` | Blocked by a company quarantine rule. |
| `failed` | Failed and retained for inspection. |

## Offline mode

Captures that cannot be sent are **queued** automatically and
retried. You can force delivery and inspect the queue:

```ts theme={null}
await woku.flush();           // tries to send everything pending
const pending = await woku.pendingCount();
await woku.clearQueue();      // discards the queue (with care)
```

A good time to call `flush()` is when the app returns to the
foreground or when connectivity is restored.

## Error handling

The SDK exposes typed error classes to distinguish the causes:

```ts theme={null}
import {
  WokuConfigError,
  WokuValidationError,
  WokuQuarantineError,
  WokuNetworkError,
} from '@wokuapp/react-native';
```

* `WokuValidationError`, invalid data (e.g. `rating` outside 1..5).
* `WokuQuarantineError`, the capture was blocked by quarantine.
* `WokuNetworkError`, network failure (the capture is usually queued).
* `WokuConfigError`, incomplete configuration at initialization.

## Platforms

<Note>
  The **`@wokuapp/react-native`** SDK integrates woku feedback into mobile apps
  and **works on both Android and iOS**. React Native exposes a single API
  in JavaScript/TypeScript and bridges to each platform's native capabilities,
  so the same code runs on both.
</Note>

| Platform | Support | Minimum |
| - | - | - |
| **Android** | Full | API 24 (Android 7.0) |
| **iOS** | Full | iOS 13 |

The SDK does not record audio: for voice comments it receives a file already
recorded by the app (its `uri` and `mimeType`) and sends it as multipart. The
SDK's API is identical on Android and iOS.

## Versioning

The SDK follows **semantic versioning** (`MAJOR.MINOR.PATCH`):

* **MAJOR**, incompatible changes to the SDK's public API.
* **MINOR**, new backward-compatible features.
* **PATCH**, backward-compatible bug fixes.

The current published version is **`0.1.0`**. The versions and their notes
are available online on the
[npm package](https://www.npmjs.com/package/@wokuapp/react-native) and in the
[GitHub releases](https://github.com/wokuApp/sdks/releases). We
recommend pinning a compatible range (for example `^0.1.0`) and reviewing the
changelog before moving up a MAJOR version.

## Changelog

Most recent entries first. The published version covers
**Android and iOS** equally.

### 0.1.0

First published version of the SDK:

* Capture of **woku** ratings (1 to 5) and **NPS** (0 to 10), with a
  text or audio comment.
* Persistent offline queue configurable via the `storage` adapter, with
  `flush()`, `pendingCount()`, `clearQueue()` and `maxQueueAttempts`.
* `respondent.externalId` field to correlate with your own systems.
* Typed errors: `WokuConfigError`, `WokuValidationError`,
  `WokuQuarantineError`, `WokuNetworkError`.
* Delivery aware of the company's **quarantine** rules
  (`quarantined` status).

## Resources

* **npm package:** [@wokuapp/react-native](https://www.npmjs.com/package/@wokuapp/react-native)
* **Code and examples:** [github.com/wokuApp/sdks](https://github.com/wokuApp/sdks)
* **Releases and changelog:** [github.com/wokuApp/sdks/releases](https://github.com/wokuApp/sdks/releases)

## Identified journey responses

```ts theme={null}
await woku.captureCsat({ csatId: prepared.toolId, score: 5,
  respondent: { email: 'ana@example.com' }, dispatchToken: prepared.token });
await woku.captureCes({ cesId: effortToolId, score: 4,
  respondent: { phone: '56911111111' } });
const retained = await woku.failedCaptures();
```

The token belongs to one prepared evaluation. Send it in JSON or multipart, never
in a URL. Authentication uses `x-woku-key` with a publishable `pk_` key; management
keys are rejected. CSAT/CES accept scores from 1 to 5 without audio. Woku/NPS audio
supports `language: 'es' | 'en'`, defaulting to Spanish.

Call `flush()` on reconnect or foreground. Share one persistent storage adapter
and one SDK per company. Reads, sends and clearing are scoped to that company.
Permanent errors, exhausted attempts and captures older than 24h are retained in
`failedCaptures()` for inspection. Device clock determines that window. In-memory
storage does not survive restart. `timeoutMs` bounds a network attempt, default 30s.

`timeoutMs` includes reading the response body. `clearQueue()` prevents an active
flush from starting more removed captures, but cannot recall an in-flight request.
An accepted capture returns `sent` even when its local acknowledgement fails;
its original ID remains queued for reconciliation.

## Capture provenance

Since version `0.3.0`, the SDK accepts `collectionKind?: 'standalone' | 'flow'` and
`flowId?: string` on all four instruments. New captures default to `standalone`.
Inside a Flow send both fields, including single-step and partially answered
Flows; the API validates company and instrument membership.

```ts theme={null}
await woku.captureNps({
  npsId: 'nps_123', score: 2, comment: 'Delivery took too long.',
  collectionKind: 'flow', flowId: 'flow_123',
});
```

The queue preserves body, ID and provenance from the first attempt, in JSON and
Woku/NPS audio, even after restart or screen changes. Old captures without
provenance keep that unknown context; flush does not add fields or change IDs.
Flow responses do not activate follow-up but may create their normal ticket.
An individual Journey instrument stays standalone unless its response comes
from a Flow. This change does not add CSAT/CES audio.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.