# React Native SDK API

> Functions, options, parameters, promises, and native behavior for the Anectico React Native SDK.

Canonical page: https://anectico.com/docs/reference/react-native-sdk/


`@anectico/react-native` is a Promise-based JavaScript bridge over the native iOS and Android SDKs. The
native layer owns identity, sessions, persistence, network delivery, and native crash handlers; the
JavaScript layer adds Hermes/JSC error parsing and global JavaScript error capture.

Use a project key with `ingest:write` and `analytics:write`. React Native replay is not supported.

## Configure and shut down

```typescript
import * as Anectico from '@anectico/react-native';

await Anectico.configure({
  apiKey: 'an_...',
  environment: 'production',
  release: '1.4.0',
  dist: '42',
});
```

| Function | Parameters | Returns | Behavior |
| --- | --- | --- | --- |
| `configure(options)` | `AnecticoOptions` | `Promise<void>` | Configures native SDK state and installs JS error/rejection handlers unless disabled. Rejects invalid native options; native configuration is idempotent. |
| `flush()` | — | `Promise<boolean>` | Flushes the native diagnostic-event queue and resolves whether every batch it attempted was accepted. See [Knowing whether your events arrived](#knowing-whether-your-events-arrived). |
| `shutdown()` | — | `Promise<boolean>` | Removes JS/native hooks, flushes, and releases background resources. Resolves the final flush's outcome, like `flush()`. |
| `configure(options, { resumeAnalyticsCollection: true })` | Explicit new consent after awaited shutdown | `Promise<void>` | Purges all old analytics queue data before reopening collection; failures reject configuration. |
| `disableAnalytics()` | — | `Promise<boolean>` | Persist analytics withdrawal and purge queued data; await the result before relying on the native gate. |
| `stats()` | — | `Promise<AnalyticsStats>` | Delivery counters — `recorded`, `delivered`, `dropped`, `queued`. |
| `bridgeStats()` | — | `{ recorded, dropped }` | Narrower: product events passed through the bridge, and how many of them the bridge itself discarded. |
| `onDeliveryError(handler)` | handler or `null` | `void` | Registers a handler called with `{ status, dropped, reason }` once per permanently discarded batch. |
| `installGlobalErrorCapture()` | — | `void` | Idempotently installs JS global error and unhandled-rejection capture. Normally called by `configure`. |

Configuration rejects when the native module is unavailable. Other bridge calls resolve safe defaults
rather than crashing the application. Rebuild the native application after installing the package;
Metro reload cannot add a native module.

When the native module is missing, every product event is discarded on the spot — there is nothing to
deliver it to. That is counted and reported rather than silently resolving: `bridgeStats().dropped`
rises, any handler registered through `onDeliveryError` is called with `reason:
"native_module_unlinked"` and `status: 0`, and a `console.warn` names the count. In that state
`flush()` and `shutdown()` resolve `false` and `stats()` reports what the bridge saw — nothing was
delivered, so nothing is reported as accepted. A handler that throws is swallowed and never reaches
your `capture()` call.

## Withdrawing analytics consent

Await `Anectico.disableAnalytics()` when analytics consent is withdrawn. The native SDK closes analytics admission,
including capture, identify, group, reset, and lifecycle events, and discards pending events without
flushing them. Errors, crashes, agent traces, and OTLP logs have separate controls and continue.
An already-admitted request can still reach the server: validated receipt outcomes remain credited;
uncertain retries and unsent remainder are discarded with `collection_disabled` and status `0`.
This does not erase previously accepted data. `recorded = delivered + dropped + queued` remains true.

A `true` result confirms both the persistent withdrawal marker and deletion of the analytics spool.
On `false`, this configured client stays disabled, but persistence/purge needs retry; do not assume
restart safety until a retry succeeds. Await the promise before relying on the native admission fence. A missing native module returns `false`.
Ordinary configuration preserves the marker across restart. Only after obtaining new consent,
await `Anectico.shutdown()`, then call `await Anectico.configure(options, { resumeAnalyticsCollection: true })`.
Explicit renewal purges all old analytics queue data even when the marker is absent; a purge failure
fails configuration. Repeated configuration of an already configured SDK does not renew consent.
Wait for shutdown completion before reconfiguring; configuration during retirement fails.

## Knowing whether your events arrived

`flush` returns `true` only when every attempted product-event position has a validated
`queued` acknowledgement. An empty queue succeeds. This is evidence of queue acceptance;
it does not prove query visibility, unique stored rows, or identity application.
Errors and crash reports use a separate pipeline.

A complete version-one receipt classifies each original position before the SDK updates
its queue or counters:

| Receipt outcome | Your events | `flush` | Queue and callback |
| --- | --- | --- | --- |
| `queued` | removed from the pending queue | succeeds if all positions were queued | increments `delivered` |
| `rejected` | refused positions are discarded | failure | increments `dropped`; fires a drop callback |
| `unknown`, malformed, truncated, oversized, or absent receipt | uncertain positions remain pending | failure | retains original message IDs; no drop callback |

Typed permanent request failures also discard the attempted batch. Network failures,
rate limits, and dependency failures retain it. Repeated uncertainty backs off from one
second to 60 seconds; a fully settled receipt resets that delay. Server retry hints are
clamped to that range.

`stats()` reports `recorded`, `delivered`, `dropped`, and `queued`; `recorded` equals
the other three added together. `delivered` counts validated queue acknowledgements,
not unique stored events.

`onDeliveryError(handler)` reports the number of discarded events once per affected chunk. A batch
receipt can refuse events with HTTP `200`: `invalid_event`, `quota_exceeded`, or
`mixed_rejection`. Typed request failures use `bad_request`, `unauthorized`, `forbidden`,
`not_found`, `payload_too_large`, `unprocessable`, or `rejected`. Local `queue_overflow`
and `not_serializable` drops carry status `0`. Unknown outcomes remain queued without a callback unless explicitly discarded on withdrawal with `collection_disabled`. The handler also receives `native_module_unlinked` drops when the native module is missing. A throwing handler is swallowed.

Capturing stays non-blocking: `capture`, `identify`, `group`, and `screen` queue the event and return
immediately, so the delivery outcome reaches you through the three signals above and never through
their own return value.

```ts
Anectico.onDeliveryError((error) => {
  console.warn(`lost ${error.dropped} events: ${error.reason} (HTTP ${error.status})`);
});

if (!(await Anectico.flush())) {
  const stats = await Anectico.stats();
  // stats.queued > 0 means a retry is pending; otherwise the events are gone.
}
```

## `AnecticoOptions`

Only `apiKey` is required. Native defaults match the iOS/Android contract.
Invalid endpoints, timers, capacities, frame limits, and non-finite or out-of-range sampling values
reject the configuration promise instead of being clamped.

| Option | Type/default | Purpose |
| --- | --- | --- |
| `apiKey` | `string`; required | Error/event API key. |
| `endpoint` | `string`; `https://api.anectico.com` | Native API base URL. |
| `environment` | `string`; `development` | Deployment environment. |
| `release`, `dist` | optional strings | Release and artifact identifiers. |
| `serviceName`, `serviceVersion` | optional strings | Native resource identity; defaults from the app. |
| `flushAt` | `number`; `20` | Event-count flush threshold. |
| `flushIntervalMs` | `number`; `5000` | Foreground-only native periodic flush; zero disables it. |
| `maxStackTraceFrames` | `number`; `50` | Native and JS frame cap. |
| `breadcrumbCapacity` | `number`; `100` | Native ring-buffer capacity. |
| `maxQueueSize` | `number`; `10000` | Native event queue cap. |
| `errorSampleRate` | `number`; `1` | Non-fatal error sampling from 0–1. |
| `enableCrashReporting` | `boolean`; `true` | Install native crash handlers. |
| `debug` | `boolean`; `false` | Native diagnostic logging. |
| `enableJsErrorCapture` | `boolean`; `true` | JavaScript-only global error/rejection handlers. |

## Identity, accounts, and events

| Function | Parameters | Returns | Behavior |
| --- | --- | --- | --- |
| `identify(distinctId, set?)` | stable ID; person properties | `Promise<void>` | Links anonymous and known identity and queues identify. |
| `group(type, key, set?)` | account type/key; properties | `Promise<void>` | Records membership and `$groupidentify`. |
| `capture(event, properties?)` | event; properties | `Promise<void>` | Queues a diagnostic event in native storage, natively stamped with the reserved `$release`/`$app_version` properties (see [Reserved event properties](/docs/investigate/event-schema#reserved-properties)) when `configure()` set `release`/`serviceVersion`. |
| `screen(name, properties?)` | screen; properties | `Promise<void>` | Queues `$screen` with `$screen_name`. |
| `reset()` | — | `Promise<void>` | Logout: rotates native identity/session and clears groups. |
| `getDistinctId()` | — | `Promise<string>` | Current identity, or `""` without native configuration. |
| `getSessionId()` | — | `Promise<string>` | Current session without extending its idle window, or `""`. |

## Errors, messages, users, and breadcrumbs

| Function | Parameters | Returns | Behavior |
| --- | --- | --- | --- |
| `captureError(error, options?)` | `unknown`; `CaptureOptions` | `Promise<string>` | Normalizes the value, parses Hermes/JSC frames, attaches the SDK-owned `rn.captureError` mechanism, and returns the native error ID. |
| `captureMessage(message, level?, options?)` | text; `ErrorLevel`; options | `Promise<string>` | Captures a message; `error`/`fatal` receive error status. |
| `addBreadcrumb(crumb)` | `Breadcrumb` | `Promise<void>` | Adds native trail context for the next error. |
| `setUser(user)` | `AnecticoUser` | `Promise<void>` | Sets native global error user context. |
| `clearUser()` | — | `Promise<void>` | Clears that error user context. |

`CaptureOptions` currently transmits `tags` and `level`. Per-capture `extra`, user, and fingerprint
are not supported by this bridge; use `setUser` for user context. `ErrorLevel` is `debug`, `info`,
`warning`, `error`, or `fatal`. A `Breadcrumb` contains `category`, `message`, optional level, and
optional `data`. `AnecticoUser` contains `id`, `email`, `username`, `ipAddress`, and `segment`.

The native transport adds SDK-owned app/build, OS, and privacy-safe hardware-model context. It does
not collect stable device identifiers or user-assigned device names.

Global handlers preserve and chain previous React Native handlers. On iOS and Android, every
JavaScript error has SDK-owned level, handled state, and mechanism: fatal errors are `fatal` /
unhandled, other errors are `error` / handled, and the mechanism is `rn.captureError` for explicit
captures, `rn.globalHandler` for uncaught errors, or `rn.unhandledRejection` for rejected promises.
Application tags cannot override those classification fields. A fatal JavaScript error bypasses
client sampling. For fatal global errors only, the bridge durably captures JavaScript frames through
a blocking native method before chaining React Native's previous handler. A five-second, one-shot
native handoff suppresses only RN's matching wrapper report; it does not suppress genuine native
crashes. Missing, throwing, or unsuccessful synchronous capture falls back to the asynchronous path
with native fallback reporting left active.

## Agent runs

`startAgentRun(options: AgentRunOptions): AgentRun` is synchronous. It copies the options and
records a start timestamp; the native bridge attaches current identity when the run ends.

```typescript
import * as Anectico from '@anectico/react-native';

const run = Anectico.startAgentRun({
  agent: 'checkout-helper',
  agentId: 'checkout',
  agentVersion: '1.4.0',
  conversationId: 'chat-42',
});
// Perform the agent's work, then declare its actual outcome.
const accepted = await run.end('completed');
// On failure instead: await run.end('failed', 'tool_failed');
```

`AgentRunOptions.agent` is required. `agentId`, `agentVersion`, and `conversationId` are optional strings mapping to
`gen_ai.agent.id`, `gen_ai.agent.version`, and `gen_ai.conversation.id`. The agent name maps to
`gen_ai.agent.name`. Configure and identify the customer before starting a run. A terminal record
is an `invoke_agent` span sent with `ingest:write`; it does not require an agent-read or agent-write
management scope. It is not automatic instrumentation of nested model/tool calls.

`end(status?: AgentRunTerminalStatus, terminalReason?: string): Promise<boolean>` defaults to
`completed` and accepts `completed`, `failed`, `timed_out`, `cancelled`, and `max_steps`.

Use a stable, non-sensitive reason code, not an exception message, prompt, or customer value.
Reasons are trimmed, lowercased, and must match `^[a-z][a-z0-9_]{0,63}$`. Omitted reasons default to
`timeout` for a timeout, `user_cancelled` for cancellation, and the wire status for other outcomes.
These are source-declared outcomes; Anectico does not infer success from the absence of an error.

An invalid status or reason rejects the promise and leaves the handle open. A native `false`
result or rejection also leaves it open for retry. Concurrent valid end calls share the in-flight
promise; after one is accepted, later valid calls resolve `true` without emitting again. A `true`
result is native acceptance, not confirmed network delivery. Finish the run before resetting or
switching customer identity.

## Backend propagation

`propagationHeaders(): Promise<Record<string,string>>` creates a fresh W3C `traceparent` and current
identity baggage. Add the returned headers only to a trusted, instrumented application backend.
They are correlation metadata, not proof of authentication.

## Exported stack types

`StackFrame` is the bridge wire shape: `filename`, `function`, `lineno`, `colno`, and `in_app`. Stack
normalization/parsing is internal to `captureError`; applications should not construct raw bridge
errors.

- [Install and use React Native](/docs/instrument/react-native)
- [Mobile SDK behavior](/docs/instrument/mobile)
- [Capture errors and releases](/docs/instrument/errors)

## Native capture receipt migration

Both bundled native sources now validate complete version-one indexed capture acknowledgements.
Mixed receipts retire queued and refused positions while retaining uncertain original events in
their durable spools. Malformed or incomplete responses remain uncertain. Ledger refusals can carry
HTTP 200 with `invalid_event`, `quota_exceeded`, or `mixed_rejection`; those codes cross this bridge.
Without a hint, native retry delay doubles from one second to a 60-second cap until a receipt
fully settles. Retry-After is clamped to 1–60 seconds. Published-package, device and backend qualification remains open; this is not a completed release.
