apex_kyc 1.1.4 copy "apex_kyc: ^1.1.4" to clipboard
apex_kyc: ^1.1.4 copied to clipboard

A comprehensive Flutter SDK for KYC (Know Your Customer) verification featuring document capture, real-time liveness detection with randomized challenges, and seamless backend integration. Supports mu [...]

Apex KYC Flutter SDK #

pub package License: MIT Flutter

The complete Flutter SDK for KYC verification β€” document capture, liveness detection, and seamless backend integration.

πŸ“– Full Documentation Β· 🌐 KYC Web App Β· 🏠 Website Β· πŸ› Issues


Table of contents #

Full interactive API reference, Flutter SDK examples, and webhook documentation are available at apexkyc.com/docs.


Installation πŸ“¦ #

dependencies:
  apex_kyc: ^1.1.4
flutter pub get

Choose your integration πŸ”€ #

Pick the approach that fits your product:

Way 1 β€” Native SDK Way 2 β€” WebView Way 3 β€” Browser link
UX βœ… Best native 🟑 Good embedded πŸ”΅ Opens browser
Camera Native device Web in WebView Web in browser
Requires apex_kyc βœ… Yes For applicant creation Optional
Extra package None webview_flutter url_launcher
Best for Mobile-first apps Hybrid apps Email/SMS links, web

Full in-app experience: native camera, randomised liveness challenges, and document capture β€” all inside your Flutter app.

Step 1 β€” Initialize once in main() #

import 'package:apex_kyc/index.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  ApexKycConfig.initialize(
    apiKey: 'your-api-key', // From https://apexkyc.com/ β†’ Dashboard β†’ API Keys
    // baseUrl defaults to https://api.apexkyc.com
  );

  runApp(const MyApp());
}

Step 2 β€” Get an applicantId #

An applicant is a person going through KYC. You must get their id from the API before starting the flow.

Using the SDK (simplest)

final service = SdkVerificationService();

final applicant = await service.createApplicant(
  customerIdentifier: 'user-12345', // Your stable internal user ID or email
  fullName: 'Jane Doe',             // Optional
  email: 'jane@example.com',        // Optional
);

final String applicantId = applicant.id; // ← pass this to ApexKycFlowWidget

βœ… Same customerIdentifier β†’ same applicant returned (no duplicates ever created).

Step 3 β€” Launch the KYC flow #

Navigator.of(context).push(
  MaterialPageRoute(
    builder: (_) => ApexKycFlowWidget(
      applicantId: applicantId,
      showProgress: true,
      onComplete: (SdkVerificationResponse verification) {
        print('βœ… Done: ${verification.id} β€” ${verification.status}');
      },
      onError: (String error) {
        print('❌ Error: $error');
      },
    ),
  ),
);

Full working example #

import 'package:flutter/material.dart';
import 'package:apex_kyc/index.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  ApexKycConfig.initialize(apiKey: 'your-api-key');
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) => MaterialApp(
    title: 'KYC Demo',
    theme: ThemeData(
      colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
      useMaterial3: true,
    ),
    home: const KycScreen(),
  );
}

class KycScreen extends StatefulWidget {
  const KycScreen({super.key});
  @override
  State<KycScreen> createState() => _KycScreenState();
}

class _KycScreenState extends State<KycScreen> {
  final _service = SdkVerificationService();
  String? _applicantId;
  bool _loading = false;
  String? _error;

  Future<void> _getApplicant() async {
    setState(() { _loading = true; _error = null; });
    try {
      final applicant = await _service.createApplicant(
        customerIdentifier: 'demo-user-001',
        fullName: 'Demo User',
        email: 'demo@example.com',
      );
      setState(() { _applicantId = applicant.id; _loading = false; });
    } catch (e) {
      setState(() { _error = e.toString(); _loading = false; });
    }
  }

  Future<void> _startKyc() async {
    if (_applicantId == null) return;
    await Navigator.of(context).push(
      MaterialPageRoute(
        builder: (_) => ApexKycFlowWidget(
          applicantId: _applicantId!,
          showProgress: true,
          onComplete: (v) {
            Navigator.of(context).pop();
            ScaffoldMessenger.of(context).showSnackBar(SnackBar(
              content: Text('βœ… Verification done β€” ${v.status}'),
              backgroundColor: Colors.green,
            ));
          },
          onError: (e) {
            Navigator.of(context).pop();
            ScaffoldMessenger.of(context).showSnackBar(SnackBar(
              content: Text('❌ $e'),
              backgroundColor: Colors.red,
            ));
          },
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Identity Verification')),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            const Text(
              'Complete identity verification to continue.',
              style: TextStyle(fontSize: 16),
            ),
            const SizedBox(height: 24),
            if (_error != null)
              Container(
                margin: const EdgeInsets.only(bottom: 12),
                padding: const EdgeInsets.all(12),
                decoration: BoxDecoration(
                  color: Colors.red.shade50,
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Text(_error!, style: TextStyle(color: Colors.red.shade700)),
              ),
            if (_applicantId == null)
              FilledButton.icon(
                icon: const Icon(Icons.person_add),
                label: Text(_loading ? 'Please wait…' : 'Start verification'),
                onPressed: _loading ? null : _getApplicant,
              )
            else
              FilledButton.icon(
                icon: const Icon(Icons.verified_user),
                label: const Text('Verify my identity'),
                onPressed: _startKyc,
              ),
          ],
        ),
      ),
    );
  }
}

Way 2 β€” WebView inside Flutter 🟑 #

Embed the hosted KYC web app (kyc.apexkyc.com) inside your Flutter app using webview_flutter. The SDK is still used to create the applicant; the KYC UI runs in-app but on a web page.

Setup #

dependencies:
  apex_kyc: ^1.1.4        # Create applicant
  webview_flutter: ^4.0.0  # Embed the web app

Get the KYC URL #

// Initialize config first (same as Way 1)
ApexKycConfig.initialize(apiKey: 'your-api-key');

final service = SdkVerificationService();
final applicant = await service.createApplicant(
  customerIdentifier: 'user-12345',
);

// Prefer kycWebUrl from the API; fall back to the public URL pattern
final String kycUrl = applicant.kycWebUrl?.isNotEmpty == true
    ? applicant.kycWebUrl!
    : 'https://kyc.apexkyc.com/?id=${applicant.id}';

Embed the WebView #

import 'package:webview_flutter/webview_flutter.dart';

class KycWebViewScreen extends StatefulWidget {
  final String kycUrl;
  const KycWebViewScreen({super.key, required this.kycUrl});

  @override
  State<KycWebViewScreen> createState() => _KycWebViewScreenState();
}

class _KycWebViewScreenState extends State<KycWebViewScreen> {
  late final WebViewController _controller;
  bool _loading = true;

  @override
  void initState() {
    super.initState();
    _controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (_) => setState(() => _loading = true),
        onPageFinished: (_) => setState(() => _loading = false),
      ))
      ..loadRequest(Uri.parse(widget.kycUrl));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Identity Verification'),
        leading: const CloseButton(),
      ),
      body: Stack(
        children: [
          WebViewWidget(controller: _controller),
          if (_loading) const Center(child: CircularProgressIndicator()),
        ],
      ),
    );
  }
}

Open it #

await Navigator.of(context).push(
  MaterialPageRoute(
    builder: (_) => KycWebViewScreen(kycUrl: kycUrl),
  ),
);

Android: Camera access in WebView requires the permissions in the Platform setup section below.


No Flutter KYC widgets at all. Create an applicant on your backend and open the KYC web app in the device's default browser β€” or send the link by email/SMS.

Flutter (with url_launcher) #

dependencies:
  url_launcher: ^6.0.0
  apex_kyc: ^1.1.4          # Optional β€” only if you also create the applicant in Flutter
import 'package:url_launcher/url_launcher.dart';
import 'package:apex_kyc/index.dart';

Future<void> openKycInBrowser(SdkApplicantResponse applicant) async {
  // Prefer the ready-made URL from the API
  final String raw = applicant.kycWebUrl?.isNotEmpty == true
      ? applicant.kycWebUrl!
      : 'https://kyc.apexkyc.com/?id=${applicant.id}';

  final uri = Uri.parse(raw);
  if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) {
    throw Exception('Could not open $raw');
  }
}

Backend only (no Flutter) #

# 1. Create applicant on your server
curl -X POST "https://api.apexkyc.com/sdk/kyc-verification/applicants" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{"customerIdentifier": "user-12345", "email": "jane@example.com"}'

# Response β†’ { "id": "664f...", "kycWebUrl": "https://kyc.apexkyc.com/?id=664f..." }

# 2. Send kycWebUrl to the user via email / SMS / push notification
#    The user clicks it β†’ completes KYC in their browser β€” no app install needed

Getting an applicant ID πŸͺͺ #

Every KYC flow requires an applicant ID. This ID is always created and stored server-side β€” you never invent it in the UI.

SDK helper methods #

Method When to use
createApplicant(customerIdentifier: ...) Always safe to call β€” creates or returns the existing record
findApplicantByIdentifier(id) Look up without creating
findApplicantByEmail(email) Look up by email
getApplicant(applicantId) Fetch full details when you already have the ID

HTTP API (any language / Postman) #

Endpoint: POST https://api.apexkyc.com/sdk/kyc-verification/applicants

Headers

Header Value
Content-Type application/json
X-API-Key Your SDK API key

Request body

Field Type Required Notes
customerIdentifier string βœ… Yes Stable unique ID in your system
fullName string No
email string No
phone string No
dateOfBirth string No ISO date: 1990-01-15
nationality string No

Response

Field Description
id Applicant ID β€” use as applicantId
customerIdentifier Echo of what you sent
kycWebUrl Ready-to-open link (e.g. https://kyc.apexkyc.com/?id=...) β€” present when backend has KYC_WEB_APP_URL set
createdAt ISO timestamp

API reference πŸ“‘ #

Interactive reference with live try-it fields β†’ apexkyc.com/docs

Base URL: https://api.apexkyc.com/sdk/kyc-verification
All requests need: X-API-Key: your-api-key

Applicants #

Method Path Description
POST /applicants Create (or resolve) applicant
GET /applicants List all applicants (supports ?email= ?identifier=)
GET /applicants/:id Get applicant by ID

Verifications #

Method Path Description
POST /applicants/:id/verifications Create a verification request
GET /verifications/:id Get verification status & results
PATCH /verifications/:id/verification-type Change document type
GET /applicants/:id/verifications List all verifications for an applicant

Documents #

Method Path Description
POST /verifications/:id/documents Upload a single document image
POST /verifications/:id/documents/batch Upload front + back in one call

Liveness #

Method Path Description
POST /verifications/:id/liveness Upload a liveness frame
POST /verifications/:id/liveness/batch Upload multiple liveness frames

Config #

Method Path Description
GET /config SDK config (branding, kycWebUrl, feature flags)

Full cURL examples #

# Create applicant
curl -X POST "https://api.apexkyc.com/sdk/kyc-verification/applicants" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{"customerIdentifier":"user-12345","fullName":"Jane Doe","email":"jane@example.com"}'

# Get applicant
curl "https://api.apexkyc.com/sdk/kyc-verification/applicants/APPLICANT_ID" \
  -H "X-API-Key: your-api-key"

# Create verification (ID_CARD | PASSPORT | NATIONAL_ID | DRIVING_LICENSE)
curl -X POST "https://api.apexkyc.com/sdk/kyc-verification/applicants/APPLICANT_ID/verifications" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{"verificationType":"ID_CARD"}'

# Get verification status
curl "https://api.apexkyc.com/sdk/kyc-verification/verifications/VERIFICATION_ID" \
  -H "X-API-Key: your-api-key"

Webhooks πŸ”” #

Apex KYC sends HTTP POST requests to your configured webhook URL when events occur.

Configure webhooks in your dashboard or via the Webhooks API. For payload format, retry policy, and signature verification, see apexkyc.com/docs β†’ Webhooks tab.

Applicant events #

Event Triggered when
applicant.created New applicant created
applicant.updated Applicant info updated
applicant.deleted Applicant deleted

Verification events #

Event Triggered when
verification.created Verification request created
verification.started Processing begins
verification.completed Successfully completed
verification.failed Verification failed
verification.rejected Verification rejected
verification.cancelled Verification cancelled
verification.retry User retries verification

Document events #

Event Triggered when
document.uploaded Any document uploaded
document.front.uploaded Front side uploaded
document.back.uploaded Back side uploaded
documents.uploaded All required documents received

Liveness events #

Event Triggered when
liveness.started Liveness check begins
liveness.completed Liveness check passed
liveness.failed Liveness check failed
liveness.frame.uploaded A frame is uploaded

Manual review events #

Event Triggered when
manual_review.required Review required by a human agent
manual_review.approved Reviewer approved the verification
manual_review.rejected Reviewer rejected the verification

Verification types πŸ“„ #

Type constant Document
PASSPORT International passport
ID_CARD National ID card (front + back)
NATIONAL_ID Country-specific national ID
DRIVING_LICENSE Driving licence (front + back)

In Dart, use the VerificationType enum:

VerificationType.passport
VerificationType.idCard
VerificationType.nationalId
VerificationType.drivingLicense

Platform setup πŸ”§ #

Android #

Add inside <manifest> in android/app/src/main/AndroidManifest.xml:

<!-- Camera permission β€” required for liveness and document capture -->
<uses-permission android:name="android.permission.CAMERA"/>

For WebView camera (Way 2), also add inside <application>:

<uses-feature android:name="android.hardware.camera" android:required="false"/>

iOS #

Add to ios/Runner/Info.plist:

<key>NSCameraUsageDescription</key>
<string>Camera access is required for identity verification</string>

Support πŸ’¬ #

Link
πŸ“– Full documentation apexkyc.com/docs
🌐 KYC web app kyc.apexkyc.com
🏠 Website & dashboard apexkyc.com
πŸ“§ Email contact.apexkyc@gmail.com

License πŸ“„ #

MIT β€” see LICENSE file for details.

1
likes
50
points
55
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A comprehensive Flutter SDK for KYC (Know Your Customer) verification featuring document capture, real-time liveness detection with randomized challenges, and seamless backend integration. Supports multiple document types (passport, ID card, driving license), customizable themes, company branding, and cross-platform compatibility (iOS & Android).

Homepage
Repository (GitHub)

License

MIT (license)

Dependencies

camera, collection, equatable, flutter, google_mlkit_face_detection, http, http_parser, image, image_picker, lottie, path_provider, permission_handler, plugin_platform_interface, screen_brightness, shared_preferences

More

Packages that depend on apex_kyc

Packages that implement apex_kyc