Skip to content
YeboID / Developer documentation

KYC Integration ​

YeboID integrates with YeboVerify for identity verification. This guide covers how to verify your users' identities.

Overview ​

KYC (Know Your Customer) verification allows you to:

  • Verify user identities with government-issued documents
  • Confirm user age and nationality
  • Meet regulatory compliance requirements
  • Unlock premium features for verified users

Verification Flow ​

┌─────────────┐     Start KYC     ┌─────────────┐
│   Your App  │ ─────────────────▶│  YeboID API │
└─────────────┘                   └─────────────┘
                                        │
                                        │ Returns verify URL
                                        ▼
                                  ┌─────────────┐
                                  │ YeboVerify  │
                                  │   (Web UI)  │
                                  └─────────────┘
                                        │
                                        │ User completes:
                                        │ - Document scan
                                        │ - Selfie
                                        │ - Liveness check
                                        ▼
┌─────────────┐    Webhook Event   ┌─────────────┐
│   Your App  │◀──────────────────│  YeboID API │
└─────────────┘   kyc.completed   └─────────────┘

Starting Verification ​

Flutter SDK ​

dart
YeboIDVerifyButton(
  onVerified: () {
    print('User verified!');
    // Refresh user data
    YeboIDProvider.of(context).fetchUser();
  },
  onError: (error) {
    print('Verification failed: $error');
  },
)

Or manually:

dart
final client = YeboIDProvider.of(context);
final verifyUrl = await client.startKycVerification();

if (verifyUrl != null) {
  // Open in browser
  await launchUrl(Uri.parse(verifyUrl));
}

API ​

bash
POST https://api.yeboid.com/verification/start
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json

{
  "callback": "yourapp://kyc-complete"
}

Parameters:

FieldRequiredDescription
callbackNoAbsolute URL YeboVerify returns the user to when the flow ends

There is no country parameter — YeboID resolves the country server-side from the extracted ID document (falling back to the phone's E.164 prefix), so nothing the client sends can influence it.

Response:

json
{
  "success": true,
  "verifyUrl": "https://verify.yeboverify.com/v/sess_abc123",
  "expiresIn": 3600
}

Send the user to verifyUrl. The response carries no session id — YeboID tracks the session internally and reports the outcome through webhooks and GET /verification/status.

Errors:

StatuscodeMeaning
401—Missing or invalid access token
404—User not found
409ALREADY_VERIFIEDUser is already VERIFIED; there is nothing to start

Checking Status ​

User Properties ​

After the user completes verification, their profile is updated:

dart
final user = context.yeboIdUser;

if (user.isVerified) {
  print('✅ Verified in ${user.kycCountry}');
  print('Verified at: ${user.kycVerifiedAt}');
} else if (user.isPendingVerification) {
  print('⏳ Verification pending');
} else {
  print('❌ Not verified');
}

API ​

bash
GET https://api.yeboid.com/verification/status
Authorization: Bearer ACCESS_TOKEN

Response:

json
{
  "success": true,
  "kycStatus": "VERIFIED",
  "kycData": {
    "verificationId": "ver_abc123",
    "decision": "approved",
    "confidence": 0.97,
    "faceScore": 0.94,
    "ocrConfidence": 0.99,
    "extracted": {
      "names": "John",
      "surname": "Doe",
      "dateOfBirth": "1990-05-15",
      "nationality": "SZ"
    },
    "verifiedAt": "2024-01-15T10:30:00Z"
  }
}

kycData is stored encrypted at rest and decrypted only for the authenticated owner on this endpoint. It is null until a decision webhook lands, and the exact keys inside extracted come from YeboVerify's OCR — treat every one of them as optional.

This endpoint is for the YeboID account app

/verification/status is authenticated with a user access token and is how the YeboID app polls its own user. Third-party OAuth apps should read KYC state from GET /oauth/userinfo with the kyc or kyc:full scope, or subscribe to the user.kyc.verified / user.kyc.rejected webhooks, rather than calling this.

KYC Status Values ​

StatusDescription
NONEUser hasn't started verification
PENDINGVerification in progress (document submitted)
VERIFIEDSuccessfully verified
REJECTEDVerification failed

Supported Countries ​

YeboVerify currently supports:

CountryCodeDocuments
EswatiniSZNational ID, Passport
South AfricaZANational ID, Passport, Driver's License
MozambiqueMZNational ID, Passport
ZimbabweZWNational ID, Passport
NamibiaNANational ID, Passport
BotswanaBWNational ID, Passport
LesothoLSNational ID, Passport

More countries coming soon.

Requiring KYC ​

You can require KYC verification for login:

dart
YeboIDProvider(
  config: YeboIDConfig(
    clientId: 'your-client-id',
    redirectUri: 'yourapp://auth',
    requireKyc: true,  // Only allow verified users
  ),
  child: MyApp(),
)

Or handle it in your app:

dart
if (!context.isYeboIdVerified) {
  return VerificationRequiredScreen();
}

Webhooks ​

Get notified when KYC status changes:

json
{
  "event": "kyc.completed",
  "data": {
    "user_id": "usr_abc123",
    "status": "VERIFIED",
    "country": "SZ",
    "verified_at": "2024-01-15T10:30:00Z"
  }
}

See Webhooks for setup.

Best Practices ​

1. Explain the Benefits ​

dart
Container(
  padding: EdgeInsets.all(16),
  child: Column(
    children: [
      Icon(Icons.verified_user, size: 48, color: Colors.amber),
      Text('Verify Your Identity'),
      Text('Unlock these benefits:'),
      BenefitRow(icon: Icons.money, text: 'Higher transfer limits'),
      BenefitRow(icon: Icons.lock, text: 'Enhanced security'),
      BenefitRow(icon: Icons.check, text: 'Priority support'),
      YeboIDVerifyButton(),
    ],
  ),
)

2. Handle Pending State ​

dart
Widget buildKycStatus(YeboIDUser user) {
  if (user.isVerified) {
    return VerifiedBadge();
  }
  
  if (user.isPendingVerification) {
    return Row(
      children: [
        CircularProgressIndicator(),
        Text('Verification in progress...'),
        TextButton(
          onPressed: () => _checkStatus(),
          child: Text('Refresh'),
        ),
      ],
    );
  }
  
  return YeboIDVerifyButton();
}

3. Graceful Failure ​

dart
YeboIDVerifyButton(
  onError: (error) {
    showDialog(
      context: context,
      builder: (_) => AlertDialog(
        title: Text('Verification Issue'),
        content: Text(
          'We couldn\'t complete your verification. '
          'Please try again or contact support.',
        ),
        actions: [
          TextButton(
            onPressed: () => _contactSupport(),
            child: Text('Contact Support'),
          ),
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: Text('Try Again'),
          ),
        ],
      ),
    );
  },
)

Data Access ​

After verification, you can access:

FieldDescriptionScope Required
kyc_statusVerification statuskyc
kyc_countryVerified countrykyc
kyc_birthdayDate of birthkyc (with additional consent)
Full nameLegal name from documentkyc

Request the kyc scope to access this data:

dart
YeboIDConfig(
  clientId: 'your-client-id',
  redirectUri: 'yourapp://auth',
  scopes: ['openid', 'profile', 'phone', 'kyc'],
)

Identity for Africa that understands Africa.