Inyo

Check Card Account (ANI)

La API Check Card Account valida una tarjeta sin procesar un pago. Realiza hasta tres verificaciones más un perfilado de capacidades de la tarjeta y devuelve los resultados:

  • AVS — Address Verification Service (coincidencia de la dirección de facturación) — todas las redes de tarjetas
  • CVC — Card Verification Code (coincidencia del código de seguridad) — todas las redes de tarjetas
  • AAV Cardholder NameAccount Name Inquiry de Visa (coincidencia del nombre del tarjetahabiente contra los registros del emisor) — solo tarjetas Visa

Las verificaciones AVS y CVC son controles estándar realizados para cualquier tarjeta. La verificación del nombre del tarjetahabiente está impulsada por el producto Account Name Inquiry (ANI) de Visa, que consulta los registros del banco emisor para verificar que el nombre enviado coincida con el nombre legal en la cuenta. ANI solo está disponible para tarjetas Visa — en cualquier otra red verificationResults.aavCardholderName no trae veredicto.

La respuesta también reporta la capacidad OCT (push/payout) y AFT (fondeo/pull) de la tarjeta para que puedas decidir la elegibilidad de una tarjeta para un flujo determinado antes de iniciar una transacción.

¿Qué es Visa ANI?

Account Name Inquiry (ANI) es un producto de Visa que permite a los comercios verificar el nombre del tarjetahabiente directamente con el banco emisor antes de una transacción financiera o de forma independiente a ella. Cuando se envía una tarjeta, Visa reenvía el primer nombre, segundo nombre y apellido proporcionados al emisor, quien los compara contra el nombre legal en la cuenta y devuelve un resultado de coincidencia.

Detalles clave sobre Visa ANI:

  • Solo Visa — ANI es un servicio de la red Visa. No está disponible para Mastercard, Amex, Discover u otras redes.
  • Participación del emisor — ANI se volvió obligatorio para los emisores Visa de EE. UU. y Canadá en octubre de 2023, lo que significa que la mayoría de los emisores Visa en estos mercados lo soportan. Algunos emisores fuera de estos mercados pueden aún no soportar ANI, en cuyo caso el resultado no trae veredicto — NOT_CHECKED o NOT_SUPPORTED.
  • Coincidencia de nombres — Visa verifica los componentes de primer nombre, segundo nombre y apellido por separado contra los registros del emisor. Como mínimo, debe proporcionarse el apellido. El emisor devuelve la coincidencia más cercana cuando hay varios nombres registrados (p. ej., cuentas conjuntas).
  • Independiente del pago — ANI opera de forma independiente a la transacción financiera. No se retienen ni se mueven fondos.
  • Exclusiones — Las tarjetas empresariales/corporativas y las tarjetas prepagadas no recargables sin un nombre registrado no son soportadas por ANI.

Casos de Uso

  • Onboarding — Valida la tarjeta de un cliente antes de almacenarla para cargos futuros
  • Prevención de fraude — Confirma que la persona que envía la tarjeta es el tarjetahabiente real
  • Mejora de KYC — Cruza el nombre en la tarjeta con el nombre proporcionado durante la verificación de identidad
  • Elegibilidad de payout — Verifica octStatus antes de enviar fondos a una tarjeta; verifica aftStatus antes de extraerlos (solo tarjetas Visa)
  • Verificación de tarjeta guardada — Comprueba que una tarjeta almacenada sigue siendo válida y pertenece a la persona esperada

Cómo Funciona

sequenceDiagram
    participant B as Navegador<br/>inyo.js
    participant S as Tu servidor
    participant G as Inyo
    participant I as Emisor

    B->>G: Datos de la tarjeta +<br/>nombre del tarjetahabiente
    G-->>B: cardTokenId
    B->>S: cardTokenId
    S->>G: POST<br/>/v2/check-card-account
    G->>I: Autorización de monto cero:<br/>AVS + CVC
    opt Tarjeta Visa
        G->>I: Consulta de nombre<br/>ANI
    end
    I-->>G: Resultados
    G-->>S: verificationResults +<br/>octStatus / aftStatus

Nota: Esta API no realiza cargos a la tarjeta — se ejecuta como una autorización de monto cero, así que no se retienen ni mueven fondos. No se requiere amount en la solicitud.


Endpoint

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

Encabezados:

EncabezadoValor
AuthorizationBearer {accessToken}
Content-Typeapplication/json

Cuerpo de la Solicitud

El payload es simplificado en comparación con las solicitudes de pago estándar — no se necesitan los campos amount, paymentType ni capture. Internamente el gateway ejecuta la verificación como una autorización CHECK de monto cero, por lo que la solicitud se valida contra el esquema del endpoint y contra el esquema compartido de pagos con tarjeta. Las tablas siguientes reflejan el resultado combinado.

Objeto Raíz

CampoTipoRequeridoDescripción
externalPaymentIdstringTu identificador único para esta solicitud de validación
ipAddressstringDirección IP del solicitante — debe ser un literal IPv4 o IPv6 válido
senderobjectDatos del tarjetahabiente (ver abajo)

Objeto sender

CampoTipoRequeridoDescripción
firstNamestringPrimer nombre del tarjetahabiente, al menos 1 carácter (comparado contra los registros del emisor vía Visa ANI para tarjetas Visa)
lastNamestringApellido del tarjetahabiente, al menos 1 carácter (comparado contra los registros del emisor vía Visa ANI para tarjetas Visa)
addressobjectDirección de facturación — lo que compara AVS (ver abajo)
paymentMethodobjectDatos de la tarjeta tokenizada (ver abajo)
emailstringNoCorreo electrónico del tarjetahabiente — se almacena con el registro de la verificación
phoneNumberstringNoNúmero de teléfono del tarjetahabiente — se almacena con el registro de la verificación

Objeto sender.address

CampoTipoRequeridoDescripción
countryCodestringCódigo de país ISO Alpha-3 (p. ej., "USA" — no "US")
stateCodestringAbreviatura de estado/provincia (p. ej., "MA")
citystringNombre de la ciudad
line1stringLínea 1 de la dirección
zipCodestringCódigo postal/ZIP
statestringNoEstado/provincia tal como queda en el registro de dirección almacenado — envía el mismo valor que stateCode
line2stringNoLínea 2 de la dirección — envía "" cuando no haya segunda línea

Objeto sender.paymentMethod

CampoTipoRequeridoDescripción
typestring"CARD"
cardTokenIdstringUUID del token obtenido del tokenizador — debe ser un UUID bien formado

Ejemplo de Solicitud

curl -X POST https://{FQDN}/v2/check-card-account \
  -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIs...' \
  -H 'Content-Type: application/json' \
  -d '{
    "externalPaymentId": "ANI-0001",
    "ipAddress": "203.0.113.42",
    "sender": {
      "firstName": "John",
      "lastName": "Smith",
      "email": "[email protected]",
      "address": {
        "countryCode": "USA",
        "stateCode": "NY",
        "state": "NY",
        "city": "New York",
        "line1": "123 Main Street",
        "line2": "",
        "zipCode": "10001"
      },
      "paymentMethod": {
        "type": "CARD",
        "cardTokenId": "ab5fc589-8b48-4531-94c0-68b0629c13fe"
      }
    }
  }'

Respuesta

Tres resultados comparten el HTTP 200 y no comparten la forma del cuerpo. Ramifica según los campos presentes, nunca solo según el código de estado.

Verificada (200)

La autorización de monto cero fue aprobada. card, verificationResults, octStatus, aftStatus y redirectAcsUrl siempre están presentes:

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

Las llamadas repetidas se responden con el resultado almacenado. Una vez que ANI se ejecutó para un firstName + lastName + token de tarjeta dados, una llamada idéntica devuelve el resultado registrado en lugar de volver a consultar al emisor. Cambiar cualquiera de los dos nombres genera una nueva consulta al emisor.

Desafío 3DS (200)

El banco emisor requiere autenticación del tarjetahabiente antes de que se conozcan los resultados. El cuerpo conserva la forma verificada, redirectAcsUrl viene poblado y todas las verificaciones devuelven NOT_SUPPORTED hasta que el desafío se complete:

{
  "card": {
    "created": "2026-05-16 16:37:40",
    "issuerName": "MODULR FS, LTD.",
    "issuerCountry": "UNITED KINGDOM",
    "bin": "446203",
    "lastFour": "0000"
  },
  "verificationResults": {
    "avs": "NOT_SUPPORTED",
    "cvc": "NOT_SUPPORTED",
    "aavCardholderName": "NOT_SUPPORTED"
  },
  "octStatus": {
    "capable": false,
    "highPerforming": false,
    "lowPerforming": false
  },
  "aftStatus": {
    "capable": false,
    "highPerforming": false,
    "lowPerforming": false
  },
  "redirectAcsUrl": "https://{FQDN}/secure-code/start-challenge?token=dce568c6-..."
}

Cuando redirectAcsUrl no está vacío, redirige al tarjetahabiente hacia esa URL — y no leas las verificaciones de este cuerpo, todavía no traen veredicto. Consulta Manejo de 3D Secure para el flujo completo.

Rechazada (200)

Cuando la autorización de monto cero subyacente no es aprobada, el endpoint responde con la forma de respuesta de pago. No hay objeto verificationResults, y los resultados de las verificaciones llegan como campos planos:

{
  "paymentId": "870bf24b-885f-4b1f-a8de-3c3944d5e266",
  "parentPaymentId": "870bf24b-885f-4b1f-a8de-3c3944d5e266",
  "externalPaymentId": "ANI-GMT9433682",
  "created": "2026-01-26 16:25:50",
  "amount": 0.00,
  "approved": false,
  "status": "DECLINED",
  "responseCode": "PAY_022",
  "message": "Rejected by provider",
  "issuerName": "MASTERCARD EUROPE",
  "issuerCountry": "BELGIUM",
  "avsResult": "N/A",
  "cvcResult": "N/A",
  "aavCardholderNameResult": "N/A",
  "redirectAcsUrl": ""
}

Comprueba la existencia de verificationResults antes de leerlo. Nota que N/A puede aparecer en estos campos planos — nunca aparece dentro de verificationResults.

Error de Validación (400)

Se reportan a la vez todos los campos que fallaron la validación:

{
  "code": "VE_001",
  "message": "Validation error",
  "errors": [
    {
      "field": "sender.address.city",
      "message": "sender.address.city can't be empty"
    },
    {
      "field": "sender.paymentMethod.cardTokenId",
      "message": "sender.paymentMethod.cardTokenId does not match the expected format uuid"
    }
  ]
}

Campos de la Respuesta

Los campos nulos se omiten de la respuesta, así que un registro de tarjeta sin nombre de emisor simplemente no trae la clave issuerName.

card

CampoTipoDescripción
createdstringMarca de tiempo de creación de la verificación
issuerNamestringNombre del banco emisor
issuerCountrystringPaís emisor
binstringBank Identification Number (primeros 6 dígitos)
lastFourstringÚltimos 4 dígitos de la tarjeta

verificationResults

CampoTipoDescripción
avsstringResultado de verificación de dirección (ver abajo)
cvcstringResultado de verificación del código de seguridad (ver abajo)
aavCardholderNamestringResultado de verificación del nombre del tarjetahabiente — Visa ANI, solo Visa (ver abajo)

octStatus / aftStatus

Indicadores de capacidad de la tarjeta, poblados solo para tarjetas Visa. OCT (Original Credit Transaction) refleja la capacidad de la tarjeta de recibir envíos/payouts; AFT (Account Funding Transaction) refleja su capacidad de fondear cobros.

CampoTipoDescripción
capablebooleanSi la tarjeta soporta este tipo de transacción
highPerformingbooleanLa tarjeta está en el nivel de alto desempeño para este tipo de transacción
lowPerformingbooleanLa tarjeta está en el nivel de bajo desempeño para este tipo de transacción

Para una tarjeta no Visa la consulta de readiness no se ejecuta, por lo que los tres indicadores vuelven en false. Eso significa "no evaluado" — no "no capaz".

redirectAcsUrl

CampoTipoDescripción
redirectAcsUrlstringURL del desafío 3DS. Vacía ("") cuando no se requiere desafío; cuando viene poblada, redirige al tarjetahabiente para completar la autenticación.

Interpretación de los Resultados de Verificación

Los tres valores son las descripciones de resultado del emisor/adquirente resueltas por el mapeo de códigos de proveedor del gateway, con una normalización adicional a nivel de gateway: un resultado ausente, vacío, NA o N/A se convierte en NOT_SUPPORTED. Por eso N/A nunca te llega dentro de verificationResults.

ValorSignificadoAcción
APPROVEDEl emisor encontró coincidencia con el valor enviadoTrátalo como verificado
NOT_CHECKEDEl emisor o el adquirente no ejecutó esta verificaciónSin señal — apóyate en las otras verificaciones
NOT_SUPPORTEDNo volvió ningún resultado: no soportado para esta tarjeta, o hay un desafío 3DS pendienteSin señal
cualquier otro valorUna descripción de resultado específica del emisor, como coincidencia parcial o fallidaNo lo trates como verificado

Solo APPROVED es una aprobación. El conjunto de valores depende del emisor y del adquirente, así que compara por igualdad con APPROVED en lugar de enumerar cadenas de falla.

Resultado AVS (verificationResults.avs)

Compara la dirección de facturación de sender.address con la dirección registrada en el emisor de la tarjeta. Los cinco campos de dirección requeridos alimentan la comparación.

Resultado CVC (verificationResults.cvc)

Valida el código de seguridad capturado durante la tokenización. La solicitud de Check Card Account no lleva código de seguridad — este viaja dentro del token de la tarjeta.

Resultado AAV Cardholder Name (verificationResults.aavCardholderName)

Solo tarjetas Visa. Verifica si sender.firstName y sender.lastName coinciden con el nombre legal registrado en el banco emisor, mediante el servicio Account Name Inquiry (ANI) de Visa.

Importante: ANI se ejecuta solo para tarjetas Visa. Para Mastercard, Amex, Discover y otras redes este campo no trae veredicto — apóyate en AVS y CVC.

Formato del nombre: la comparación la realiza el emisor Visa, que verifica por separado los componentes de primer nombre, segundo nombre y apellido. Envía el nombre exactamente como aparece en la tarjeta. Visa soporta hasta 35 caracteres por campo de nombre. Los sufijos (Jr., III) y prefijos (Dr.) no son soportados por ANI y deben omitirse.

Ejemplo de Integración

Paso 1 — Tokeniza la Tarjeta

Usa inyo.js para recopilar y tokenizar los datos de la tarjeta del lado del cliente. El nombre del tarjetahabiente ingresado en el campo data-field="cardholder" se incluye en el 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)
});

Paso 2 — Llama a Check Card Account

Envía el token a tu backend, que llama a la API Check Card Account:

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: `ANI-${crypto.randomUUID()}`,
      ipAddress: customerIpAddress,
      sender: {
        firstName: 'John',
        lastName: 'Smith',
        email: '[email protected]',
        address: {
          countryCode: 'USA',
          stateCode: 'NY',
          state: 'NY',
          city: 'New York',
          line1: '123 Main Street',
          line2: '',
          zipCode: '10001'
        },
        paymentMethod: {
          type: 'CARD',
          cardTokenId: cardTokenId
        }
      }
    })
  });

  const result = await response.json();

  if (result.redirectAcsUrl) {
    // Manejar 3DS — redirigir o abrir un iframe
    window.open(result.redirectAcsUrl, '_blank');
    return;
  }

  // Evaluar las señales de verificación estructuradas
  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);
}

Paso 3 — Evalúa los Resultados

Ramifica primero según la forma del cuerpo y después según las verificaciones. Solo APPROVED es una aprobación, y aavCardholderName trae veredicto únicamente para tarjetas Visa.

function evaluateCardCheck(result) {
  // Rechazada: la forma de respuesta de pago, sin objeto verificationResults
  if (!result.verificationResults) {
    return { accept: false, reason: result.message || `Rechazada (${result.responseCode})` };
  }

  // Desafío 3DS pendiente — las verificaciones aún no traen veredicto
  if (result.redirectAcsUrl) {
    return { accept: false, reason: 'Se requiere desafío 3DS' };
  }

  const { avs, cvc, aavCardholderName } = result.verificationResults;
  const passed = (v) => v === 'APPROVED';
  const noSignal = (v) => v === 'NOT_CHECKED' || v === 'NOT_SUPPORTED';

  // Todo lo que no sea APPROVED ni un valor sin señal es una discrepancia
  if (!passed(cvc) && !noSignal(cvc)) {
    return { accept: false, reason: `El CVC no coincidió (${cvc})` };
  }
  if (!passed(aavCardholderName) && !noSignal(aavCardholderName)) {
    return { accept: false, reason: `El nombre no coincidió con los registros del emisor (${aavCardholderName})` };
  }
  if (!passed(avs) && !noSignal(avs)) {
    return { accept: false, reason: `El AVS no coincidió (${avs})` };
  }

  const verified = [['AVS', avs], ['CVC', cvc], ['ANI', aavCardholderName]]
    .filter(([, value]) => passed(value))
    .map(([name]) => name);

  return verified.length > 0
    ? { accept: true, reason: `Verificado por ${verified.join(' + ')}` }
    : { accept: true, reason: 'Ninguna verificación devolvió resultado — aplica tu propia lógica de riesgo' };
}

Pruebas

Usa la siguiente tarjeta de prueba en sandbox para Check Card Account:

Número de TarjetaRedDescripción
4462 0300 0000 0000Visa DebitTarjeta de prueba estándar para ANI

Usa el nombre de tarjetahabiente AUTHORISED para simular un resultado aprobado. Consulta Datos de Prueba — Tarjetas para los valores de simulación de CVV y AVS.

Buenas Prácticas

  1. Envía la dirección de facturación completacountryCode, stateCode, city, line1 y zipCode son todos requeridos, y son exactamente lo que compara AVS. Envía state junto con stateCode para que el registro de dirección almacenado también lo tenga.

  2. Haz coincidir el nombre del tokenizador con el de la API — El campo cardholder del formulario del tokenizador debe contener el mismo nombre que envías en sender.firstName y sender.lastName. Para Visa ANI, una discrepancia entre el nombre tokenizado y el de la API hace que el emisor devuelva un resultado sin coincidencia.

  3. Decide por APPROVED, no por cadenas de falla — Los valores de resultado provienen del emisor y del adquirente, así que el vocabulario de falla no es fijo. Acepta solo APPROVED; trata cualquier otro valor que no sea NOT_CHECKED ni NOT_SUPPORTED como una discrepancia.

  4. Maneja NOT_CHECKED y NOT_SUPPORTED con cuidado — Ninguno es una falla. Ambos significan que la verificación no produjo resultado, ya sea porque la tarjeta no es Visa, porque el emisor no ejecuta la verificación, o porque hay un desafío 3DS pendiente. Apóyate en las verificaciones que sí devolvieron resultado.

  5. octStatus / aftStatus son solo para Visa — Para una tarjeta no Visa la consulta de readiness nunca se ejecuta y los tres indicadores vienen en false. No lo interpretes como "esta tarjeta no puede recibir un payout".

  6. Ramifica por la forma del cuerpo, no por el código de estado — Una verificación rechazada responde HTTP 200 con la forma de respuesta de pago y sin verificationResults. Comprueba la existencia de ese objeto antes de leerlo.

  7. Envía externalPaymentId e ipAddress — Ambos son requeridos, y la IP debe ser un literal IPv4 o IPv6 válido. Un valor ausente o mal formado falla la validación con HTTP 400 antes de que se contacte la tarjeta.

  8. Úsalo antes de almacenar tarjetas — Ejecuta una llamada de Check Card Account antes de guardar un token de tarjeta con storeLaterUse: true para confirmar que la tarjeta es válida y pertenece a la persona esperada.

  9. Usa el nombre legal de la tarjeta — Visa ANI compara contra el nombre legal que el emisor tiene registrado, no apodos ni nombres preferidos. Omite sufijos (Jr., III) y prefijos (Dr.), que ANI no soporta.

Qué Sigue