Webhooks

Complete guide for receiving identity verification events in your application. Learn how to set up webhook endpoints, handle events, and implement reliable event processing.

IDV SDK Feature

Webhooks are used to receive server-side notifications for identity verification events. Events are sent to your server when verification status changes occur.

Quick Start

Get webhook events up and running in minutes with these essential steps:

  1. Create Endpoint - Set up a public HTTPS URL to receive events
  2. Handle Events - Process verification events in your application
  3. Configure & Test - Set up authentication and validate events

What You'll Receive

verification.completed - Approved

Sent when identity verification completes successfully with an approved decision.

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "eventType": "verification.completed",
  "eventVersion": "1.0",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "source": "vecu-idv",
  "data": {
    "verificationId": "ver_1234567890",
    "referenceId": "customer_1234567890",
    "configurationId": "your_configuration_id",
    "previousStatus": "in_progress",
    "currentStatus": "completed",
    "decision": "approved",
    "previousDecision": "review",
    "reasons": [
      "identity_resolution_success",
      "document_validation_success",
      "address_validation_success"
    ],
    "completedAt": "2024-01-15T10:30:00.000Z"
  }
}

verification.completed - Rejected

Sent when verification completes but identity cannot be verified.

{
  "eventId": "6b3d2f1e-c8a7-4d5f-9e1b-3a7c9d4e2f5a",
  "eventType": "verification.completed",
  "eventVersion": "1.0",
  "timestamp": "2024-01-15T10:35:00.000Z",
  "source": "vecu-idv",
  "data": {
    "verificationId": "ver_0987654321",
    "referenceId": "customer_0987654321",
    "configurationId": "your_configuration_id",
    "previousStatus": "in_progress",
    "currentStatus": "completed",
    "decision": "rejected",
    "previousDecision": "review",
    "reasons": [
      "document_validation_failure",
      "address_correlation_failure",
      "fraud_alerts"
    ],
    "completedAt": "2024-01-15T10:35:00.000Z"
  }
}

verification.status_changed

Sent when the verification status or decision changes during the verification process.

{
  "eventId": "9f2e8c4a-7d3b-4e1f-8a6c-5b9d2e3f4a7b",
  "eventType": "verification.status_changed",
  "eventVersion": "1.0",
  "timestamp": "2024-01-15T10:28:00.000Z",
  "source": "vecu-idv",
  "data": {
    "verificationId": "ver_1234567890",
    "referenceId": "customer_1234567890",
    "configurationId": "your_configuration_id",
    "previousStatus": "pending",
    "currentStatus": "in_progress",
    "decision": "review",
    "previousDecision": null,
    "reasons": ["input_completeness"]
  }
}

Reverification Events

When using startReverification(), your webhook endpoint receives reverification-specific events with the reverification.* event type prefix and verification IDs starting with reverify.

reverification.completed

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "eventType": "reverification.completed",
  "eventVersion": "1.0",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "source": "vecu-idv",
  "data": {
    "verificationId": "reverify_1234567890",
    "referenceId": "customer_1234567890",
    "previousStatus": "in_progress",
    "currentStatus": "completed",
    "decision": "approved",
    "reasons": ["FACE_MATCHED", "LIVENESS_CHECK_PASSED"]
  }
}

Webhook Configuration

Webhook URL Requirements

  • Must be a valid HTTPS URL
  • Should be publicly accessible
  • Must support POST method with JSON content type
  • Must respond within 30 seconds
  • Should return HTTP 2xx status codes for successful processing

Example: https://api.yourclient.com/webhooks/vecu-idv

Authentication Types

None (No Authentication)

{
  "type": "none"
}

Basic Authentication

{
  "type": "basic",
  "username": "your_username",
  "password": "your_password"
}

Headers sent: Authorization: Basic <base64-encoded-credentials>

Bearer Token Authentication

{
  "type": "bearer",
  "token": "your_bearer_token"
}

Headers sent: Authorization: Bearer your_bearer_token

OAuth2 Authentication

{
  "type": "oauth2",
  "clientId": "your_client_id",
  "clientSecret": "your_client_secret",
  "tokenUrl": "https://auth.provider.com/token",
  "scopes": ["webhook", "read"]
}

Headers sent: Authorization: Bearer current_access_token

Webhook Events

Event Types

Event TypeDescription
verification.status_changedGeneral status change event
verification.completedVerification successfully completed
verification.failedVerification failed
reverification.status_changedReverification status change
reverification.completedReverification completed
reverification.failedReverification failed

Event Payload Structure

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "eventType": "verification.completed",
  "eventVersion": "1.0",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "source": "vecu-idv",
  "data": {
    "verificationId": "ver_1234567890",
    "referenceId": "your_reference_id",
    "configurationId": "your_configuration_id",
    "previousStatus": "pending",
    "currentStatus": "completed",
    "previousDecision": "review",
    "decision": "approved",
    "reasons": ["identity_resolution_success", "document_validation_success"],
    "completedAt": "2024-01-15T10:30:00.000Z"
  }
}

Verification Statuses

StatusDescription
pendingVerification is queued or starting
in_progressVerification is actively processing
completedVerification process finished - check decision
failedTechnical failure occurred
expiredVerification session expired
unknownStatus could not be determined

Status Details and Resume Behavior

Understanding how each status affects user experience when re-initiating verification:

  • pending - Verification link has been generated and the user is completing the capture process. Resume behavior: If a user (based on referenceId) re-initiates a verification while in this state, a new verification session will be started.

  • in_progress - Document capture is complete and the user is in the Information Verification screen in the SDK. Resume behavior: If a user (based on referenceId) re-initiates a verification while in this state, the existing verification session will be resumed.

  • completed - Check decision field for outcome (e.g., approved, rejected). Resume behavior: If a user (based on referenceId) re-initiates a verification while in this state, a new verification session will be started.

  • failed - System error, timeout, or configuration issue. Resume behavior: If a user (based on referenceId) re-initiates a verification while in this state, a new verification session will be started.

  • expired - User exceeded the 24-hour capture window. Note: verification will not expire once it reaches the in_progress state. Resume behavior: If a user (based on referenceId) re-initiates a verification while in this state, a new verification session will be started.

  • unknown - Unexpected state or communication issue. Resume behavior: If a user (based on referenceId) re-initiates a verification while in this state, a new verification session will be started.

Decision Types

DecisionDescription
approvedIdentity verification passed all required checks
rejectedIdentity verification failed
manual_reviewFlagged for manual review by an operator
reviewAutomated review process in progress (temporary)
inconclusiveTechnical issue prevented decision

Using referenceId for Event Correlation

The referenceId field in webhook events enables you to correlate verification events with your internal customer records. This is your primary key for tracking and managing verifications.

Tracking Multiple Events

All webhook events for the same customer share the same referenceId. Use this to:

  • Link multiple verification.status_changed events
  • Connect initial verification to reverification events
  • Update customer records in your database
  • Maintain audit trails and verification history

Example: Customer Verification Timeline

// Initial verification
{
  "eventType": "verification.completed",
  "data": {
    "verificationId": "ver_123",
    "referenceId": "customer_12345",  // Your stable customer ID
    "decision": "approved"
  }
}

// Later: Reverification for same customer
{
  "eventType": "reverification.completed",
  "data": {
    "verificationId": "reverify_456",
    "referenceId": "customer_12345",  // Same referenceId links them
    "decision": "approved"
  }
}

// Your webhook handler can now correlate these events:
const customer = await db.customers.findByReferenceId("customer_12345");
customer.verifications.push({ verificationId, decision, timestamp });

Stable referenceId Required

For effective correlation, always provide a stable customer identifier as the referenceId when starting verifications. If you rely on the SDK's auto-generated timestamp-based IDs, each verification will have a different referenceId, preventing correlation.

Reason Codes Reference

Complete reference for all reason codes returned in webhook events. These codes explain why a verification decision was made and help you determine the appropriate next steps.

Code Format

Reason codes may appear in different formats depending on your backend configuration. Handle codes case-insensitively where possible.

Positive Reason Codes

These codes indicate successful validation checks and support approval decisions:

CategoryCodeDescription
Identityidentity_resolution_successIdentity successfully resolved
IdentityFACE_MATCHEDFace matches document photo
Documentdocument_validation_successDocument verification passed
DocumentDOCUMENT_VALIDATEDDocument successfully verified
Documentdocument_processingDocument processing details
BiometricLIVENESS_CHECK_PASSEDLiveness detection passed
GovernmentGOVERNMENT_VALIDATION_PASSEDGovernment database validation passed
Addressaddress_validation_successAddress verified successfully
Phonephone_validation_successPhone number verified
Phonephone_characteristicsPhone service information
Emailemail_validation_successEmail address verified
Emailemail_characteristicsEmail pattern information
Ageage_validation_successAge verification passed
Accountaccount_correlation_matchAccount data correlates
Accountaccount_historyAccount historical activity
Namename_correlation_matchName matching succeeded
Safetydeceased_check_clearNot reported as deceased
Safetysim_swap_clearNo SIM swap detected
Safetywatchlist_clearNo watchlist matches found
Safetypositive_list_matchesPositive list matches
Datainput_completenessData completeness verified
Devicedevice_informationDevice analysis information
Networkconsortium_dataConsortium network information
Networkfraud_network_positive_indicatorsNetwork analysis positive
Syntheticsynthetic_positive_indicatorsSynthetic identity positive

Risk Reason Codes

These codes indicate validation failures or risk factors that may lead to rejection or review:

CategoryCodeDescription
Documentdocument_validation_failureDocument verification failed
DocumentINVALID_DOCUMENTDocument is invalid
DocumentDOCUMENT_QUALITY_ISSUEDocument image quality insufficient
DocumentDOCUMENT_VALIDATION_WARNINGDocument validation warning
BiometricLIVENESS_CHECK_FAILEDLiveness detection failed
BiometricLIVENESS_CHECK_WARNINGLiveness detection warning
BiometricFACE_MISMATCHFace does not match document photo
BiometricFACE_MATCH_WARNINGFace match warning
BiometricSELFIE_QUALITY_ISSUESelfie image quality insufficient
BiometricSPOOF_DETECTEDSpoofing attempt detected
GovernmentGOVERNMENT_VALIDATION_FAILEDGovernment database validation failed
GovernmentGOVERNMENT_VALIDATION_WARNINGGovernment validation warning
Identityidentity_resolution_failureCannot resolve identity
IdentityEXISTING_USER_DETECTEDExisting user match detected
Identityssa_verification_failureSSN verification failed
Identityssn_issuesSocial Security Number problems
Identitydeceased_indicatorsIdentity shows as deceased
Identityage_verification_failureAge verification failed
Addressaddress_validation_failureAddress validation failed
Addressaddress_correlation_failureAddress correlation failed
Addressaddress_type_riskRisky address type detected
Addressaddress_zip_issuesZIP code validation failures
Phonephone_validation_failurePhone validation failed
Phonephone_type_riskRisky phone type detected
Phonephone_age_riskPhone age and porting risk
Phonephone_network_riskPhone network risk
Emailemail_validation_failureEmail validation failed
Emailemail_risk_patternsEmail risk patterns
Emailemail_age_riskEmail age risk
Emailemail_geolocation_riskEmail geolocation risk
Accountaccount_mismatchAccount information mismatch
Accountaccount_issuesAccount problems
Fraudfraud_alertsFraud alert indicators found
Fraudsynthetic_identitySynthetic identity detected
Fraudfirst_party_fraudFirst-party fraud indicators
Fraudidentity_fraudGeneral identity fraud risk
Fraudtransaction_fraudTransaction fraud history
Fraudconsortium_riskConsortium risk indicators
Networkip_geolocation_riskIP geolocation risk
Networkproxy_vpn_riskProxy/VPN risk
Devicedevice_riskHigh-risk device characteristics
Watchlistwatchlist_matchesFound on watchlists
Watchlistalert_list_matchesAlert list matches
Watchlistnegative_list_matchesNegative list matches
Watchlistsuspect_list_matchesSuspect list matches
Systemservice_errorsService processing errors

Retry Logic and Reliability

Automatic Retries

The webhook delivery service implements automatic retry logic with exponential backoff:

  • Maximum retries: 3 attempts per webhook
  • Base delay: 60 seconds
  • Timeout: 30 seconds per request

Retry Schedule

  1. Initial attempt: Immediate
  2. First retry: 60 seconds after failure
  3. Second retry: 120 seconds after first retry failure
  4. Third retry: 240 seconds after second retry failure

Retry Conditions

Webhooks are retried for:

  • Network errors (connection failures, timeouts)
  • Server errors (HTTP 5xx status codes)
  • Rate limiting (HTTP 429 status code)

Webhooks are NOT retried for:

  • Client errors (HTTP 4xx, except 429)
  • Invalid webhook URLs
  • Authentication failures

Webhook Endpoint Implementation

Response Requirements

Your webhook endpoint should:

  1. Respond quickly - Process within 30 seconds
  2. Return appropriate status codes:
    • 200-299: Success (delivery confirmed)
    • 429: Rate limited (will retry)
    • 500-599: Server error (will retry)
    • 400-499 (except 429): Client error (will not retry)

Example Handler (Node.js)

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

  switch (event.eventType) {
    case 'verification.completed':
      const { verificationId, decision, reasons } = event.data;

      if (decision === 'approved') {
        await updateUserVerificationStatus(verificationId, 'verified');
        await sendWelcomeEmail(event.data.customerInfo.email);
      } else if (decision === 'rejected') {
        await updateUserVerificationStatus(verificationId, 'failed');
        await notifyUserOfVerificationFailure(event.data, reasons);
      }
      break;

    case 'verification.status_changed':
      await updateVerificationProgress(event.data);
      break;
  }

  res.status(200).json({ status: 'processed', eventId: event.eventId });
});

Security Considerations

  1. HTTPS Only - Always use HTTPS endpoints
  2. SSL Certificate Verification - Production requires valid certificates
  3. Input Validation - Validate all incoming webhook data
  4. Rate Limiting - Implement rate limiting on your endpoints
  5. IP Allowlisting - Consider restricting to known VEC-IDV IP ranges
  6. Authentication - Use webhook authentication for additional security

Testing Your Webhook

Use this sample payload to test your webhook implementation:

{
  "eventId": "test-event-12345",
  "eventType": "verification.completed",
  "eventVersion": "1.0",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "source": "vecu-idv",
  "data": {
    "verificationId": "test-ver-123",
    "referenceId": "test-ref-456",
    "configurationId": "test-configuration",
    "previousStatus": "in_progress",
    "currentStatus": "completed",
    "decision": "approved",
    "previousDecision": "review",
    "reasons": [
      "identity_resolution_success",
      "document_validation_success",
      "address_validation_success"
    ],
    "completedAt": "2024-01-15T10:30:00.000Z"
  }
}

Configuration Management API

The Configuration Management API allows you to programmatically manage webhook configurations. Complete API documentation with detailed request/response schemas is available in the OpenAPI/Swagger specification provided with your API access package.

Example Configuration Request

{
  "configurationId": "generated-config-id",
  "configuration": {
    "name": "Production Webhook",
    "webhookUrl": "https://api.example.com/webhooks/vecu",
    "authSettings": {
      "type": "bearer",
      "credentials": {
        "token": "your-webhook-bearer-token"
      }
    },
    "authorizationPoolSettings": {
      "firstAcceptCancelsOthers": true,
      "authorizationExpiryDays": 30,
      "poolExpiryDays": 30,
      "maxAuthorizationsPerPool": 10,
      "maxPoolsPerVin": 5,
      "pushNotificationsEnabled": false,
      "autoIssueCredential": true
    }
  },
  "setActive": true
}

Authorization Pool Settings

The authorizationPoolSettings object configures behavior for the authorization-pool service. If omitted, default values are applied automatically.

firstAcceptCancelsOthersbooleanDefault: true

When true, the first accepted authorization cancels all other pending authorizations in the pool.

authorizationExpiryDaysintegerDefault: 30

Number of days until an authorization expires (1-90).

poolExpiryDaysintegerDefault: 30

Number of days until an authorization pool expires (1-90).

maxAuthorizationsPerPoolintegerDefault: 10

Maximum number of authorizations allowed per pool (1-50).

maxPoolsPerVinintegerDefault: 5

Maximum number of active pools allowed per VIN (1-20).

pushNotificationsEnabledbooleanDefault: false

Enable push notifications for authorization events.

notificationPrioritystring

Priority level for push notifications: HIGH, NORMAL, or LOW. Only used if pushNotificationsEnabled is true.

autoIssueCredentialbooleanDefault: true

Automatically issue a credential when an authorization is accepted.

Default Values

If authorizationPoolSettings is not provided in the request, the system automatically applies default values. You only need to specify settings you want to override.

Active Configuration

Only one configuration can be active at a time per environment. Setting setActive: true automatically deactivates the previous configuration.

Next Steps