Skip to main content

Complete ID check Onboarding Guide

This comprehensive guide will take you from zero to production with ARGOS ID check. Whether you’re a developer new to identity verification or migrating from another solution, this guide covers everything you need to know.
Time to Complete: 30-45 minutes for basic integration, 2-3 hours for advanced featuresPrerequisites:
  • ARGOS Identity account (Sign up here)
  • Basic knowledge of REST APIs
  • Development environment with internet access

Table of Contents

Part 1: Foundation

Understanding ID check, account setup, and core concepts

Part 2: Integration

Liveform and API integration methods

Part 3: Production

Security, testing, and going live

Part 1: Foundation

What is ARGOS ID check?

ARGOS ID check is a comprehensive identity verification platform that combines AI-powered document verification with fraud detection and compliance features. Core Capabilities:

Document Verification

Verify 20+ document types from 200+ countries including passports, driver’s licenses, national IDs, and residence permits

Data Extraction

Automatically extract and structure data from identity documents with 98%+ accuracy

Fraud Detection

AI algorithms detect forgeries, photo substitutions, and document tampering

Compliance

Built-in KYC/AML compliance with customizable verification rules and audit trails
How It Works:
1

User Submits Documents

Users upload photos of their ID documents through your application (via Liveform URL or custom UI)
2

AI Analysis

ARGOS AI engine analyzes documents for authenticity, extracts data fields, and performs liveness checks
3

Verification Decision

Automated approval/rejection based on your configured rules, or flagged for manual review
4

Results Delivered

Structured verification data delivered via webhooks and APIs with full audit trail

Account Setup and Dashboard Orientation

Let’s get you set up and familiar with the dashboard.
1

Create Your Account

  1. Visit idcheck.argosidentity.com
  2. Click “Sign Up” and complete registration
  3. Verify your email address
  4. Log in to access your dashboard
Dashboard
2

Navigate the Dashboard

Key Dashboard Sections:
  • Submissions: View and manage all verification submissions
  • Settings: Configure project settings, webhooks, and security
  • Access Management: API keys, Liveform URLs, and IP whitelisting
  • Analytics: Track verification metrics and success rates
  • Project Settings: Verification rules, document types, and policies
3

Locate Your API Credentials

Navigate to Settings → Access Management:
  1. API Key: Your authentication key for API requests (keep this secure!)
  2. Project ID (PID): Your unique project identifier
  3. Liveform URL: Your hosted verification page URL
API Key: argos_live_abc123xyz...
Project ID: pid_abc123
Liveform URL: https://form.argosidentity.com?pid=pid_abc123
Security Note: Treat your API key like a password. Never commit it to version control or expose it in client-side code.

Core Concepts You Need to Know

Before diving into integration, let’s understand the key concepts:
A submission represents a single identity verification attempt. Each submission has:
  • Submission ID: Unique identifier (sub_abc123)
  • KYC Status: approved, rejected, or pending
  • User Data: Extracted information (name, DOB, nationality, etc.)
  • Images: Document photos and selfies
  • Metadata: Timestamps, IP address, device info
Submission Lifecycle:
Created → Processing → Approved/Rejected/Pending → Archived
Liveform Integration (Fastest):
  • Use ARGOS-hosted verification page
  • Customize via URL parameters
  • No UI development required
  • Best for: Quick deployment, mobile apps
API Integration (Most Flexible):
  • Build custom verification UI
  • Full programmatic control
  • Integrate into existing workflows
  • Best for: Custom UX, complex workflows
You can use both! Many customers use Liveform for standard flows and API for special cases.
Webhooks are real-time HTTP callbacks that notify your server when events occur:
  • Triggered when submission status changes
  • Delivered as POST requests to your endpoint
  • Include full submission data
  • Support retry mechanism
Event Types:
  • approved - Verification approved
  • rejected - Verification rejected
  • pending - Manual review required
  • updated - Data updated
  • deleted - Submission deleted
Example webhook payload:
{
  "webhook_trigger": "approved",
  "submissionId": "sub_abc123",
  "kycStatus": "approved",
  "email": "user@example.com",
  "fullName": "John Doe",
  "birthDate": "1990-01-01"
}
Query Parameters customize Liveform behavior:
  • Pre-fill user data (email, userid)
  • Restrict countries/document types
  • Override verification policies
  • Control form fields
Tokens enable private mode:
  • One-time use URLs
  • Prevent URL sharing
  • Expire after 3 minutes or first use
  • Up to 100,000 tokens per project
Learn more: Query String Guide
ID check supports multiple encryption layers:1. Query String Encryption (AES-256-ECB):
  • Encrypt sensitive URL parameters
  • Protect user data in transit
2. Secure Data Transfer (AES-256-ECB/CBC):
  • Encrypt API request/response bodies
  • Encrypt webhook payloads
3. Custom Secret Keys:
  • Generate dedicated encryption keys
  • Separate from API keys
Learn more: Encryption Guide

Part 2: Integration

Now let’s integrate ID check into your application. Choose your integration method:
  • Liveform Integration
  • API Integration
The fastest way to get identity verification working in your app.

Step 1: Basic Liveform Setup

1

Get Your Liveform URL

  1. Log in to Dashboard
  2. Go to Settings → Access Management
  3. Copy your Liveform URL:
https://form.argosidentity.com?pid={your_project_id}
2

Test the Basic Flow

Open the URL in your browser to see the default verification flow:
  • Desktop: Shows QR code for mobile scanning
  • Mobile: Direct verification interface
Liveform Interface
3

Integrate into Your App

For Web Apps:
<a href="https://form.argosidentity.com?pid={your_pid}" target="_blank">
  Verify Your Identity
</a>
For Mobile Apps:
// React Native example
import { Linking } from 'react-native';

const verifyIdentity = () => {
  Linking.openURL('https://form.argosidentity.com?pid={your_pid}');
};
For Backend Redirect:
// Node.js Express example
app.get('/verify', (req, res) => {
  res.redirect('https://form.argosidentity.com?pid={your_pid}');
});

Step 2: Customize with Query Parameters

Enhance the user experience by pre-filling data and customizing behavior.
Pass user data to skip data entry:
const email = "user@example.com";
const userid = "user_12345";
const cf1 = "campaign_summer2024";

const liveformUrl = `https://form.argosidentity.com?pid={your_pid}&email=${encodeURIComponent(email)}&userid=${userid}&cf1=${cf1}`;
Available Parameters:
ParameterTypeDescriptionExample
emailstringUser’s emailuser@example.com
useridstringYour internal user IDuser_12345
cf1, cf2, cf3stringCustom fields for metadatacampaign_id
sidstringSubmission ID (for updates)sub_abc123
Use custom fields (cf1, cf2, cf3) to track campaign IDs, user segments, or any metadata you need for analytics.
Override dashboard settings for specific users:
const liveformUrl = `https://form.argosidentity.com?pid={your_pid}&blacklistCountries=false&ageLimit=false&rejectDuplicateUser=true`;
Policy Overrides:
ParameterTypeDescription
blacklistCountriesbooleanSet false to allow blacklisted countries
ageLimitbooleanSet false to disable age restrictions
approvePeriodbooleanSet false to disable duplicate check for approved
rejectPeriodbooleanSet false to disable duplicate check for rejected
rejectDuplicateUserbooleanSet true to enable duplicate prevention
Only use policy overrides when you have specific business requirements. Most apps should rely on dashboard settings.
Control which countries and ID types users can select:Step 1: Prepare configuration
const config = {
  allowedCountries: "USA,KOR,JPN",  // ISO Alpha-3 codes
  allowedIdTypes: "passport,drivers_license,government_id"
};
Step 2: Encrypt the configuration
const CryptoJS = require('crypto-js');

function encryptQueryParams(data, apiKey) {
  const hashedKey = CryptoJS.SHA256(apiKey);
  const encrypted = CryptoJS.AES.encrypt(
    JSON.stringify(data),
    hashedKey,
    { mode: CryptoJS.mode.ECB }
  );
  return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
}

const encryptedConfig = encryptQueryParams(config, YOUR_API_KEY);
Step 3: Build URL
const liveformUrl = `https://form.argosidentity.com?pid={your_pid}&encrypted=${encodeURIComponent(encryptedConfig)}`;
Available ID Types:
  • passport
  • drivers_license
  • government_id
  • residence_permit
  • pancard
  • aadhaar
  • identification_card
Country Codes: See Supported Countries
Encryption is required for allowedCountries, allowedIdTypes, and other sensitive parameters. See the Encryption Guide.
Skip the selection screens for a faster flow:
const config = {
  selectedIssuingCountry: "USA",
  selectedIdType: "drivers_license"
};

const encryptedConfig = encryptQueryParams(config, YOUR_API_KEY);
const liveformUrl = `https://form.argosidentity.com?pid={your_pid}&encrypted=${encodeURIComponent(encryptedConfig)}`;
  • selectedIdType must be used with selectedIssuingCountry
  • Cannot be used simultaneously with allowedCountries or allowedIdTypes
Collect and verify phone numbers via SMS:
const config = {
  auxidField: "phoneNumber"
};

const encryptedConfig = encryptQueryParams(config, YOUR_API_KEY);
const liveformUrl = `https://form.argosidentity.com?pid={your_pid}&encrypted=${encodeURIComponent(encryptedConfig)}`;
Important:
  • Phone verification uses SMS OTP
  • 91 countries currently don’t support SMS verification (see list)
  • Cannot be used with selectedIssuingCountry and selectedIdType (will be fixed in future update)
Phone verification adds an extra layer of security by confirming the user has access to the phone number.

Step 3: Implement Private Mode (Optional)

Private mode uses tokens to create one-time-use verification URLs.Use Cases:
  • Prevent URL sharing between users
  • Ensure each verification is unique
  • Add expiration to verification links
  • Track specific user sessions
1

Register Tokens via API

curl -X POST 'https://rest-api.argosidentity.com/v3/submission/tokens' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: text/plain' \
  -d '{
    "tokenId": [
      "user-session-001",
      "user-session-002",
      "verification-abc123"
    ]
  }'
Response:
{
  "success": true,
  "message": "All tokens are now in the pool",
  "summary": {
    "totalSubmitted": 3,
    "currentCount": 3,
    "processed": 3,
    "failed": 0
  }
}
2

Generate Tokenized URL

const tokenId = "user-session-001";
const secureUrl = `https://form.argosidentity.com?pid={your_pid}&token=${tokenId}`;

// Send this URL to the user
sendEmail(userEmail, `Complete verification: ${secureUrl}`);
3

Handle Token Expiration

Tokens become invalid when:
  • More than 3 minutes have passed since first use
  • A submission with the token reaches determined status (approved/rejected/pending)
Error Handling:
// User sees error if token is invalid
// Generate a new token for the user:

const newToken = `user-session-${Date.now()}`;

await fetch('https://rest-api.argosidentity.com/v3/submission/tokens', {
  method: 'POST',
  headers: {
    'x-api-key': YOUR_API_KEY,
    'Content-Type': 'text/plain'
  },
  body: JSON.stringify({ tokenId: [newToken] })
});

const newUrl = `https://form.argosidentity.com?pid={your_pid}&token=${newToken}`;
Token Limitations:
  • Maximum 100,000 tokens per project
  • Maximum 500 tokens per API request
  • Token ID format: 8-64 characters, alphanumeric + -_.
Learn more: POST Token API

Step 4: Configure Return URL

Redirect users back to your app after verification with results.
1

Set Return URL in Dashboard

  1. Go to Settings → General
  2. Enter your return URL:
https://yourapp.com/verification-complete
  1. Click Save
2

Receive Verification Results

Users will be redirected with query parameters:
https://yourapp.com/verification-complete?userid=user123&email=user@example.com&kycStatus=approved&cf1=campaign_summer
Available Parameters:
  • userid - User ID from original URL
  • email - User’s email
  • kycStatus - approved, rejected, or pending
  • cf1, cf2, cf3 - Custom fields
If you enabled Secure Data Transfer, these parameters will be encrypted in the encrypted parameter. See Return URL Guide.
3

Handle the Redirect

// Express.js example
app.get('/verification-complete', (req, res) => {
  const { userid, kycStatus, email } = req.query;

  if (kycStatus === 'approved') {
    // Update user status in database
    await updateUser(userid, { verified: true });
    res.render('verification-success');
  } else if (kycStatus === 'pending') {
    res.render('verification-pending');
  } else {
    res.render('verification-rejected');
  }
});

Liveform Integration Complete!

You now have a working Liveform integration. Test it end-to-end:
1

Test Desktop Flow

Open your Liveform URL on desktop → Scan QR → Complete verification on mobile
2

Test Mobile Flow

Open your Liveform URL directly on mobile → Complete verification
3

Test with Parameters

Try URLs with pre-filled data and policy overrides
4

Test Return URL

Complete verification and verify redirect with correct parameters

Next: Set Up Webhooks

Continue to webhook setup to receive real-time verification updates

Step 5: Set Up Webhooks

Webhooks provide real-time notifications when verification events occur. This is critical for production deployments.
1

Create a Webhook Endpoint

Create an HTTPS endpoint to receive webhook POST requests:
const express = require('express');
const app = express();

app.use(express.json());

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

  console.log('Webhook received:', event.webhook_trigger);
  console.log('Submission ID:', event.submissionId);
  console.log('KYC Status:', event.kycStatus);

  try {
    // Process based on event type
    switch (event.webhook_trigger) {
      case 'approved':
        await handleApproved(event);
        break;

      case 'rejected':
        await handleRejected(event);
        break;

      case 'pending':
        await handlePending(event);
        break;

      case 'updated':
        await handleUpdated(event);
        break;

      default:
        console.log('Unknown event type:', event.webhook_trigger);
    }

    // Always respond with 200 OK quickly
    res.status(200).json({ received: true });

  } catch (error) {
    console.error('Webhook processing error:', error);
    // Still return 200 to prevent retries for processing errors
    res.status(200).json({ received: true, error: error.message });
  }
});

async function handleApproved(event) {
  // Update user in database
  await db.users.update({
    id: event.userid,
    verified: true,
    verificationDate: new Date(),
    fullName: event.fullName,
    birthDate: event.birthDate
  });

  // Send confirmation email
  await sendEmail(event.email, 'Verification Approved', {
    name: event.fullName
  });

  console.log(`User ${event.userid} approved`);
}

async function handleRejected(event) {
  // Update user status
  await db.users.update({
    id: event.userid,
    verified: false,
    rejectionReason: event.rejectionReason
  });

  // Notify user
  await sendEmail(event.email, 'Verification Failed', {
    reason: event.rejectionReason
  });

  console.log(`User ${event.userid} rejected`);
}

async function handlePending(event) {
  // Send notification to admin
  await notifyAdmin(`Manual review required for ${event.userid}`);

  console.log(`User ${event.userid} pending review`);
}

async function handleUpdated(event) {
  // Sync updated data
  await db.submissions.update({
    submissionId: event.submissionId,
    data: event
  });
}

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});
Critical Webhook Best Practices:
  1. Always respond with 200 OK quickly (within 5 seconds)
  2. Process webhooks asynchronously if they take time
  3. Handle duplicate webhooks (use submission ID to deduplicate)
  4. Implement retry logic on your end for failed processing
  5. Log all webhooks for debugging
2

Register Webhook URL in Dashboard

  1. Log in to Dashboard
  2. Navigate to Settings → Access Management
  3. Enter your webhook URL in the Webhook URL field:
    https://yourapp.com/webhooks/idcheck
    
  4. Click Save
Webhook Setup
Your webhook URL must use HTTPS. For local testing, use ngrok or similar tools to expose your local server.
3

Test Webhook Delivery

Option 1: Use webhook.site for testing
1. Visit https://webhook.site
2. Copy the unique URL
3. Enter it in dashboard webhook settings
4. Perform a test verification
5. Check webhook.site for the payload
Option 2: Use ngrok for local testing
# Install ngrok
npm install -g ngrok

# Start your local server on port 3000
node server.js

# In another terminal, expose it
ngrok http 3000

# Copy the HTTPS URL (e.g., https://abc123.ngrok.io)
# Enter https://abc123.ngrok.io/webhooks/idcheck in dashboard
Option 3: Test with curl
curl -X POST https://yourapp.com/webhooks/idcheck \
  -H 'Content-Type: application/json' \
  -d '{
    "webhook_trigger": "approved",
    "submissionId": "test_123",
    "kycStatus": "approved",
    "email": "test@example.com",
    "userid": "test_user"
  }'
4

Handle Webhook Events

Available Event Types:
EventTriggerUse Case
approvedVerification approvedUpdate user status, grant access
rejectedVerification rejectedNotify user, request resubmission
pendingManual review neededAlert admins, inform user
updatedData modifiedSync changes to your database
deletedSubmission deletedClean up related data
createdSubmission createdTrack new verifications
retryUser retried verificationMonitor retry patterns
injectionData injected via APILog API operations
amlAML check completedProcess compliance results
Example Webhook Payload:
{
  "webhook_trigger": "approved",
  "submissionId": "sub_abc123",
  "kycStatus": "approved",
  "email": "user@example.com",
  "userid": "user_12345",
  "fullName": "John Doe",
  "birthDate": "1990-01-01",
  "nationality": "USA",
  "gender": "male",
  "documentType": "passport",
  "documentNumber": "123456789",
  "issuingCountry": "USA",
  "expiryDate": "2030-01-01",
  "createdAt": "2024-01-15T10:30:00Z",
  "verifiedAt": "2024-01-15T10:35:00Z",
  "cf1": "campaign_summer",
  "cf2": null,
  "cf3": null,
  "ipAddress": "192.168.1.1"
}
Learn more: Webhook Events Reference

Part 3: Production Deployment

Security Configuration

Before going live, implement these essential security features:
Encrypt all API requests, responses, and webhooks.
1

Enable in Dashboard

  1. Navigate to Settings → Access Management
  2. Toggle ON the “Secure Data Transfer” option
  3. Click Save
Secure Data Transfer
2

Implement Encryption in Code

const CryptoJS = require('crypto-js');

function encryptData(data, apiKey) {
  // Hash the API key with SHA-256
  const hashedKey = CryptoJS.SHA256(apiKey);

  // Extract 32 bytes for AES-256 key
  const key = CryptoJS.lib.WordArray.create(
    hashedKey.words.slice(0, 8),
    32
  );

  // Encrypt data with AES-256-ECB
  const encrypted = CryptoJS.AES.encrypt(
    JSON.stringify(data),
    key,
    { mode: CryptoJS.mode.ECB }
  );

  return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
}

// Usage in API request
const userData = {
  email: 'user@example.com',
  fullName: 'John Doe',
  birthDate: '1990-01-01'
};

const encryptedBody = encryptData(userData, YOUR_API_KEY);

const response = await axios.post(
  'https://rest-api.argosidentity.com/v3/submission/migration',
  { body: encryptedBody },
  {
    headers: {
      'x-api-key': YOUR_API_KEY,
      'Content-Type': 'application/json'
    }
  }
);
Key Differences:
  • API requests/responses: Use AES-256-ECB
  • Webhooks: Use AES-256-CBC
  • Always hash API key with SHA-256 first
3

Test Encryption

Use the Encryption/Decryption Tool to verify your implementation:
  1. Download and run the tool
  2. Enter your API key
  3. Test encryption/decryption with sample data
  4. Compare results with your code
The tool supports both ECB and CBC modes. Make sure to test both!
Learn more: Encryption Guide
Restrict API access to trusted IP addresses.
1

Find Your Server IPs

# Find your server's public IP
curl ifconfig.me

# Or check in your cloud provider dashboard
# AWS: EC2 Elastic IP
# Google Cloud: External IP
# Azure: Public IP
2

Add IPs to Whitelist

  1. Navigate to Settings → Access Management → IP Whitelist
  2. Enter your server IP addresses (one per line):
    52.12.34.56
    52.12.34.57
    
  3. Click Save
3

Test Access

From whitelisted IP (should succeed):
curl -H "x-api-key: YOUR_API_KEY" \
  https://rest-api.argosidentity.com/v3/submission
From non-whitelisted IP (should fail with 403):
{
  "errorCode": "forbidden",
  "errorMessage": "Access denied. IP not whitelisted."
}
Make sure to whitelist all server IPs that will call the API, including:
  • Production servers
  • Staging servers
  • CI/CD pipeline IPs (if applicable)
  • Admin/developer IPs for testing
Use tokens for secure, one-time verification URLs.When to use Private Mode:
  • High-security applications (financial, healthcare)
  • Preventing URL sharing/forwarding
  • Time-sensitive verifications
  • Tracking specific user sessions
Implementation:
// 1. Generate unique token for user session
const tokenId = `session-${userId}-${Date.now()}`;

// 2. Register token with ARGOS
await fetch('https://rest-api.argosidentity.com/v3/submission/tokens', {
  method: 'POST',
  headers: {
    'x-api-key': YOUR_API_KEY,
    'Content-Type': 'text/plain'
  },
  body: JSON.stringify({ tokenId: [tokenId] })
});

// 3. Generate secure Liveform URL
const secureUrl = `https://form.argosidentity.com?pid=${projectId}&token=${tokenId}`;

// 4. Send URL to user (email, SMS, etc.)
await sendEmail(userEmail, {
  subject: 'Complete Identity Verification',
  body: `Click here to verify: ${secureUrl}`,
  expiresIn: '3 minutes'
});

// 5. Handle token expiration
setTimeout(async () => {
  // Check if token was used
  const submission = await getSubmissionByToken(tokenId);

  if (!submission) {
    console.log(`Token ${tokenId} expired unused`);
    // Optionally notify user or generate new token
  }
}, 3 * 60 * 1000); // 3 minutes
Token Lifecycle:
Generated → Registered → URL Sent → User Opens → Submission Created → Token Consumed

                       Expires after 3 min or when submission reaches final status
Learn more: POST Token API
Never expose your API key in client-side code or version control.Best Practices:
# .env file (add to .gitignore!)
ARGOS_API_KEY=argos_live_abc123xyz...
ARGOS_PROJECT_ID=pid_abc123

# Load in Node.js
require('dotenv').config();
const apiKey = process.env.ARGOS_API_KEY;
Never commit API keys to git!Add to .gitignore:
.env
.env.local
.env.production
config/secrets.js
Use tools like git-secrets to prevent accidental commits.
Protect your integration from abuse and unexpected costs.ARGOS Rate Limits:
  • API calls: 100 requests/minute per IP
  • Webhook retries: 5 attempts with exponential backoff
  • Token registration: 500 tokens per request, 100k total
Your Application Rate Limiting:
const rateLimit = require('express-rate-limit');

// Limit verification requests per user
const verificationLimiter = rateLimit({
  windowMs: 60 * 60 * 1000, // 1 hour
  max: 3, // Max 3 verifications per hour per IP
  message: 'Too many verification attempts. Please try again later.',
  standardHeaders: true,
  legacyHeaders: false,
});

app.post('/api/create-verification',
  verificationLimiter,
  async (req, res) => {
    // Your verification logic
  }
);

// Track per-user limits in database
async function checkUserVerificationLimit(userId) {
  const recentAttempts = await db.verifications.count({
    userId,
    createdAt: { $gte: new Date(Date.now() - 24 * 60 * 60 * 1000) }
  });

  if (recentAttempts >= 5) {
    throw new Error('Daily verification limit exceeded');
  }
}

Testing Checklist

Before going live, test all integration points thoroughly:
1

Functional Testing

Desktop Flow:
  • QR code displays correctly
  • QR code scans and opens mobile flow
  • All query parameters work as expected
  • Return URL redirects with correct data
  • Error messages display properly
Mobile Flow:
  • Form loads on mobile browsers
  • Camera permissions request works
  • Document capture is smooth
  • Selfie capture works
  • Upload completes successfully
  • Success/error screens display
  • POST /submission creates submissions
  • PUT /image uploads images successfully
  • GET /submission retrieves correct data
  • PATCH /submission updates data
  • DELETE /submission removes data
  • All error codes handled properly
  • Encrypted requests/responses work
  • Rate limits are respected
  • Webhook endpoint receives events
  • All event types handled correctly
  • Webhook signature verification works (if implemented)
  • Duplicate webhooks are deduplicated
  • Failed processing doesn’t block webhook delivery
  • Encrypted webhooks decrypt properly
  • Retry logic works for failed deliveries
2

Security Testing

  • Invalid API keys are rejected
  • Non-whitelisted IPs are blocked (403)
  • Encrypted data can’t be read in transit
  • API keys are not exposed in client code
  • HTTPS is enforced for all requests
  • Tokens expire after 3 minutes
  • Used tokens cannot be reused
  • Invalid tokens show proper error
  • Token pool limit is enforced (100k)
  • Personal data is encrypted in transit
  • Webhook payloads are encrypted (if enabled)
  • Images are served over HTTPS
  • Sensitive data is not logged
3

Error Handling Testing

Test these error scenarios:
  • Network errors: Timeout, connection failed
  • Invalid data: Malformed JSON, wrong types
  • Missing fields: Required parameters missing
  • Rate limiting: Too many requests
  • Server errors: 500 responses
  • Webhook failures: Endpoint down, timeout
  • Image issues: File too large, invalid format
  • Expired tokens: Token already used/expired
4

User Experience Testing

  • Verification flow is intuitive
  • Error messages are helpful
  • Loading states are shown
  • Success confirmations display
  • Mobile experience is smooth
  • Multiple document types work
  • Different countries work
  • Return URL experience is good
5

Performance Testing

  • API responses are fast (<2s)
  • Image uploads complete quickly
  • Webhooks are received promptly
  • Large payloads don’t timeout
  • Concurrent requests handled
  • Database writes are efficient

Go-Live Checklist

Final checks before production launch:
1

Configuration Review

Dashboard Settings:
  • Webhook URL is correct and HTTPS
  • IP whitelist includes all production IPs
  • Secure Data Transfer is enabled
  • Return URL is configured correctly
  • Project settings match requirements:
    • Accepted document types
    • Country blacklist/whitelist
    • Age restrictions
    • Duplicate prevention rules
    • AML settings (if applicable)
2

Code Review

  • API keys loaded from environment variables
  • No hardcoded credentials in code
  • Error handling is comprehensive
  • Logging is implemented (but not sensitive data!)
  • Rate limiting is in place
  • Webhook retry logic implemented
  • Database queries are optimized
  • Frontend doesn’t expose API keys
3

Infrastructure

  • Production servers are provisioned
  • Load balancer configured (if needed)
  • SSL certificates installed
  • Database is backed up
  • Monitoring/alerting set up
  • CDN configured for static assets
  • Firewall rules configured
4

Monitoring Setup

Set up monitoring for:
// Example: Log key metrics
const metrics = {
  verifications_started: 0,
  verifications_completed: 0,
  verifications_approved: 0,
  verifications_rejected: 0,
  api_errors: 0,
  webhook_failures: 0,
  average_completion_time: 0
};

// Track in application
function trackVerificationStart() {
  metrics.verifications_started++;
  // Send to monitoring service (Datadog, New Relic, etc.)
}

// Monitor webhook delivery
app.post('/webhooks/idcheck', async (req, res) => {
  const startTime = Date.now();

  try {
    await processWebhook(req.body);
    metrics.verifications_completed++;

    if (req.body.kycStatus === 'approved') {
      metrics.verifications_approved++;
    } else if (req.body.kycStatus === 'rejected') {
      metrics.verifications_rejected++;
    }

  } catch (error) {
    metrics.webhook_failures++;
    logger.error('Webhook processing failed', { error, body: req.body });
  }

  const duration = Date.now() - startTime;
  metrics.average_completion_time =
    (metrics.average_completion_time + duration) / 2;

  res.status(200).json({ received: true });
});
Key Metrics to Monitor:
  • Verification success rate
  • Average completion time
  • API error rate
  • Webhook delivery rate
  • System uptime
  • Database performance
5

Documentation

  • Internal documentation written
  • Runbook created for ops team
  • Incident response plan documented
  • API integration guide for team
  • User flow diagrams created
6

Rollout Plan

Gradual Rollout Strategy:
// Phase 1: 5% of users (canary)
function shouldUseNewVerification(userId) {
  return parseInt(userId.slice(-2), 16) % 100 < 5;
}

// Phase 2: 25% of users
function shouldUseNewVerification(userId) {
  return parseInt(userId.slice(-2), 16) % 100 < 25;
}

// Phase 3: 100% of users
function shouldUseNewVerification(userId) {
  return true;
}

// Usage
if (shouldUseNewVerification(user.id)) {
  redirectToArgosVerification(user);
} else {
  redirectToOldVerification(user);
}
  • Phase 1: 5% of traffic for 48 hours
  • Monitor metrics, fix issues
  • Phase 2: 25% of traffic for 24 hours
  • Monitor metrics, fix issues
  • Phase 3: 100% of traffic
7

Launch!

  • Enable production integration
  • Monitor dashboards actively
  • Be ready for support requests
  • Have rollback plan ready
  • Celebrate! 🎉

Advanced Features

AML (Anti-Money Laundering) Screening

Perform compliance checks against global watchlists and sanctions lists.
1

Enable AML in Dashboard

  1. Navigate to Settings → General → AML Settings
  2. Enable AML screening
  3. Configure screening options:
    • Watchlist sources (UN, OFAC, EU, etc.)
    • Match threshold (fuzzy matching sensitivity)
    • Auto-reject on match
2

Request AML Check via API

curl -X POST 'https://rest-api.argosidentity.com/v3/submission/aml' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "fullName": "John Doe",
    "birthDate": "1990-01-01",
    "nationality": "USA",
    "submissionId": "sub_abc123"
  }'
3

Retrieve AML Report

curl -X GET 'https://rest-api.argosidentity.com/v3/submission/aml/report?submissionId=sub_abc123' \
  -H 'x-api-key: YOUR_API_KEY'
Response:
{
  "submissionId": "sub_abc123",
  "amlStatus": "clear",
  "matches": [],
  "checkedAt": "2024-01-15T10:35:00Z",
  "sources": ["UN", "OFAC", "EU", "UK"]
}
If matches found:
{
  "submissionId": "sub_abc123",
  "amlStatus": "match",
  "matches": [
    {
      "name": "John Doe",
      "matchScore": 0.95,
      "source": "OFAC",
      "listType": "sanctions",
      "details": "Sanctioned individual"
    }
  ],
  "checkedAt": "2024-01-15T10:35:00Z"
}
4

Handle AML Results

async function handleAMLWebhook(event) {
  if (event.webhook_trigger === 'aml') {
    const { submissionId, amlStatus, matches } = event;

    if (amlStatus === 'match') {
      // Flag for review
      await db.submissions.update({
        submissionId,
        flagged: true,
        flagReason: 'AML match detected',
        requiresManualReview: true
      });

      // Alert compliance team
      await notifyCompliance({
        type: 'AML_MATCH',
        submissionId,
        matches
      });

      // Reject verification if auto-reject enabled
      if (config.aml.autoReject) {
        await rejectVerification(submissionId, 'AML compliance issue');
      }
    } else {
      // Clear to proceed
      console.log(`AML clear for ${submissionId}`);
    }
  }
}
Learn more: AML API Reference

Ongoing AML Monitoring

Continuously monitor approved users against updated watchlists.
// Register user for ongoing monitoring
await fetch('https://rest-api.argosidentity.com/v3/submission/aml/ongoing', {
  method: 'POST',
  headers: {
    'x-api-key': YOUR_API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    submissionId: 'sub_abc123',
    recordId: 'user_12345'
  })
});

// Receive webhook when new match is found
app.post('/webhooks/idcheck', (req, res) => {
  if (req.body.webhook_trigger === 'aml_monitor') {
    console.log('Ongoing AML match detected:', req.body);
    // Take action (freeze account, notify user, etc.)
  }
  res.status(200).send('OK');
});
Learn more: AML Ongoing Monitoring

Data Projection (Field Filtering)

Control which data fields are collected and displayed. Use Cases:
  • Minimize data collection for GDPR compliance
  • Create different verification levels (basic vs full)
  • Customize for specific document types or countries
1

Create Projection via API

curl -X POST 'https://rest-api.argosidentity.com/v3/projection' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "projectionName": "basic-kyc",
    "allowedFields": [
      "fullName",
      "birthDate",
      "nationality"
    ]
  }'
Response:
{
  "message": "success",
  "projectionId": "proj_123abc"
}
2

Use Projection in Liveform

const config = {
  projectionId: "proj_123abc"
};

const encryptedConfig = encryptQueryParams(config, YOUR_API_KEY);
const liveformUrl = `https://form.argosidentity.com?pid={your_pid}&encrypted=${encodeURIComponent(encryptedConfig)}`;
You can also use projectionName instead of projectionId, but they cannot be used together.
3

Result

With this projection, the form will:
  • Only collect name, birth date, and nationality
  • Skip other fields (address, document number, etc.)
  • Return only projected fields in API responses and webhooks
Learn more: Projection API

Multi-Language Support

ID check Liveform supports multiple languages for global users. Available Languages:
  • English (en)
  • Korean (ko)
  • Japanese (ja)
  • Spanish (es)
  • French (fr)
  • German (de)
  • And more…
Usage:
// Add lang parameter to Liveform URL
const liveformUrl = `https://form.argosidentity.com?pid={your_pid}&lang=ko`;

// Or let user's browser language determine
const userLang = navigator.language.split('-')[0]; // 'en', 'ko', 'ja', etc.
const liveformUrl = `https://form.argosidentity.com?pid={your_pid}&lang=${userLang}`;
Learn more: Liveform Languages

Troubleshooting Guide

Common issues and how to resolve them:
Symptoms:
  • No webhook events arriving
  • Webhook endpoint not being called
Possible Causes & Solutions:
  1. Webhook URL not HTTPS
    ❌ http://yourapp.com/webhook
    ✅ https://yourapp.com/webhook
    
  2. Endpoint returning non-200 status
    • Check your server logs
    • Ensure endpoint returns 200 OK within 5 seconds
    • Process webhooks asynchronously if needed
  3. Firewall blocking ARGOS IPs
    • Whitelist ARGOS webhook IPs in your firewall
    • Check with ARGOS support for IP ranges
  4. Endpoint URL typo in dashboard
    • Double-check the URL in Settings → Access Management
    • Test endpoint with curl: curl -X POST https://yourapp.com/webhook
Debugging Steps:
// Add detailed logging
app.post('/webhooks/idcheck', (req, res) => {
  console.log('=== WEBHOOK RECEIVED ===');
  console.log('Headers:', req.headers);
  console.log('Body:', req.body);
  console.log('========================');

  res.status(200).json({ received: true });
});

// Test with webhook.site
// 1. Go to https://webhook.site
// 2. Copy unique URL
// 3. Enter in dashboard
// 4. Trigger test event
// 5. Check webhook.site for delivery
Symptoms:
{
  "errorCode": "forbidden",
  "errorMessage": "Access denied"
}
Possible Causes & Solutions:
  1. Invalid or missing API key
    # Check header format
     x-api-key: argos_live_abc123...
     x-api-key: "argos_live_abc123..."  (no quotes!)
     Authorization: Bearer argos_live... (wrong header!)
    
  2. IP not whitelisted
    • Check your server’s public IP: curl ifconfig.me
    • Add to IP whitelist in dashboard
    • If using proxy/load balancer, whitelist proxy IP
  3. Using wrong API key
    • Verify you’re using the correct project’s API key
    • Check for copy-paste errors
    • Regenerate API key if needed
Debugging:
# Test from command line
curl -v -H "x-api-key: YOUR_API_KEY" \
  https://rest-api.argosidentity.com/v3/submission

# Check response headers for clues
# Look for: X-Request-Id, X-Error-Code
Symptoms:
  • “Invalid encrypted data” errors
  • Decrypted data is gibberish
  • JSON parse error when decrypting
Possible Causes & Solutions:
  1. Using wrong encryption mode
    • API requests/responses: Use AES-256-ECB
    • Webhooks: Use AES-256-CBC
    • Query strings: Use AES-256-ECB
  2. Not hashing API key first
    const key = apiKey; // Wrong!
    const hashedKey = CryptoJS.SHA256(apiKey); // Correct!
    
  3. Encoding issues
    // Encryption output must be Base64
    encrypted.ciphertext.toString(CryptoJS.enc.Base64)
    encrypted.toString() // Wrong encoding!
    
    // Decryption input must parse Base64
    CryptoJS.enc.Base64.parse(encryptedData)
    encryptedData // Wrong!
    
  4. Wrong key extraction (ECB)
    CryptoJS.lib.WordArray.create(hashedKey.words.slice(0, 8), 32)
    hashedKey // Wrong!
    
Testing:
// Use this test to verify your encryption
const testData = { test: "hello" };
const encrypted = encryptData(testData, YOUR_API_KEY);
const decrypted = decryptData(encrypted, YOUR_API_KEY);

console.log('Original:', testData);
console.log('Encrypted:', encrypted);
console.log('Decrypted:', decrypted);

if (JSON.stringify(testData) === JSON.stringify(decrypted)) {
  console.log('✅ Encryption working correctly!');
} else {
  console.log('❌ Encryption failed!');
}
Use the Encryption Tool to verify!
Symptoms:
  • Image upload returns 400 or 413 error
  • “Image too large” errors
  • “Invalid image format” errors
Possible Causes & Solutions:
  1. Image too large (>10MB)
    // Compress before upload
    const compressedImage = await compressImage(originalImage, {
      maxWidth: 1920,
      maxHeight: 1080,
      quality: 0.8
    });
    
  2. Unsupported file format
    • ✅ Supported: JPEG, PNG
    • ❌ Not supported: GIF, BMP, WebP, HEIC
    // Convert HEIC to JPEG (iOS photos)
    import heic2any from 'heic2any';
    
    if (file.type === 'image/heic') {
      const converted = await heic2any({
        blob: file,
        toType: 'image/jpeg'
      });
      file = converted;
    }
    
  3. Poor image quality
    • Ensure minimum resolution: 1280x720
    • Check image isn’t blurry
    • Ensure all document edges visible
    • Verify no glare on document
  4. Wrong Content-Type header
     Content-Type: image/jpeg
     Content-Type: application/octet-stream
    
Symptoms:
  • Blank screen when opening Liveform URL
  • “Invalid project ID” error
  • QR code not displaying
Possible Causes & Solutions:
  1. Invalid project ID (PID)
    • Verify PID from dashboard Settings → Access Management
    • Check for typos in URL
    ✅ ?pid=proj_abc123
    ❌ ?pid=abc123 (missing prefix)
    
  2. Malformed query parameters
    • URL encode all parameter values
    • Check for proper formatting
    ?email=user@example.com&userid=user 123
    ?email=${encodeURIComponent('user@example.com')}&userid=${encodeURIComponent('user 123')}
    
  3. Encrypted parameter issues
    • Verify encryption is correct
    • Ensure URL encoding of encrypted value
    • Check encryption tool output matches
  4. Browser compatibility
    • Check supported browsers
    • Test in different browsers
    • Check for JavaScript errors in console (F12)
Testing:
// Test basic URL first
https://form.argosidentity.com?pid={your_pid}

// Then add parameters one by one
https://form.argosidentity.com?pid={your_pid}&email=test@example.com

// Use browser DevTools (F12) → Console for errors
Symptoms:
  • “Duplicate user detected” error
  • User can’t submit even though they haven’t before
Possible Causes & Solutions:
  1. Duplicate prevention enabled
    • Check dashboard Settings → Project Settings → Duplicate Prevention
    • rejectDuplicateUser is enabled
    • User with same name+DOB+nationality already verified
  2. Approved/Reject period restrictions
    • Dashboard settings prevent re-submission within X days
    • Override with query parameters:
      ?approvePeriod=false&rejectPeriod=false
      
  3. Same email/userid reused
    • Use unique identifiers for each user
    • Don’t reuse test email addresses
Solutions:
// Option 1: Override for specific user
const liveformUrl = `https://form.argosidentity.com?pid={your_pid}&rejectDuplicateUser=false`;

// Option 2: Delete previous submission
await fetch(`https://rest-api.argosidentity.com/v3/submission?submissionId=${oldSubmissionId}`, {
  method: 'DELETE',
  headers: { 'x-api-key': YOUR_API_KEY }
});

// Option 3: Use different userid/email
const uniqueUserid = `user_${userId}_${Date.now()}`;
Symptoms:
{
  "errorCode": "too_many_requests",
  "errorMessage": "Rate limit exceeded"
}
Solutions:
  1. Implement retry with exponential backoff
    async function callAPIWithRetry(url, options, maxRetries = 3) {
      for (let i = 0; i < maxRetries; i++) {
        try {
          const response = await fetch(url, options);
    
          if (response.status === 429) {
            const retryAfter = response.headers.get('Retry-After') || (2 ** i);
            console.log(`Rate limited. Retrying after ${retryAfter}s...`);
            await sleep(retryAfter * 1000);
            continue;
          }
    
          return response;
    
        } catch (error) {
          if (i === maxRetries - 1) throw error;
          await sleep(1000 * 2 ** i); // 1s, 2s, 4s
        }
      }
    }
    
  2. Implement request queuing
    const queue = require('p-queue').default;
    
    const apiQueue = new queue({
      concurrency: 1,
      interval: 1000, // 1 request per second
      intervalCap: 1
    });
    
    async function queuedAPICall(url, options) {
      return apiQueue.add(() => fetch(url, options));
    }
    
  3. Cache API responses
    const cache = new Map();
    
    async function cachedGetSubmission(submissionId) {
      if (cache.has(submissionId)) {
        return cache.get(submissionId);
      }
    
      const submission = await getSubmission(submissionId);
      cache.set(submissionId, submission);
    
      // Expire after 5 minutes
      setTimeout(() => cache.delete(submissionId), 5 * 60 * 1000);
    
      return submission;
    }
    
Symptoms:
  • “Token expired” error
  • “Token not found” error
  • “Token already used” error
Possible Causes & Solutions:
  1. Token expired (>3 minutes since first use)
    // Generate new token
    const newToken = `session-${userId}-${Date.now()}`;
    
    await fetch('https://rest-api.argosidentity.com/v3/submission/tokens', {
      method: 'POST',
      headers: { 'x-api-key': YOUR_API_KEY, 'Content-Type': 'text/plain' },
      body: JSON.stringify({ tokenId: [newToken] })
    });
    
    // Send new URL to user
    const newUrl = `https://form.argosidentity.com?pid={your_pid}&token=${newToken}`;
    
  2. Token already used
    • Each token can only create one submission
    • Generate new token for each verification attempt
  3. Token pool exceeded (100k limit)
    • Delete old tokens:
      curl -X DELETE 'https://rest-api.argosidentity.com/v3/submission/tokens?startDate=2024-01-01&endDate=2024-01-31' \
        -H 'x-api-key: YOUR_API_KEY'
      
    • Enable auto-deletion in dashboard
  4. Token format invalid
    • Must be 8-64 characters
    • Only alphanumeric + -_.
    • Must start/end with letter or number
    "user-session-123"
    "token_abc.xyz"
    "-invalid-" (starts with hyphen)
    "short" (too short, &lt;8 chars)
    "has space" (contains space)
    

Best Practices Summary

For All Integrations

Security

  • Enable Secure Data Transfer encryption
  • Use IP whitelisting in production
  • Never expose API keys in client code
  • Implement Private Mode for sensitive apps
  • Regularly rotate API keys (quarterly)

Error Handling

  • Handle all HTTP error codes (400, 403, 500, etc.)
  • Implement retry logic with exponential backoff
  • Log errors for debugging (without sensitive data)
  • Show user-friendly error messages
  • Have fallback flows for critical errors

Webhooks

  • Always respond with 200 OK quickly (<5s)
  • Process webhooks asynchronously
  • Implement idempotency (deduplicate)
  • Log all webhook events
  • Monitor webhook delivery rate
  • Implement retry logic for processing failures

Testing

  • Test all integration points before launch
  • Use test accounts/data during development
  • Test error scenarios thoroughly
  • Perform load testing for high-traffic apps
  • Monitor in staging before production

Performance

  • Cache API responses when appropriate
  • Implement rate limiting on your end
  • Optimize database queries
  • Use CDN for static assets
  • Monitor API response times

Compliance

  • Minimize data collection (use projections)
  • Implement data retention policies
  • Enable AML screening for regulated industries
  • Keep audit logs of verifications
  • Follow GDPR/CCPA requirements

Additional Resources


Support

Need help? We’re here for you:

Email Support

support@argosidentity.comResponse time: Within 24 hours (business days)

Documentation

Browse our comprehensive documentation and guides

Community

Join our developer community (link from support team)

Enterprise Support

For enterprise customers: Dedicated support channel available

What’s Next?

1

Start Building

You now have everything you need! Start with the integration method that best fits your use case.
2

Join the Community

Connect with other developers, share experiences, and get help from the community.
3

Stay Updated

Subscribe to the changelog for updates on new features and improvements.
4

Provide Feedback

Your feedback helps us improve! Let us know how we can make ID check better for you.

Congratulations! You’ve completed the ID check onboarding guide. You’re ready to build secure, compliant identity verification into your application.
Pro Tip: Bookmark this guide and refer back to the troubleshooting section as you build. Happy coding!
I