Connect
v2025-08-28Support

User Onboarding & KYB

Cleavr Connect provides a streamlined onboarding flow that handles KYB (Know Your Business) verification, payment setup, and compliance requirements—all in one seamless experience.

Info

Platform Accounts vs User Accounts: Platform accounts are separate from direct Cleavr accounts. Users creating accounts through your platform will have dedicated platform-linked accounts.

Onboarding Flow Overview

Three-phase onboarding journey from setup to completion.

SetupVerificationCompleteUser redirectedApproved
Info

Detailed Steps: Setup (create user, prefill data) → Verification (hosted onboarding, KYB, terms) → Complete (platform callback, user ready to send receivables)

Implementation

Step 1: Create User Account

Create a user account with prefilled data from your platform:

javascript
const user = await cleavr.users.create({
// Required fields
email: 'user@company.com',
// Company information (prefillable)
company: {
name: 'ACME Corporation',
siret: '12345678900001', // French company ID
vat_number: 'FR12345678901',
address: {
line1: '123 Rue de la Paix',
line2: 'Floor 3',
city: 'Paris',
postal_code: '75001',
country: 'FR'
},
website: 'https://acme-corp.com'
},
// User information (prefillable)
contact: {
first_name: 'Jean',
last_name: 'Dupont',
phone: '+33612345678',
job_title: 'CEO'
},
// Platform configuration
platform: {
callback_url: 'https://yourapp.com/onboarding/complete',
metadata: {
platform_user_id: 'usr_123456',
account_type: 'premium'
}
}
});

Response:

json
{
"id": "usr_clv_a1b2c3d4e5f6",
"email": "user@company.com",
"status": "pending_onboarding",
"onboarding_url": "https://onboarding.api.cleavr.fr/start?token=xxx",
"created_at": "2025-08-28T10:00:00Z"
}

Step 2: Direct to Hosted Onboarding

Redirect the user to complete onboarding:

javascript
// Option 1: Full page redirect
window.location.href = user.onboarding_url;
// Option 2: Modal/iframe (if enabled for your platform)
const modal = new CleavrOnboardingModal({
url: user.onboarding_url,
onComplete: (result) => {
console.log('Onboarding completed:', result);
},
onCancel: () => {
console.log('User cancelled onboarding');
}
});
modal.open();

Step 3: Handle Callback

After onboarding completion, we redirect to your callback URL:

Command Line
https://yourapp.com/onboarding/complete?
user_id=usr_clv_a1b2c3d4e5f6&
status=completed&
signature=xxx

Verify the callback signature:

javascript
app.get('/onboarding/complete', async (req, res) => {
const { user_id, status, signature } = req.query;
// Verify signature
const expectedSignature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(`${user_id}:${status}`)
.digest('hex');
if (signature !== expectedSignature) {
return res.status(400).send('Invalid signature');
}
// Check onboarding status
if (status === 'completed') {
// User is ready to send receivables
await markUserAsOnboarded(user_id);
res.redirect('/dashboard?onboarding=success');
} else {
// Handle incomplete onboarding
res.redirect('/dashboard?onboarding=incomplete');
}
});

Checking Onboarding Status

Get User Requirements

Check what's missing for a user to be fully onboarded:

javascript
const requirements = await cleavr.users.getRequirements(userId);

Response:

json
{
"user_id": "usr_clv_a1b2c3d4e5f6",
"status": "pending_verification",
"requirements": {
"currently_due": [
"identity_document",
"proof_of_address"
],
"eventually_due": [
"business_registration"
],
"past_due": [],
"errors": []
},
"capabilities": {
"send_receivables": false,
"receive_payments": false
},
"verification": {
"identity": "pending",
"business": "verified",
"bank_account": "verified"
}
}

Status Webhooks

Subscribe to onboarding status changes:

json
{
"event": "user.onboarding.updated",
"data": {
"user_id": "usr_clv_a1b2c3d4e5f6",
"status": "completed",
"capabilities": {
"send_receivables": true,
"receive_payments": true
}
}
}

Prefilling Strategies

Maximum Prefill

Prefill everything you have to minimize user friction:

javascript
const userData = {
email: platformUser.email,
company: {
name: platformUser.company_name,
siret: await fetchFromAPI('sirene', platformUser.company_name),
vat_number: platformUser.vat_id,
address: { ...platformUser.billing_address },
website: platformUser.website,
phone: platformUser.company_phone
},
contact: {
first_name: platformUser.first_name,
last_name: platformUser.last_name,
phone: platformUser.mobile_phone,
job_title: platformUser.position,
civility: platformUser.title // 'M', 'Mme', 'Mx'
},
legal_representative: {
first_name: platformUser.legal_rep_first_name,
last_name: platformUser.legal_rep_last_name,
date_of_birth: platformUser.legal_rep_dob,
nationality: platformUser.legal_rep_nationality
}
};

Terms of Service

Automatic Acceptance

Terms are accepted as part of the onboarding flow:

javascript
// Terms acceptance is tracked automatically
{
terms_accepted: {
version: "2025.8",
accepted_at: "2025-08-28T10:30:00Z",
ip_address: "192.168.1.1",
user_agent: "Mozilla/5.0..."
}
}

Troubleshooting

Common Issues

IssueCauseSolution
Onboarding URL expiredURLs expire after 7 daysGenerate new URL with getOnboardingUrl()
KYB verification stuckMissing documentsCheck getRequirements() for missing items
Callback not receivedNetwork issueImplement webhook backup
Duplicate userEmail already existsUse unique email per platform account

Next Steps

Once users are onboarded:

  1. Start Sending Receivables
  2. Configure Webhooks