addressiq_sdk 0.11.0
addressiq_sdk: ^0.11.0 copied to clipboard
AddressIQ address verification SDK for Flutter — background location collection, address capture UI, and the verify lifecycle for KYC and fraud detection in emerging markets.
AddressIQ — Flutter SDK #
addressiq_sdk is the Flutter SDK for AddressIQ — background location
collection, address-capture UI (AddressIQVerify), and the verification
lifecycle (AddressIQ.instance).
Install #
dependencies:
addressiq_sdk: ^0.4.0
flutter pub get
Quick start #
import 'package:addressiq_sdk/addressiq.dart';
// 1. Initialize once at app start.
AddressIQ.instance.initialize(AddressIQConfig(
apiKey: 'aiq_...',
environment: 'production', // 'production' | 'staging' | 'development'
));
// 2. Bind the signed-in user.
await AddressIQ.instance.setUser(const SdkUser(appUserId: 'cust_abc'));
// 3. Make sure location permissions are granted (see Permissions below).
await AddressIQ.instance.requestPermissions();
// 4. Start a verification. The SDK begins background collection
// automatically using the returned codes.
final res = await AddressIQ.instance.startVerification(
const StartVerificationArgs(locationCode: 'loc_123'),
);
print(res['verificationCode']); // ver_…
Collect UI (AddressIQVerify) #
Track A — a drop-in full-screen widget that captures the address (search,
map-pin, property details, photos, consent) and starts background
collection on submit. onComplete returns a VerifyResult with the
public verificationCode and locationCode the backend assigned.
import 'package:flutter/material.dart';
import 'package:addressiq_sdk/addressiq.dart';
// The Collect UI config is hidden from the barrel (the barrel re-exports the
// lifecycle AddressIQConfig); import it directly under a prefix.
import 'package:addressiq_sdk/src/api/models.dart' as collect;
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => AddressIQVerify(
config: collect.AddressIQConfig(
apiKey: 'aiq_...',
environment: 'production',
sessionToken: '<widget-session-token>',
),
onComplete: (VerifyResult result) {
print(result.verificationCode); // ver_…
print(result.locationCode); // loc_…
},
onCancel: () {},
onError: (error) {},
),
));
SDK API (AddressIQ.instance) #
| Method | Purpose |
|---|---|
initialize(AddressIQConfig) |
Configure the SDK (apiKey + environment). |
setUser(SdkUser) |
Bind the active app user. |
startVerification(StartVerificationArgs) |
Start a digital verification (POST …/verifications/digital, digitalProvider defaults to internal_ai). |
startPhysicalVerification(StartPhysicalArgs) |
Start a physical (agent/KYC) verification. |
startDigitalAndPhysicalVerification(StartCombinedArgs) |
Start a combined digital + physical verification. |
cancelVerification(verificationCode) |
Cancel an in-flight verification. |
getVerificationState() |
Current lifecycle state snapshot. |
pauseVerification() / resumeVerification() |
Pause / resume background collection. |
sync() |
Force-flush the telemetry queue. |
listProviders({type}) |
List available providers. |
getLocation(locationCode) |
Fetch the location envelope (geofence, status). |
logout() / reset() |
Detach the user / tear the SDK down. |
startVerification signature:
Future<Map<String, dynamic>> startVerification(StartVerificationArgs args);
class StartVerificationArgs {
final String locationCode;
final String? digitalProvider; // defaults to 'internal_ai' server-side
final Map<String, dynamic>? metadata;
final String? idempotencyKey;
final String? branchId;
const StartVerificationArgs({ required this.locationCode, ... });
}
All start* methods return the backend response map containing
verificationCode, locationCode, and status, gate on location
permissions, mark the session COLLECTING, and kick off background
collection automatically.
Permissions #
start* requires both foreground and background location to be
GRANTED, otherwise it throws an AddressIQException with code
PERMISSION_DENIED. Drive the OS prompt and inspect state first:
await AddressIQ.instance.requestPermissions();
final state = await AddressIQ.instance.getPermissionState();
// { foregroundLocation, backgroundLocation, notifications } ∈
// { GRANTED, DENIED, NOT_DETERMINED, BLOCKED, UNAVAILABLE }
if (state['backgroundLocation'] != 'GRANTED' &&
!(await AddressIQ.instance.canRequestPermission())) {
await AddressIQ.instance.openSettings(); // deep-link when BLOCKED
}
Declare ACCESS_BACKGROUND_LOCATION (Android) / the always-usage
strings (iOS Info.plist) in the host app so the OS will prompt for
background access.
Example app #
example/ is a runnable lifecycle demo. The hub exposes the imperative
lifecycle buttons (initialize → setUser → start → pause/resume/sync →
cancel → logout) plus a Collect Address button that opens the
AddressIQVerify Collect UI (Track A).
cd example
flutter create . # generate platform folders (android/ ios/ — gitignored)
flutter pub get # resolves addressiq_sdk from `path: ../`
flutter run \
--dart-define=API_KEY=aiq_... \
--dart-define=SESSION_TOKEN=<widget-session-token>
The API host is resolved from the selected environment — you never pass a URL.
Choose the development environment (Login screen) to target a local backend.
example/pubspec.yaml uses addressiq_sdk: { path: ../ }, so it always
builds against this repo's SDK source.
Environment #
AddressIQConfig.environment selects which backend the SDK talks to.
Integrators never pass a URL — the SDK owns host resolution. Just choose one
of the supported environments:
productionstaging(sandboxis a deprecated alias that resolves identically)development
staging is canonical across all AddressIQ SDKs. sandbox was the former
Flutter spelling and is still accepted by the resolver
(lib/src/api/environment.dart:26), so existing integrators keep working.
Choose development to target a backend running locally during development.
Each environment resolves three hosts — API, ingest, and CDN. production and
staging are baked in at publish time from GitHub repository variables (see
docs/RELEASE.md); development is local-only and never
baked.
final config = AddressIQConfig(apiKey: 'aiq_...', environment: 'staging');
config.resolvedApiUrl; // API host
config.resolvedIngestUrl; // telemetry ingest host
config.resolvedCdnUrl; // CDN host — config value only, see below
resolvedCdnUrldoes not make the SDK load anything remotely. The Collect UI widget ships bundled in the package (assets/iqcollect.js), is injected inline, and fails closed if it is missing — it never falls back to a remote script. The CDN URL is exposed so hosts (and any future asset loading) resolve the same per-environment host the web SDK publishes to.
There are two exported AddressIQConfig classes — the lifecycle one
(lib/src/lifecycle/addressiq.dart:28-53, re-exported by the barrel) and the
Collect UI one (lib/src/api/models.dart:5-42). Both expose the same
resolved* getters and resolve identically.
Errors #
Lifecycle methods throw AddressIQException(code, message). Common codes:
| code | meaning |
|---|---|
SDK_NOT_INITIALIZED |
A method was called before initialize. |
INVALID_CONFIG |
apiKey missing or env resolved to an empty URL. |
INVALID_USER |
setUser called without an appUserId. |
PERMISSION_DENIED |
Foreground/background location not GRANTED at start. |
NO_ACTIVE_SESSION |
resumeVerification with nothing to resume. |
HTTP_* / backend code |
Surfaced from the API response. |
Develop #
flutter pub get
flutter analyze
flutter test # smoke test
Release #
Push a semver tag to publish to pub.dev (.github/workflows/release.yml):
git tag v0.4.0 && git push origin v0.4.0
Uses pub.dev OIDC trusted publishing — configure this repo as a trusted
publisher in the package's pub.dev admin settings (no secret required). Run the
workflow manually with dry_run: true to validate first.
The release bakes lib/src/generated/build_config.dart from six GitHub
repository variables (staging + production × API/ingest/CDN) with
scripts/bake-build-config.sh --strict — a release fails if any of them is
unset. See docs/RELEASE.md.
Cross-links #
- Cross-SDK contract:
../../geo-tagging/docs/sdk-contract.md - Flutter SDK reference:
flutter.md
Contributing #
Fork, branch, PR. CI runs flutter analyze + flutter test on the SDK and
analyzes the example against the local SDK on every push/PR.