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
YeboIDVerifyButton(
onVerified: () {
print('User verified!');
// Refresh user data
YeboIDProvider.of(context).fetchUser();
},
onError: (error) {
print('Verification failed: $error');
},
)Or manually:
final client = YeboIDProvider.of(context);
final verifyUrl = await client.startKycVerification();
if (verifyUrl != null) {
// Open in browser
await launchUrl(Uri.parse(verifyUrl));
}API
POST https://api.yeboid.com/verification/start
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"callback": "yourapp://kyc-complete"
}Parameters:
| Field | Required | Description |
|---|---|---|
callback | No | Absolute 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:
{
"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:
| Status | code | Meaning |
|---|---|---|
| 401 | — | Missing or invalid access token |
| 404 | — | User not found |
| 409 | ALREADY_VERIFIED | User is already VERIFIED; there is nothing to start |
Checking Status
User Properties
After the user completes verification, their profile is updated:
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
GET https://api.yeboid.com/verification/status
Authorization: Bearer ACCESS_TOKENResponse:
{
"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
| Status | Description |
|---|---|
NONE | User hasn't started verification |
PENDING | Verification in progress (document submitted) |
VERIFIED | Successfully verified |
REJECTED | Verification failed |
Supported Countries
YeboVerify currently supports:
| Country | Code | Documents |
|---|---|---|
| Eswatini | SZ | National ID, Passport |
| South Africa | ZA | National ID, Passport, Driver's License |
| Mozambique | MZ | National ID, Passport |
| Zimbabwe | ZW | National ID, Passport |
| Namibia | NA | National ID, Passport |
| Botswana | BW | National ID, Passport |
| Lesotho | LS | National ID, Passport |
More countries coming soon.
Requiring KYC
You can require KYC verification for login:
YeboIDProvider(
config: YeboIDConfig(
clientId: 'your-client-id',
redirectUri: 'yourapp://auth',
requireKyc: true, // Only allow verified users
),
child: MyApp(),
)Or handle it in your app:
if (!context.isYeboIdVerified) {
return VerificationRequiredScreen();
}Webhooks
Get notified when KYC status changes:
{
"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
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
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
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:
| Field | Description | Scope Required |
|---|---|---|
kyc_status | Verification status | kyc |
kyc_country | Verified country | kyc |
kyc_birthday | Date of birth | kyc (with additional consent) |
| Full name | Legal name from document | kyc |
Request the kyc scope to access this data:
YeboIDConfig(
clientId: 'your-client-id',
redirectUri: 'yourapp://auth',
scopes: ['openid', 'profile', 'phone', 'kyc'],
)