Platform Integration Layers

Overview

This guide enables partners to build identity verification solutions that are use case agnostic and support both initial identity establishment and fast re-verification flows. The integration uses CLEAR's User Profile Matching technology to bind verified identity to customer employee records, enabling seamless authentication across multiple use cases.

Key Outcome: Once a user completes identity establishment, all subsequent verifications across any use case become fast, friction-reduced selfie-only flows.


Integration Layers: What Partners Must Build

A complete CLEAR integration requires partners to build two critical layers:

Layer 1: Admin Configuration Experience

The backend configuration and setup that enables customers to connect their CLEAR environment to your platform. This includes:

  • CLEAR Environment Provisioning: How customers obtain CLEAR credentials
  • Credential Management: Where customers input and manage their Project IDs and API keys
  • Workflow Configuration: Defining which use cases trigger CLEAR verification
  • Data Mapping Configuration: Specifying which customer fields map to CLEAR data

Layer 2: Customer End User Experience

The actual verification flow that your customer's end users (their employees/users) experience. Once your customer configures CLEAR credentials (Layer 1), their end users can verify their identity. This layer is about facilitating the standard CLEAR integration experience for your customers:

Core Integration Components:

  • Create Verification Session (API Docs): Initiate CLEAR verification with the right project and data
  • Get Verification Results (API Docs): Retrieve session results and map data back to user records
  • User Profile Matching Logic: Check if CLEAR userID exists, route to appropriate flow (Project A with UPM or Project B with known user key)
  • Result Retrieval Mechanism: Define redirect path to pull verification results (redirect, polling, or button-triggered)

What Partners Must Build:

  1. Data System Check: Mechanism to check if CLEAR userID exists on user record
  2. Flow Routing:
    • If no userID → Create session with Project A (User Profile Matching), send employee_id in custom_fields
    • If userID exists → Create session with Project B (Known User Key), send user_id in request
  3. Redirect Path Definition: Specify redirect_url in both create session API calls
  4. Result Processing: When user redirects back, call Get Verification endpoint to retrieve results
  5. Data Correlation: Map returned data back to correct user record using employee_id from custom_fields
  6. UserID Storage: Store CLEAR user_id when User Profile Matching returns match_result: "match"

User Experience Patterns:

  • Traditional Web Application: Pre-verification screen → CLEAR verification → Post-verification landing screen
  • Terminal Screen: CLEAR ends on final screen, results retrieved via polling or agent-triggered button
  • Call Center Assisted: Agent helps user verify, retrieves results manually

Key Point: The end goal is to create the session, retrieve results, and map the verified identity back to the correct user record by correlating data.

Both layers must work together seamlessly to deliver a complete identity verification solution.


Layer 1: Admin Configuration Experience

Overview

Before any end user can verify their identity with CLEAR, your platform must enable customers (admins/IT teams) to configure CLEAR within your system. This configuration determines:

  • Which CLEAR environment and projects power the verification
  • Who owns and controls the verification data
  • Which workflows and use cases trigger CLEAR
  • Where and how data is stored

Configuration Options for Partners

Partners must implement at minimum Option A (Bring Your Own Keys). Option B (Self-Service Procurement) is optional but recommended for a seamless customer experience.


Option A: Bring Your Own Keys (BYOK) - REQUIRED

What It Is: A configuration interface that allows customers to input their own CLEAR environment credentials (Project IDs and API keys) obtained directly from CLEAR.

Why It's Critical: Ensures customers own and control their verification data. Data flows through customer-specific CLEAR tenants, not shared infrastructure. This is a fundamental requirement for enterprise security and compliance.

What Partners Must Build:

  1. Admin Configuration UI - A secure settings page where authorized admins can input:

    • Establish Identity Project ID: For first-time verification with User Profile Matching
    • Known User Key Project ID: For fast re-verification flows
    • API Key: Authentication credential (supports both projects)
    • Environment Selection: Production vs. Sandbox
  2. Credential Storage - Secure backend storage for customer-specific CLEAR credentials:

    • Encrypted at rest
    • Scoped per customer/tenant
    • Accessible only to authorized platform services
  3. Credential Validation - Test connectivity before saving:

    async function validateClearCredentials(projectId, apiKey) {
      try {
        // Validate by attempting to create a test session
        const response = await fetch('https://verified.clearme.com/v1/verification_sessions', {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${apiKey}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            project_id: projectId,
            redirect_url: 'https://yourapp.com/test',
            custom_fields: { test: 'validation' }
          })
        });
        
        // Valid credentials return 200/201
        return response.ok;
      } catch (error) {
        return false;
      }
    }

    Note: There is no dedicated /validate endpoint. Validate credentials by creating a test session and checking for a successful response (200/201 status).

Implementation Checklist:

  • Secure settings page accessible only to authorized admins
  • Input fields for both Project IDs and API Key
  • Credential validation before saving
  • Encrypted storage of credentials
  • Credential rotation support
  • Audit logging of configuration changes

Option B: Self-Service Procurement (OPTIONAL)

What It Is: Enable customers to provision CLEAR environments, create projects, and generate credentials directly through your platform using CLEAR's provisioning APIs. Credentials are automatically populated into the BYOK configuration UI.

Why Consider It:

  • Reduces customer friction (no need to contact CLEAR separately)
  • Faster time-to-value (instant provisioning vs. manual setup)
  • Seamless customer experience (never leave your platform)
  • Automatic credential management

How to Implement:

Self-service procurement requires access to CLEAR's provisioning APIs, which are not yet publicly available.

To enable Option B, please contact CLEAR:

  • Email: [email protected]
  • Request: Access to provisioning APIs, code samples, and API reference documentation
  • What You'll Receive:
    • Provisioning API credentials
    • Complete API reference for environment and project creation
    • Code samples for orchestrating the provisioning workflow
    • Integration guide for automatic credential population
    • Testing environment access

Workflow Configuration

Once CLEAR credentials are configured, admins must define where and when CLEAR verification is triggered.

Key Configuration Points:

  1. Use Case Selection: Which workflows require CLEAR verification?

    • Employee onboarding
    • Password reset
    • Account recovery
    • High-risk transactions
    • Conditional access (new device/location)
    • VPN/network access
    • Application access
  2. Trigger Conditions: When should verification be required?

    • Always (every login)
    • Conditional (risk-based triggers)
    • On-demand (user-initiated)
    • Periodic (time-based re-verification)
  3. Flow Routing Logic: Which CLEAR project to use?

    • If clear_user_id exists → Known User Key Project
    • If clear_user_id null → Establish Identity Project

Data Mapping Configuration

Admins must specify which fields from their user database map to CLEAR's expected fields for User Profile Matching.

Required Mappings:

CLEAR FieldCustomer Field (Example)Required For
employee_idemployee_id or user_idEstablish Identity
first_namefirst_name or given_nameEstablish Identity
last_namelast_name or family_nameEstablish Identity
date_of_birthdob or birth_dateEstablish Identity
emailemail or work_emailOptional

Layer 2: Customer End User Experience

Overview

This layer enables your customer's end users (their employees) to complete identity verification through CLEAR. Once customers configure their CLEAR credentials in Layer 1, their end users can verify. This layer implements the core CLEAR integration workflow.

What This Layer Does:
Partners facilitate the standard CLEAR verification flow documented at:

The Critical Addition: User Profile Matching (UPM)

When creating a session, partners must check if the user has a stored CLEAR userID:

  • No CLEAR userID exists → Use Project A (configured for User Profile Matching):
    • Send employee_id, first_name, last_name, date_of_birth in custom_fields
    • CLEAR performs biometric verification AND matches verified data against the data you sent
    • Result includes match_result: "match" or match_result: "no_match"
    • If match succeeds, store the returned CLEAR user_id to the user record
  • CLEAR userID exists → Use Project B (re-verification):
    • Send the stored CLEAR user_id in the request
    • User completes selfie-only flow (3-5 seconds)
    • Verify returned user_id matches stored user_id

CLEAR Owns the Matching: When using User Profile Matching, CLEAR determines if the verified identity data matches the employee data you sent. The verification result tells you two things:

  1. Did the user pass CLEAR verification? (document valid, selfie matches ID)
  2. Did the verified data match the employee data you sent? (match_result)

Three Core Components Partners Must Build:

  1. End User Experience Design: Where CLEAR is triggered, what the user sees before/during/after verification, error handling, and success paths
  2. User Matching & Verification Logic: Check for CLEAR userID, route to correct project, process match results, store userID
  3. Data Storage & Correlation: Store CLEAR userID, map results back to correct user record using employee_id, retrieve verification data

Component 1: End User Experience Design

Partners must design and implement the following UX touchpoints:

1. Verification Trigger Points

Question: Where and how is CLEAR verification initiated?

Common Trigger Patterns:

A. Button/Link Click

User explicitly clicks a button to start verification.

When to Use: Password reset, account recovery, on-demand verification

B. Automatic Redirect

System automatically redirects user to CLEAR when conditions are met.

async function handleLogin(username, password) {
  const user = await authenticateCredentials(username, password);
  
  // Check if conditional access verification required
  if (isNewDevice(user.id) || isHighRiskLogin(user.id)) {
    // Automatic redirect to CLEAR
    const sessionUrl = await initiateVerification(user.id, 'conditional_access');
    return redirect(sessionUrl);
  }
  
  // Normal login flow
  return redirect('/dashboard');
}

When to Use: Conditional access, risk-based authentication

C. Workflow Step

CLEAR verification as part of a multi-step process.

Step 1: Create Account  →  Step 2: Verify Identity  →  Step 3: Set Preferences
                               (CLEAR verification)

When to Use: Employee onboarding, account setup flows

D. SMS/Email Link

User receives a message with a link to start verification.

SMS: "To complete your account recovery, verify your identity: 
https://yourapp.com/verify/abc123"

When to Use: Async verification requests, out-of-band authentication


2. Pre-Verification Experience

Question: What does the user see immediately before entering CLEAR?

Design Considerations:

A. Context Setting
Explain why verification is needed and what will happen (e.g., "We need to verify your identity to reset your password. You'll scan a photo ID and take a quick selfie. Verification completes in under 60 seconds.").

B. Returning User (Known User Key)
Provide a different message for users who have already completed their first verification (e.g., "Welcome back! We just need a quick selfie to verify it's you. This will only take 3-5 seconds.").

Implementation:

async function showPreVerificationScreen(userId) {
  const user = await getUserProfile(userId);
  
  if (user.clear_user_id) {
    // Returning user - show Known User Key message
    return renderScreen('quick_verification_prompt');
  } else {
    // New user - show full Establish Identity message
    return renderScreen('full_verification_prompt');
  }
}

3. CLEAR Session Flow

Question: How does the user navigate to and from CLEAR?

Required Pattern: Full Redirect

CLEAR verification must redirect the user outside of the partner application. Popups and iframe embeds are not supported.

User leaves partner app entirely, completes CLEAR verification, and is redirected back to partner app.

Partner App  →  CLEAR Verification  →  Partner App
(redirect)      (verify.clearme.com)   (redirect_url callback)

Implementation:

async function initiateVerification(userId) {
  // 1. Create session and get token
  const session = await createClearSession(userId);
  
  // 2. Construct CLEAR verification URL with token
  const verificationUrl = `https://verified.clearme.com/verify?token=${session.token}`;
  
  // 3. Full page redirect to CLEAR
  window.location.href = verificationUrl;
}

// User completes verification on CLEAR's site, then CLEAR redirects back
// to the redirect_url you specified during session creation

// Callback endpoint handles the return
app.get('/verify/confirmation', async (req, res) => {
  const sessionId = req.query.session_id;
  const results = await getSessionResults(sessionId);
  
  await processResults(results);
  res.redirect('/verification/success');
});

Why Full Redirect Is Required:

  • Ensures consistent user experience across all devices
  • Avoids popup blocker issues
  • Works reliably on mobile devices
  • Maintains CLEAR's security and verification integrity
  • No complex iframe or postMessage handling needed

4. Post-Verification Experience

Question: What happens after CLEAR returns the user?

Critical Steps:

A. Loading/Processing State

Show user that verification is being processed (e.g., loading spinner with message "Verifying your identity... This may take a few seconds.").

B. Retrieve Session Results

Fetch verification data from CLEAR.

app.get('/clear/callback', async (req, res) => {
  const sessionId = req.query.session_id;
  
  try {
    // Show loading screen
    res.send(renderLoadingScreen());
    
    // Fetch results (redirect or polling)
    const results = await getSessionResults(sessionId);
    
    // Process based on flow type
    if (results.mode === 'user_profile_matching') {
      await handleEstablishIdentityResults(results);
    } else {
      await handleKnownUserKeyResults(results);
    }
    
    // Redirect to success
    res.redirect('/verification/success');
    
  } catch (error) {
    res.redirect(`/verification/error?reason=${error.message}`);
  }
});

C. Success Path

User verification succeeded - grant access and provide confirmation (e.g., "Identity Verified Successfully. Your identity has been confirmed. You can now proceed with your password reset.").

Implementation:

async function handleEstablishIdentityResults(results) {
  if (results.status === 'completed' && results.match_result === 'match') {
    // Store CLEAR userID
    await updateUserProfile(results.custom_fields.employee_id, {
      clear_user_id: results.user_id,
      identity_verified_at: new Date()
    });
    
    // Grant access
    await grantWorkflowAccess(results.custom_fields.employee_id);
    
    // Log success event
    await logEvent('verification_success', { 
      employee_id: results.custom_fields.employee_id,
      session_id: results.session_id,
      flow_type: 'establish_identity'
    });
  }
}

D. Failure Paths

Handle various failure scenarios gracefully:

Scenario 1: Verification Failed - Unable to verify identity (e.g., unclear ID, poor lighting, information mismatch). Provide retry option and support contact.

Scenario 2: User Profile Match Failed (Establish Identity) - Verified identity doesn't match employee record on file. Direct user to contact IT/HR to update employee information. Include session reference code.

Scenario 3: UserID Mismatch (Known User Key) - Verified identity doesn't match stored userID. This is a security event - log it, notify administrators, and provide clear messaging about potential unauthorized access attempt.

Scenario 4: Session Expired - Verification session timed out. Provide option to start new verification.

Error Handling Implementation:

async function processVerificationResults(results) {
  // Handle different statuses
  switch (results.status) {
    case 'completed':
      if (results.match_result === 'match') {
        return handleSuccess(results);
      } else if (results.match_result === 'no_match') {
        return handleProfileMismatch(results);
      }
      break;
      
    case 'failed':
      return handleVerificationFailed(results);
      
    case 'expired':
      return handleSessionExpired(results);
      
    case 'cancelled':
      return handleUserCancelled(results);
      
    default:
      return handleUnknownError(results);
  }
}

async function handleVerificationFailed(results) {
  // Log failure
  await logEvent('verification_failed', {
    employee_id: results.custom_fields?.employee_id,
    session_id: results.session_id,
    reason: results.failure_reason
  });
  
  // Show user-friendly error
  return renderErrorScreen('verification_failed', {
    canRetry: true,
    supportContact: '[email protected]'
  });
}

Component 2: User Matching & Verification Logic

Overview

This component handles how users are matched to their records during verification and how the system validates identity on subsequent verifications.

First-Time Verification: User Profile Matching (UPM)

Purpose: Match the verified identity data from CLEAR against the customer's employee/user records to ensure the right person is accessing the right account.

How It Works:

  1. Customer sends employee data in the session creation request:

    {
      project_id: "proj_abc123",
      redirect_url: "https://yourapp.com/verify/confirmation",
      custom_fields: {
        employeeID: "EMP12345"  // For correlation only
      },
      user_profile_information: {  // Biographic data for matching
        name: {
          first_name: "Jane",
          last_name: "Smith"
        },
        dob: "1990-05-15"
      }
    }

    Important:

    • custom_fields is for correlation data only (e.g., employeeID, department, etc.)
    • user_profile_information contains the biographic data CLEAR will match against
  2. User completes CLEAR verification (ID scan + selfie)

  3. CLEAR performs biometric matching:

    • Extracts data from government-issued ID
    • Matches selfie to ID photo using facial biometrics
    • Compares verified data to employee data sent in user_profile_information
    • If data matches, returns user_id in the response
    • If data doesn't match, no user_id is returned
  4. Partner validates the match:

    if (results.user_id) {
      // Success: Verified identity matches employee record
      // Store CLEAR userID to employee profile
      await updateUserProfile(employeeId, {
        clear_user_id: results.user_id
      });
    } else {
      // No match: Verified identity doesn't match employee data
      // Flag for manual review
      await flagForReview(employeeId, results);
    }

Key Point: User Profile Matching ensures the person verifying is the same person as the employee record, preventing account takeover or identity confusion.


Subsequent Verifications: UserID-to-UserID Matching

Purpose: On subsequent verifications, match the CLEAR userID returned from the session against the stored userID on the employee profile.

How It Works:

  1. Partner sends stored userID in the session creation request:

    {
      project_id: "known_user_key_project_id",
      user_id: "psuid_abc123def456"  // From employee profile
    }
  2. User completes selfie-only verification (3-5 seconds)

  3. CLEAR matches selfie to stored biometric using the provided userID

  4. Partner validates userID match:

    const storedUserId = userProfile.clear_user_id;
    const returnedUserId = results.user_id;
    
    if (returnedUserId === storedUserId) {
      // Success: UserIDs match
      await grantAccess(employeeId);
    } else {
      // SECURITY ALERT: UserID mismatch
      await logSecurityAlert({
        employee_id: employeeId,
        stored_user_id: storedUserId,
        returned_user_id: returnedUserId
      });
      throw new Error('Unauthorized access attempt');
    }

Key Point: UserID-to-userID matching prevents unauthorized users from accessing accounts even if they bypass initial verification flows.


Component 3: Data Storage Strategy

Overview

After verification, partners must decide what data from the CLEAR session to store on user profiles. The requirements vary based on your system's capabilities and compliance needs.

Required Data (Minimum)

Always store these fields:

await updateUserProfile(employeeId, {
  // REQUIRED: Enables Known User Key flow
  clear_user_id: results.user_id,  // e.g., "psuid_abc123def456"
  
  // REQUIRED: Audit and troubleshooting
  verification_session_id: results.session_id,  // e.g., "session_xyz789"
  
  // REQUIRED: Timestamps for compliance
  identity_verified_at: new Date()
});

Why Required:

  • clear_user_id: Without this, you cannot use Known User Key flow. Every verification would require full ID + selfie.
  • verification_session_id: Essential for audit trails, troubleshooting, and linking back to CLEAR session data.
  • identity_verified_at: Compliance requirement for tracking when identity was last verified.

Recommended Data (If Your System Supports PII Storage)

If your system can store PII, we recommend also storing verified data from the CLEAR session:

await updateUserProfile(employeeId, {
  // Required minimum
  clear_user_id: results.user_id,
  verification_session_id: results.session_id,
  identity_verified_at: new Date(),
  
  // RECOMMENDED: Verified PII from government-issued ID
  verified_first_name: results.verified_data.first_name,
  verified_last_name: results.verified_data.last_name,
  verified_dob: results.verified_data.date_of_birth,
  verified_address: results.verified_data.address,
  
  // RECOMMENDED: Document metadata
  document_type: results.verified_data.document_type,  // "drivers_license", "passport"
  document_number: results.verified_data.document_number,
  document_expiration: results.verified_data.document_expiration,
  
  // RECOMMENDED: Contact information
  verified_phone_number: results.verified_data.phone_number,
  verified_email: results.verified_data.email,
  
  // RECOMMENDED: Audit metadata
  match_result: results.match_result,  // "match" or "no_match"
  verification_method: 'clear_user_profile_matching'
});

Why Recommended:

  • System of Record: Your platform becomes the authoritative source for verified employee data
  • Compliance: Meets regulatory requirements for identity verification documentation
  • Audit Trail: Complete record of what data was verified and when
  • Reconciliation: Compare stored data against employee records to detect discrepancies
  • User Profile Enhancement: Populate or update employee profiles with verified, authoritative data

Optional Data (Not Required If PII Storage Is Not Allowed)

If your system cannot store PII (due to data minimization policies, GDPR, or security constraints):

await updateUserProfile(employeeId, {
  // Only store required minimum
  clear_user_id: results.user_id,
  verification_session_id: results.session_id,
  identity_verified_at: new Date(),
  
  // NO verified PII stored
});

When to Use This Approach:

  • Data minimization requirements
  • Systems with limited PII storage capabilities
  • Environments where PII storage increases compliance burden
  • Known User Key flow still works (only requires clear_user_id)

Trade-offs:

  • Cannot use verified data for profile updates or reconciliation
  • Must rely on session_id to look up historical verification data if needed
  • Limited audit trail visibility without accessing CLEAR API

Known User Key Flow: Event Logging Only

On subsequent verifications (Known User Key), DO NOT update stored data. Only log the verification event:

// DO NOT update clear_user_id (already stored)
// Only log the verification event
await logVerificationEvent({
  employee_id: employeeId,
  session_id: results.session_id,
  clear_user_id: results.user_id,
  verification_type: 'known_user_key',
  verified_at: new Date(),
  use_case: 'password_reset',  // Or 'conditional_access', etc.
  result: 'success'
});

Why: The userID never changes, so no profile updates are needed. Only track that verification occurred.


Data Retention Guidelines

Data TypeRetention PeriodPurpose
clear_user_idPermanentRequired for all future verifications
verification_session_id90 days minimumAudit and troubleshooting
Verified PIIPer compliance policySystem of record, reconciliation
Verification logs1-7 years typicalCompliance and security audit
Session metadata90 days minimumDebugging and support

Component 4: Result Retrieval & Data Correlation

Overview

After the user completes CLEAR verification, partners MUST retrieve the session results and map the data back to the correct user record. This is a required step to complete the verification workflow.

Critical Requirement: Define a redirect_url in BOTH create session API calls (User Profile Matching and Known User Key). This enables the system to retrieve results when the user is redirected back to your application.

Three Methods to Retrieve Results

Partners must implement at least one method to retrieve verification results:

Method 1: Redirect (RECOMMENDED - Most Common)

How It Works:

  1. When creating the session, include redirect_url:
    {
      "project_id": "proj_abc123",
      "redirect_url": "https://yourapp.com/clear/callback?employee_id={employee_id}"
    }
  2. User completes CLEAR verification
  3. User is redirected back to your callback URL with session_id parameter
  4. Your system calls Get Verification to retrieve results
  5. Map results back to user record using employee_id from custom_fields

When to Use:

  • Standard web application flows (most common pattern)
  • User-present verification (login, password reset, onboarding)
  • Browser-based experiences
  • Real-time user feedback required

Implementation:

// Helper function to create verification session
async function createVerificationSession(
  apiKey,
  projectId,
  redirectUrl,
  employeeId,
  pii,      // { first_name, last_name, dob } for User Profile Matching
  userId    // CLEAR user_id for re-verification
) {
  const body = {
    project_id: projectId,
    redirect_url: redirectUrl,
    custom_fields: { employeeID: employeeId },
  };

  // If userId provided, this is re-verification
  if (userId) {
    body.user_id = userId;
  } else if (pii) {
    // Otherwise, use User Profile Matching for initial verification
    body.user_profile_information = {
      name: {
        first_name: pii.first_name,
        last_name: pii.last_name,
      },
      dob: pii.dob,
    };
  }

  const response = await fetch('https://verified.clearme.com/v1/verification_sessions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });

  const data = await response.json();

  if (!response.ok) {
    throw new Error(data.message || 'Failed to create CLEAR verification session');
  }

  return data; // { id, token, status }
}

// 1. Create session with redirect_url
app.post('/create-session', async (req, res) => {
  const { employeeId } = req.body;
  
  // Look up employee
  const employee = await getEmployeeById(employeeId);
  
  // Determine if this is initial verification or re-verification
  const isReverification = !!employee.clear_user_id;
  
  const redirectUrl = `https://yourapp.com/verify/confirmation`;
  let clearSession;
  
  if (isReverification) {
    // Re-verification with Known User Key
    clearSession = await createVerificationSession(
      apiKey,
      reverificationProjectId,
      redirectUrl,
      employee.employee_id,
      undefined,
      employee.clear_user_id  // Pass stored userID
    );
  } else {
    // Initial verification with User Profile Matching
    const pii = {
      first_name: employee.first_name,
      last_name: employee.last_name,
      dob: employee.date_of_birth
    };
    
    clearSession = await createVerificationSession(
      apiKey,
      initialProjectId,
      redirectUrl,
      employee.employee_id,
      pii,
      undefined
    );
  }
  
  // Save session to database
  await saveSession({
    employee_id: employee.id,
    clear_session_id: clearSession.id,
    status: 'pending'
  });
  
  // Return token to frontend
  res.json({ token: clearSession.token });
});

// 2. Frontend redirects user to CLEAR
// window.location.href = `https://verified.clearme.com/verify?token=${token}`;

// 3. Handle redirect callback
app.get('/verify/confirmation', async (req, res) => {
  // User was redirected back from CLEAR
  // Now retrieve results using Get Verification endpoint
  
  const { sessionId } = req.query; // Your internal session ID
  
  // Look up session
  const session = await getSessionById(sessionId);
  
  // Get results from CLEAR
  const response = await fetch(
    `https://verified.clearme.com/v1/verification_sessions/${session.clear_session_id}`,
    {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
      },
    }
  );
  
  const clearData = await response.json();
  
  // Extract employee_id from custom_fields to map back to correct record
  const employeeId = clearData.custom_fields.employeeID;
  
  // Process and store results
  await processResults(employeeId, clearData);
  
  // Show success screen
  res.redirect('/verification/success');
});

User Experience Pattern:

[Pre-Verification Screen] → [CLEAR Verification] → [Post-Verification Landing Screen]
     Your Application              CLEAR              Your Application (with results)

Method 2: Polling

How It Works:

  1. Create session and redirect user to CLEAR
  2. Periodically poll Get Verification endpoint
  3. When status changes to completed, failed, or expired, retrieve results
  4. Map results back to user record

When to Use:

  • Terminal screen flows (CLEAR ends on final screen)
  • Call center assisted verification (agent triggers result retrieval)
  • Async workflows (background verification)
  • Mobile apps with deep linking
  • SMS/Email initiated flows

Implementation:

// Helper function to get verification session
async function getVerificationSession(apiKey, clearSessionId) {
  const response = await fetch(
    `https://verified.clearme.com/v1/verification_sessions/${clearSessionId}`,
    {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
      },
    }
  );

  const data = await response.json();

  if (!response.ok) {
    throw new Error(data.message || 'Failed to get CLEAR verification session');
  }

  return data;
}

// Polling implementation
async function pollForResults(apiKey, clearSessionId, employeeId) {
  const maxAttempts = 60;  // 2 minutes with 2-second intervals
  
  for (let i = 0; i < maxAttempts; i++) {
    const clearData = await getVerificationSession(apiKey, clearSessionId);
    
    // Check for completion
    const isComplete = clearData.status === 'complete' || 
                      clearData.status === 'success' || 
                      clearData.status === 'completed';
    
    if (isComplete) {
      console.log('Verification complete!');
      console.log('Status:', clearData.status);
      console.log('user_id:', clearData.user_id);
      
      // Map results back using employee_id from custom_fields
      const employeeIdFromClear = clearData.custom_fields.employeeID;
      await processResults(employeeIdFromClear, clearData);
      
      return clearData;
    } else if (clearData.status === 'failed' || clearData.status === 'expired') {
      throw new Error(`Session ${clearData.status}`);
    }
    
    console.log(`Polling attempt ${i + 1}/${maxAttempts}, status: ${clearData.status}`);
    
    // Wait 2 seconds before next poll
    await new Promise(resolve => setTimeout(resolve, 2000));
  }
  
  throw new Error('Polling timeout - verification took too long');
}

// Usage
app.get('/poll-status/:sessionId', async (req, res) => {
  const { sessionId } = req.params;
  
  // Look up session
  const session = await getSessionById(sessionId);
  
  try {
    const results = await pollForResults(
      apiKey,
      session.clear_session_id,
      session.employee_id
    );
    
    res.json({ success: true, results });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Method 3: Agent/Button-Triggered Retrieval

How It Works:

  1. User completes CLEAR verification (ends on terminal screen)
  2. Agent or automated system clicks button to retrieve results
  3. System calls Get Verification endpoint
  4. Results mapped back to user record

When to Use:

  • Call center scenarios (agent assists user with verification)
  • Administrative workflows (manual review required)
  • Kiosk or in-person verification scenarios

Implementation:

// Agent clicks "Retrieve Results" button
app.post('/admin/retrieve-verification', async (req, res) => {
  const { sessionId } = req.body;
  
  try {
    // Look up session
    const session = await getSessionById(sessionId);
    
    // Retrieve results from CLEAR
    const clearData = await getVerificationSession(apiKey, session.clear_session_id);
    
    console.log('=== VERIFICATION RESULTS ===');
    console.log('Status:', clearData.status);
    console.log('user_id:', clearData.user_id);
    console.log('Custom fields:', clearData.custom_fields);
    
    // Extract employee_id to map back to correct record
    const employeeId = clearData.custom_fields.employeeID;
    
    // Process and store results
    await processResults(employeeId, clearData);
    
    res.json({ success: true, clearData });
  } catch (error) {
    console.error('Error retrieving verification:', error);
    res.status(500).json({ error: error.message });
  }
});

Data Correlation: Mapping Results to User Records

Critical Step: After retrieving results, map the verified identity data back to the correct user record.

How to Correlate:

  1. Use employee_id from custom_fields:

    const employeeId = results.custom_fields.employee_id;
    const userRecord = await getUserProfile(employeeId);
  2. For User Profile Matching (first-time):

    • Check match_result === "match"
    • If match, store results.user_id to user record
    • If no match, flag for manual review
  3. For Known User Key (returning):

    • Verify results.user_id === userRecord.clear_user_id
    • If mismatch, trigger security alert

Example Complete Flow (from real production code):

async function processResults(clearSessionId, apiKey) {
  // 1. Get verification data from CLEAR
  const clearData = await getVerificationSession(apiKey, clearSessionId);
  
  console.log('=== PROCESSING VERIFICATION RESULTS ===');
  console.log('CLEAR Status:', clearData.status);
  console.log('CLEAR user_id:', clearData.user_id);
  
  // 2. Extract employee_id from custom_fields to map back
  const employeeId = clearData.custom_fields.employeeID;
  console.log('Employee ID:', employeeId);
  
  // 3. Fetch user record
  const employee = await getEmployeeById(employeeId);
  console.log('Current employee clear_user_id:', employee.clear_user_id);
  
  // 4. Route based on flow type
  const isComplete = clearData.status === 'complete' || 
                    clearData.status === 'success' || 
                    clearData.status === 'completed';
  
  if (isComplete && clearData.user_id) {
    if (!employee.clear_user_id) {
      // First-time verification with User Profile Matching
      console.log('🔄 First-time verification complete! Saving user_id...');
      
      // Store CLEAR userID to employee record
      await updateEmployee(employee.id, {
        clear_user_id: clearData.user_id,
        identity_verified_at: new Date()
      });
      
      console.log('✅ Successfully saved user_id to employee record');
      
      // Log verification event
      await logVerificationEvent({
        employee_id: employee.id,
        clear_user_id: clearData.user_id,
        verification_type: 'initial',
        status: 'success'
      });
      
    } else {
      // Returning user verification (Known User Key)
      console.log('🔄 Re-verification complete. Validating user_id...');
      
      if (clearData.user_id === employee.clear_user_id) {
        console.log('✅ user_id matches! Re-verification successful');
        
        // Log verification event (don't update employee record)
        await logVerificationEvent({
          employee_id: employee.id,
          clear_user_id: clearData.user_id,
          verification_type: 'reverification',
          status: 'success'
        });
        
      } else {
        // SECURITY ALERT - userID mismatch
        console.error('❌ SECURITY ALERT: user_id mismatch!');
        console.error('Expected:', employee.clear_user_id);
        console.error('Received:', clearData.user_id);
        
        await triggerSecurityAlert({
          employee_id: employee.id,
          stored_user_id: employee.clear_user_id,
          returned_user_id: clearData.user_id,
          alert_type: 'user_id_mismatch'
        });
        
        throw new Error('UserID mismatch - unauthorized access attempt');
      }
    }
  } else {
    console.log('⏸️ Verification not complete. Status:', clearData.status);
  }
  
  console.log('=== END PROCESSING ===');
  
  return clearData;
}

Key Takeaways

Always define redirect_url in create session requests (required for traditional web flows)

Choose a retrieval method that matches your use case (redirect, polling, or button-triggered)

Retrieve results using Get Verification endpoint: https://docs.clearme.com/reference/get_verification

Map results back to user records using employee_id from custom_fields

Store CLEAR userID when User Profile Matching returns match_result: "match"

Validate userID match on subsequent verifications to prevent unauthorized access


End User Experience Checklist

Use this checklist to ensure complete end user experience implementation:

Pre-Verification:

  • Clear context explaining why verification is required
  • Different messaging for new vs. returning users
  • Instructions on what to expect
  • Cancel/back option if verification is optional

Verification Flow:

  • Seamless navigation to CLEAR (redirect/popup/iframe)
  • Consistent branding throughout journey
  • Mobile-responsive design
  • Loading states during transitions

Post-Verification:

  • Loading indicator while processing results
  • Clear success confirmation message
  • Appropriate error messages for all failure scenarios
  • Retry mechanism for recoverable errors
  • Support contact information for unrecoverable errors

Data Handling:

  • Store clear_user_id to user profile immediately
  • Log all verification events for audit
  • Handle session expiration gracefully
  • Implement proper error logging and monitoring

Security:

  • Verify userID match on Known User Key flows
  • Log suspicious activity (userID mismatches)
  • Implement rate limiting on verification attempts
  • Secure credential storage and transmission


Did this page help you?