API Reference — Flutter

SDK-Only Access

To ensure your integration remains stable and supported, always use the official SDKs. The underlying API endpoints are internal implementation details that may change in purpose, functionality, or be removed at any time without notice. Direct API access is not supported. Learn more →

The SDK methods documented here are your supported interface. Versioning is managed through SDK upgrades.

createVerifierSDK(config)

Creates and returns a VerifierSDK instance.

import 'package:vecu_verifier_flutter_sdk/vecu_verifier_flutter_sdk.dart';

final sdk = createVerifierSDK(VerifierConfig(
  stage: DeploymentStage.production,
  bearerToken: 'your-token',
));

Configuration

VerifierConfig constructor parameters:

stageDeploymentStagerequired

.development, .sandbox, or .production. Determines the backend URL.

bearerTokenStringrequired

VECU API authentication token.

apiBaseUrlString?

Override the default endpoint for the selected stage.

pollingIntervalMsint

Milliseconds between status checks.

pollingTimeoutMsint

Maximum wait time (5 minutes).

pollingMaxRetriesint

Consecutive errors before stopping.

logLevelLogLevel

Logging verbosity: .debug, .info, .warn, .error, .none.

The SDK automatically resolves the correct endpoint for each stage. The apiBaseUrl property is available for local mock server testing only.

Widgets

VerificationView

Full verification flow widget. Handles loading, QR display, polling, and all result states.

VerificationView(
  sdk: sdk,
  vin: '1HGBH41JXMN109186',
  onApproved: (result) { /* VerificationApproved */ },
  onDenied: (result) { /* VerificationDenied */ },
  onExpired: (result) { /* VerificationExpired */ },
  onError: (error) { /* VerifierError */ },
  decoration: BoxDecoration(...),
  padding: EdgeInsets.all(24),
)
sdkVerifierSDKrequired

SDK instance from createVerifierSDK().

vinStringrequired

Vehicle Identification Number to verify.

onApprovedvoid Function(VerificationApproved)?

Called when verification succeeds.

onDeniedvoid Function(VerificationDenied)?

Called when verification is denied.

onExpiredvoid Function(VerificationExpired)?

Called when the session expires.

onErrorvoid Function(VerifierError)?

Called on any error.

decorationBoxDecoration?

Custom decoration for the outer container (background, border, etc.).

proximityProximityConfig?

Optional GPS proximity verification. Device coordinates are retrieved automatically via platform location services. If location permission is denied, result will be unchecked.

paddingEdgeInsetsGeometry?

Custom padding for the outer container.

VerificationController

ChangeNotifier-based state manager for building custom verification UI. Manages the full flow (create request, poll, state transitions) and exposes a reactive state for your UI.

final controller = VerificationController(
  sdk: sdk,
  vin: '1HGBH41JXMN109186',
  proximity: const ProximityConfig(thresholdMiles: 5.0),
  onApproved: (result) { /* VerificationApproved */ },
  onDenied: (result) { /* VerificationDenied */ },
  onExpired: (result) { /* VerificationExpired */ },
  onError: (error) { /* VerifierError */ },
);
sdkVerifierSDKrequired

SDK instance from createVerifierSDK().

vinStringrequired

Vehicle Identification Number to verify.

proximityProximityConfig?

Optional GPS proximity configuration.

onApprovedVerificationApprovedCallback?

Called when verification succeeds.

onDeniedVerificationDeniedCallback?

Called when verification is denied.

onExpiredVerificationExpiredCallback?

Called when the session expires.

onErrorVerifierErrorCallback?

Called when an error occurs.

Properties

PropertyTypeDescription
stateUIStateCurrent UI state (see below)
vinStringThe VIN being verified

Methods

MethodDescription
restart()Stop polling and start a new verification flow
notifyQRExpired()Transition to QRExpiredState when QR timer expires
addListener(callback)Register a state change listener (inherited from ChangeNotifier)
dispose()Clean up event subscriptions and stop polling

UIState (Sealed Class)

Use pattern matching on controller.state:

switch (controller.state) {
  LoadingState() => // Creating request...
  QRState(:final qrContent, :final expiresAt, :final vin) => // Show QR
  QRExpiredState() => // QR timer expired, show restart
  ApprovedState(:final result, :final vin) => // Verified
  DeniedState(:final result, :final vin) => // Do not release
  ExpiredState(:final result) => // Session expired
  ErrorState(:final error) => // Show error.userMessage
}

Core SDK Methods

createPresentationRequest(vin, [options])

final result = await sdk.createPresentationRequest(
  '1HGBH41JXMN109186',
  CreatePresentationOptions(
    proximity: ProximityConfig(thresholdMiles: 5.0),
  ),
);
if (result is ApiSuccess<CreatePresentationResponse>) {
  final data = result.data;
  // data.requestId, data.qrContent, data.expiresAt
}

ApiResult is a sealed class with two subtypes:

  • ApiSuccess<T> — contains data: T
  • ApiFailure<T> — contains error: VerifierError

Returns: Future<ApiResult<CreatePresentationResponse>>

CreatePresentationResponse

requestIdStringrequired

Unique identifier for polling and support triage.

qrContentStringrequired

OID4VP URL to render as a QR code for the driver's wallet to scan.

expiresAtStringrequired

ISO 8601 timestamp when the QR code/request expires.

startPolling()

Starts polling for verification status. Stops automatically on terminal states.

Returns: void Function() — cleanup function to stop polling.

stopPolling({String reason})

Manually stop polling. Accepts an optional reason parameter (defaults to 'manual').

getStatus() / getRequest()

Get current verification status or full request state.

on<T>(listener) / off<T>(listener)

Subscribe/unsubscribe to typed events.

sdk.on<StatusChangedEvent>((event) {
  print(event.currentStatus.status);
});

destroy()

Clean up all resources (timers, listeners).

Events

sdk.on<RequestCreatedEvent>((e) { e.requestId; e.qrContent; e.vin; });
sdk.on<StatusChangedEvent>((e) { e.previousStatus; e.currentStatus; });
sdk.on<PollingStartedEvent>((e) { e.requestId; e.intervalMs; });
sdk.on<PollingStoppedEvent>((e) { e.requestId; e.reason; });
sdk.on<ErrorEvent>((e) { e.error; });

Verification Status Types

Sealed class hierarchy with pattern matching:

All statuses share common fields requestId, createdAt?, and expiresAt?:

switch (status) {
  case VerificationPending(:final requestId):
    print('Waiting...');
  case VerificationApproved(:final requestId, :final proximityCheck):
    print('Verified: $requestId');
    if (proximityCheck?.status == ProximityCheckStatus.fail) {
      print('Warning: device is far from origin');
    }
  case VerificationDenied(:final requestId, :final error):
    print('DO NOT RELEASE: $requestId (${error ?? "no reason"})');
  case VerificationExpired(:final requestId):
    print('Expired: $requestId');
}

Helper methods: status.isTerminal, status.isApproved, status.isDenied

VerificationApproved includes optional verifiedClaims and proximityCheck:

VerifiedClaims

Credential claims extracted by the backend on approval. Access via result.verifiedClaims:

vinString?

Vehicle Identification Number from the verified credential.

originLocationString?

Origin location from the credential (e.g. auction site name).

destinationLocationString?

Destination location from the credential (e.g. dealer name).

case VerificationApproved(:final verifiedClaims, :final proximityCheck):
  final vin = verifiedClaims?.vin ?? 'N/A';
  final origin = verifiedClaims?.originLocation;
  final destination = verifiedClaims?.destinationLocation;

Proximity Types

ProximityConfig

Device GPS coordinates are retrieved automatically via platform location services. If location permission is not granted, the proximity check result will be unchecked.

const ProximityConfig({
  required double thresholdMiles, // Max distance from origin (miles)
})

ProximityCheck

Returned on VerificationApproved.proximityCheck:

statusProximityCheckStatusrequired

pass, fail, or unchecked.

distanceMilesdouble?

Actual distance between device and origin in miles. Present on pass and fail.

thresholdMilesdouble?

Threshold that was applied (from your ProximityConfig).

originCoordinatesCoordinates?

GPS coordinates from the credential (origin location). Has lat and lng fields.

deviceCoordinatesCoordinates?

GPS coordinates of the verifier's device. Has lat and lng fields.

Status behavior:

StatusMeaning
passDevice is within thresholdMiles of origin
failDevice is beyond threshold — distanceMiles shows how far
uncheckedLocation permission denied or proximity not configured
final proximity = result.proximityCheck;
if (proximity != null && proximity.status == ProximityCheckStatus.fail) {
  print('Device is ${proximity.distanceMiles?.toStringAsFixed(1)} mi '
      'from origin (threshold: ${proximity.thresholdMiles} mi)');
}

Error Types

All errors extend VerifierError with these common fields:

codeStringrequired

Machine-readable error code (e.g. NETWORK_ERROR, API_ERROR).

messageStringrequired

Technical error message (may contain internal details — not for UI display).

userMessageStringrequired

UI-safe, human-friendly message. Always use this for display.

timestampDateTimerequired

When the error occurred.

displayCodeString

Triage-friendly code. For ApiError, includes HTTP status (e.g. API_ERROR_401).

Subtypes:

TypeExtra FieldsuserMessage example
NetworkErrorcause"Unable to connect. Please check your internet connection"
ApiErrorstatusCode, details"Access denied" (401), "Service busy, try again" (429)
ValidationErrorfield"Invalid input provided"
TimeoutErrortimeoutMs"The request timed out. Please try again"
SessionErrorsessionId"Your verification session has expired"

ApiError.isRetryable returns true for 5xx and 429 status codes. The top-level isRetryableError() function works on any VerifierError.

onError: (error) {
  // Show to user
  showSnackBar(error.userMessage);
  // Log for support
  print('Error ${error.displayCode}: ${error.message}');
}

Individual UI Widgets

For headless integrations that want to reuse specific built-in views, the SDK exports individual widgets:

WidgetDescription
QRCodeDisplayQR code with countdown timer
ApprovedViewGreen success card
DeniedViewRed "DO NOT RELEASE" card
ExpiredViewOrange session expired card
ErrorViewError card with code and retry
LoadingViewLoading spinner
QRExpiredViewQR expired with refresh button