Skip to main content

User Onboarding & KYC

KYC is required before users can deposit funds or use cards. This is the #1 integration blocker — plan for it early in your development timeline.

Overview

Every User must complete Know Your Customer (KYC) verification before they can:
  • Deposit funds
  • Have agents issue cards
  • Make transactions
This is a regulatory requirement for card issuing and cannot be bypassed.

KYC Timeline

StageTypical Duration
User creationInstant
KYC initiationInstant (returns verification URL)
User completes KYC5-10 minutes (user action)
Automated approval1-5 minutes
Manual review (if flagged)1-2 business days
Ready to depositImmediately after approval
Best practice: Initiate KYC as early as possible in your user flow. Don’t wait until the user wants to make their first purchase.

Required Information

The KYC process collects:
CategoryRequired Fields
IdentityFull legal name, date of birth
ContactEmail, phone number
AddressStreet address, city, state, postal code, country
Tax IDSSN (US) or equivalent for other countries
DocumentsGovernment-issued ID (passport, driver’s license)
Additional documents (proof of address, selfie) may be requested if automated verification fails.

Integration Flow

Step 1: Create a User

curl -X POST https://api.ledger.so/v1/users \
  -H "Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "John",
    "lastName": "Doe",
    "email": "[email protected]"
  }'

Step 2: Initiate KYC

curl -X POST https://api.ledger.so/v1/verification/user \
  -H "Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user_abc123"
  }'
Response:
{
  "object": "verification",
  "userId": "user_abc123",
  "applicationStatus": "pending",
  "verificationUrl": "https://kyc.ledger.so/verify/xyz789"
}

Step 3: User Completes Verification

Redirect the user to verificationUrl. They’ll complete the KYC flow which includes:
  1. Personal information form
  2. Government ID upload
  3. Selfie verification (liveness check)
  4. Address verification

Step 4: Handle Webhooks

Subscribe to KYC status webhooks to react to verification results:
app.post('/webhooks', (req, res) => {
  const event = req.body;

  switch (event.type) {
    case 'user.application.approved':
      // User is ready! Enable deposits and card creation
      await enableUserFeatures(event.data.userId);
      break;

    case 'user.application.denied':
      // Verification failed
      await notifyUserDenied(event.data.userId, event.data.reason);
      break;

    case 'user.application.needs_info':
      // Additional documents needed
      await requestAdditionalDocs(event.data.userId, event.data.requiredFields);
      break;
  }

  res.status(200).send('OK');
});

Application Statuses

StatusMeaningNext Step
notStartedKYC not initiatedCall POST /v1/verification/user
pendingUser is completing verificationWait for webhook
needsInformationAdditional docs requiredUser must upload more documents
needsVerificationRe-verification requiredUser must complete verification again
manualReviewUnder manual reviewWait (1-2 business days)
approvedReady to useUser can deposit and transact
deniedVerification failedCannot proceed
lockedAccount lockedContact support

Handling Edge Cases

User Abandons KYC

If a user doesn’t complete verification, you can:
  1. Resend the verification URL — The same URL remains valid
  2. Check statusGET /v1/verification/user/{userId}
  3. Send reminders — Implement your own reminder flow

Additional Documents Needed

When status is needsInformation:
# Check what's needed
curl https://api.ledger.so/v1/verification/user/$USER_ID \
  -H "Api-Key: $API_KEY"

# Response includes requiredFields
{
  "applicationStatus": "needsInformation",
  "requiredFields": ["proofOfAddress", "governmentIdBack"]
}
Upload documents:
curl -X PUT https://api.ledger.so/v1/verification/user/$USER_ID/document \
  -H "Api-Key: $API_KEY" \
  -H "Content-Type: multipart/form-data" \
  -F "documentType=proofOfAddress" \
  -F "file=@/path/to/document.pdf"

KYC Denied

If verification is denied, the user cannot use LedgerOS. Common denial reasons:
  • Identity could not be verified
  • Document appears fraudulent
  • Sanctions list match
  • High-risk jurisdiction
Denied users cannot retry KYC. They must contact support to appeal.

Best Practices

Don’t wait until the user wants to spend. Initiate KYC during signup or onboarding to minimize friction later.
Tell users upfront that identity verification is required. This reduces drop-off and support tickets.
Subscribe to user.application.* webhooks instead of polling the status endpoint.
Some users will be flagged for manual review. Display appropriate messaging (“verification in progress”) rather than leaving them confused.
Use test users in sandbox to verify your KYC flow works end-to-end before going live.