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

# Flutter

> Native billing enforcement for Flutter apps — no WebView, no platform channels.

## Installation

Add to `pubspec.yaml`:

```yaml theme={null}
dependencies:
  gatlio_flutter:
    git:
      url: https://github.com/gatlio/gatlio-flutter.git
```

## Quick start

Wrap the authenticated portion of your app in `GatlioGate`:

```dart theme={null}
import 'package:gatlio_flutter/gatlio_flutter.dart';

GatlioGate(
  apiBase: 'https://api.gatlio.io',
  tenantSlug: 'acme',
  customerId: currentUser.stripeCustomerId,
  publishableKey: 'pk_live_abc123',
  child: YourApp(),
)
```

* **Active** — `YourApp` renders normally
* **Warning** — dismissable banner above content
* **Lockout** — full-screen overlay until card is updated

## Parameters

| Parameter        | Type                    | Required | Default                 |
| ---------------- | ----------------------- | -------- | ----------------------- |
| `apiBase`        | `String`                | ✓        | —                       |
| `tenantSlug`     | `String`                | ✓        | —                       |
| `customerId`     | `String`                | ✓        | —                       |
| `publishableKey` | `String`                | ✓        | —                       |
| `pollInterval`   | `Duration`              |          | `Duration(minutes: 10)` |
| `forcedStatus`   | `GatlioStatus?`         |          | `null`                  |
| `callbacks`      | `GatlioCallbacks?`      |          | `null`                  |
| `lockoutScreen`  | `LockoutScreenBuilder?` |          | built-in                |
| `warningBanner`  | `WarningBannerBuilder?` |          | built-in                |
| `child`          | `Widget`                | ✓        | —                       |

## Callbacks

```dart theme={null}
GatlioGate(
  apiBase: 'https://api.gatlio.io',
  tenantSlug: 'acme',
  customerId: currentUser.stripeCustomerId,
  publishableKey: 'pk_live_abc123',
  callbacks: GatlioCallbacks(
    onLockout: () => print('locked out'),
    onWarning: () => print('warning'),
    onActive: () => print('active'),
    onRecovered: () => print('recovered'),
    onError: (err) => print('error: $err'),
  ),
  child: YourApp(),
)
```

Callbacks fire on status **transitions only** — not on every poll tick.

## Custom enforcement UI

```dart theme={null}
GatlioGate(
  // ...
  lockoutScreen: ({required triggerCardUpdate, entitlements}) =>
      MyBrandedLockout(onUpdate: triggerCardUpdate),
  warningBanner: ({required triggerCardUpdate, required dismissWarning}) =>
      MyBrandedBanner(onUpdate: triggerCardUpdate, onDismiss: dismissWarning),
  child: YourApp(),
)
```

## Testing

### Force a state

```dart theme={null}
GatlioGate(
  apiBase: 'https://api.gatlio.io',
  tenantSlug: 'acme',
  customerId: 'cus_test',
  publishableKey: 'pk_test_abc',
  forcedStatus: GatlioStatus.lockout,
  child: YourApp(),
)
```

No network calls are made when `forcedStatus` is set. Remove before shipping.

### Interactive sandbox

```dart theme={null}
GatlioSandbox(
  onLockout: () => print('locked out'),
  onWarning: () => print('warning'),
  onActive: () => print('active'),
  onError: (err) => print('error: $err'),
  child: YourApp(),
)
```

A `DEV` badge appears in the bottom-right corner. Tap to open a control sheet with state pills and a callback log. Remove before shipping to production.

## Direct controller usage

For custom state management with Riverpod, Bloc, or other state managers:

```dart theme={null}
final controller = GatlioController(
  GatlioConfig(
    apiBase: 'https://api.gatlio.io',
    tenantSlug: 'acme',
    customerId: currentUser.stripeCustomerId,
    publishableKey: 'pk_live_abc123',
  ),
)
controller.start()

StreamBuilder<GatlioState>(
  stream: controller.stateStream,
  builder: (context, snap) { /* ... */ },
)
```

Call `controller.dispose()` when done.
