---
title: "Flutter SDK reference"
description: "Dart lifecycle, reactive feature state, event streams, and typed operation results."
sidebar:
  label: "Flutter"
search:
  tags: ["sdk", "reference", "flutter"]
  keywords: ["Dart", "Flutter", "configure", "identify", "consumeFeature", "App Action"]
---

The Flutter SDK provides a Dart client, feature listeners, and activity streams. [Configure the SDK](/docs/sdks/flutter) before making calls through `Nuxie.instance`.

<span id="interfaces-and-contracts" />

## Configuration and lifecycle

`Nuxie.instance` implements `NuxieClient`. Pass the interface into application services or widgets so tests can supply a fake client.

| Configuration | Default | Description |
| --- | --- | --- |
| `apiKeys` | Required | `NuxieApiKeys(ios: ..., android: ...)`. |
| `environment` | `NuxieEnvironment.production` | Production or development service. |
| `logLevel` | `NuxieLogLevel.warning` | `debug`, `info`, `warning`, `error`, or `none`. |
| `localeIdentifier` | `null` | Follow the device locale, or provide an override. |
| `billing` | `NuxieBilling.native()` | Native billing or an external controller. |

Use the public `pk_test_` key for preview content and the `pk_live_` key for live content. Keep the default service environment for both. The development environment selects a separate Nuxie service; it does not select test mode for your app.

Equivalent concurrent `configure()` calls share setup. A different configuration requires `await shutdown()` first. `isConfigured` becomes true after setup completes; `versions` exposes the wrapper, native version, and bridge contract.

## Identify a customer

```dart
import 'package:nuxie_flutter/nuxie_flutter.dart';

final nuxie = Nuxie.instance;
await nuxie.identify('customer_123', userProperties: {'plan': 'pro'});
```

`getDistinctId()` and `getAnonymousId()` return the current IDs. Call `reset()` when the customer signs out; the anonymous ID rotates by default.

`identify()` also accepts `userPropertiesSetOnce` for values that should be set only when missing. Use `getIsIdentified()` to distinguish a known customer from an anonymous one. `reset(keepAnonymousId: true)` explicitly preserves the anonymous ID.

`setLocaleIdentifier('fr_FR')` changes the locale used at the next profile synchronization. Pass `null` to restore the device locale.

## Trigger an Experience

```dart
await nuxie.trigger('upgrade_requested', properties: {'source': 'settings'});
```

The Future completes after native invocation. Whether an Experience appears depends on its published delivery rules. Call `dismiss()` to close the current presentation.

## Read feature access

`nuxie.features` is a `ValueListenable<NuxieFeatureSnapshot>`. `NuxieFeatureBuilder` rebuilds a widget when its selected feature changes. Read the state as well as the access value: `unknown` means access is still loading.

To query access directly:

```dart
final access = await nuxie.hasFeature('premium-export');
if (access.allowed) {
  // Enable premium export.
}
```

The default policy uses fresh cached access. Pass `policy: FeatureCheckPolicy.remote` for a server query. `requiredBalance` and `entityId` select the amount and entity to check.

For example, render a selected feature with the same client used to configure the SDK:

```dart
NuxieFeatureBuilder(
  client: Nuxie.instance,
  featureId: 'premium-export',
  builder: (context, access, state) {
    if (state == FeatureState.unknown) {
      return const CircularProgressIndicator();
    }
    return Text(access?.allowed == true ? 'Export available' : 'Upgrade to export');
  },
)
```

Import Flutter's Material widgets for this example. The builder requires `client`, `featureId`, and `builder`; it manages its feature listener with the widget lifecycle.

### Feature state

A snapshot contains `state`, `all`, `identityGeneration`, and `revision`. `state` is `unknown` while loading, `reconciling` while purchase access is being synchronized, or `ready`. A ready snapshot may be empty.

Each `FeatureAccess` has `allowed`, `unlimited`, nullable `balance`, and `type`. Missing access is distinct from a zero balance. `NuxieFeatureBuilder` passes `(context, access, state)` to its builder and does not fetch or consume usage.

Entity queries use grants assigned to that entity and do not replace the global snapshot. A failed query throws; a successful query can return `allowed: false`.

## Consume usage

```dart
final receipt = await nuxie.consumeFeature(
  'credits',
  quantity: 5,
  operationId: 'generation_123',
);

if (receipt.accepted) {
  // Start the generation once.
}
```

Keep the operation ID with the action and reuse it for retries. A remaining balance of zero can accompany an accepted final use. A network error does not prove the deduction was cancelled.

### Consumption and usage results

`FeatureConsumptionResult` contains `operationId`, `customerId`, `featureId`, nullable `occurredAtMs`, `accepted`, `code`, `quantity`, `balance`, `unlimited`, `active`, and `idempotentReplay`. Match a returned receipt to the customer and saved action before applying its effect.

Quantities must be positive whole units up to 9,007,199,254,740,991. For shared credits, query and consume the credit feature's key using the action's credit cost.

### Usage reporting

| Method | Behavior |
| --- | --- |
| `useFeature(id, amount: 1, entityId:, metadata:)` | Enqueues usage without waiting for server confirmation. |
| `useFeatureAndWait(id, amount: 1, entityId:, setUsage: false, metadata:)` | Waits for `FeatureUsageResult`; inspect `success`. |

`FeatureUsageResult` includes `featureId`, `amountUsed`, optional `message`, optional `usage`, and optional `authoritativeAccess`. Use `consumeFeature()` when your app needs to retain an explicit operation ID across retries.

With `setUsage: true`, the amount is a cumulative total: reporting 20 then 25 charges 20 then 5. A lower later total does not restore credits. Use one reporting method per action so it is not charged twice.

## Activity and App Actions

```dart
final subscription = nuxie.appActions.listen((action) {
  // Handle action.name and action.payload.
});
```

Use `appActions` to connect an Experience to your Flutter app, such as opening the library after onboarding. `activities` reports what happened in Nuxie for analytics and UI updates. Both are live broadcast streams. Subscribe before the operation you want to observe and cancel the subscription when finished. They do not replay past events.

An activity contains `schemaVersion`, `id`, `name`, UTC `timestamp`, `receivedAt`, and immutable `properties`. An App Action contains its `name`, optional `payload`, and Experience reference. Validate action data before performing app-specific work.

## Restore purchases

`restorePurchases()` returns a `RestoreResult`: `restored`, `noPurchases`, or `failed`. Purchases use the configured native billing integration or your external `NuxiePurchaseController`.

### External checkout

Set `billing: NuxieBilling.external(controller)` before configuration. The controller implements `Future<PurchaseResult> purchase(NuxieStoreProduct product)` and `Future<RestoreResult> restorePurchases()`.

Return `PurchaseResult.purchased()`, `.cancelled()`, `.pending()`, or `.failed(message)`. Restore returns `RestoreResult.restored()`, `.noPurchases()`, or `.failed(message)`.

The supplied product includes the selected store identifiers, offer, placement, price fields, and platform-specific billing terms. Preserve these when opening provider checkout. Available fields vary by platform; do not substitute a different offer when a term is absent or unsupported. Return a failure instead.

For native billing where your app finishes transactions, use `NuxieBilling.native(handling: PurchaseHandlingMode.observer)`.

### Product fields

`NuxieStoreProduct` contains:

| Fields | Description |
| --- | --- |
| `platform`, `productId`, `storeProductId` | Platform and product identity. |
| `basePlanId`, `purchaseOptionId`, `offerId`, `placementId` | Optional identifiers for the selected placement and store offer. |
| `displayName`, `description`, `displayPrice`, `productType` | Product display information, when available. |
| `period`, `periodCount`, `billingPlan` | Optional subscription terms. |
| `eligibilityJws`, `introductoryTerms` | Optional introductory offer eligibility and terms. |

`NuxieIntroductoryTerms` contains `price`, `period`, `periodCount`, `cycles`, `paymentMode`, and `displayDuration`. Keep absent values nullable when passing a product to your provider.

## Errors and cleanup

Commands throw `NuxieException` with `code`, `message`, and optional `details`. Invalid Dart arguments throw `ArgumentError`. Purchase and restore business outcomes use typed results rather than transport exceptions.

Cancel stream subscriptions when the owner is disposed. `await nuxie.shutdown()` settles outstanding controller requests and resets feature state to unknown. Wait for shutdown before configuring again. A thrown network error does not prove a durable usage command was cancelled; retry the saved command with its original ID.

Event and customer properties must be finite JSON values. Cyclic structures, non-finite numbers, and event names starting with the reserved `$` prefix are rejected.

<span id="shared-platform-behavior" />

See [Features and entitlements](/docs/monetization/features-and-entitlements) for access configuration and the [Dart API reference](https://github.com/nuxieai/nuxie-flutter/blob/main/docs/api-reference.md) for all options and result fields.
