Inyo

Check Card Account (ANI)

The Check Card Account API validates a card without processing a payment. It performs up to three verification checks plus card capability profiling and returns the results:

  • AVS — Address Verification Service (billing address match) — all card networks
  • CVC — Card Verification Code (security code match) — all card networks
  • AAV Cardholder Name — Visa Account Name Inquiry (cardholder name match against issuer records) — Visa cards only

AVS and CVC verification are standard checks performed for any card. The cardholder name check is powered by Visa's Account Name Inquiry (ANI) product, which queries the issuing bank's records to verify that the name submitted matches the legal name on the account. ANI is only available for Visa cards — for non-Visa cards, verificationResults.aavCardholderName returns NOT_SUPPORTED.

The response also reports the card's OCT (push/payout) and AFT (funding/pull) capability so you can decide a card's eligibility for a given flow before initiating a transaction.

What is Visa ANI?

Account Name Inquiry (ANI) is a Visa product that enables merchants to verify the cardholder's name directly with the issuing bank before or independently of a financial transaction. When a card is submitted, Visa forwards the provided first, middle, and last name to the issuer, who compares them against the legal name on the account and returns a match result.

Key details about Visa ANI:

  • Visa only — ANI is a Visa network service. It is not available for Mastercard, Amex, Discover, or other networks.
  • Issuer participation — ANI became mandatory for U.S. and Canadian Visa issuers in October 2023, meaning most Visa issuers in these markets support it. Some issuers outside these markets may not yet support ANI, in which case the result will be NOT_SUPPORTED.
  • Name matching — Visa checks first, middle, and last name components separately against the issuer's records. At minimum, the last name must be provided. The issuer returns the closest match when multiple names are on file (e.g., joint accounts).
  • Independent of payment — ANI operates independently of the financial transaction. No funds are held or moved.
  • Exclusions — Business/corporate cards and non-reloadable prepaid cards without a registered name are not supported for ANI.

Use Cases

  • Onboarding — Validate a customer's card before storing it for future charges
  • Fraud prevention — Confirm the person submitting the card is the actual cardholder
  • KYC enhancement — Cross-reference the name on the card with the name provided during identity verification
  • Payout eligibility — Check octStatus before pushing funds to a card; check aftStatus before pulling
  • Card-on-file verification — Check that a stored card is still valid and belongs to the expected person

How It Works

1. Tokenize card          2. POST /v2/check-card-account       3. Read results
   (client-side)             (server-side)
       │                          │                             For all cards:
       ▼                          ▼                               → verificationResults.avs
   inyo.js encrypts       Gateway verifies AVS + CVC             → verificationResults.cvc
   card + name →          for all cards. If Visa,                → octStatus / aftStatus
   returns cardTokenId    also queries ANI for                  For Visa cards only:
                          cardholder name match →                 → verificationResults.aavCardholderName

Note: This API does not charge the card or create a payment. It is purely a validation call. No amount is required in the request.


Endpoint

POST https://{FQDN}/v2/check-card-account

Headers:

HeaderValue
AuthorizationBearer {accessToken}
Content-Typeapplication/json

Request Body

The payload is simplified compared to standard payment requests — no amount, paymentType, or capture fields are needed.

Root Object

FieldTypeRequiredDescription
externalPaymentIdstringYour unique identifier for this validation request (idempotency key)
ipAddressstringRequester's IPv4 or IPv6 address
senderobjectCardholder + identity details

sender Object

The sender binds the card check to a verified identity — email, phoneNumber, and at least one documents entry are required.

FieldTypeRequiredDescription
firstNamestringCardholder's first name (compared against issuer records via Visa ANI for Visa cards)
lastNamestringCardholder's last name (compared against issuer records via Visa ANI for Visa cards)
emailstringCardholder's email address
phoneNumberstringCardholder's phone number (E.164, e.g. +15555550123)
phoneNumberTypestringPhone type (e.g. MOBILE, HOME)
birthDatestringDate of birth, YYYY-MM-DD
birthCountryCodestringCountry of birth (ISO country code)
documentsarrayIdentity documents — at least one entry (see below)
addressobjectBilling address (used for AVS verification)
paymentMethodobjectTokenized card details

sender.documents[] Object

FieldTypeRequiredDescription
documentstringDocument number/value
typestringDocument type (e.g. PASSPORT, NATIONAL_ID, SSN)
countryCodestringIssuing country (ISO country code)

sender.address Object

FieldTypeRequiredDescription
countryCodestringISO Alpha-3 country code (e.g., "USA")
stateCodestringState/province abbreviation (e.g., "NY")
citystringCity name
line1stringStreet address line 1
line2stringStreet address line 2
zipCodestringPostal/ZIP code

sender.paymentMethod Object

FieldTypeRequiredDescription
typestring"CARD"
cardTokenIdstringToken UUID from the tokenizer

Example Request

curl -X POST https://{FQDN}/v2/check-card-account \
  -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIs...' \
  -H 'Content-Type: application/json' \
  -d '{
    "externalPaymentId": "card-check-001",
    "ipAddress": "203.0.113.42",
    "sender": {
      "firstName": "John",
      "lastName": "Smith",
      "email": "john.smith@example.com",
      "phoneNumber": "+15555550123",
      "birthDate": "1985-04-12",
      "birthCountryCode": "US",
      "documents": [
        {
          "document": "123-45-6789",
          "type": "SSN",
          "countryCode": "US"
        }
      ],
      "address": {
        "countryCode": "US",
        "stateCode": "NY",
        "city": "New York",
        "line1": "123 Main Street",
        "zipCode": "10001"
      },
      "paymentMethod": {
        "type": "CARD",
        "cardTokenId": "ab5fc589-8b48-4531-94c0-68b0629c13fe"
      }
    }
  }'

Response

Verified (200)

{
  "card": {
    "created": "2026-05-16 16:37:40",
    "issuerName": "MODULR FS, LTD.",
    "issuerCountry": "UNITED KINGDOM",
    "bin": "446203",
    "lastFour": "0000"
  },
  "verificationResults": {
    "avs": "PARTIAL_MATCH",
    "cvc": "NOT_SUPPORTED",
    "aavCardholderName": "APPROVED"
  },
  "octStatus": {
    "capable": false,
    "highPerforming": false,
    "lowPerforming": false
  },
  "aftStatus": {
    "capable": true,
    "highPerforming": true,
    "lowPerforming": false
  },
  "redirectAcsUrl": ""
}

3DS Challenge (200)

The issuing bank requires cardholder authentication before returning verification results. redirectAcsUrl is populated and the verification results are pending until the challenge completes:

{
  "card": {
    "issuerName": "MODULR FS, LTD.",
    "issuerCountry": "UNITED KINGDOM",
    "bin": "446203",
    "lastFour": "0000"
  },
  "verificationResults": {
    "avs": "N/A",
    "cvc": "N/A",
    "aavCardholderName": "N/A"
  },
  "redirectAcsUrl": "https://{FQDN}/secure-code/start-challenge?token=dce568c6-..."
}

When redirectAcsUrl is non-empty, redirect the cardholder to it. See Handling 3D Secure for the complete flow.

Response Fields

card

FieldTypeDescription
createdstringTimestamp the card record was created
issuerNamestringIssuing bank name
issuerCountrystringIssuing country
binstringBank Identification Number (first 6 digits)
lastFourstringLast 4 digits of the card

verificationResults

FieldTypeDescription
avsstringAddress verification result (see below)
cvcstringCard verification code result (see below)
aavCardholderNamestringCardholder name verification result — Visa ANI, Visa only (see below)

octStatus / aftStatus

Card capability indicators. OCT (Original Credit Transaction) reflects the card's ability to receive pushes/payouts; AFT (Account Funding Transaction) reflects its ability to fund pulls.

FieldTypeDescription
capablebooleanWhether the card supports this transaction type
highPerformingbooleanCard is in the high-performing tier for this transaction type
lowPerformingbooleanCard is in the low-performing tier for this transaction type

redirectAcsUrl

FieldTypeDescription
redirectAcsUrlstring3DS challenge URL. Empty ("") when no challenge is required; when populated, redirect the cardholder to complete authentication.

Understanding the Verification Results

AVS Result (verificationResults.avs)

Compares the billing address provided in the request with the address on file at the card issuer.

ValueMeaningAction
APPROVEDAddress matches issuer records✅ Low fraud risk
PARTIAL_MATCHSome components matched (e.g., ZIP matched but street did not)⚠️ Review with other signals
FAILEDAddress does not match⚠️ Elevated fraud risk
NOT_SUPPORTEDIssuer/network does not support AVSℹ️ Fall back to CVC and ANI
NOT_SENTNo billing address was providedℹ️ No verification performed
N/ANot applicable (e.g., 3DS challenge pending)ℹ️ Check after challenge completes

CVC Result (verificationResults.cvc)

Validates the 3 or 4-digit security code printed on the card.

ValueMeaningAction
APPROVEDCVC matches issuer records✅ Card in possession
FAILEDCVC does not match⚠️ High fraud risk
NOT_SUPPORTEDIssuer/network does not support CVC verificationℹ️ Fall back to AVS and ANI
NOT_SENTCVC was not providedℹ️ No verification performed
N/ANot applicableℹ️ Check after challenge completes

AAV Cardholder Name Result (verificationResults.aavCardholderName)

Visa cards only. Verifies whether the firstName and lastName in the request match the legal name registered with the issuing bank. This is powered by Visa's Account Name Inquiry (ANI) service.

ValueMeaningAction
APPROVEDName matches issuer records✅ Confirmed cardholder identity
PARTIAL_MATCHSome name components matched⚠️ Review with other signals
FAILEDName does not match⚠️ Possible identity mismatch — investigate
NOT_SUPPORTEDCard is not Visa, or issuer does not support ANIℹ️ Fall back to AVS and CVC results
N/ANot available — 3DS challenge pendingℹ️ Check after challenge completes

Important: ANI is only performed for Visa cards. For Mastercard, Amex, Discover, and other networks, aavCardholderName will return NOT_SUPPORTED. In these cases, rely on AVS and CVC for verification.

Name formatting: The cardholder name comparison is performed by the Visa issuer, which checks first, middle, and last name components separately. Ensure you pass the name exactly as it appears on the card. Visa supports up to 35 characters per name field. Suffixes (Jr., III) and prefixes (Dr.) are not supported by ANI and should be omitted.

Integration Example

Step 1 — Tokenize the Card

Use inyo.js to collect and tokenize the card data client-side. The cardholder name entered in the data-field="cardholder" input is included in the token.

const tokenizer = new InyoTokenizer({
  targetId: '#payment-form',
  publicKey: 'YOUR_PUBLIC_KEY',
  storeLaterUse: false,
  threeDSData: { enable: true, enablePostMessage: true },
  successCallback: (response) => {
    if (response.reasonCode === 'WAITING_TRANSACTION') {
      checkCardAccount(response.additionalData.token);
    }
  },
  errorCallback: (err) => console.error('Tokenization failed:', err)
});

Step 2 — Call Check Card Account

Send the token to your backend, which calls the Check Card Account API:

async function checkCardAccount(cardTokenId) {
  const response = await fetch('https://{FQDN}/v2/check-card-account', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      externalPaymentId: crypto.randomUUID(),
      ipAddress: customerIpAddress,
      sender: {
        firstName: 'John',
        lastName: 'Smith',
        email: 'john.smith@example.com',
        phoneNumber: '+15555550123',
        documents: [
          { document: '123-45-6789', type: 'SSN', countryCode: 'US' }
        ],
        paymentMethod: {
          type: 'CARD',
          cardTokenId: cardTokenId
        }
      }
    })
  });

  const result = await response.json();

  if (result.redirectAcsUrl) {
    // Handle 3DS — redirect or open iframe
    window.open(result.redirectAcsUrl, '_blank');
    return;
  }

  // Evaluate the structured verification signals
  console.log('AVS:', result.verificationResults.avs);
  console.log('CVC:', result.verificationResults.cvc);
  console.log('ANI (Name):', result.verificationResults.aavCardholderName);
  console.log('Push (OCT) capable:', result.octStatus?.capable);
  console.log('Pull (AFT) capable:', result.aftStatus?.capable);
}

Step 3 — Evaluate Results

Combine all signals to make a decision. Remember that aavCardholderName is only meaningful for Visa cards — for other networks it will be NOT_SUPPORTED.

function evaluateCardCheck(result) {
  // 3DS challenge pending — results not yet available
  if (result.redirectAcsUrl) {
    return { accept: false, reason: '3DS challenge required' };
  }

  const { avs, cvc, aavCardholderName } = result.verificationResults;

  // CVC mismatch — card not in possession
  if (cvc === 'FAILED') {
    return { accept: false, reason: 'Invalid security code' };
  }

  // Visa ANI: name mismatch — high risk
  // (NOT_SUPPORTED means non-Visa card or issuer doesn't support ANI — not a failure)
  if (aavCardholderName === 'FAILED') {
    return { accept: false, reason: 'Cardholder name does not match issuer records (Visa ANI)' };
  }

  // All available checks passed
  if (avs === 'APPROVED' && (cvc === 'APPROVED' || cvc === 'NOT_SUPPORTED')) {
    const aniStatus = aavCardholderName === 'NOT_SUPPORTED'
      ? 'not available (non-Visa or unsupported issuer)'
      : 'name verified';
    return { accept: true, reason: `AVS + CVC passed; ANI: ${aniStatus}` };
  }

  // Partial results — use your own risk logic
  return { accept: true, reason: 'Partial verification — review recommended' };
}

Testing

Use the following test card in sandbox for Check Card Account:

Card NumberNetworkDescription
4462 0300 0000 0000Visa DebitStandard ANI test card

Use the cardholder name AUTHORISED to simulate an approved result. See Test Data — Cards for CVV and AVS simulation values.

Best Practices

  1. Always send the billing address — Including the address enables AVS verification alongside CVC (and ANI for Visa), giving you multiple independent fraud signals regardless of card network.

  2. Match the tokenizer name to the API name — The cardholder field in the tokenizer form should contain the same name you pass as sender.firstName and sender.lastName. For Visa ANI, name mismatches between the tokenized name and the API name will cause the issuer to return a no-match result.

  3. Don't rely on a single signal — Evaluate AVS + CVC together for all cards, and add the ANI result for Visa. A single FAILED result doesn't necessarily mean fraud, but multiple failures are a strong indicator.

  4. Handle NOT_SUPPORTED gracefully — The aavCardholderName field returns NOT_SUPPORTED for all non-Visa cards, and for Visa cards from issuers that don't yet support ANI. This is expected behavior — fall back to AVS and CVC results for your fraud decision.

  5. Check OCT/AFT before transacting — Use octStatus.capable to confirm a card can receive a payout before a push, and aftStatus.capable before a pull. The highPerforming / lowPerforming tiers help you anticipate authorization success rates.

  6. Use before storing cards — Run a Check Card Account call before saving a card token with storeLaterUse: true to confirm the card is valid and belongs to the expected person.

  7. Use the legal name on the card — Visa ANI compares against the legal name the issuer has on file, not nicknames or preferred names. Omit suffixes (Jr., III) and prefixes (Dr.) as they are not supported by Visa ANI.

What's Next