Skip to main content

KYC Integration

This guide covers how to integrate KYC (Know Your Customer) verification into your application using NowRamp.

Overview

KYC verification is required before customers can purchase crypto. The flow is:
  1. Create a customer
  2. Start a KYC case
  3. Customer completes verification (via redirect)
  4. Receive webhook notification
  5. Customer can now transact

Starting KYC

1. Create Customer (if needed)

const customer = await fetch('https://api.nowramp.com/v1/customers', {
  method: 'POST',
  headers: {
    'X-API-Key': apiKey,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    externalUserId: 'user_123',
    email: '[email protected]',
  }),
});

2. Start KYC Case

const kycCase = await fetch('https://api.nowramp.com/v1/kyc-cases', {
  method: 'POST',
  headers: {
    'X-API-Key': apiKey,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    customerId: customer.data.id,
    redirectUrl: 'https://partner-app.com/kyc-complete',
    tier: 'basic',
  }),
});

// Redirect user to KYC provider
window.location.href = kycCase.data.verificationUrl;

3. Handle Completion

When KYC completes, the user is redirected to your redirectUrl:
https://partner-app.com/kyc-complete?status=approved&kycCaseId=kyc_abc123
Handle the redirect:
// pages/kyc-complete.js (Next.js example)
export default function KycComplete() {
  const { status, kycCaseId } = useRouter().query;

  useEffect(() => {
    if (status === 'approved') {
      // KYC approved - redirect to continue flow
      router.push('/buy');
    } else {
      // KYC failed or pending
      router.push('/kyc-status');
    }
  }, [status]);

  return <LoadingSpinner />;
}

Using the Widget

The widget handles KYC automatically:
import { RampWidget } from '@ramp-orchestrator/sdk';

const widget = new RampWidget({
  apiKey: 'your_api_key',
  projectId: 'your_project_id',
  externalUserId: 'user_123',
});

// Widget will show KYC step when needed
widget.on('kycRequired', () => {
  console.log('KYC verification needed');
});

widget.on('kycCompleted', (result) => {
  console.log('KYC status:', result.status);
});

widget.mount('#widget-container');

KYC Tiers

Different tiers have different requirements and limits:
TierDocuments RequiredDaily LimitMonthly Limit
basicID + Selfie$1,000$5,000
standardBasic + Proof of Address$10,000$50,000
enhancedStandard + Source of Funds$100,000$500,000

Requesting a Specific Tier

const kycCase = await startKyc({
  customerId: 'cust_abc123',
  tier: 'standard', // Request higher tier
});

Upgrading Tiers

Customers can upgrade their KYC tier:
// Check current tier
const customer = await getCustomer(customerId);
console.log('Current tier:', customer.data.kycTier);

// Start upgrade
const upgrade = await fetch('https://api.nowramp.com/v1/kyc-cases', {
  method: 'POST',
  headers: { 'X-API-Key': apiKey },
  body: JSON.stringify({
    customerId,
    tier: 'enhanced',
    upgradeFrom: customer.data.kycTier,
  }),
});

Handling KYC Statuses

async function checkKycStatus(customerId) {
  const response = await fetch(
    `https://api.nowramp.com/v1/customers/${customerId}/kyc`,
    { headers: { 'X-API-Key': apiKey } }
  );
  const { data } = await response.json();

  switch (data.status) {
    case 'approved':
      return { canTransact: true, message: 'Ready to buy crypto' };

    case 'pending':
      return {
        canTransact: false,
        message: 'Please complete KYC verification',
        action: 'start_kyc',
      };

    case 'in_progress':
      return {
        canTransact: false,
        message: 'Verification in progress',
        action: 'wait',
      };

    case 'rejected':
      return {
        canTransact: false,
        message: 'Verification failed. Please contact support.',
        reason: data.rejectionReason,
      };

    case 'expired':
      return {
        canTransact: false,
        message: 'Verification expired. Please try again.',
        action: 'restart_kyc',
      };
  }
}

Webhook Integration

Listen for KYC events:
app.post('/webhooks/ramp', (req, res) => {
  const { type, data } = req.body;

  switch (type) {
    case 'kyc.approved':
      // Update user status in your database
      await db.users.update(data.externalUserId, {
        kycStatus: 'approved',
        kycApprovedAt: new Date(),
      });
      // Send notification
      await sendEmail(data.email, 'Your verification is complete!');
      break;

    case 'kyc.rejected':
      await db.users.update(data.externalUserId, {
        kycStatus: 'rejected',
        kycRejectionReason: data.rejectionReason,
      });
      await sendEmail(data.email, 'Verification issue - please contact support');
      break;
  }

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

KYC Providers

KYCAID (Default)

  • Fast automated verification
  • 190+ countries
  • ID + Selfie + Liveness check

Ondato

  • EU-focused
  • Video verification available
  • Enhanced document checks
KYC providers are configured by the NowRamp team during your onboarding process. Contact your account manager to set up or change your KYC provider configuration.

Testing in Sandbox

Use test documents in sandbox:
DocumentResult
Passport with “APPROVED”KYC approved
Passport with “REJECTED”KYC rejected
Passport with “REVIEW”Sent to manual review
// Sandbox testing
const kycCase = await startKyc({
  customerId: 'test_customer_123',
  tier: 'basic',
});

// Use sandbox KYC provider - accepts test documents