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
octStatusbefore pushing funds to a card; checkaftStatusbefore 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:
| Header | Value |
|---|---|
Authorization | Bearer {accessToken} |
Content-Type | application/json |
Request Body
The payload is simplified compared to standard payment requests — no amount, paymentType, or capture fields are needed.
Root Object
| Field | Type | Required | Description |
|---|---|---|---|
externalPaymentId | string | ❌ | Your unique identifier for this validation request (idempotency key) |
ipAddress | string | ❌ | Requester's IPv4 or IPv6 address |
sender | object | ✅ | Cardholder + identity details |
sender Object
The sender binds the card check to a verified identity — email, phoneNumber, and at least one documents entry are required.
| Field | Type | Required | Description |
|---|---|---|---|
firstName | string | ✅ | Cardholder's first name (compared against issuer records via Visa ANI for Visa cards) |
lastName | string | ✅ | Cardholder's last name (compared against issuer records via Visa ANI for Visa cards) |
email | string | ✅ | Cardholder's email address |
phoneNumber | string | ✅ | Cardholder's phone number (E.164, e.g. +15555550123) |
phoneNumberType | string | ❌ | Phone type (e.g. MOBILE, HOME) |
birthDate | string | ❌ | Date of birth, YYYY-MM-DD |
birthCountryCode | string | ❌ | Country of birth (ISO country code) |
documents | array | ✅ | Identity documents — at least one entry (see below) |
address | object | ❌ | Billing address (used for AVS verification) |
paymentMethod | object | ❌ | Tokenized card details |
sender.documents[] Object
| Field | Type | Required | Description |
|---|---|---|---|
document | string | ✅ | Document number/value |
type | string | ✅ | Document type (e.g. PASSPORT, NATIONAL_ID, SSN) |
countryCode | string | ✅ | Issuing country (ISO country code) |
sender.address Object
| Field | Type | Required | Description |
|---|---|---|---|
countryCode | string | ✅ | ISO Alpha-3 country code (e.g., "USA") |
stateCode | string | ✅ | State/province abbreviation (e.g., "NY") |
city | string | ✅ | City name |
line1 | string | ✅ | Street address line 1 |
line2 | string | ❌ | Street address line 2 |
zipCode | string | ✅ | Postal/ZIP code |
sender.paymentMethod Object
| Field | Type | Required | Description |
|---|---|---|---|
type | string | ✅ | "CARD" |
cardTokenId | string | ✅ | Token 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
| Field | Type | Description |
|---|---|---|
created | string | Timestamp the card record was created |
issuerName | string | Issuing bank name |
issuerCountry | string | Issuing country |
bin | string | Bank Identification Number (first 6 digits) |
lastFour | string | Last 4 digits of the card |
verificationResults
| Field | Type | Description |
|---|---|---|
avs | string | Address verification result (see below) |
cvc | string | Card verification code result (see below) |
aavCardholderName | string | Cardholder 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.
| Field | Type | Description |
|---|---|---|
capable | boolean | Whether the card supports this transaction type |
highPerforming | boolean | Card is in the high-performing tier for this transaction type |
lowPerforming | boolean | Card is in the low-performing tier for this transaction type |
redirectAcsUrl
| Field | Type | Description |
|---|---|---|
redirectAcsUrl | string | 3DS 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.
| Value | Meaning | Action |
|---|---|---|
APPROVED | Address matches issuer records | ✅ Low fraud risk |
PARTIAL_MATCH | Some components matched (e.g., ZIP matched but street did not) | ⚠️ Review with other signals |
FAILED | Address does not match | ⚠️ Elevated fraud risk |
NOT_SUPPORTED | Issuer/network does not support AVS | ℹ️ Fall back to CVC and ANI |
NOT_SENT | No billing address was provided | ℹ️ No verification performed |
N/A | Not 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.
| Value | Meaning | Action |
|---|---|---|
APPROVED | CVC matches issuer records | ✅ Card in possession |
FAILED | CVC does not match | ⚠️ High fraud risk |
NOT_SUPPORTED | Issuer/network does not support CVC verification | ℹ️ Fall back to AVS and ANI |
NOT_SENT | CVC was not provided | ℹ️ No verification performed |
N/A | Not 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.
| Value | Meaning | Action |
|---|---|---|
APPROVED | Name matches issuer records | ✅ Confirmed cardholder identity |
PARTIAL_MATCH | Some name components matched | ⚠️ Review with other signals |
FAILED | Name does not match | ⚠️ Possible identity mismatch — investigate |
NOT_SUPPORTED | Card is not Visa, or issuer does not support ANI | ℹ️ Fall back to AVS and CVC results |
N/A | Not available — 3DS challenge pending | ℹ️ Check after challenge completes |
Important: ANI is only performed for Visa cards. For Mastercard, Amex, Discover, and other networks,
aavCardholderNamewill returnNOT_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 Number | Network | Description |
|---|---|---|
4462 0300 0000 0000 | Visa Debit | Standard 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
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.
Match the tokenizer name to the API name — The
cardholderfield in the tokenizer form should contain the same name you pass assender.firstNameandsender.lastName. For Visa ANI, name mismatches between the tokenized name and the API name will cause the issuer to return a no-match result.Don't rely on a single signal — Evaluate AVS + CVC together for all cards, and add the ANI result for Visa. A single
FAILEDresult doesn't necessarily mean fraud, but multiple failures are a strong indicator.Handle
NOT_SUPPORTEDgracefully — TheaavCardholderNamefield returnsNOT_SUPPORTEDfor 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.Check OCT/AFT before transacting — Use
octStatus.capableto confirm a card can receive a payout before a push, andaftStatus.capablebefore a pull. ThehighPerforming/lowPerformingtiers help you anticipate authorization success rates.Use before storing cards — Run a Check Card Account call before saving a card token with
storeLaterUse: trueto confirm the card is valid and belongs to the expected person.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
- Tokenizing Cards — Set up client-side card tokenization
- Handling AVS / CVC — Deep dive into address and security code verification
- Handling 3D Secure — Handle CHALLENGE responses
- Authorizing a Card Payment — Create actual payment transactions after validation
