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

# Flutter

> Official Flutter SDK with native verification UI and API client.

## Requirements

* Flutter **3.10+**
* Dart **3.0+**
* iOS 13+ / Android API 21+
* Camera permission (for hosted verification UI)

## Installation

Add the SDK to your `pubspec.yaml`:

```yaml pubspec.yaml theme={null}
dependencies:
  verilock_identity: ^1.0.0
```

Then run:

```bash theme={null}
flutter pub get
```

## Two Modes

The SDK provides two distinct clients for different use cases:

| Client                   | Auth Method   | Use Case                                                           |
| ------------------------ | ------------- | ------------------------------------------------------------------ |
| `VerilockIdentityClient` | Session token | Hosted verification flow with camera capture UI                    |
| `VerilockApiClient`      | API key       | Full server-side API access (sessions, AML, transactions, wallets) |

<Warning>
  **Never embed your API key in client-side code.** Use `VerilockIdentityClient` with a session token in your mobile app. Use `VerilockApiClient` only from a backend server or secure environment.
</Warning>

***

## Hosted Verification UI

The hosted flow uses a session token to guide users through document capture, selfie, and submission -- all with built-in camera widgets.

### Create a session on your backend

First, create a session from your server and pass the token to your Flutter app:

```dart theme={null}
// On your backend -- use VerilockApiClient
final verilock = VerilockApiClient(apiKey: 'qi_live_...');

final session = await verilock.createSession(
  applicantEmail: 'john@example.com',
  redirectUrl: 'https://example.com/callback',
);

// Send session['session_token'] to your Flutter app
```

### Use the pre-built verification screen

The fastest integration -- a single widget that handles the entire flow:

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

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (_) => VerilockVerificationScreen(
      sessionToken: 'tok_abc123',
      onComplete: (result) {
        print('Decision: ${result.decision}');
        Navigator.pop(context);
      },
      onError: (error) {
        print('Error: ${error.message}');
      },
    ),
  ),
);
```

### Programmatic hosted flow

For full control, use `VerilockIdentityClient` directly:

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

final client = VerilockIdentityClient(sessionToken: 'tok_abc123');

// 1. Upload document front
await client.uploadDocument(
  File('path/to/id_front.jpg'),
  side: 'front',
  documentType: 'passport',
);

// 2. Upload document back
await client.uploadDocument(
  File('path/to/id_back.jpg'),
  side: 'back',
);

// 3. Upload selfie
await client.uploadSelfie(File('path/to/selfie.jpg'));

// 4. Submit for verification
await client.submit();

// 5. Poll for result
final result = await client.pollForResult(
  interval: Duration(seconds: 2),
  timeout: Duration(seconds: 120),
  onStatus: (status) => print('Status: $status'),
);

print('Decision: ${result.decision}');
print('Risk score: ${result.riskScore}');

// Clean up
client.dispose();
```

<Tip>
  `pollForResult` automatically polls `getStatus()` every 2 seconds until a decision is reached or the timeout expires. You can also call `getStatus()` manually for custom polling logic.
</Tip>

***

## Server API Client

`VerilockApiClient` gives you full access to the Verilock API using API key authentication. Use this from your backend or secure server environment.

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

final verilock = VerilockApiClient(apiKey: 'qi_live_...');
```

### Sessions

```dart theme={null}
// Create a session
final session = await verilock.createSession(
  applicantEmail: 'john@example.com',
  externalId: 'user_12345',
  redirectUrl: 'https://example.com/callback',
  metadata: {'plan': 'premium'},
);

// List sessions with filters
final sessions = await verilock.listSessions(
  status: 'completed',
  decision: 'approved',
  perPage: 20,
  page: 1,
);

// Retrieve a single session
final detail = await verilock.getSession('ses_abc123');
```

### AML Screening

```dart theme={null}
// Screen a person against sanctions, PEP, and watchlists
final aml = await verilock.screenAml(
  name: 'John Doe',
  dateOfBirth: '1990-01-15',
  nationality: 'US',
);

// Retrieve result
final result = await verilock.getAmlScreening(aml['id']);

// Submit a decision
await verilock.decideAml(aml['id'], decision: 'clear', notes: 'No matches.');
```

### Transaction Screening

```dart theme={null}
// Screen a single transaction
final tx = await verilock.screenTransaction(
  transactionRef: 'TX-001',
  senderName: 'Alice Smith',
  senderCountry: 'US',
  receiverName: 'Bob Johnson',
  receiverCountry: 'NG',
  amount: 5000,
  currency: 'USD',
  transactionType: 'wire_transfer',
);

// Screen a batch of transactions
final batch = await verilock.screenTransactionBatch([
  {'transaction_ref': 'TX-002', 'sender_name': 'Alice', 'receiver_name': 'Charlie', 'amount': 200, 'currency': 'EUR'},
  {'transaction_ref': 'TX-003', 'sender_name': 'Alice', 'receiver_name': 'Diana', 'amount': 15000, 'currency': 'USD'},
]);

// List transactions with risk filter
final txList = await verilock.listTransactions(riskLevel: 'high', perPage: 50);
```

### Wallet Screening

```dart theme={null}
// Screen a crypto wallet address
final wallet = await verilock.screenWallet(
  address: '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD08',
  network: 'ethereum',
);

// Retrieve result
final walletResult = await verilock.getWalletScreening(wallet['id']);
```

### Credentials

```dart theme={null}
// Create a reusable KYC credential
final credential = await verilock.createCredential(
  sessionId: 'ses_abc123',
  sharedFields: ['full_name', 'date_of_birth', 'document_number'],
  expiresInDays: 365,
);

// Verify a credential token
final verified = await verilock.verifyCredential('cred_token_...');

// Revoke a credential
await verilock.revokeCredential(credential['id']);
```

***

## Error Handling

All SDK methods throw `VerilockIdentityError` on failure:

```dart theme={null}
try {
  await client.uploadDocument(File('id.jpg'), side: 'front');
} on VerilockIdentityError catch (e) {
  print('Code: ${e.code}');         // e.g. 'session_expired'
  print('Message: ${e.message}');   // Human-readable description
  print('Status: ${e.statusCode}'); // HTTP status (if applicable)
}
```

| Error Code            | Description                                        |
| --------------------- | -------------------------------------------------- |
| `network_error`       | No internet connection or DNS failure              |
| `session_expired`     | Session token has expired (HTTP 410)               |
| `session_completed`   | Session already has a final decision (HTTP 409)    |
| `api_error`           | General API error (check `statusCode` for details) |
| `parse_error`         | Response body could not be parsed as JSON          |
| `polling_timeout`     | `pollForResult` exceeded the timeout duration      |
| `verification_failed` | Verification completed with a decline decision     |

***

## UI Widgets

The SDK includes pre-built widgets you can compose into your own screens.

### VerilockVerificationScreen

Full-screen verification flow with all steps (document capture, selfie, processing, result):

```dart theme={null}
VerilockVerificationScreen(
  sessionToken: 'tok_abc123',
  onComplete: (VerificationResult result) { /* ... */ },
  onError: (VerilockIdentityError error) { /* ... */ },
)
```

### DocumentCaptureWidget

Camera viewfinder with a document frame overlay. Captures front or back of an ID:

```dart theme={null}
DocumentCaptureWidget(
  side: 'front', // 'front' or 'back'
  onCaptured: (File photo) {
    // Upload the captured photo
  },
)
```

### SelfieCaptureWidget

Camera viewfinder with a face oval overlay for selfie capture:

```dart theme={null}
SelfieCaptureWidget(
  onCaptured: (File photo) {
    // Upload the selfie
  },
)
```

### ProcessingWidget

Animated progress indicator shown while verification is in progress:

```dart theme={null}
ProcessingWidget(
  status: 'processing', // Updates as polling progresses
)
```
