---
description: >-
  Validate a card without charging it using the Check Card Account API (v2). Returns structured AVS and CVC results for all cards, Visa ANI cardholder name verification for Visa cards, and OCT/AFT push/pull capability indicators.
---

# 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](https://corporate.visa.com/content/dam/VCOM/regional/na/us/support-legal/documents/account-name-inquiry-onesheet-merchant-version.pdf) (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)](https://corporate.visa.com/content/dam/VCOM/regional/na/us/support-legal/documents/account-name-inquiry-onesheet-merchant-version.pdf) 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:**

| 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](tokenizing-cards.md) |

## Example Request

```bash
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)

```json
{
  "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:

```json
{
  "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](payment/pulling-funds/cards/authorizing/handling-3d-secure.md) 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)](https://corporate.visa.com/content/dam/VCOM/regional/na/us/support-legal/documents/account-name-inquiry-onesheet-merchant-version.pdf) 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, `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.

```javascript
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:

```javascript
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`.

```javascript
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](test-data/cards.md) 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

- [Tokenizing Cards](tokenizing-cards.md) — Set up client-side card tokenization
- [Handling AVS / CVC](payment/pulling-funds/cards/authorizing/handling-avs-cvc.md) — Deep dive into address and security code verification
- [Handling 3D Secure](payment/pulling-funds/cards/authorizing/handling-3d-secure.md) — Handle CHALLENGE responses
- [Authorizing a Card Payment](payment/pulling-funds/cards/authorizing/) — Create actual payment transactions after validation
