Skip to main content

Fetch a Verification

Overview

Retrieve detailed information about a specific Verification by its ID. View verification status, type, and error details if failed.

Resource Access

  • User Permissions: Admin users only
  • Endpoint: GET /verifications/\{verification_id}

Arguments

ParameterTypeRequiredDescription
verification_idstringYesUnique Verification ID (in URL path)

Example Request

curl -X GET \
'https://api.ahrvo.network/payments/na/verifications/VIverification123' \
-u username:password

Example Response (Successful Merchant Verification)

{
"id": "VIverification123",
"created_at": "2023-12-10T20:00:00Z",
"updated_at": "2023-12-10T20:00:05Z",
"state": "SUCCEEDED",
"merchant": "MUmerchant123",
"payment_instrument": null,
"processor": "DUMMY_V1",
"raw": null,
"trace_id": "VT_98765432",
"type": "MERCHANT",
"_links": {
"self": {
"href": "https://api.ahrvo.network/payments/na/verifications/VIverification123"
},
"merchant": {
"href": "https://api.ahrvo.network/payments/na/merchants/MUmerchant123"
}
}
}

Example Response (Successful Card Verification)

{
"id": "VIverification456",
"created_at": "2023-12-10T19:30:00Z",
"updated_at": "2023-12-10T19:30:03Z",
"state": "SUCCEEDED",
"merchant": "MUmerchant123",
"payment_instrument": "PIcreditCard456",
"processor": "DUMMY_V1",
"raw": null,
"trace_id": "VT_12345678",
"type": "PAYMENT_INSTRUMENT",
"_links": {
"self": {
"href": "https://api.ahrvo.network/payments/na/verifications/VIverification456"
},
"payment_instrument": {
"href": "https://api.ahrvo.network/payments/na/payment_instruments/PIcreditCard456"
},
"merchant": {
"href": "https://api.ahrvo.network/payments/na/merchants/MUmerchant123"
}
}
}

Example Response (Failed Verification)

{
"id": "VIverification789",
"created_at": "2023-12-10T18:00:00Z",
"updated_at": "2023-12-10T18:00:08Z",
"state": "FAILED",
"merchant": "MUmerchant456",
"payment_instrument": "PIcreditCard789",
"processor": "DUMMY_V1",
"raw": "{\"error\": \"Card expired\", \"code\": \"EXPIRED_CARD\", \"details\": \"Card expired in 11/2023\"}",
"trace_id": "VT_12345679",
"type": "PAYMENT_INSTRUMENT",
"_links": {
"self": {
"href": "https://api.ahrvo.network/payments/na/verifications/VIverification789"
},
"payment_instrument": {
"href": "https://api.ahrvo.network/payments/na/payment_instruments/PIcreditCard789"
},
"merchant": {
"href": "https://api.ahrvo.network/payments/na/merchants/MUmerchant456"
}
}
}

Example Response (Pending Verification)

{
"id": "VIverification999",
"created_at": "2023-12-10T17:00:00Z",
"updated_at": "2023-12-10T17:00:00Z",
"state": "PENDING",
"merchant": "MUmerchant789",
"payment_instrument": null,
"processor": "DUMMY_V1",
"raw": null,
"trace_id": "VT_98765435",
"type": "MERCHANT",
"_links": {
"self": {
"href": "https://api.ahrvo.network/payments/na/verifications/VIverification999"
},
"merchant": {
"href": "https://api.ahrvo.network/payments/na/merchants/MUmerchant789"
}
}
}

Additional Information

  • Verification ID: Unique identifier
    • Starts with "VI"
    • Immutable
    • Use for support tickets
    • Reference in logs
  • Type: What was verified
    • MERCHANT: Merchant identity/business verification
      • Validates tax ID
      • Checks business info
      • Verifies owner identity
      • payment_instrument is null
    • PAYMENT_INSTRUMENT: Card/bank account verification
      • Validates card is active
      • Checks bank account
      • Confirms ownership
      • payment_instrument has ID
  • State: Current status
    • PENDING: Verification in progress
      • Submitted to processor
      • Awaiting response
      • Usually seconds
      • Rare to see (fast processing)
    • SUCCEEDED: Verification passed
      • Merchant/payment instrument validated
      • Ready to use
      • Can process payments
    • FAILED: Verification failed
      • Check raw field for reason
      • Invalid information
      • Expired card
      • Incorrect details
  • Created At: When verification started
    • ISO 8601 timestamp
    • UTC timezone
    • Never changes
  • Updated At: Last state change
    • When verification completed
    • Changes from PENDING to SUCCEEDED/FAILED
    • ISO 8601 timestamp
  • Merchant: Associated merchant
    • Always populated
    • Who owns the verified resource
    • Links to Merchant resource
  • Payment Instrument: Card/bank being verified
    • Null for MERCHANT type
    • ID for PAYMENT_INSTRUMENT type
    • Links to Payment Instrument resource
  • Processor: Verification provider
    • DUMMY_V1: Test/sandbox
    • Production processors vary
    • Determines verification method
    • Different rules per processor
  • Raw: Processor response details
    • Usually null for SUCCEEDED
    • Contains error info for FAILED
    • JSON string format
    • Technical details
    • Error codes like EXPIRED_CARD, INVALID_NUMBER
    • Not for end-user display
  • Trace ID: Processor reference
    • External verification ID
    • Use for support tickets
    • Links to processor logs
    • Helps troubleshoot issues
  • Links: Related resources
    • merchant: Full merchant details
    • payment_instrument: Card/bank details (if applicable)
    • Self reference

Use Cases

Debug Specific Verification

# Support ticket references verification ID
curl -X GET \
'https://api.ahrvo.network/payments/na/verifications/VIverification123' \
-u username:password

# Check state and raw error details

Webhook Handler

// Webhook provides verification ID
app.post('/webhooks/finix', async (req, res) => {
const event = req.body;

if (event.type === 'merchant.verification.failed' ||
event.type === 'payment_instrument.verification.failed') {

// Get full verification details
const verificationId = event.data.id;
const verification = await fetchVerification(verificationId);

console.log('Verification failed:', verification.id);
console.log('Type:', verification.type);
console.log('State:', verification.state);

if (verification.raw) {
const error = JSON.parse(verification.raw);
console.log('Error:', error);

// Take action based on error
if (verification.type === 'MERCHANT') {
await notifyMerchantToUpdateInfo(
verification.merchant,
error.error
);
} else if (verification.type === 'PAYMENT_INSTRUMENT') {
await notifyCustomerCardDeclined(
verification.payment_instrument,
error.code
);
}
}
}

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

Analyze Verification Failure

// Deep dive into why verification failed
async function analyzeVerificationFailure(verificationId) {
const verification = await fetchVerification(verificationId);

if (verification.state !== 'FAILED') {
console.log('Verification not failed:', verification.state);
return;
}

console.log('Verification Details:');
console.log(' ID:', verification.id);
console.log(' Type:', verification.type);
console.log(' Merchant:', verification.merchant);
console.log(' Payment Instrument:', verification.payment_instrument || 'N/A');
console.log(' Processor:', verification.processor);
console.log(' Trace ID:', verification.trace_id);
console.log(' Created:', verification.created_at);
console.log(' Failed:', verification.updated_at);

if (verification.raw) {
console.log('\nError Details:');
const error = JSON.parse(verification.raw);
console.log(' Code:', error.code);
console.log(' Message:', error.error);
console.log(' Details:', error.details || 'None');

// Provide resolution steps
const resolution = getResolutionSteps(error.code, verification.type);
console.log('\nResolution Steps:');
console.log(resolution);
}

return verification;
}

function getResolutionSteps(errorCode, type) {
if (type === 'MERCHANT') {
switch (errorCode) {
case 'INVALID_TAX_ID':
return '1. Verify tax ID is correct\n2. Update Merchant entity.tax_id\n3. Wait for re-verification';
case 'INVALID_ADDRESS':
return '1. Check business address\n2. Update Merchant entity.business_address\n3. Wait for re-verification';
default:
return 'Contact support with verification ID';
}
} else {
switch (errorCode) {
case 'EXPIRED_CARD':
return '1. Request new card from customer\n2. Create new Payment Instrument';
case 'INVALID_NUMBER':
return '1. Ask customer to verify card number\n2. Re-enter card details';
case 'INSUFFICIENT_FUNDS':
return '1. Ask customer to add funds or use different card';
default:
return 'Request different payment method from customer';
}
}
}

Support Ticket Investigation

// Customer support looking up verification
async function supportTicketLookup(verificationId) {
const verification = await fetchVerification(verificationId);

// Format for support agent
const report = {
verificationId: verification.id,
type: verification.type === 'MERCHANT' ? 'Business Verification' : 'Payment Method Verification',
status: verification.state,
merchantId: verification.merchant,
paymentInstrumentId: verification.payment_instrument,
processor: verification.processor,
traceId: verification.trace_id,
createdAt: new Date(verification.created_at).toLocaleString(),
completedAt: new Date(verification.updated_at).toLocaleString(),
duration: `${Math.floor((new Date(verification.updated_at) - new Date(verification.created_at)) / 1000)} seconds`
};

if (verification.state === 'FAILED') {
const error = verification.raw ? JSON.parse(verification.raw) : {};
report.errorCode = error.code;
report.errorMessage = error.error;
report.errorDetails = error.details;
}

console.log('=== Verification Report ===');
console.log(JSON.stringify(report, null, 2));

return report;
}

Verification Monitoring

// Check verification status over time
async function monitorVerification(verificationId, maxWaitSeconds = 60) {
const startTime = Date.now();
let attempts = 0;

while ((Date.now() - startTime) < maxWaitSeconds * 1000) {
attempts++;
const verification = await fetchVerification(verificationId);

console.log(`Attempt ${attempts}: ${verification.state}`);

if (verification.state === 'SUCCEEDED') {
console.log('✓ Verification succeeded');
return { success: true, verification };
} else if (verification.state === 'FAILED') {
console.error('✗ Verification failed');
const error = verification.raw ? JSON.parse(verification.raw) : {};
return { success: false, verification, error };
} else if (verification.state === 'PENDING') {
console.log('⏳ Still pending, waiting...');
await sleep(3000); // Wait 3 seconds
}
}

console.error('Timeout waiting for verification');
return { success: false, timeout: true };
}

Compare Multiple Verifications

// Compare verification attempts for same resource
async function compareVerifications(verificationIds) {
const verifications = await Promise.all(
verificationIds.map(id => fetchVerification(id))
);

console.log('Verification Comparison:');
console.log('========================\n');

verifications.forEach((v, index) => {
console.log(`Verification ${index + 1}:`);
console.log(` ID: ${v.id}`);
console.log(` Created: ${v.created_at}`);
console.log(` State: ${v.state}`);
console.log(` Type: ${v.type}`);

if (v.state === 'FAILED' && v.raw) {
const error = JSON.parse(v.raw);
console.log(` Error: ${error.code} - ${error.error}`);
}

console.log('');
});

// Check if same error across attempts
const failedWithSameError = verifications
.filter(v => v.state === 'FAILED')
.map(v => v.raw ? JSON.parse(v.raw).code : null)
.filter((code, index, arr) => arr.indexOf(code) === index);

if (failedWithSameError.length === 1) {
console.log(`⚠ All failures have same error: ${failedWithSameError[0]}`);
console.log('This indicates a persistent issue that needs to be fixed.');
}
}

Best Practices

  • Use for Debugging: Primary use case
    • Not needed for normal flow
    • Use list endpoints for latest status
    • Fetch when you have specific ID
    • Good for webhook handlers
  • Parse Raw Carefully: Error details
    • Always check if raw exists
    • Parse JSON safely (try/catch)
    • Map error codes to user messages
    • Don't display raw to end users
  • Check Type: Handle differently
    • MERCHANT: Business verification
    • PAYMENT_INSTRUMENT: Card/bank verification
    • Different error types
    • Different resolution steps
  • Store Verification ID: For reference
    • Link to orders/merchants
    • Include in support tickets
    • Log for debugging
    • Audit trail
  • Use Trace ID: For processor support
    • Include in support tickets
    • Reference with processor
    • Links to their logs
    • Faster resolution
  • Don't Poll: Use webhooks
    • Verification usually completes fast
    • Webhooks notify instantly
    • Polling wastes resources
    • Only poll if webhook failed

Common Workflows

Webhook-Driven Flow

  1. Create Merchant or Payment Instrument
  2. Platform creates Verification automatically
  3. Webhook sent when verification completes
  4. Fetch Verification by ID from webhook
  5. Check state and handle accordingly
  6. Update your system

Support Ticket Flow

  1. Customer reports issue
  2. Support agent gets verification ID from logs
  3. Fetch Verification details
  4. Check state and raw error
  5. Provide resolution steps to customer
  6. Escalate to engineering if needed

Failed Verification Recovery

async function handleFailedVerification(verificationId) {
const verification = await fetchVerification(verificationId);

if (verification.state !== 'FAILED') {
return;
}

const error = verification.raw ? JSON.parse(verification.raw) : {};

if (verification.type === 'MERCHANT') {
// Merchant verification failed
console.log('Merchant verification failed:', error.error);

// Update merchant based on error
if (error.code === 'INVALID_TAX_ID') {
console.log('Action: Update merchant tax ID');
// Guide merchant to correct tax ID
} else if (error.code === 'INVALID_ADDRESS') {
console.log('Action: Update merchant address');
// Guide merchant to verify address
}
} else if (verification.type === 'PAYMENT_INSTRUMENT') {
// Card/bank verification failed
console.log('Payment instrument verification failed:', error.error);

if (error.code === 'EXPIRED_CARD') {
console.log('Action: Request new card');
// Prompt customer for new card
} else if (error.code === 'INVALID_NUMBER') {
console.log('Action: Re-enter card details');
// Ask customer to verify and re-enter
}
}
}

Troubleshooting

Verification Not Found

  • Check verification ID is correct
  • Starts with "VI"
  • Case sensitive
  • May be from different environment

State is PENDING for Long Time

  • Usually completes in seconds
  • If > 1 minute for cards, retry
  • Bank accounts can take days
  • Contact support with trace_id

Raw Field is Null for FAILED

  • Rare but possible
  • Check trace_id
  • Contact support
  • May be processor issue

Can't Understand Error Code

  • Check processor documentation
  • Common codes: EXPIRED_CARD, INVALID_NUMBER, INSUFFICIENT_FUNDS
  • Contact support with verification ID
  • May need processor clarification
  • GET /merchants/{id}/verifications: List merchant verifications
  • GET /payment_instruments/{id}/verifications: List payment instrument verifications
  • GET /merchants/{id}: View merchant details
  • GET /payment_instruments/{id}: View payment instrument details