Start User Verification
curl --request GET \
--url https://api.example.com/v1/user/verification \
--header 'Authorization: <authorization>' \
--header 'x-client-key: <x-client-key>'import requests
url = "https://api.example.com/v1/user/verification"
headers = {
"x-client-key": "<x-client-key>",
"Authorization": "<authorization>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'x-client-key': '<x-client-key>', Authorization: '<authorization>'}
};
fetch('https://api.example.com/v1/user/verification', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/user/verification",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"x-client-key: <x-client-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/user/verification"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-client-key", "<x-client-key>")
req.Header.Add("Authorization", "<authorization>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/v1/user/verification")
.header("x-client-key", "<x-client-key>")
.header("Authorization", "<authorization>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/user/verification")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-client-key"] = '<x-client-key>'
request["Authorization"] = '<authorization>'
response = http.request(request)
puts response.read_body{
"message": "Not authenticated"
}
{
"message": "Not authorized"
}
{
"message": "Internal server error"
}
User
Start User Verification
Generates a verification session URL for identity verification
GET
/
v1
/
user
/
verification
Start User Verification
curl --request GET \
--url https://api.example.com/v1/user/verification \
--header 'Authorization: <authorization>' \
--header 'x-client-key: <x-client-key>'import requests
url = "https://api.example.com/v1/user/verification"
headers = {
"x-client-key": "<x-client-key>",
"Authorization": "<authorization>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'x-client-key': '<x-client-key>', Authorization: '<authorization>'}
};
fetch('https://api.example.com/v1/user/verification', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/user/verification",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"x-client-key: <x-client-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/user/verification"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-client-key", "<x-client-key>")
req.Header.Add("Authorization", "<authorization>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/v1/user/verification")
.header("x-client-key", "<x-client-key>")
.header("Authorization", "<authorization>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/user/verification")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-client-key"] = '<x-client-key>'
request["Authorization"] = '<authorization>'
response = http.request(request)
puts response.read_body{
"message": "Not authenticated"
}
{
"message": "Not authorized"
}
{
"message": "Internal server error"
}
Overview
This endpoint generates a time-limited, single-use verification session URL that you direct your users to for completing identity verification. The verification process is handled by Baanx’s integrated identity verification provider. Use this endpoint when:- A user registers and needs to complete identity verification
- A user’s verification was rejected and they need to retry
- You want to upgrade an unverified user to verified status
How It Works
1
Generate Session URL
Call this endpoint to receive a unique verification session URL
2
Redirect User
Direct the user to the session URL (web redirect or open in webview/browser)
3
User Completes Verification
User uploads documents and completes identity checks on the verification provider’s page
4
Verification Processing
The provider processes the submission (typically 5-30 minutes)
5
Status Update
User’s
verificationState is updated to either PENDING, VERIFIED, or REJECTED6
Verification Complete
Check the user’s verification status via GET /v1/user
Authentication
This endpoint requires both client authentication and user authentication:string
required
Your client public key for API authentication
string
required
Bearer token obtained from OAuth flow or login endpoint
boolean
default:"false"
Set to
true to route requests to the US backend environment (if available for your client). Defaults to international environment.Response
string
Time-limited verification session URL. Direct the user to this URL to complete identity verification. The URL typically expires after 24 hours and is single-use only.
Examples
curl --request GET \
--url https://dev.api.baanx.com/v1/user/verification \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'x-client-key: YOUR_CLIENT_KEY'
const response = await fetch('https://dev.api.baanx.com/v1/user/verification', {
method: 'GET',
headers: {
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'x-client-key': 'YOUR_CLIENT_KEY'
}
});
const { sessionUrl } = await response.json();
window.location.href = sessionUrl;
interface VerificationSession {
sessionUrl: string;
}
async function startVerification(accessToken: string): Promise<string> {
const response = await fetch('https://dev.api.baanx.com/v1/user/verification', {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-client-key': 'YOUR_CLIENT_KEY'
}
});
if (!response.ok) {
throw new Error('Failed to start verification');
}
const data: VerificationSession = await response.json();
return data.sessionUrl;
}
const sessionUrl = await startVerification(accessToken);
window.location.href = sessionUrl;
import requests
url = "https://dev.api.baanx.com/v1/user/verification"
headers = {
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"x-client-key": "YOUR_CLIENT_KEY"
}
response = requests.get(url, headers=headers)
data = response.json()
session_url = data['sessionUrl']
print(f"Redirect user to: {session_url}")
Response Example
{
"sessionUrl": "https://example.com?sessionId=12345-12345-12345b"
}
Error Responses
{
"message": "Not authenticated"
}
{
"message": "Not authorized"
}
{
"message": "Internal server error"
}
Error Response Details
Error Response Details
401 Unauthorized
The access token is missing, invalid, or expired. You need to:- Ensure the Authorization header is present and properly formatted
- Verify the access token hasn’t expired (6-hour lifetime)
- Obtain a new access token using the refresh token if expired
403 Forbidden
The access token is valid but doesn’t have permission to access this resource. This may occur if:- The token doesn’t belong to a valid user
- The client key doesn’t match the user’s associated client
- The user account has been suspended or disabled
500 Internal Server Error
An unexpected error occurred on the server. If this persists:- Check the API status page
- Contact support with the request timestamp
- Implement retry logic with exponential backoff
Implementation Examples
Web Application Flow
import { useRouter } from 'next/navigation';
async function handleStartVerification() {
try {
const response = await fetch('https://dev.api.baanx.com/v1/user/verification', {
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-client-key': process.env.NEXT_PUBLIC_CLIENT_KEY
}
});
if (!response.ok) {
throw new Error('Failed to start verification');
}
const { sessionUrl } = await response.json();
window.location.href = sessionUrl;
} catch (error) {
console.error('Verification error:', error);
showErrorToast('Unable to start verification. Please try again.');
}
}
Mobile Application Flow (React Native)
import { Linking } from 'react-native';
async function startVerificationMobile(accessToken: string) {
try {
const response = await fetch('https://dev.api.baanx.com/v1/user/verification', {
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-client-key': YOUR_CLIENT_KEY
}
});
const { sessionUrl } = await response.json();
const canOpen = await Linking.canOpenURL(sessionUrl);
if (canOpen) {
await Linking.openURL(sessionUrl);
}
} catch (error) {
console.error('Failed to open verification:', error);
}
}
In-App Browser Flow
For better UX, open the verification URL in an in-app browser:import { InAppBrowser } from 'react-native-inappbrowser-reborn';
async function startVerificationInApp(accessToken: string) {
try {
const response = await fetch('https://dev.api.baanx.com/v1/user/verification', {
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-client-key': YOUR_CLIENT_KEY
}
});
const { sessionUrl } = await response.json();
if (await InAppBrowser.isAvailable()) {
await InAppBrowser.open(sessionUrl, {
dismissButtonStyle: 'cancel',
preferredBarTintColor: '#16A34A',
preferredControlTintColor: 'white',
readerMode: false,
animated: true,
modalEnabled: true,
enableBarCollapsing: false
});
}
} catch (error) {
console.error('Failed to open verification:', error);
}
}
Polling for Verification Completion
After redirecting the user, implement polling to detect when verification is complete:async function pollVerificationStatus(
accessToken: string,
onComplete: (verified: boolean) => void
) {
const maxAttempts = 60; // 5 minutes with 5-second intervals
let attempts = 0;
const poll = setInterval(async () => {
try {
const response = await fetch('https://dev.api.baanx.com/v1/user', {
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-client-key': YOUR_CLIENT_KEY
}
});
const user = await response.json();
if (user.verificationState === 'VERIFIED') {
clearInterval(poll);
onComplete(true);
} else if (user.verificationState === 'REJECTED') {
clearInterval(poll);
onComplete(false);
}
attempts++;
if (attempts >= maxAttempts) {
clearInterval(poll);
console.log('Verification still pending after 5 minutes');
}
} catch (error) {
console.error('Polling error:', error);
}
}, 5000); // Poll every 5 seconds
return () => clearInterval(poll);
}
const stopPolling = pollVerificationStatus(accessToken, (verified) => {
if (verified) {
showSuccessMessage('Verification complete! You can now order a card.');
} else {
showErrorMessage('Verification was rejected. Please contact support.');
}
});
Important Notes
Session Expiry: The verification session URL typically expires after 24 hours. If a user doesn’t complete verification within this time, you’ll need to generate a new session URL by calling this endpoint again.
Single Use: Each session URL is single-use. Once the user completes (or abandons) the verification session, the URL becomes invalid. Generate a new URL for retry attempts.
User Experience: For the best user experience:
- Display a clear message explaining why verification is needed
- Show what documents will be required (government ID, proof of address)
- Inform users about the typical processing time (5-30 minutes)
- Provide a way to check verification status after completion
Verification Process Details
Required Documents
Users will typically need to provide:Government-Issued ID
Government-Issued ID
One of the following:
- Passport
- Driver’s license
- National ID card
- Residence permit
- Must be valid (not expired)
- Clear, readable photo of the document
- All corners visible in the image
Selfie Verification
Selfie Verification
- Live selfie or video recording
- Used for biometric matching with ID photo
- Ensures the person presenting the ID is the actual holder
Proof of Address (Region Dependent)
Proof of Address (Region Dependent)
Document showing current residential address (dated within last 3 months):
- Utility bill (electricity, water, gas)
- Bank statement
- Government correspondence
- Rental agreement
Verification Timeline
1
Immediate (0-2 minutes)
Automated checks: Document authenticity, facial recognition, data extraction
2
Quick Review (5-15 minutes)
Most verifications complete automatically within this timeframe
3
Manual Review (15-30 minutes)
If automated checks are inconclusive, manual review by compliance team
4
Extended Review (1-24 hours)
Complex cases requiring additional verification or document requests
Edge Cases & Limitations
Already Verified Users
If a user is already verified and calls this endpoint:- A new verification session is still generated
- The existing verification status remains until the new session completes
- This allows users to update their verification documents if needed
Verification Rejection
If verification is rejected, the user’sverificationState becomes REJECTED. Common rejection reasons:
Document Issues
Document Issues
- Expired documents
- Poor image quality (blurry, dark, cut-off)
- Documents not accepted in user’s region
- Mismatched document information
Identity Mismatch
Identity Mismatch
- Selfie doesn’t match ID photo
- Name on documents doesn’t match registration
- Age doesn’t meet minimum requirements (typically 18+)
Fraud Detection
Fraud Detection
- Document appears altered or fake
- User on sanctions or watchlist
- Previous account with same credentials
- Suspicious behavior patterns
Address Verification
Address Verification
- Proof of address doesn’t match registered address
- Document too old (must be within 3 months)
- Address in restricted region
Retry After Rejection
When a user is rejected:- Check rejection reason (contact support if not clear)
- Wait 24 hours before retry (cooldown period)
- Generate new verification session
- Ensure documents meet all requirements
- Submit with corrected/additional documents
async function retryVerification(accessToken: string) {
const userResponse = await fetch('https://dev.api.baanx.com/v1/user', {
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-client-key': YOUR_CLIENT_KEY
}
});
const user = await userResponse.json();
if (user.verificationState === 'REJECTED') {
// Show guidance on what went wrong
showRejectionGuidance();
// Generate new session after user confirms they're ready
const verificationResponse = await fetch(
'https://dev.api.baanx.com/v1/user/verification',
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-client-key': YOUR_CLIENT_KEY
}
}
);
const { sessionUrl } = await verificationResponse.json();
window.location.href = sessionUrl;
}
}
Regional Differences
International Environment:- Standard KYC requirements
- Typical processing: 5-30 minutes
- Document requirements vary by country
- Enhanced KYC requirements
- SSN verification
- Additional compliance checks
- May require proof of address
- Typical processing: 15-60 minutes
Session Abandonment
If a user starts verification but doesn’t complete it:- The session URL remains valid until expiry (24 hours)
- User’s
verificationStatestays at current value - No partial progress is saved
- User can restart by generating a new session URL
Rate Limiting
- Maximum 10 verification sessions per user per day
- Maximum 3 concurrent active sessions per user
- Cooldown period of 1 hour after 3 consecutive failures
{
"message": "Rate limit exceeded",
"retryAfter": 3600,
"limit": "3_per_hour"
}
Webhook Notifications
While this endpoint doesn’t directly support webhooks, you can configure verification status webhooks in your client dashboard to receive real-time notifications when a user’s verification status changes.
{
"event": "user.verification.completed",
"userId": "100a99cf-f4d3-4fa1-9be9-2e9828b20ebb",
"verificationState": "VERIFIED",
"timestamp": "2024-01-15T10:30:00Z"
}
Testing
Sandbox Environment
In sandbox/test environments, you can use test documents to simulate different verification outcomes:// Test user - will auto-approve
const testApprovedUser = {
firstName: "Test",
lastName: "Approved"
};
// Test user - will auto-reject
const testRejectedUser = {
firstName: "Test",
lastName: "Rejected"
};
// Test user - will remain pending
const testPendingUser = {
firstName: "Test",
lastName: "Pending"
};
Related Endpoints
- Get User Details - Check current verification status
- Order Card - Requires VERIFIED status
- Register User - Initial user registration
- Get External Wallets - View wallet balances (some features require verification)
Best Practices
User Guidance
User Guidance
Before redirecting users to verification:
- Explain why verification is required
- List required documents
- Estimate processing time
- Provide preparation tips (good lighting, clear images)
Error Handling
Error Handling
Implement robust error handling:
- Network failures during session generation
- User closing verification window prematurely
- Session expiry
- Verification rejection
Status Monitoring
Status Monitoring
After verification:
- Poll user status periodically
- Show loading state while verification processes
- Display clear success/failure messages
- Provide next steps based on outcome
Security
Security
- Never store or log verification session URLs
- Implement CSRF protection on your redirect endpoints
- Validate the user’s session before generating verification URL
- Use HTTPS for all communications
Was this page helpful?