Reverification

Streamlined identity re-verification for returning users who need to authenticate from a new device or after a security event.

What is Reverification?

Reverification allows users to quickly verify their identity using only a new selfie - no need to re-enter personal information or upload documents again. Perfect for device changes, step-up authentication, or periodic security checks.

When to Use Reverification

Verification vs Reverification

ScenarioUse VerificationUse Reverification
New user signing up✅ Full identity verification❌ No existing identity data
User logging in from new device❌ Unnecessary friction✅ Quick re-authentication
Suspicious activity detected❌ Overkill for existing user✅ Fast security check
Periodic re-verification❌ Too time-consuming✅ Quick security check

User Experience Comparison

Initial Verification

📋 Personal Info Form

📄 Document Upload

📸 Selfie Photo

Reverification

📸 Selfie Photo Only

✓ Uses data from original verification
✓ No form required
✓ No document upload

Integration Steps

1. Trigger Detection (Your Responsibility)

Detect when reverification is needed based on your business logic:

async function handleUserLogin(userId: string, deviceId: string) {
  // Check if this device is registered
  const isKnownDevice = await yourDatabase.checkDevice(userId, deviceId);

  if (!isKnownDevice) {
    // ⚠️ NEW DEVICE DETECTED - Trigger Reverification
    return await startReverificationFlow(userId);
  }

  // Known device - proceed normally
  return await grantAccess(userId);
}

Your Decision

YOU decide when to trigger reverification: - New device login - High-value transaction - Suspicious activity - Time-based (every N days) - Risk score threshold

2. Start Reverification Flow

Call the SDK with the referenceId from the original verification:

import { createVecuIDVSDK } from 'vec-idp-web-sdk';

async function startReverificationFlow(userId: string) {
  // 1. referenceId is your customer/user ID
  const referenceId = userId; // This is what you used during original verification

  // 2. Initialize SDK
  const sdk = createVecuIDVSDK();
  await sdk.updateConfig({
    deploymentStage: 'production',
    bearerToken: await getYourOAuthToken(),
  });

  // 3. Start reverification (this triggers the selfie flow)
  try {
    const cleanup = await sdk.startReverification(
      document.getElementById('verification-container'),
      {
        referenceId: referenceId,

        // Optional: Phone number for SMS notifications
        phoneNumber: user.phoneNumber, // e.g., '+1-555-123-4567'
        sendMessage: true, // Default: true (sends SMS with verification link)

        onSuccess: result => {
          console.log('Reverification completed!', result);
          // User successfully reverified
        },
        onError: error => {
          console.error('Reverification failed:', error);
          // Handle error
        },
      }
    );

    // The SDK now displays the selfie capture UI
  } catch (error) {
    // Handle errors (network issues, invalid referenceId, etc.)
    console.error('Failed to start reverification:', error);
    await showUserError('Unable to verify. Please try again.');
  }
}

Optional Parameters

phoneNumber - Provide the user's phone number to receive SMS notifications with the verification link. If omitted, no SMS is sent.

sendMessage - Control whether SMS is sent (default: true). Set to false to disable SMS even if phone number is provided.

What Happens Behind the Scenes

  1. SDK calls VECU API
  2. VECU looks up original verification using referenceId
  3. VECU retrieves verificationId
  4. Identity provider shows selfie capture UI
  5. User takes selfie
  6. Provider performs face match against original documents
  7. Result delivered via webhook to your server

3. Handle Webhook Results

Same Webhook Endpoint

Reverification uses your existing webhook endpoint from verification. Simply add handling for the reverification.completed event type - no need to configure a new webhook URL.

Webhook Event Types:

Your webhook will receive the following event types during reverification:

  • reverification.status_changed - Intermediate status updates during processing
  • reverification.completed - Final result with status completed (decision: approved/rejected/manual_review)
  • reverification.failed - Final result with status failed (system error or unable to process)

Receive and process the reverification decision:

app.post('/webhooks/vecu', async (req, res) => {
  const event = req.body;

  // Handle intermediate status updates
  if (event.eventType === 'reverification.status_changed') {
    const { referenceId, status } = event.data;
    const userId = await yourDatabase.getUserIdByReference(referenceId);

    // Update UI or log progress
    await yourDatabase.updateVerificationStatus(userId, status);
    await sendProgressUpdate(userId, status);
  }

  // Handle successful completion
  if (event.eventType === 'reverification.completed') {
    const { referenceId, decision, verificationId } = event.data;
    const userId = await yourDatabase.getUserIdByReference(referenceId);

    if (decision === 'approved') {
      // ✅ VERIFIED - Grant access
      await yourDatabase.registerDevice(userId, currentDeviceId);
      await yourDatabase.updateUserSession(userId, { verified: true });
      await sendPushNotification(userId, 'Device verified successfully');
    } else if (decision === 'rejected') {
      // ❌ FAILED - Handle rejection
      await yourDatabase.logSecurityEvent(userId, 'reverification_failed');
      await handleVerificationFailure(userId);
    } else if (decision === 'manual_review') {
      // ⚠️ NEEDS REVIEW - Temporary state
      await yourDatabase.setUserStatus(userId, 'pending_review');
      await sendEmail(userId, 'Your verification is under review');
    }
  }

  // Handle system failures
  if (event.eventType === 'reverification.failed') {
    const { referenceId, error } = event.data;
    const userId = await yourDatabase.getUserIdByReference(referenceId);

    // Log error and notify user
    await yourDatabase.logError(userId, 'reverification_system_error', error);
    await sendEmail(userId, 'Verification unavailable - please try again');
  }

  // Always return 200 to acknowledge receipt
  res.status(200).json({ received: true });
});

Integration Flow

👤
User
Login from new device

Your Application

✓ Detect new device or security event

✓ Retrieve

referenceId

from database

✓ Call

sdk.startReverification()

VECU SDK

📸 Display selfie capture UI
👤 User takes selfie
🔍 Process and verify identity

Your Webhook Endpoint

✓ Receive

reverification.completed

event

✓ Check decision (approved/rejected/manual_review)
✓ Register device or handle rejection
✓ Grant or deny access

User Verified
Access granted

Step-by-Step Process

1. User Action

  • User attempts login from new device

2. Your Application Detects & Triggers

  • Detect: New device or security event
  • Decide: Reverification needed
  • Get referenceId (same customer ID used in original verification)
  • Call: sdk.startReverification(container, { referenceId })

3. VECU API Processing

  • Lookup original verification using referenceId
  • Call identity provider API to retrieve existing verification record and initiate selfie check

4. User Experience

  • Identity provider displays selfie capture UI
  • User takes selfie photo
  • Liveness detection performed
  • Face match against original documents

5. Decision & Result

  • Identity provider generates decision (approved/rejected/manual_review)
  • VECU API stores result
  • Webhook triggered to your endpoint

6. Your Application Responds

  • Receive webhook event: reverification.completed
  • Process decision (approved/rejected/manual_review)
  • Register device or handle rejection
  • Grant or deny access to user

Asynchronous Flow

The process is asynchronous - from SDK call to webhook delivery. Your application should show a loading state while the user completes the selfie capture and processing occurs.

Decision Outcomes

Approved ✅

{
  "decision": "approved",
  "reasons": [
    {
      "code": "id.selfie.match",
      "description": "Selfie matches document photo"
    },
    {
      "code": "id.liveness.passed",
      "description": "Liveness check passed"
    }
  ]
}

Your Action: Grant access, register device, allow transaction

Rejected ❌

{
  "decision": "rejected",
  "reasons": [
    {
      "code": "id.selfie.no_match",
      "description": "Selfie does not match document photo"
    }
  ]
}

Your Action: Deny access, optionally allow retry or escalate to support

Manual Review ⚠️

{
  "decision": "manual_review",
  "reasons": [
    {
      "code": "id.selfie.unclear",
      "description": "Image quality insufficient for automated decision"
    }
  ]
}

Your Action: Display "under review" message, check status later

Implementation Checklist

  • Implement trigger logic (detect new device/high-risk action)
  • Use consistent customer ID as referenceId (same as initial verification)
  • Add startReverification() call with user's referenceId
  • Add reverification.completed event handling to existing webhook
  • Handle reverification decisions (approved/rejected/manual_review)
  • Add business logic for device registration
  • Add error handling for network/API failures
  • Test in sandbox with sample users
  • Test all decision outcomes (approved/rejected/manual_review)
  • Test webhook delivery and retries
  • Test edge cases (invalid referenceId, expired verification)

Frequently Asked Questions

What if the user refuses the selfie?

Your decision. Handle it in your app:

  • Lock the account until they complete reverification
  • Allow limited access (read-only mode)
  • Escalate to manual review

What if the webhook fails to deliver?

We retry automatically:

  • 3 attempts with exponential backoff
  • If all fail, event goes to Dead Letter Queue

Can I test without a real camera?

Yes, use the interactive demo:

  • Experience the flow in our Interactive Demo
  • Simulates the complete reverification process
  • No camera or real verification required

Try It Now

Interactive Demo

Experience the reverification flow in our Interactive Demo:

  1. Complete a full verification first (get a referenceId)
  2. Use the reverification tab to simulate a returning user
  3. See the simplified selfie-only flow
  4. Compare the streamlined experience

Next Steps

  1. Review Webhook Structure: See Webhooks for complete event schemas
  2. Check API Reference: See API Reference for startReverification() method details
  3. Try the Interactive Demo: Use the Demo to experience the reverification flow

Support

Questions?