En esta página
INTRODUCCIÓN
CONCEPTOS CLAVES
INTEGRACIONES
SEGURIDAD
PAGOS CON TARJETA
LINKS
3DS
SUSCRIPCIONES
ALTERNATIVE PAYMENT METHODS (APMS))
NANO Y MICRO MERCHANTS

INTRODUCCIÓN

3

Bienvenido a las Guías de Akua

Esta documentación es el punto de partida para desarrolladores y clientes que quieran crear su primer cobro e integrarse con los servicios de Akua. Está diseñada para ser un recurso paso a paso, claro y siempre actualizado.

Esta documentación evoluciona junto con el producto. Las sugerencias de mejora son bienvenidas.


¿Qué vas a encontrar acá?

Un conjunto de guías organizadas que cubren desde los primeros pasos de integración hasta configuraciones avanzadas, con el objetivo de que cualquier equipo pueda entender, implementar y mantener su integración con Akua de forma autónoma.


Principios de esta documentación

PrincipioDescripción
Lenguaje unificadoTerminología estandarizada para facilitar la comunicación entre equipos técnicos y de negocio
ConsistenciaFormato y estructura coherentes en todos los documentos
CentralizaciónTodo en un solo lugar, con búsqueda eficiente
Actualización continuaProcesos de revisión que mantienen la información precisa y vigente
Soporte a decisionesInformación confiable como base para implementaciones y definiciones técnicas

¿Te resultó útil?

Solución Flexible para el Procesamiento de Pagos

Akua es una plataforma de procesamiento de pagos que se adapta a los requisitos de cada negocio. Puede operar como procesador y adquirente completo o como solo procesador, según la estructura del cliente.


Modelos operativos

Akua como Procesador y Adquirente

Akua como Procesador y Adquirente

Akua opera bajo su propia licencia de adquirencia con Visa y Mastercard. Pasarelas de pago, facilitadores y orquestadores integran pagos de comerciantes directamente con las redes de tarjetas sin depender de adquirentes locales. Akua asume la responsabilidad total del flujo de pago.


Akua como Solo Procesador

Akua como Solo Procesador

Akua provee la infraestructura y el soporte técnico a otro adquirente que mantiene la relación de licencia con las redes de tarjetas. Akua maneja la tecnología y la logística sin interacción directa con comerciantes ni licencias propias de red.


Comparación

AspectoProcesador y AdquirenteSolo Procesador
RolPosee licencias con las redes de tarjetasProvee servicios tecnológicos a otro adquirente
FuncionesGestiona conexiones de comerciantes, transacciones, riesgo y disputasSuministra infraestructura de autorización y liquidación
ClientesGrandes comerciantes, pasarelas, facilitadores de pagoAdquirentes que necesitan delegar el procesamiento técnico

Los ciclos de transacción y el flujo de información son consistentes en ambos modelos.

¿Te resultó útil?

Tipos de clientes

¿Qué tipo de clientes pueden integrarse con Akua?

Akua ofrece un proceso adaptable para diferentes tipos de clientes. La plataforma reconoce que las necesidades varían según el perfil del integrado, por lo que proporciona experiencias personalizadas y eficientes.

Adquirente

Instituciones financieras que procesan pagos de tarjetas o soluciones de pago electrónico:

  • Adquiriente Financiero: Regulados por entidades gubernamentales
  • Adquiriente No Vigilado: Operan bajo un modelo flexible

Proceso de Integración:

Adquiriente Financiero:

  1. Presentación de licencias y certificaciones regulatorias
  2. Sincronización directa con sistemas de pago diario

Adquiriente No Vigilado:

  1. Validación contractual y revisión de políticas internas
  2. Pruebas intensivas para garantizar estabilidad

Facilitadores de pago | PayFacs

Empresas intermediarias entre comerciantes y adquirientes que permiten la aceptación de pagos electrónicos. Akua actúa como adquiriente en estos casos.

Proceso de Integración:

  1. Validación regulatoria: Licencias para operar como facilitador, información sobre sub-merchants gestionados
  2. Configuración técnica: Acceso a API para registrar sub-merchants, implementación de herramientas de split payments
  3. Soporte avanzado: Resolución continua de disputas y contracargos

Pasarelas de pago | Gateways

Proveedores de infraestructura que conectan comerciantes con adquirientes.

Proceso de Integración:

  1. Validación: Cumplimiento con normativas internacionales (PCI DSS)
  2. Configuración técnica: Sincronización de flujos transaccionales, configuración de redundancia
  3. Reportes: Dashboards para monitoreo en tiempo real

Billeteras | Wallets | SDWOs

Plataformas que permiten almacenar dinero digitalmente y realizar pagos seguros, operando con modelos "stored value" u "open loop".

Proceso de Integración:

  1. Carga de documentación: Licencias como billetera electrónica, certificaciones de cumplimiento (PCI DSS si aplica)
  2. Configuración técnica: Acceso a API para gestión de transacciones y saldo, implementación de Webhooks para notificaciones
  3. Pruebas: Escenarios simulados (carga y retiro de saldo)

Comercios | Merchants

Negocios que aceptan pagos electrónicos, desde pequeñas tiendas hasta grandes cadenas retail.

Proceso de Integración:

  1. Registro: Documentos de identidad empresarial, validación de cuenta bancaria
  2. Configuración técnica: Integración con POS o sistema e-commerce, configuración de tasas y límites
  3. Pruebas: Tutoriales para dashboard y gestión de reportes

Conclusión

El proceso de integración de Akua busca ser flexible y adaptarse a necesidades específicas de cada cliente, con enfoque en experiencia del usuario y cumplimiento normativo para implementación segura y eficiente.

¿Te resultó útil?

CONCEPTOS CLAVES

3

Clientes, Organizaciones, Agregadores & Comercios

Esta sección describe las entidades del ecosistema Akua, sus relaciones y cómo se estructuran jerárquicamente.

Jerarquía de cuentas

Las cuentas en Akua se organizan en cuatro niveles:

Cliente
└── Organización
    └── Agregador
        └── Merchant

organigrama.png


Clientes

Representan a las empresas u organizaciones que utilizan las soluciones de adquirencia financiera de Akua para gestionar pagos. Pueden ser desde pequeñas operaciones hasta grandes organizaciones que buscan simplificar sus procesos de cobro.


Organizaciones

Ofrecen una forma lógica de agrupar y estructurar los agregadores y comercios dentro de un cliente. Cada cliente recibe una organización "default" al registrarse, pero puede crear múltiples organizaciones según su modelo de negocio.


Agregadores

El Agregador es la entidad que contiene el payfacID — el identificador que lo acredita como facilitador de pagos ante las redes. Todos los merchants que procesan transacciones deben pertenecer a un agregador.

AtributoDescripción
payfac_idIdentificador del facilitador de pagos ante las redes (Visa, Mastercard, etc.)
Merchants asociadosTodos los comercios que procesan bajo ese agregador

Comercios

Los merchants pertenecen a un agregador y son quienes reciben los pagos electrónicos de los consumidores mediante tarjetas de crédito, débito u otros métodos digitales. Un Comercio es una unidad principal de procesamiento. Puede representar una marca, razón social o una línea de negocio específica. Ejemplo: Tienda A, Tienda B

Cada comercio puede tener:

  • Subcomercios
  • Sucursales o puntos de venta
  • Terminales

Subcomercios

Un Subcomercio representa una división más específica dentro de un comercio. Ideal para casos como franquicias, unidades independientes o regiones. Ejemplo: Tienda A - Franquicia Córdoba

Cada subcomercio puede tener:

  • Puntos de venta
  • Terminales

¿Te resultó útil?

Venta Presente

Entidades POS y Terminales

La gestión de Puntos de Venta y terminales representa un proceso clave para asegurar que las transacciones ocurran de manera eficiente y segura. Esta sección describe las relaciones entre POS y terminales y los procedimientos de integración.

¿Qué es un Point of Sale?

Un Point of Sale (POS) es una representación de ubicación física o digital donde ocurren las transacciones. El POS incluye:

  • Detalles completos de dirección
  • Nombre de sucursal o tienda
  • Coordenadas geográficas
  • Capacidad máxima de terminales asignables

¿Qué es un Terminal?

Un terminal es un dispositivo físico que procesa pagos electrónicos en un POS, que incluye:

  • Modelo y número de serie
  • Métodos de pago soportados (VISA, Mastercard, QR)
  • Estado operacional (Activo/Inactivo)

Venta Presente con POS

bc52dbca75c66cb65e240549dd2fa341c2d7d05c1570534860f1e2920b831e33-Jerarquias_POS.png

Para transacciones desde terminales POS, la jerarquía sigue: Organization > Merchant > POS > Terminal.

Adherir un Point y un Terminal

La asociación de terminales requiere primero crear un POS. El POS funciona como el punto de referencia que organiza las transacciones.

Por qué esta relación importa:

  • Organización: Gestión de terminales por POS específico
  • Trazabilidad: Seguimiento de transacciones hasta el POS de origen
  • Escalabilidad: Fácil adición de terminales en múltiples ubicaciones

Paso 1: Crear un Point of Sale (POS)

Datos requeridos:

  • Nombre del punto de venta
  • Dirección completa (calle, número, ciudad, país, código postal)
  • Coordenadas opcionales (latitud/longitud)
{
  "name": "Sucursal Palermo",
  "address": {
    "street": "Av. Santa Fe",
    "number": "3250",
    "city": "Buenos Aires",
    "state": "CABA",
    "country": "Argentina",
    "zip_code": "1425",
    "coordinates": {
      "latitude": -34.5886,
      "longitude": -58.4061
    }
  },
  "merchant_id": "mer-12345",
  "max_active_pos": 10
}

Paso 2: Registrar un Terminal

Información requerida:

  • Modelo y número de serie del terminal
  • ID del POS asociado
  • Métodos de pago soportados y estado inicial
{
  "model": "Verifone VX520",
  "serial_number": "SN123456789",
  "status": "ACTIVE",
  "point_id": "point-8clm7v3hqjt0k8e9g1f",
  "supported_payment_methods": ["VISA", "MASTERCARD"],
  "firmware_version": "1.2.3",
  "remote_management": {
    "ota_updates_enabled": true
  }
}

Paso 3: Asignar el Terminal al POS

Asocia el terminal creado al POS deseado, vinculando transacciones a las ubicaciones apropiadas.

{
  "terminal_id": "trm-xidn01b5cq5t2rf7gk4m",
  "point_id": "point-8clm7v3hqjt0k8e9g1f"
}

¿Te resultó útil?

Instrumentos / Tarjetas

Las tarjetas son instrumentos que representan de forma virtual una tarjeta física. Al registrar una nueva tarjeta, el sistema genera automáticamente un identificador único con el prefijo ins- seguido de 20 caracteres alfanuméricos.


Atributos principales

AtributoDescripción
IDIdentificador único del instrumento (ins-xxxxxxxxxxxxxxxxxxxx)
FingerprintHash que identifica la tarjeta física sin exponer datos sensibles
Payment MethodTipo de instrumento, marca y categoría de la tarjeta
StatusEstado operacional: ACTIVE / INACTIVE
ValidationEstado de validación: VALID / PENDING

Detalle de atributos

ID

Se genera automáticamente al crear la tarjeta. Identifica al instrumento de forma exclusiva en el sistema.

ins-a1b2c3d4e5f6g7h8i9j0

Fingerprint

Valor alfanumérico generado a partir de los datos de la tarjeta. Permite identificar la tarjeta física subyacente sin exponer información sensible, incluso cuando existen múltiples instrumentos asociados a una misma cuenta.

El fingerprint nunca expone datos privados fuera de un entorno seguro (PCI).


Payment Method

Describe el tipo de instrumento con un formato compuesto de tres partes:

TIPO_INSTRUMENTO_MARCA_TIPO_TARJETA

Ejemplo:

ParteValor
Tipo de instrumentoCARD
MarcaMASTERCARD
Tipo de tarjetaCREDIT
ResultadoCARD_MASTERCARD_CREDIT

Status y Validation

AtributoValorSignificado
StatusACTIVELa tarjeta está habilitada para transacciones
StatusINACTIVELa tarjeta no está disponible
ValidationVALIDLa tarjeta pasó el proceso de validación
ValidationPENDINGLa tarjeta aún no fue validada

Datos del número de tarjeta

El número completo (PAN) nunca se expone fuera de un entorno PCI. Solo se pueden visualizar partes no sensibles:

CampoDescripción
BINPrimeros 6 u 8 dígitos — identifican a la entidad emisora
Últimos 4 dígitosSe usan para identificar la tarjeta en ciertas operaciones
CVVVálido por 3 minutos desde su generación o última transacción exitosa. Nunca se muestra fuera de un entorno PCI

¿Te resultó útil?

INTEGRACIONES

1

Akua es una plataforma de Adquirencia como Servicio (AaaS). Esta guía cubre todo lo que necesitás saber para integrarte: desde el acuerdo inicial hasta la autenticación y los entornos de desarrollo.

Tiempo estimado de kickoff a producción: ~14 días.


Pasos de integración

1. Firma del contrato y Kickoff

Se formaliza el acuerdo con Akua y se coordina una reunión de Kickoff para alinear equipos, expectativas y definir el alcance del proyecto. Es el punto de partida para una integración ordenada y ágil.


2. Acceso al Dashboard

El equipo de Akua enviará un correo de invitación con un link para registrarte como administrador en el Dashboard de Autogestión.

Una vez dentro:

  • Ingresá tu Company ID (generalmente tu dominio) para acceder
  • Iniciá sesión con el usuario y contraseña que hayas creado
  • Gestioná usuarios y asigná roles según el área:
RolDescripción
AdministradorAcceso total a configuración y usuarios
DeveloperAcceso a API Keys y herramientas técnicas
FinanzasAcceso a reportes y conciliación
FraudeMonitoreo y gestión de alertas
OperacionesGestión operativa del día a día

3. API Keys y Autenticación

Las credenciales se generan desde el Dashboard en Developers > API Keys.

Credenciales a generar:

  • Client ID
  • Client Secret
  • Permisos (scopes) según la integración

Flujo de autenticación:

  1. Envía tus credenciales al endpoint /oauth/token para obtener un JWT token
  2. Usa ese token como Bearer Token en el header de cada request
  3. El token tiene duración de 24 horas — será necesaria una lógica de refresh

4. Entornos disponibles

EntornoURL Base
SandboxPruebas y desarrollo (datos simulados, sin impacto contable)
ProducciónOperaciones reales

La migración a producción se realiza una vez validado el checklist de homologación, que cubre:

  • Base técnica (JWT, API Keys, Webhooks)
  • E-commerce (Autorizaciones, Capturas, Reembolsos)
  • Tarjeta Presente (si aplica)

⏱️ Timeout recomendado: 40 segundos

El tiempo de timeout recomendado es de 40 segundos para requests de pagos.

Los tiempos de respuesta de Akua son sólidos: p95 de 3 segundos y p99 de 8 segundos. El timeout de 40 segundos no refleja la latencia de Akua, sino el margen necesario para cubrir casos borde en la red de franquicia. Timeouts más ajustados generan rechazos innecesarios que pueden escalar a contracargos.

🔁 Idempotency-Key

Es necesario incluir el header Idempotency-Key en todos los requests para manejar reintentos de forma segura y evitar transacciones duplicadas.


Herramientas y soporte

RecursoDescripción
Postman CollectionsColecciones listas para testear la API
MCP (Módulo de Integración Rápida)Herramienta para acelerar el time-to-market
Tarjetas de pruebaNúmeros que simulan aprobaciones y rechazos reales
Documentación online100% accesible, siempre actualizada
Sandbox gratuitoDisponible desde el día uno, sin costo

Soporte disponible 24/7:

  • Autogestión vía documentación y Help Center
  • Agente de IA (FIN)
  • Agentes humanos
  • Escalación interna para casos críticos

¿Te resultó útil?

SEGURIDAD

3

¿Qué es PCI DSS?

PCI DSS (Payment Card Industry Data Security Standards) es el conjunto de requisitos de seguridad establecidos por el PCI Security Standards Council para organizaciones que manejan datos de tarjetas de pago. Su cumplimiento es exigido por Visa, Mastercard, Discover y American Express.

Cualquier entidad que almacene, procese o transmita datos de tarjetas de crédito puede estar sujeta a estos requisitos.

Akua está certificado como Proveedor de Servicios Nivel 1 en cumplimiento con PCI DSS.


Niveles de cumplimiento

Los niveles se definen según el volumen anual de transacciones:

NivelVolumen de transacciones
Nivel 1Más de 6 millones en todos los canales
Nivel 2Entre 1 y 6 millones en todos los canales
Nivel 3Entre 20.000 y 1 millón en línea
Nivel 4Menos de 20.000 en línea, o hasta 1 millón en todos los canales

Validación — Cuestionarios SAQ

Los comerciantes de niveles 2 a 4 validan su cumplimiento mediante Cuestionarios de Auto-Evaluación (SAQ). El tipo aplicable depende del modelo de integración:

TipoAplica a
AComerciantes que externalizan completamente las funciones de pago a proveedores validados
A-EPE-commerce que externaliza pagos sin almacenar datos del tarjetahabiente
BComerciantes que usan solo máquinas de impresión o terminales independientes
B-IPComerciantes con terminales conectadas por IP aprobadas por PTS
C-VTComerciantes con terminales virtuales basadas en internet
CComerciantes con aplicaciones de pago conectadas a internet
P2PEComerciantes con terminales dentro de soluciones P2PE validadas
DTodos los demás comerciantes y proveedores de servicios

Akua pre-llena la información del SAQ basándose en los detalles de integración del comerciante y monitorea el cumplimiento de forma continua, notificando ante cambios o incidencias.

¿Te resultó útil?

Seguridad y Cumplimiento

Akua cuenta con certificación PCI DSS Nivel 1 — el nivel de seguridad más estricto disponible en el ecosistema de pagos.

La documentación de Attestation of Compliance (AoC) está disponible bajo solicitud en trust.akua.la.


Prácticas de seguridad

PrácticaDescripción
HTTPS / TLSTodas las APIs y el Dashboard operan sobre HTTPS. Las conexiones HTTP no cifradas son rechazadas. TLS protege los datos en tránsito, incluyendo datos de tarjeta e información personal (PII).
Cifrado de datosLa información sensible nunca se expone en texto plano. Los datos del cliente se cifran con algoritmos criptográficos avanzados. Las llaves de cifrado son accesibles únicamente para personal autorizado de Akua.
TokenizaciónLos números de tarjeta se reemplazan por tokens cifrados no sensibles. Todos los datos de tarjetas se almacenan en un vault certificado PCI DSS.

Evaluaciones y auditorías

ActividadFrecuenciaDetalle
Evaluación independiente (QSA)AnualRealizada por Evaluadores de Seguridad Calificados
Escaneo de vulnerabilidadesRegularPor Proveedores de Escaneo Aprobados (ASV)
Pruebas de penetraciónRegularÉticas, con remediación documentada de hallazgos

¿Te resultó útil?

Dual Encryption — Datos de Tarjeta

Descripción general

Akua permite enviar datos sensibles de tarjeta encriptados usando RSA-OAEP-256. Esto permite a los integradores encriptar los campos de tarjeta del lado del cliente antes de enviarlos en una solicitud de autorización, de forma que el PAN y el CVV nunca viajen en texto plano.

El merchant solo necesita trabajar con RSA. El proceso es directo: cada campo sensible se cifra de forma independiente con la clave pública RSA del cliente y el resultado en Base64 se envía en el campo encrypted_* correspondiente.

Nota sobre la arquitectura interna: Internamente, el servicio de encriptación también utiliza AES-256-GCM, pero exclusivamente para proteger las claves privadas RSA en reposo (en base de datos). Esto es completamente transparente para el integrador y no forma parte del flujo de encriptación del request.


¿Cómo funciona?

El objeto card en una solicitud de autorización acepta cinco campos en texto plano o en forma encriptada. Las variantes encriptadas usan el prefijo encrypted_:

Campo originalEquivalente encriptado
numberencrypted_number
expiration_monthencrypted_expiration_month
expiration_yearencrypted_expiration_year
holder_nameencrypted_holder_name
cvvencrypted_cvv

Los campos se pueden combinar — por ejemplo, se puede enviar encrypted_number junto con expiration_month en texto plano.

Regla de precedencia: Si se envía un campo en texto plano y su equivalente encrypted_* al mismo tiempo, el campo en texto plano tiene prioridad. Para evitar confusión, se recomienda enviar solo uno de los dos por campo.


Referencia del objeto card

Sin encriptación (9 campos)

{
  "card": {
    "number": "4111111111111111",
    "expiration_month": "12",
    "expiration_year": "2027",
    "holder_name": "John Doe",
    "cvv": "123",
    "discretionary_data": "...",
    "sequence_number": "...",
    "service_code": "...",
    "pin_block_data": "..."
  }
}

Con encriptación (reemplazando los 5 campos sensibles — 9 campos)

{
  "card": {
    "encrypted_number": "<base64-encriptado>",
    "encrypted_expiration_month": "<base64-encriptado>",
    "encrypted_expiration_year": "<base64-encriptado>",
    "encrypted_holder_name": "<base64-encriptado>",
    "encrypted_cvv": "<base64-encriptado>",
    "discretionary_data": "...",
    "sequence_number": "...",
    "service_code": "...",
    "pin_block_data": "..."
  }
}

Ambientes

Los endpoints de gestión de claves viven en la MISMA base que el resto de la API del comercio (la que ya se usa para /oauth/token, /v1/instruments, /v1/users, etc.):

AmbienteURL base
Sandboxhttps://sandbox.akua.la
Producciónhttps://api.akua.la

Gestión de claves

El flujo de integración requiere dos pasos: primero obtener la clave pública activa (creándola si aún no existe), luego usarla para encriptar los campos de tarjeta.

Ambos endpoints se autentican con el mismo Bearer token client_credentials que ya se usa para el resto de la API. No hace falta enviar el header client-id — el servicio resuelve el cliente a partir del JWT.


Paso 1 — Crear o rotar el par de claves

Antes de poder encriptar, el cliente debe generar su par de claves RSA en el sistema. Este paso se realiza una sola vez (o cada vez que se quiera rotar la clave).

⚠️ Este endpoint reemplaza la clave activa si ya existe una — no llamarlo en cada arranque de tu app. Hacé GET primero y solo POST si no hay clave.

Endpoint

POST /v1/encryption/keys

Ejemplo

TOKEN=$(curl -s -X POST https://sandbox.akua.la/oauth/token \
  -H "Content-Type: application/json" \
  -d '{"grant_type":"client_credentials","client_id":"<CLIENT_ID>","client_secret":"<CLIENT_SECRET>","audience":"https://sandbox.akua.la"}' \
  | jq -r '.access_token')

curl -X POST https://sandbox.akua.la/v1/encryption/keys \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json"

Respuesta (201)

{
  "client_id": "cli-d6g4fk97st004b10ai70",
  "kid": "key_d965l7hg7c83rpt50pag",
  "algorithm": "RSA-OAEP-256",
  "key_size": 2048,
  "status": "active",
  "public_key": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n",
  "valid_from": "2026-07-07T01:47:11.151315844Z",
  "valid_until": "2027-07-07T01:47:11.151315844Z",
  "created_at": "2026-07-07T01:47:11.151315844Z",
  "updated_at": "2026-07-07T01:47:11.151315844Z"
}

Paso 2 — Obtener la clave pública activa

Una vez creada, se obtiene la clave pública para encriptar los campos de tarjeta. Este endpoint devuelve la clave existente sin rotarla.

Endpoint

GET /v1/encryption/keys
HeaderValor
AuthorizationBearer <token>

Ejemplo — Descargar y guardar como .pem

curl https://sandbox.akua.la/v1/encryption/keys \
  -H "Authorization: Bearer $TOKEN" \
  | jq -r '.public_key' > pub.pem

Devuelve el mismo shape que el POST, con la clave ya existente.


Encriptar un campo de tarjeta

Una vez guardada la clave pública como pub.pem, se usa RSA-OAEP con SHA-256 para encriptar cada campo. El resultado debe estar codificado en Base64.

Ejemplo — Encriptar un PAN por línea de comandos

echo -n "4111111111111111" | openssl pkeyutl -encrypt \
  -pubin -inkey pub.pem \
  -pkeyopt rsa_padding_mode:oaep \
  -pkeyopt rsa_oaep_md:sha256 \
  | base64

El string Base64 resultante se coloca en el campo encrypted_* correspondiente del objeto card.

Repetir este proceso para cada campo que se desee encriptar (number, expiration_month, expiration_year, holder_name, cvv).


Rotación de claves

  • Las claves se rotan anualmente.
  • Solo se permite una clave activa por cliente a la vez — llamar a POST /v1/encryption/keys reemplaza la clave activa existente.
  • Los integradores deben siempre obtener la clave activa desde GET /v1/encryption/keys antes de encriptar, para asegurarse de usar la clave vigente.

¿Te resultó útil?

PAGOS CON TARJETA

29

¿Te resultó útil?

Transacciones CIT / MIT — Guía de Integración

Endpoint: POST /v1/payments/authorizations

Las redes de tarjetas (Visa, Mastercard) exigen identificar quién inicia cada transacción y qué tipo de cobro es. Akua resuelve esto con dos campos en el request de autorización: initiator y order_type.


Conceptos clave

CIT (Customer Initiated Transaction): el tarjetahabiente está presente (física o digitalmente) y autoriza el cobro de forma activa. Ejemplos: una compra en un e-commerce, el primer pago de una suscripción, guardar una tarjeta para uso futuro.

MIT (Merchant Initiated Transaction): el comercio cobra sin presencia del cliente, basándose en un acuerdo previo que el cliente autorizó en una CIT. Ejemplos: el cobro mensual de una suscripción, un cargo por no-show en un hotel, un reintento de cobro.

La regla fundamental es: toda MIT debe vincularse a la CIT que le dio origen. Esto se hace enviando parent_transaction_data con los identificadores de red que Akua devuelve en la respuesta de la CIT original.


Los campos

initiator

ValorSignifica
customerEl tarjetahabiente inicia y autoriza el pago (CIT)
merchantEl comercio inicia el cobro sin presencia del tarjetahabiente (MIT)

order_type

Este campo le dice a la red de tarjetas qué tipo de cobro se está haciendo. Dependiendo del valor, puede usarse como CIT, como MIT, o como ambos en distintos momentos del flujo.

Valores que aplican como CIT y como MIT:

ValorComo CIT (Initial)Como MIT (Subsequent)
recurringAlta inicial de la suscripciónCobros periódicos posteriores
installmentPrimera cuota del planCuotas siguientes
standing_orderAutorización inicial del débito automáticoCobros por monto variable
unscheduledGuardado de la credencialCobros futuros no programados
deferredAutorización inicialCobro posterior
delayedAutorización inicial del servicio (ej: check-in de hotel)Cargos adicionales post-servicio (ej: minibar, peajes)

Cuando se usan como CIT, estos valores actúan como CIT-Initial: la credencial se almacena (card-on-file) y se activa la tokenización y el Account Updater (ABU) para mantener los datos de la tarjeta vigentes.

Valores solo CIT:

ValorDescripción
purchaseCompra puntual. La credencial no se guarda para cobros futuros. No se activa tokenización ni ABU

purchase es el único tipo CIT que no funciona como CIT-Initial. Es una transacción aislada sin relación con cobros posteriores.

Valores solo MIT:

ValorDescripción
no_showCargo por no presentación a una reserva (penalidad según política del comercio)
resubmissionReenvío de una transacción previamente rechazada (solo cuando la respuesta del emisor no prohíbe reintentar)

Flujo completo: CIT → MIT

El patrón siempre es el mismo, sin importar el order_type:

  1. Se hace una CIT (el cliente autoriza)
  2. En la respuesta, Akua devuelve network_data dentro de la transacción, con los identificadores de la red
  3. El comercio guarda esos identificadores
  4. Cuando toca cobrar sin el cliente, se envía una MIT incluyendo parent_transaction_data con esos identificadores

Paso 1 — CIT inicial

El cliente autoriza el primer cobro. En este ejemplo, es una suscripción (recurring):

POST /v1/payments/authorizations

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "recurring",
    "initiator": "customer",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": {
        "value": 29900,
        "currency": "COP"
    },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    },
    "customer_data": {
        "billing_address": {
            "street": "Calle 26",
            "number": "45A-60",
            "city": "Bogotá",
            "state": "Cundinamarca",
            "zip_code": "110911",
            "country": "COL"
        }
    }
}

Respuesta de la CIT (extracto relevante)

La respuesta incluye los datos de red dentro de transaction.network_data. Lo importante es guardar estos valores para usarlos en las MIT posteriores:

{
    "payment_id": "pay-abc123xxxxxxxxxx",
    "transaction": {
        "id": "trx-xyz789xxxxxxxxxx",
        "status": "APPROVED",
        "network_data": {
            "approval_code": "772886",
            "response_code": "00",
            "financial_network_code": "MCC",
            "banknet_reference_number": "000UNB",
            "settlement_date": "0315",
            "transmission_date_time": "0315143000"
        }
    },
    "instrument_id": "ins-xxxxxxxxxx"
}

Importante: guardar el payment_id o transaction.id devuelto. Estos se usan para construir parent_transaction_data en las MIT posteriores. Adicionalmente, dependiendo de la red, la respuesta puede incluir campos específicos como mastercard_economic_tlid o visa_initial_transaction_identifier dentro de network_data.

Paso 2 — MIT posterior

Cuando llega el momento de cobrar sin presencia del cliente, se envía la misma autorización pero con initiator: "merchant" y parent_transaction_data para vincularla a la CIT original.

Con datos de Mastercard:

POST /v1/payments/authorizations

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "recurring",
    "initiator": "merchant",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": {
        "value": 29900,
        "currency": "COP"
    },
    "instrument": {
        "id": "ins-xxxxxxxxxx"
    },
    "parent_transaction_data": {
        "network_data": {
            "mastercard_economic_tlid": "AABB1234CCDD5678EEFF01"
        }
    }
}

Con datos de Visa:

POST /v1/payments/authorizations

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "recurring",
    "initiator": "merchant",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": {
        "value": 29900,
        "currency": "COP"
    },
    "instrument": {
        "id": "ins-xxxxxxxxxx"
    },
    "parent_transaction_data": {
        "network_data": {
            "visa_initial_transaction_identifier": "012345678901234"
        }
    }
}

Notas sobre las MIT:

  • Se usa instrument.id (el instrumento almacenado), no los datos crudos de la tarjeta. El CVV no se almacena ni se reenvía.
  • No se envía customer_data — el cliente no está presente.
  • parent_transaction_data.network_data lleva el identificador de red correspondiente a la marca de la tarjeta.

Vinculación por red (parent_transaction_data)

El campo que se envía dentro de parent_transaction_data.network_data depende de la red de la tarjeta:

RedCampoFormato
Mastercardmastercard_economic_tlidAlfanumérico, máximo 22 caracteres
Visavisa_initial_transaction_identifierNumérico, exactamente 15 dígitos

Estos valores los devuelve Akua en la respuesta de la CIT aprobada. El comercio debe almacenarlos y enviarlos sin modificar en cada MIT posterior de la misma serie.

Opcionalmente, parent_transaction_data también acepta first_payment_id y first_transaction_id para vincular usando los identificadores internos de Akua en lugar de (o además de) los de red.


Ejemplos por caso de uso

En todos los ejemplos de MIT se omiten los campos que no cambian respecto al flujo general (la estructura completa se mostró arriba). Solo se muestran los campos relevantes para cada caso.

Suscripción — recurring

Caso: streaming, SaaS, membresías. Monto fijo, frecuencia fija.

CIT (el cliente se suscribe):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "recurring",
    "initiator": "customer",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 29900, "currency": "COP" },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    }
}

MIT (cobro mensual automático):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "recurring",
    "initiator": "merchant",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 29900, "currency": "COP" },
    "instrument": { "id": "ins-xxxxxxxxxx" },
    "parent_transaction_data": {
        "network_data": {
            "mastercard_economic_tlid": "AABB1234CCDD5678EEFF01"
        }
    }
}

Cuotas — installment

Caso: el cliente compra un producto y paga en N cuotas. La primera cuota es CIT, las siguientes son MIT.

CIT (primera cuota):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "installment",
    "initiator": "customer",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 150000, "currency": "COP" },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    },
    "installments": {
        "type": "issuer-financed",
        "quantity": 6
    }
}

MIT (cuota siguiente):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "installment",
    "initiator": "merchant",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 25000, "currency": "COP" },
    "instrument": { "id": "ins-xxxxxxxxxx" },
    "parent_transaction_data": {
        "network_data": {
            "visa_initial_transaction_identifier": "012345678901234"
        }
    }
}

Débito automático variable — standing_order

Caso: servicios públicos, seguros, membresías donde el monto varía cada periodo.

CIT (autorización inicial):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "standing_order",
    "initiator": "customer",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 85000, "currency": "COP" },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    }
}

MIT (cobro del periodo, monto distinto):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "standing_order",
    "initiator": "merchant",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 92300, "currency": "COP" },
    "instrument": { "id": "ins-xxxxxxxxxx" },
    "parent_transaction_data": {
        "network_data": {
            "mastercard_economic_tlid": "AABB1234CCDD5678EEFF01"
        }
    }
}

Cobro no programado — unscheduled

Caso: recarga automática de saldo cuando baja de un umbral, cobro por uso bajo demanda.

CIT (el cliente guarda su tarjeta y autoriza cobros futuros):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "unscheduled",
    "initiator": "customer",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 50000, "currency": "COP" },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    }
}

MIT (recarga automática):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "unscheduled",
    "initiator": "merchant",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 50000, "currency": "COP" },
    "instrument": { "id": "ins-xxxxxxxxxx" },
    "parent_transaction_data": {
        "network_data": {
            "visa_initial_transaction_identifier": "012345678901234"
        }
    }
}

Autorización diferida — deferred

Caso: el cliente autoriza un monto que se cobrará después (ej: reserva de hotel donde el cobro final se hace al checkout).

CIT (autorización):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "deferred",
    "initiator": "customer",
    "capture": { "mode": "MANUAL" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 350000, "currency": "COP" },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    }
}

MIT (cobro posterior):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "deferred",
    "initiator": "merchant",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 350000, "currency": "COP" },
    "instrument": { "id": "ins-xxxxxxxxxx" },
    "parent_transaction_data": {
        "network_data": {
            "mastercard_economic_tlid": "AABB1234CCDD5678EEFF01"
        }
    }
}

Cargo posterior al servicio — delayed

Caso: hotel, transporte, servicios donde pueden surgir cargos adicionales después del servicio principal. La CIT es la autorización al inicio del servicio (ej: check-in), y las MIT son los cargos adicionales posteriores (ej: minibar, peajes, daños).

CIT (check-in del hotel, autorización inicial):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "delayed",
    "initiator": "customer",
    "capture": { "mode": "MANUAL" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 500000, "currency": "COP" },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    }
}

MIT (cargo por minibar post-checkout):

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "delayed",
    "initiator": "merchant",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 15000, "currency": "COP" },
    "instrument": { "id": "ins-xxxxxxxxxx" },
    "parent_transaction_data": {
        "network_data": {
            "visa_initial_transaction_identifier": "012345678901234"
        }
    }
}

Cargo por no presentación — no_show

Caso: el cliente reservó y no se presentó. Solo MIT.

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "no_show",
    "initiator": "merchant",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 120000, "currency": "COP" },
    "instrument": { "id": "ins-xxxxxxxxxx" },
    "parent_transaction_data": {
        "network_data": {
            "mastercard_economic_tlid": "AABB1234CCDD5678EEFF01"
        }
    }
}

Reenvío de transacción rechazada — resubmission

Caso: un cobro MIT fue rechazado (ej: fondos insuficientes) y se reintenta después. Solo MIT.

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "resubmission",
    "initiator": "merchant",
    "capture": { "mode": "AUTOMATIC" },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": { "value": 29900, "currency": "COP" },
    "instrument": { "id": "ins-xxxxxxxxxx" },
    "parent_transaction_data": {
        "network_data": {
            "visa_initial_transaction_identifier": "012345678901234"
        }
    }
}

Validaciones

Combinaciones inválidas retornan 400 Bad Request con error code INVALID_INITIATOR_ORDER_TYPE_COMBINATION:

CombinaciónMotivo
initiator: "customer" + order_type: "no_show"no_show es exclusivo de MIT
initiator: "customer" + order_type: "resubmission"resubmission es exclusivo de MIT
initiator: "merchant" + order_type: "purchase"purchase es exclusivo de CIT
initiator: "merchant" sin parent_transaction_dataToda MIT requiere vinculación con la CIT original

¿Te resultó útil?

¿Qué es una autorización?

La autorización es el primer paso en el proceso de pago, donde se presentan los detalles de la tarjeta de crédito del tarjetahabiente al comercio para el pago. El comerciante envía la transacción al banco adquirente, que reenvía la solicitud al emisor de la tarjeta para su autorización a través de la red.

Ciclo de un pago - Autorización

El proceso de un pago incluye tres etapas principales, que se traducen de la siguiente manera:

  1. Autorización:

Es el primer paso del proceso, en el cual:

  • El titular de la tarjeta proporciona los detalles de pago al comerciante.
  • El banco adquirente (el banco del comerciante) envía la solicitud a través de la red de tarjetas al banco emisor (el banco del titular de la tarjeta).
  • El banco emisor verifica la validez de la tarjeta, los fondos disponibles y la seguridad de la transacción, y responde aprobando o rechazando la operación.
  • Si se aprueba, se genera un código de autorización y se reserva temporalmente el monto en la cuenta del titular, pero aún no se transfiere al comerciante.
  1. Compensación

En esta etapa:

  • Los detalles de la transacción aprobada se procesan y se preparan para la liquidación.
  • El adquirente y la red de tarjetas realizan una reconciliación de la transacción con el emisor para confirmar montos y aplicar cualquier ajuste (como tasas o conversiones de moneda).
  • Esta etapa asegura que todos los participantes en la transacción estén alineados con la información registrada.
  • No implica transferencia de dinero aún, pero garantiza que los datos sean precisos para la siguiente etapa.
  1. Liquidación:

Finalmente:

  • Los fondos reservados en la autorización se transfieren del banco emisor al banco adquirente, pasando por la red de tarjetas.
  • El banco adquirente acredita el monto al comerciante, menos las comisiones aplicables (como la tasa de descuento).
  • En este punto, la transacción se completa y el comerciante recibe su pago.

Roles y Responsabilidades

Roles

RolResponsabilidad
CLIENTEInicia la transacción realizando un pago.
COMERCIANTERecibe el pago del cliente y actúa como intermediario entre el cliente y Akua.
AkuaConecta a los comerciantes con las redes de tarjetas y bancos emisores. Valida y procesa las solicitudes de autorización del comerciante.
REDES DE TARJETASFacilitan la comunicación entre Akua y el banco emisor.
BANCO EMISORDecide si la transacción es aprobada o rechazada.

El camino de una transacción

Camino de una transacción

  1. El cliente realiza el pago: Usa su tarjeta (física o digital) para realizar una compra en un negocio (tienda física o en línea).
  2. El comerciante envía la solicitud: Compartimos los detalles esenciales del pago con el banco del cliente (emisor) para su evaluación.
  3. El emisor responde: Aprueba o rechaza la solicitud en función de la validez de la tarjeta, los fondos disponibles y las políticas de seguridad.

¿Qué sucede cuando el banco responde?

APROBACIÓN

Código de Autorización:

  • Un número único que confirma la transacción.

Aprobaciones Parciales:

  • En algunos casos, el emisor puede aprobar solo una parte del monto (esto se aplica particularmente a ciertos tipos de comerciantes).

RECHAZO

La tarjeta puede ser rechazada por razones como:

  • Fondos insuficientes.
  • Información incorrecta.
  • Sospecha de fraude.
  • En casos especiales, si el emisor sospecha fraude, puede ser necesaria una verificación manual (llamada por teléfono).

Flujo de autorización en un pago y sus estados

Flujo de autorización

FlujoEstadoDescripción del estado
Estado InicialCREATEDEste es el primer estado del flujo. Indica que el proceso ha sido creado, pero no se ha tomado ninguna acción aún.
Estado intermedioPENDINGUna vez creado, el proceso pasa al estado pendiente, esperando una acción o procesamiento adicional.
Estado finalSUCCEEDEDEl proceso fue aprobado exitosamente.
REJECTEDIndica que el proceso fue rechazado.
CANCELEDIndica que el proceso fue cancelado por alguna razón.

📘 Cualquier estado puede llevar finalmente a un ERROR. Esto sugiere que puede ocurrir una falla en cualquier etapa del proceso.

¿Te resultó útil?

Pre-autorización

Descripción

Más allá de la autorización estándar, la pre-autorización permite a los comerciantes reservar un monto estimado de pago sin hacerlo final. Este proceso se usa comúnmente en industrias de hospitalidad y alquiler de vehículos donde los montos finales de transacción pueden fluctuar.

Durante la pre-autorización:

  • Una suma se retiene en la cuenta del titular de la tarjeta como garantía
  • Se pueden hacer ajustes posteriormente—aumentando o disminuyendo el monto reservado
  • Si el monto final es menor, la diferencia se libera automáticamente
  • Si es mayor, el comerciante debe solicitar autorización adicional

Flujo de los estados de una Preautorización

a38325375fc94438c0ccb02985ee65f3b6bf802c59beafa46be6f0c9badaf5a4-PRE_authorization.png

Casos de Uso

La pre-autorización proporciona flexibilidad y seguridad tanto para comerciantes como para clientes, asegurando que los fondos estén disponibles para bienes o servicios entregados.

Escenarios comunes incluyen:

  • Hoteles: cubriendo costos de habitación más extras potenciales
  • Alquiler de autos: cubriendo tarifas de alquiler y posibles cargos por daños
  • Aerolíneas: garantizando pago mientras se procesa la emisión de boletos
  • E-commerce: asegurando pago antes de confirmar disponibilidad de producto

Requisitos Clave

  • La pre-autorización debe liquidarse dentro de 30 días
  • En pre-autorizaciones, sólo se acepta modo de captura MANUAL
  • Las transacciones deben vincularse usando el Trace ID (DE 48, subelemento 63) para asociación precisa con el emisor

¿Te resultó útil?

Autorización Parcial

Descripción

Un proceso que ocurre cuando el monto total de una transacción no puede ser aprobado debido a fondos insuficientes o crédito limitado. En lugar de rechazar la transacción completamente, el banco emisor aprueba un monto parcial, permitiendo al titular de la tarjeta usar un método de pago adicional para el saldo restante.

Puntos Clave

El proceso asegura que los titulares de tarjetas puedan completar compras incluso con fondos disponibles limitados. El sistema de pago del comerciante debe soportar autorización parcial para manejar estas transacciones correctamente. El saldo restante puede pagarse usando otra tarjeta, efectivo o método de pago alternativo.

Casos de Uso

Este enfoque resulta especialmente valioso para tarjetas prepago o cuando los clientes combinan múltiples métodos de pago. Ofrece flexibilidad tanto a comerciantes como a clientes, previniendo rechazos de transacción innecesarios.

Flujo del Proceso

7b3142f27e64c984ed42053431aa59bd5e8bf3034f50c5f046c77a96d8102da0-Partial_authorization.png

  1. Solicitud Inicial: El comerciante envía el monto total de la transacción para aprobación
  2. Respuesta del Emisor: El banco aprueba el monto parcial y envía respuesta de autorización con la suma aprobada
  3. Notificación del Terminal: Muestra el saldo restante; solicita método de pago alternativo
  4. Completar o Reversar: Ya sea un mensaje de advice (0120) confirma la aprobación parcial, o un mensaje de reversa (0400) explica la cancelación

Escenarios de Ejemplo

  • El titular de tarjeta intenta un pago de $100 con $75 disponibles; recibe aprobación de $75 con $25 pendientes
  • El titular de tarjeta paga $50 coincidiendo con el saldo disponible; no se solicitan fondos adicionales
  • La continuación envía advice confirmando aprobación; la cancelación envía reversa explicando la razón

Requisitos Clave

  • Campo DE 6: Muestra el monto aprobado disponible para compra
  • Notificación al Comerciante: El adquirente debe notificar al comerciante si la aprobación parcial iguala el monto solicitado para prevenir cargos adicionales

¿Te resultó útil?

Compensación

¿Qué es la compensación?

El clearing es el precursor del settlement (liquidación). Ambas partes involucradas (Adquirente y Emisor) comparten y acuerdan los detalles de la transacción. Normalmente, cuando el proceso de clearing de una transacción se completa, el emisor actualiza el saldo del titular de la tarjeta (los fondos aún no se han transferido). En caso de desacuerdo, puede ocurrir un contracargo (chargeback).

d3935c1ed58d1d0afa5d75aba2d74e20b19aede570308c2a4e8fcfbc8f7ac0ec-Ciclo_de_un_pago_-_Compensacion.png

Resumen del proceso de clearing

El proceso de clearing implica coordinar datos de pago, validación y liquidación entre los comerciantes, Akua y las redes de tarjetas. Esto asegura una reconciliación eficiente y pagos precisos.

Pasos del proceso:

11115ddf61721358b1ed5094e2e3e90173deae22eac1d91996d2895087fd86c4-Clearing_steps.png

  1. Inicio: Un cliente (a través de un trabajo programado - cron job) inicia una solicitud para activar el proceso de captura basado en el ID de pago. El proceso puede activarse automáticamente (captura instantánea) o programarse.

  2. Validación del pago: El orquestador recupera los detalles del pago desde la API de pagos y verifica la elegibilidad del pago para ser capturado.

  3. Notificación: El orquestador utiliza SNS (Simple Notification Service) para notificar a otros servicios sobre el proceso de clearing.

  4. Preparación del servicio de clearing: Los datos de la transacción se envían al servicio de clearing para su procesamiento. Los metadatos necesarios se almacenan en la base de datos.

  5. Creación del archivo: El servicio de clearing compila un archivo de clearing basado en las transacciones pendientes y los ciclos de compensación.

  6. Almacenamiento del archivo: El archivo de clearing se guarda en S3 para propósitos de auditoría y luego se envía a las redes de tarjetas.

¿Te resultó útil?

Captura de un Pago

La captura conecta la autorización con el clearing y la liquidación. Una vez que un pago es autorizado, la captura confirma que la transacción está lista para ser enviada a las redes de tarjetas, reconciliada y liquidada al comerciante.

Solo los pagos con estado AUTHORIZED pueden ser capturados.


a36d5fa21bfa29540955413967bc846085dc16fa055126cfc2eed2755d44d3c7-Capture_flow.png

Modos de captura

ModoDescripción
MANUALLa captura debe iniciarse explícitamente por el comerciante
AUTOMATICEl sistema captura la transacción sin intervención manual

Flujo de captura

EstadoDescripción
AUTHORIZEDLa autorización fue exitosa. Según el modo configurado, la captura se inicia de forma manual o automática.
CAPTURE IN PROGRESSEl proceso de clearing comenzó. Si falla, el pago pasa a REJECTED.
CAPTURE PRESENTEDEl archivo de clearing fue enviado a las redes de tarjetas. Si se confirma, avanza a CAPTURADO. Si no, pasa a REJECTED.
CAPTUREDLa captura fue confirmada exitosamente. El pago queda listo para liquidación.
REJECTEDOcurrió una falla en el clearing o en la confirmación de captura.

¿Te resultó útil?

Modos de Captura

Akua soporta tres modos de captura según las necesidades del negocio: AUTOMATIC, SCHEDULED y MANUAL.

Comparación de modos

Modo¿Cuándo se presenta?Requiere intervención
MANUALSolo cuando el comerciante envía una solicitud explícita
AUTOMATICEn la próxima presentación de Akua (~30 min)No
AUTOMATIC + hora en merchantEn la primera presentación de Akua luego de la hora configuradaNo
AUTOMATIC + capture_afterEn la primera presentación de Akua luego del datetime especificadoNo
AUTOMATIC + amboscapture_after toma precedencia sobre la hora del merchantNo

Importante: una vez que Akua presenta un pago a la red, no es posible cancelarlo, aunque el ciclo de compensación aún no haya corrido. Comercios con alto índice de cancelaciones deben considerar MANUAL o configurar una hora de captura adecuada.


Captura Manual — MANUAL

La captura se activa solo cuando el comerciante envía una solicitud explícita. La transacción permanece en estado AUTHORIZED hasta ese momento.

{
  "capture": {
    "mode": "MANUAL"
  }
}

Si no se envía la petición de captura en aproximadamente 7 días, la autorización expira automáticamente. O 30 días para preautorizaciones.

Casos de uso: compras de alto valor que requieren validación, negocios con alto índice de cancelaciones, modelos que verifican entrega del producto antes de cobrar.


Captura Automática — AUTOMATIC

Akua presenta el pago en la próxima ronda (~30 min después de la autorización). No requiere ninguna acción del comerciante.

{
  "capture": {
    "mode": "AUTOMATIC"
  }
}

Casos de uso: e-commerce con pagos instantáneos, suscripciones y cargos recurrentes, tiendas con alto volumen de transacciones.


Captura Automática con hora configurada en el merchant

El merchant puede tener una hora diaria de captura configurada en su perfil. En ese caso, Akua solo presenta los pagos en la primera ronda posterior a esa hora.

Ejemplo: hora configurada = 21:00. Si Akua presenta a las 21:30, esos pagos recién se incluyen en esa ronda. Los pagos autorizados antes de las 21:00 esperan hasta ese momento para ser elegibles.

{
  "capture": {
    "mode": "AUTOMATIC"
  }
}

La hora se configura a nivel de merchant desde el Dashboard. No requiere cambios en el request de pago.

Casos de uso: comercios que necesitan agrupar capturas en un horario fijo diario, modelos de negocio con cierre de caja a hora determinada.


Captura Automática con capture_after

Permite especificar un datetime exacto a partir del cual el pago es elegible para ser presentado. Akua lo incluye en la primera ronda posterior a ese momento.

{
  "capture": {
    "mode": "AUTOMATIC",
    "capture_after": "2026-02-27T21:00:00Z"
  }
}

El campo acepta timezone explícito — la Z indica UTC. Podés especificar cualquier zona horaria usando el offset correspondiente (ej: 2026-02-27T21:00:00-05:00 para Colombia).

Casos de uso: pagos que deben capturarse en una fecha futura específica, reservas donde el cobro se efectúa el día del servicio.


Combinación: hora en merchant + capture_after

Si el merchant tiene una hora de captura configurada y el pago incluye capture_after, el campo de la transacción toma precedencia. El datetime enviado en el request es más específico que la configuración general del merchant.

{
  "capture": {
    "mode": "AUTOMATIC",
    "capture_after": "2026-02-27T22:00:00Z"
  }
}

En este caso, aunque el merchant tenga configuradas las 21:00, el pago no será elegible hasta las 22:00 UTC.

¿Te resultó útil?

Liquidación

¿Cómo funciona la liquidación?

Es el paso final en el que los fondos se transfieren del banco del tarjetahabiente (emisor) al banco del comerciante (adquirente). Las redes de tarjetas facilitan esta transferencia de fondos entre emisor y adquirente, contabilizando las tarifas aplicables. El adquirente entonces acredita la cuenta del comerciante con el monto de la transacción menos las tarifas.

8bd63c24057d9756b4f73ba2d1fa5eb9094d6aa11a86010193842595f5c9619a-Ciclo_de_un_pago_-_Liquidacion.png

Diferencias entre Clearing y Settlement

Clearing

Esta fase involucra el intercambio de datos de transacción. Las transacciones se mueven del adquirente al emisor para el registro en la cuenta del tarjetahabiente. Los mensajes de clearing contienen datos, pero no involucran el intercambio o transferencia de fondos.

Settlement

Ocurriendo después del clearing, esta fase consiste en las transferencias reales de fondos. Los fondos representan el valor monetario de las transacciones procesadas y se intercambian entre clientes según la posición neta calculada por Mastercard.

¿Te resultó útil?

Cashouts

¿Qué es un Cashout?

Un cashout representa el proceso mediante el cual un usuario recibe los fondos acumulados en su cuenta, transfiriéndolos a su método de pago predeterminado. Este mecanismo permite a los clientes obtener pagos de manera rápida y con total transparencia.

Características Clave:

  • Opera a través de procesamiento automatizado y periódico para asegurar liquidez del usuario
  • Proporciona desgloses detallados de montos y descuentos aplicados antes de la transferencia
  • Ofrece seguimiento en dashboard para el estado de cada cashout
  • Facilita la gestión financiera del usuario con visibilidad y control completos

Acciones del Cliente

Configurar Método de Pago Predeterminado

Los clientes deben establecer un método de pago predeterminado para recibir fondos de Akua, validado y gestionado a través del dashboard por usuarios autorizados.

Visibilidad del Estado del Cashout

Los usuarios pueden ver cashouts con estados PENDING, PROCESSING y PAID en el dashboard. Detalles adicionales incluyendo recibos de pago y comentarios permanecen accesibles para personal autorizado, junto con información de transacciones asociadas.

Pasos de Gestión

  • Revisar detalles del cashout
  • Validar información sobre montos, descuentos y pagos asociados
  • Subir comprobante de pago

Descarga de Recibo de Pago

Los clientes pueden acceder y ver el comprobante de cada transferencia vinculada a un cashout.

Este flujo de trabajo asegura transparencia y control, permitiendo a los clientes gestionar sus fondos eficientemente.

¿Te resultó útil?

Diferencias

Las devoluciones agrupan todos los procesos para interrumpir, revertir o reembolsar un pago. Dependiendo del estado en que se encuentre el pago, aplica una u otra modalidad.


Cancelación vs. Reembolso

CancelaciónReembolso
¿Cuándo aplica?Antes de la captura o liquidaciónDespués de la captura o liquidación
Estados válidosCREATED, AUTHORIZEDCAPTURED, SETTLED
¿Se debita al cliente?No — el monto nunca se cobraSí — se devuelve el monto ya cobrado
Vía de devoluciónSe libera la reservaMisma fuente de pago utilizada

Cancelación

Detiene el pago antes de que sea capturado. El monto reservado se libera y nunca se debita al cliente. Es útil para gestionar errores o solicitudes de anulación en etapas tempranas del flujo.

Solo disponible en pagos con estado CREATED o AUTHORIZED.


Reembolso (Refund)

Cuando el pago ya fue capturado o liquidado, no es posible cancelarlo. El reembolso devuelve el monto al cliente a través de la misma fuente de pago.

Estado del reembolsoDescripción
IN PROCESSEl reembolso fue iniciado y está siendo procesado
PRESENTEDEl reembolso fue enviado a las redes de tarjetas
COMPLETEDEl monto fue acreditado exitosamente al cliente

¿Te resultó útil?

Cancelación

Descripción

La cancelación de pagos permite detener el procesamiento de una transacción antes de que alcance las etapas de captura y liquidación. Esta acción está restringida a fases específicas del flujo de pago y debe cumplir con las políticas de autorización y captura.

1e841ecc2e711221b2ea85e25c36de0e800145ef7b3d9ce9c773a51faecfe373-CancellatIon_flow.png

¿Cuándo Puede Cancelarse un Pago?

Los pagos pueden cancelarse durante estas etapas:

  • Created: El pago existe pero no ha pasado por autorización
  • Authorized: El pago está aprobado pero aún no capturado

Estados del Proceso de Cancelación

El flujo de cancelación incluye estas etapas:

Estado Created

  • El pago está pendiente de autorización
  • Cancelación directa posible antes de que comience la autorización
  • Transición: Created → Cancelled

Estado Pending Authorization

  • El pago espera aprobación de autorización
  • Cancelación permitida antes de que inicie la captura
  • Transición: Pending authorization → Cancelled

Estado Authorized

  • El pago está aprobado y listo para captura
  • Cancelación disponible antes de que comience la captura
  • Transición: Authorized → Cancelled

Estado Cancelled

  • Cancelación exitosa desde estados anteriores
  • Marcado como "Cancelled"
  • No ocurre procesamiento de captura o liquidación

e60314e62211ad052f950578bb1fb494008a6a9b58619bc2fe1cff27d57d53e9-Cancelletion_flow_complete.png


Relación Cancelación vs. Reembolso

Una vez que un pago alcanza captura o liquidación, la cancelación se vuelve imposible. En este punto, debe iniciarse un proceso de reembolso en su lugar.

Escenarios clave:

  • Pagos autorizados pero no capturados pueden cancelarse
  • Pagos capturados o liquidados requieren procesamiento de reembolso

Errores Comunes de Cancelación

Falla/Rechazo

Causas:

  • El estado del pago no permite cancelación
  • Restricciones del procesador de pagos

Soluciones:

  • Verificar el estado del pago antes de intentar cancelación
  • Contactar soporte técnico para fallas recurrentes

¿Te resultó útil?

Reembolso

Descripción

El proceso de reembolso permite la reversión de pagos previamente capturados. Esta documentación describe las etapas, estados involucrados y posibles transiciones en el flujo de reembolso.

Estados Iniciales para un Reembolso

Un reembolso puede iniciarse desde cualquiera de estos estados de pago:

  • Captured: El pago ha sido capturado.
  • Settled: El pago ha sido liquidado.

¿Cuándo Puedo Procesar un Reembolso?

Los reembolsos solo pueden ejecutarse si el estado del pago es válido y cumple con las políticas definidas por la plataforma.

8cc36bd7925a15e413507bdb37a437d8218e4dd0a4b5968aeaa3a7f70d999e4b-Refund_flow_simple.png

7761f5e96a6c472effae28c62cc135537be578e428f58e2602623e36a1f49adb-Refund_flow.png


Estados del Proceso de Reembolso

El flujo de reembolso incluye estos estados clave:

REFUND IN PROCESS / PRESENTED

  • Indica que el reembolso ha sido solicitado y está siendo procesado
  • Se genera un registro de transacción para seguimiento

REFUND COMPLETED

  • Muestra procesamiento exitoso del reembolso
  • La transacción asociada se marca como reembolsada
  • En algunos casos, el pago regresa a estado Settled una vez liquidado

REFUND FAILED / REJECTED

  • Indica reembolso incompleto debido a errores técnicos, fondos insuficientes o restricciones de la plataforma
  • El estado del pago permanece sin cambios

NO UPDATE

  • Usado cuando la confirmación del resultado del reembolso no está disponible

Relaciones de Estado

Los reembolsos interactúan con estados clave del flujo de pago:

  • CapturedReembolso en Proceso: El reembolso inicia después de la captura del pago
  • SettledReembolso Completado: Un reembolso exitoso puede devolver el pago a estado Settled

Errores Comunes y Soluciones

Reembolso Fallido

  • Causa: Restricciones de fondos o fallas técnicas
  • Solución: Verificar con el procesador de pagos o reenviar solicitud

Sin Actualización

  • Causa: Falla de comunicación con sistema externo
  • Solución: Escalar a soporte técnico

Mejores Prácticas

  • Verificar el estado del pago antes de iniciar el reembolso
  • Mantener registros de todas las transacciones asociadas al reembolso
  • Implementar validaciones que prevengan reembolsos en estados inválidos

¿Te resultó útil?

Contracargos

¿Cómo se administran los Contracargos?

En Akua, el objetivo es ofrecer un mecanismo fácil y sencillo tanto para clientes como para operadores. Los clientes acceden a información detallada sobre cada chargeback, pueden cargar evidencias y realizar seguimientos del estado. Los operadores de Akua monitorean y gestionan el ciclo de vida de los chargebacks, actualizando su estado y comunicándose con clientes.

¿Cómo gestionar los contracargos en dashboard?

Acceso a la Sección de Chargebacks

Para gestionar un chargeback, ingresa a la sección Chargebacks dentro del módulo Risk en el dashboard de Akua. Desde allí, podrás visualizar y administrar todos los casos abiertos.

Visualización de Chargebacks

Cada chargeback registrado incluye:

CampoDescripción
Chargeback IDIdentificador único del chargeback
AmountMonto asociado (USD, BRL, ARS, etc.)
Payment IDIdentificador de la transacción original
Due DateFecha límite para responder
ReasonMotivo del chargeback
StatusEstado actual

Detalle del Chargeback

Al seleccionar un chargeback específico, accederás a:

  • Información básica: ID, fecha de notificación, motivo, estado
  • Historial del caso: Registro cronológico de cambios y evidencias
  • Acciones disponibles: Aceptar, disputar, solicitar información, escalar

Subir Evidencia para Disputa

El proceso incluye:

  1. Selecciona el chargeback en estado "UNDER REVIEW"
  2. Dirígete a la sección Subir Evidencia
  3. Adjunta archivos (PDF, JPEG, PNG)
  4. Asegúrate de cumplir requisitos de documentación
  5. Sigue el indicador de progreso
  6. Confirma la acción

Nota: Los tiempos dependen de plazos establecidos por la entidad adquirente y red de pagos.

Manejo de estados en un chargeback

EstadoDescripciónResponsable
PENDINGContracargo solicitado pero no procesadoCliente
UNDER_REVIEWSiendo revisado, en espera de informaciónCliente
ACCEPTEDChargeback aceptado, reembolso aprobadoCliente
DISMISSED_BY_ISSUERRechazado por red o bancoAkua
EVIDENCE_UPLOADEDEvidencia cargada para disputaCliente
REPRESENTEDEnviado a red de tarjeta para revisiónAkua
AWAITING_ARBITRATIONEscalado a arbitrajeAkua
ARBITRATION_WONDecisión favorable al merchantAkua
ARBITRATION_LOSTDecisión desfavorable al merchantAkua
CLOSEDFinalizado, sin nuevas accionesCliente
INFO_REQUESTEDSe solicita más información al clienteCliente

¿Te resultó útil?

Resumen: guía de Integración

Endpoint: POST /v1/payments/authorizations

Esta guía cubre los distintos escenarios de autorización que soporta la API. Todos los ejemplos usan entry_mode: "not-present" (e-commerce / tarjeta no presente).


Campos base

Toda autorización requiere como mínimo estos campos:

CampoTipoDescripción
intentstringIntención del pago. Valores: authorization (cobro normal), account-status (verificación sin monto)
entry_modestringModo de ingreso. Para e-commerce: not-present
order_typestringTipo de orden CIT/MIT. Para compras puntuales: purchase
initiatorstringQuién inicia la transacción: customer (CIT) o merchant (MIT)
capture.modestringModo de captura. AUTOMATIC captura inmediatamente, MANUAL requiere captura posterior
merchant_idstringIdentificador del comercio (formato mer-...)
amountobjectMonto con value (numérico) y currency (ISO 4217, ej: COP, USD)
instrumentobjectInstrumento de pago (ver variantes abajo)

¿Te resultó útil?

0. Verificación de cuenta (account-status)

Transacción de monto cero para verificar que una tarjeta es válida y está activa, sin generar un cobro. Se usa intent: "account-status" y no se envía amount ni capture.

{
    "intent": "account-status",
    "entry_mode": "not-present",
    "order_type": "purchase",
    "initiator": "customer",
    "merchant_id": "mer-xxxxxxxxxx",
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    },
    "customer_data": {
        "billing_address": {
            "street": "Calle 26",
            "number": "45A-60",
            "city": "Bogotá",
            "state": "Cundinamarca",
            "zip_code": "110911",
            "country": "COL"
        }
    }
}

Casos de uso típicos: validar tarjeta antes de guardarla en bóveda, confirmar que la tarjeta sigue activa antes de un cobro recurrente, o verificar datos del titular.

¿Te resultó útil?

1. Pago con PAN directo

El caso más simple: se envían los datos crudos de la tarjeta.

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "purchase",
    "initiator": "customer",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": {
        "value": 25000.00,
        "currency": "COP"
    },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    },
    "customer_data": {
        "billing_address": {
            "street": "Calle 26",
            "number": "45A-60",
            "city": "Bogotá",
            "state": "Cundinamarca",
            "zip_code": "110911",
            "country": "COL"
        }
    }
}

customer_data.billing_address es opcional pero recomendado: mejora la tasa de aprobación y alimenta los modelos antifraude.

¿Te resultó útil?

2. Pago con impuestos (transaction_compliance)

Para jurisdicciones que requieren reportar impuestos en la transacción, se agrega el objeto transaction_compliance con un array de taxes. Hay tres formas de declararlo según la información disponible en el comercio.


Caso 1: IVA por porcentaje

El sistema asume que amount.value ya incluye el IVA y calcula la base gravable automáticamente.

"transaction_compliance": {
    "taxes": [
        {
            "code": "IVA",
            "percentage": "19"
        }
    ]
}

Para un monto de 1000 COP, la respuesta descompondría: base gravable = 840.34, IVA = 159.66.


Caso 2: IVA como monto fijo

Cuando el comercio ya conoce el monto exacto del impuesto, se declara directamente en tax_amount y se envía percentage: "0".

"transaction_compliance": {
    "taxes": [
        {
            "code": "IVA",
            "percentage": "0",
            "tax_amount": {
                "value": "200",
                "currency": "COP"
            }
        }
    ]
}

Para un monto de 1000 COP, la respuesta descompondría: base gravable = 800, IVA = 200.


Caso 3: IVA por porcentaje con base gravable explícita

Cuando solo una parte del monto total es gravable (por ejemplo, el envío o servicios exentos no aplican IVA), el comercio declara la base gravable en taxable_amount. El porcentaje se aplica únicamente sobre ese valor.

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "purchase",
    "initiator": "customer",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": {
        "value": 100000,
        "currency": "COP"
    },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    },
    "customer_data": {
        "billing_address": {
            "street": "Calle 26",
            "number": "45A-60",
            "city": "Bogotá",
            "state": "Cundinamarca",
            "zip_code": "110911",
            "country": "COL"
        }
    },
    "transaction_compliance": {
        "taxes": [
            {
                "code": "IVA",
                "percentage": "19",
                "taxable_amount": {
                    "value": "84034",
                    "currency": "COP"
                }
            }
        ]
    }
}

La respuesta aplicaría el 19% solo sobre 84034: IVA = 15966.46. El remanente (100000 - 84034 - 15966.46) se trata como porción no gravable.


Nota: El campo percentage siempre debe enviarse como string. Los casos 1 y 3 son mutuamente excluyentes con el caso 2: no se debe combinar percentage con valor mayor a "0" junto a tax_amount.

¿Te resultó útil?

3. Pago con datos antifraude

Enviar datos adicionales del comprador mejora la evaluación de riesgo. Todos los campos dentro de customer_data son opcionales, pero entre más datos se envíen, mejor será la evaluación.

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "purchase",
    "initiator": "customer",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": {
        "value": 25000.00,
        "currency": "COP"
    },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    },
    "customer_data": {
        "billing_address": {
            "street": "Calle 26",
            "number": "45A-60",
            "city": "Bogotá",
            "state": "Cundinamarca",
            "zip_code": "110911",
            "country": "COL"
        },
        "delivery_address": {
            "street": "Av. Libertador",
            "number": "1234",
            "city": "Buenos Aires",
            "state": "Buenos Aires",
            "zip_code": "C1001",
            "country": "ARG"
        },
        "email": "user@example.com",
        "phone_number": "+57899123456",
        "device_fingerprint": "a1b2c3d4e5f6g7h8i9j0",
        "ip_address": "203.0.113.42",
        "latitude": "-34.9011",
        "longitude": "-56.1645"
    }
}

Campos antifraude disponibles: email, phone_number, device_fingerprint, ip_address, latitude, longitude, delivery_address. Enviar delivery_address cuando la dirección de entrega difiere de la de facturación permite detectar patrones de fraude.

¿Te resultó útil?

4. Pago con 3D Secure

Cuando el comercio ejecuta autenticación 3DS antes del cobro, se incluyen los campos eci y three_ds con los datos resultantes de la autenticación.

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "purchase",
    "initiator": "customer",
    "eci": "02",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "three_ds": {
        "cavv": "K0nxdecnwejnckdnsfv3i4f",
        "version": "2.6.1.1",
        "ds_transaction_id": "021956238443987999831863072557355283"
    },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": {
        "value": 25000.00,
        "currency": "COP"
    },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    },
    "customer_data": {
        "billing_address": {
            "street": "Calle 26",
            "number": "45A-60",
            "city": "Bogotá",
            "state": "Cundinamarca",
            "zip_code": "110911",
            "country": "COL"
        }
    }
}
CampoDescripción
eciIndicador de comercio electrónico. Refleja el resultado de la autenticación 3DS (ej: "02" para Mastercard autenticado)
three_ds.cavvValor de autenticación del titular (Cardholder Authentication Verification Value)
three_ds.versionVersión del protocolo 3DS utilizado
three_ds.ds_transaction_idIdentificador de transacción asignado por el Directory Server

¿Te resultó útil?

5. Pago con cuotas

Para diferir el cobro en cuotas, se agrega el objeto installments.

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "purchase",
    "initiator": "customer",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": {
        "value": 25000.00,
        "currency": "COP"
    },
    "instrument": {
        "type": "CARD",
        "card": {
            "number": "53830400xxxx0002",
            "cvv": "917",
            "expiration_month": "12",
            "expiration_year": "30",
            "holder_name": "Juan Rodriguez"
        }
    },
    "customer_data": {
        "billing_address": {
            "street": "Calle 26",
            "number": "45A-60",
            "city": "Bogotá",
            "state": "Cundinamarca",
            "zip_code": "110911",
            "country": "COL"
        }
    },
    "installments": {
        "type": "issuer-financed",
        "quantity": 12
    }
}
CampoDescripción
installments.quantityNúmero de cuotas. Debe ser un valor soportado por el emisor
installments.typeTipo de financiamiento: issuer-financed (banco emisor financia), merchant-financed (comercio financia), acquirer-financed (adquirente financia), average-payment (pago promedio)

Nota: el campo type es recomendado. Si no se especifica, el comportamiento depende de la configuración del adquirente. Además, la cantidad de cuotas debe ser un valor válido según la red y el emisor (valores comunes: 2, 3, 6, 12, 18, 24, 36).

¿Te resultó útil?

6. Pago con instrumento (tokenizado)

Si previamente se almacenó un instrumento en la bóveda de Akua, basta enviar su id sin necesidad de los datos de tarjeta.

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "purchase",
    "initiator": "customer",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": {
        "value": 30000,
        "currency": "COP"
    },
    "instrument": {
        "id": "ins-xxxxxxxxxx"
    },
    "customer_data": {
        "billing_address": {
            "street": "Calle 26",
            "number": "45A-60",
            "city": "Bogotá",
            "state": "Cundinamarca",
            "zip_code": "110911",
            "country": "COL"
        }
    }
}

Al usar instrument.id, no se requieren instrument.type ni instrument.card. La plataforma recupera los datos del instrumento desde la bóveda.

¿Te resultó útil?

7. Pago con Network Token

Para pagos con billeteras digitales (Apple Pay, Google Pay, etc.), se usa instrument.type: "NETWORK_TOKEN" con los datos del token de red.

{
    "intent": "authorization",
    "entry_mode": "not-present",
    "order_type": "purchase",
    "initiator": "customer",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "merchant_id": "mer-xxxxxxxxxx",
    "amount": {
        "value": 30000,
        "currency": "COP"
    },
    "instrument": {
        "type": "NETWORK_TOKEN",
        "network_token": {
            "token": "51861700xxxx1108",
            "cryptogram": "Qwertyuio09876543",
            "provider": "apple-pay",
            "device_type": "phone",
            "url": "some.merchant.url"
        }
    },
    "customer_data": {
        "billing_address": {
            "street": "Calle 26",
            "number": "45A-60",
            "city": "Bogotá",
            "state": "Cundinamarca",
            "zip_code": "110911",
            "country": "COL"
        }
    }
}
CampoDescripción
network_token.tokenToken de red emitido por la marca (reemplaza al PAN)
network_token.cryptogramCriptograma de validación del token
network_token.providerProveedor de la billetera (apple-pay, google-pay, samsung-pay, remote-commerce)
network_token.device_typeTipo de dispositivo (phone, computer)
network_token.urlURL del comercio asociada al token

¿Te resultó útil?

Merchant Advice Codes (MAC)

Qué son

Los Merchant Advice Codes — o "MAC", también llamados "advice codes" o "códigos de aviso al comercio" — son un mecanismo definido por las redes de tarjetas (Mastercard, Visa, etc.) para que el banco emisor le comunique al comercio por qué rechazó una transacción y qué hacer con ese rechazo.

A diferencia del response_code de la red (que es un código duro: "00 aprobada", "05 no honorar", "51 fondos insuficientes"), el MAC va más allá: te dice si tiene sentido reintentar la transacción, si tenés que actualizar primero los datos de la tarjeta, si necesitás autenticación adicional, o si el rechazo es definitivo y no hay que volver a intentarlo. Sin esta información, un comercio puede reintentar una transacción rechazada miles de veces, lo cual aumenta sus tasas de fraude/disputas con la red, le cuesta dinero por cada reintento y puede llevar a sanciones de la marca.

En la respuesta de Akua, el MAC aparece dentro de transaction.network_data y solo cuando el rechazo viene acompañado de un advice code por parte del emisor. No todos los rechazos traen MAC: algunos errores técnicos (timeouts de red, fallas de Akua) responden sin merchant advice porque la transacción ni siquiera llegó al emisor.


Tres campos, uno solo importa para automatizar

Akua expone tres campos relacionados al MAC:

"network_data": {
  "merchant_advice_code": "41",
  "merchant_advice_description": "New account information available",
  "merchant_advice_action": "DO_NOT_RETRY"
}
  • merchant_advice_code: el código numérico de 2 caracteres definido por la red (01, 02, 03, 04, 21, 24, 40, 41, 42, 43...). Es el dato crudo que reporta el emisor.
  • merchant_advice_description: la descripción legible del código, en inglés. Útil para mostrar al usuario interno o loguear.
  • merchant_advice_action: la acción que Akua te recomienda tomar, derivada del código. Esto es lo que tu integración debería usar para decidir el flujo automáticamente.

Solo merchant_advice_action es enum cerrado — los otros dos son strings libres que pasan tal cual los entrega la red. Eso significa que si tu lógica depende del código exacto, tenés que estar preparado para valores nuevos que la red puede agregar sin previo aviso. Si en cambio te basás en la action, tu código sigue funcionando aunque aparezcan códigos nuevos.


Las cuatro acciones posibles

merchant_advice_action es un enum con cuatro valores. Cada uno te dice exactamente qué hacer:

RETRY

El emisor rechazó la transacción por una causa transitoria (saturación temporal, problema de comunicación, etc.). Reintentar más tarde tiene buenas chances de aprobar.

Recomendación de uso: aplicar un backoff (por ejemplo esperar 10–30 minutos antes del siguiente intento) y reintentar máximo 1 o 2 veces con los mismos datos. Sin backoff, la red puede penalizarte por reintento agresivo.

UPDATE_AND_RETRY

El instrumento de pago tiene un problema que el cliente debe resolver antes de que la transacción pueda aprobarse. Típicamente es: tarjeta vencida, número incorrecto, cuenta cambiada de banco, o que el emisor ya emitió una tarjeta nueva con otros datos.

Recomendación de uso: pedirle al cliente que actualice los datos de la tarjeta (o que use otra). No reintentar con los mismos datos — el emisor te va a seguir rechazando. Si tenés Account Updater habilitado con la red, este es el momento de invocarlo antes de reintentar.

AUTHENTICATE_AND_RETRY

El emisor rechazó la autorización porque el riesgo del fraude le pareció alto, pero te está sugiriendo que si la próxima vez la mandás con autenticación 3D Secure, probablemente la apruebe.

Recomendación de uso: redirigir al cliente al flujo 3DS (típicamente "Smart 3DS" o el flujo de autenticación que tenga el comercio configurado), obtener el CAVV/cryptogram y reintentar la transacción incluyendo los datos de autenticación. Sin la autenticación, el emisor va a volver a rechazar.

DO_NOT_RETRY

El rechazo es definitivo. La cuenta está cerrada, la tarjeta cancelada, hubo fraude confirmado, o el cliente pidió no aceptar más cobros del comercio. Reintentar sin importar qué hagas va a fallar y, peor, te puede generar penalizaciones.

Recomendación de uso: marcar la transacción como permanentemente rechazada en tu sistema, no incluir ese instrumento en reintentos automáticos, no incluir esa cuenta en cobros recurrentes futuros (esto último es especialmente importante para suscripciones — la red sanciona a comercios que siguen cobrando contra cuentas con MAC=DO_NOT_RETRY).


Tabla de códigos comunes

Esta es una referencia de los MAC más frecuentes que se ven en la red Mastercard. No es exhaustiva — la lista se actualiza con cada release de la marca y puede haber códigos específicos de Visa u otras redes que entreguen los emisores. Para el listado oficial completo de Mastercard, consultar el manual Customer Interface Specification (CIS) capítulo de Authorization Responses.

merchant_advice_codemerchant_advice_description típicamerchant_advice_action que devuelve Akua
01New account information availableUPDATE_AND_RETRY
02Try again laterRETRY
03Do not try againDO_NOT_RETRY
04Token requirements not fulfilledUPDATE_AND_RETRY
21Recurring payment cancellation serviceDO_NOT_RETRY
24Retry after 1 hourRETRY
40Consumer non-reloadable prepaid cardDO_NOT_RETRY
41Consumer single-use virtual card numberDO_NOT_RETRY
42Strong consumer authentication requiredAUTHENTICATE_AND_RETRY
43Trusted Merchant exemption used previouslyAUTHENTICATE_AND_RETRY
79Lifecycle(varía por contexto)
82Merchant suspect fraudDO_NOT_RETRY
83Recurring payment cancelledDO_NOT_RETRY

Cuando Akua mapea el código a la action, prima el merchant_advice_action que devolvemos sobre cualquier interpretación que hagas del código numérico — porque ese mapeo lo mantiene actualizado el equipo a medida que cambian las reglas de las redes.


Combinación con response_code

El MAC siempre va acompañado de un response_code de la red. La combinación da más contexto: el response_code te dice por qué fue rechazada (la causa nominal), el MAC te dice qué hacer. Algunos ejemplos:

response_codeSignificadoMAC frecuenteLectura combinada
05Do not honor03 (DO_NOT_RETRY)El emisor rechazó por riesgo y pide no reintentar.
05Do not honor02 (RETRY)Mismo rechazo nominal pero el emisor cree que puede aprobar más tarde.
51Insufficient funds02 (RETRY)El cliente puede tener fondos en otro momento.
54Expired card01 (UPDATE_AND_RETRY)Hay info de cuenta nueva disponible — invocar Account Updater.
62Restricted card03 (DO_NOT_RETRY)Rechazo definitivo, no reintentar.
65Soft decline (fraud risk)42 (AUTHENTICATE_AND_RETRY)Mandar por 3DS y reintentar.

Notar que el mismo response_code puede venir con MACs distintos según la decisión del emisor en cada caso particular. Por eso conviene siempre mirar el MAC, no solo el response code.


Casos donde NO viene MAC

El campo merchant_advice_code puede estar ausente en varios escenarios:

  • Transacciones aprobadas: si transaction.status es APPROVED, no hay MAC porque no hay rechazo que aconsejar.
  • Errores de Akua antes de la red: validaciones que fallan en el middleware (formato inválido, instrumento bloqueado en Akua, cliente sin habilitar el método de pago) responden sin MAC porque la transacción nunca llegó al emisor. En estos casos decision_source suele ser INTERNAL.
  • Errores de sistema en la red: timeouts o fallas de comunicación responden con response_code 96 (System error) y típicamente sin MAC, porque el emisor nunca evaluó la transacción. La acción razonable acá es RETRY.
  • Emisores antiguos: algunos emisores no implementan MAC todavía y rechazan solo con response_code. En esos casos el integrador tiene que tomar la decisión basándose solo en el código de respuesta.

Tu integración debería tratar la ausencia del campo como "no hay info adicional, decidí con el response_code solo".


Cómo usarlo en tu integración

Pseudocódigo recomendado:

respuesta = autorizar_pago(...)

if respuesta.transaction.status == "APPROVED":
    confirmar_compra()

elif respuesta.transaction.status == "REJECTED":
    advice = respuesta.transaction.network_data.merchant_advice_action

    if advice == "RETRY":
        encolar_reintento(esperar_minutos=15, max_intentos=2)
    elif advice == "UPDATE_AND_RETRY":
        invocar_account_updater_o_pedir_nueva_tarjeta_al_cliente()
    elif advice == "AUTHENTICATE_AND_RETRY":
        redirigir_a_3ds()
    elif advice == "DO_NOT_RETRY":
        marcar_instrumento_como_no_reusable()
        notificar_al_cliente("la tarjeta fue rechazada, contactá a tu banco")
    else:
        # No vino advice — decidir basado en response_code o defaultear a no-reintentar
        loggear_para_revision_manual()

Tres reglas duras que conviene respetar siempre:

  1. DO_NOT_RETRY significa no reintentar nunca, ni manualmente ni con Account Updater. La red lo audita y los reintentos contra cuentas marcadas así pueden generar fees o sanciones.
  2. RETRY no significa "reintentá inmediatamente". Esperá al menos 10 minutos. Reintentos sin backoff disparan alertas de fraude en la red.
  3. AUTHENTICATE_AND_RETRY requiere 3DS real, no se reemplaza con un retry simple. El emisor está pidiendo el step-up de autenticación.

¿Te resultó útil?

Transacciones de Tránsito (MTT) — Resumen

Las transacciones de tránsito son un tipo especial de pago sin contacto (contactless) diseñado para sistemas de transporte público: buses, metro, trenes, tranvías, peajes y más. Se diferencian de las transacciones retail convencionales en tres aspectos fundamentales:

  • La tarifa puede no ser conocida al momento del tap. En muchos sistemas de transporte, el monto final depende de la distancia recorrida o del tiempo de uso, por lo que se calcula después del viaje.
  • La autorización puede ser diferida. El pasajero debe poder abordar sin esperar una respuesta online del emisor.
  • No se requiere verificación del titular (CVM). No se pide PIN ni firma — el pasajero simplemente acerca su tarjeta al lector.

Todas las transacciones de tránsito cursadas por POS usan el endpoint de tarjeta presente (/pos/...) y requieren entry_mode: "contactless". El comercio debe estar registrado con un MCC de tránsito: 4111 (transporte local/suburbano), 4112 (trenes de pasajeros) o 4131 (líneas de bus).

Importante — todo lo /pos/ es tarjeta presente. Cada autorización por POS se envía exactamente como una venta card-present: con terminal_id y un instrument que incluye los datos de la lectura física de la tarjeta (track2_data y, para chip/contactless, los emv_data.tags). No se envía el PAN en claro vía instrument.card.number como en e-commerce. Si falta el track2_data, el endpoint responde 500 — "Failed to process track2 data". La única excepción es la Recuperación de deuda, que es card-not-present (e-commerce) y usa instrument.id.

Headers requeridos en todas las llamadas. Cada request (autorización, ajuste, captura, etc.) debe enviar: Authorization: Bearer {access_token}, Content-Type: application/json y un Idempotency-Key único por request (UUIDv4 recomendado). Probar sin estos headers puede romper la llamada. El Idempotency-Key garantiza at-most-once: reintentar con la misma clave y mismo body devuelve la respuesta original; con body distinto devuelve 409 CONFLICT.


Modelos de transacción

Dependiendo de si la tarifa es conocida o no al momento del tap, y de la situación particular, existen distintos modelos:

#ModeloDescripciónTarifa conocida al tap
1Retail-LikeUna autorización por viaje, tarifa fija
2Agrupación (PAYG)Ciclo de pre-autorización + ajuste/captura final con monto acumuladoNo
3Recuperación de deudaCobro de tarifa pendiente cuando la autorización original fue denegadaN/A
4ATC Counter UpdateSincronización del contador de transacciones de la tarjeta (solo Mastercard)N/A

Mapa de campos por caso de uso

Estas tablas muestran de un vistazo qué endpoint y qué campos se usan en cada caso de uso. Se leen de izquierda a derecha como un flujo progresivo: del caso más simple (Retail-Like) al más especial (Recuperación de deuda).

Mastercard

CampoRetail-LikePAYG — Fase 1 (intradía)PAYG — Fase 2: AjustePAYG — Fase 2: CapturaRecuperación de deuda
Endpoint/pos/payments/authorizations/pos/payments/authorizations/pos/payments/{id}/adjust/pos/payments/{id}/captures/payments/authorizations
intentauthorizationpre-authorizationauthorization
order_typepurchasepurchaseresubmission
entry_modecontactlesscontactlessnot-present
instrumenttrack2_data + emv_datatrack2_data + emv_datainstrument.id
amountMonto de 1 tarifaMonto nominal (1-3 viajes)Monto de la deuda
valueMonto total del ciclo
amount.valueMonto total del ciclo
initiatormerchant

Visa

CampoRetail-LikePAYG — Fase 1 (intradía)PAYG — Fase 2: AutorizaciónPAYG — Fase 2: CapturaRecuperación de deuda
Endpoint/pos/payments/authorizations/pos/payments/authorizations/pos/payments/authorizations/pos/payments/{id}/captures/payments/authorizations
intentauthorizationaccount-statusauthorizationauthorization
order_typepurchasepurchasedeferredresubmission
entry_modecontactlesscontactlesscontactlessnot-present
instrumenttrack2_data + emv_datatrack2_data + emv_datainstrument.idinstrument.id
amountMonto de 1 tarifaCero (0)Monto total del cicloMonto de la deuda
value
amount.valueMonto total del ciclo
initiatormerchantmerchant

Fase 2 — Ajuste vs. Captura: para finalizar el período PAYG hay dos opciones. El ajuste (/adjust) genera una nueva autorización por la diferencia usando amount.value (string); puede fallar si no hay fondos, pero permite montos sin límite. La captura (/captures) confirma el cobro sin nueva autorización usando amount.value (número); no falla, pero solo permite hasta un 20% por encima de la pre-autorización original. Ver la guía de Agrupación PAYG para el detalle completo.


Diferencias clave entre redes

Mastercard y Visa siguen el mismo concepto general pero difieren en la implementación:

  • En Agrupación PAYG, Mastercard usa una pre-autorización con monto nominal en la Fase 1 y un adjust en la Fase 2. Visa hace un account-status (monto cero) en la Fase 1 y una autorización diferida (deferred) como MIT en la Fase 2.
  • El ATC Counter Update es exclusivo de Mastercard. Visa no define un mecanismo equivalente, aunque los emisores Visa deben tolerar contadores fuera de secuencia sin declinar.
  • En Recuperación de deuda, ambas redes usan el mismo enfoque: una autorización con order_type: "resubmission" vía el endpoint de e-commerce (no POS), ya que la tarjeta no está presente en ese momento.

Guías detalladas

Para el paso a paso de cada modelo con ejemplos de request completos, consultar las guías específicas:

  • Retail-Like — Pago con tarifa conocida al momento del tap
  • Agrupación PAYG — Ciclo Pay-As-You-Go para tarifas desconocidas
  • Recuperación de Deuda — Cobro de tarifas pendientes
  • ATC Counter Update — Sincronización del contador de transacciones (Mastercard)

¿Te resultó útil?

Retail-Like (Tarifa Conocida)

Modelo para cuando la tarifa es conocida al momento del tap. Se procesa una autorización por viaje, igual que una compra retail convencional pero con las particularidades de tránsito: contactless, sin CVM, y con MCC de transporte.

Endpoint: POST /pos/payments/authorizations

Recordatorio card-present: al ser un endpoint /pos/, el request va como una venta con tarjeta presente. Es obligatorio enviar terminal_id, amount, intent y un instrument con track2_data (y los emv_data.tags de la lectura contactless). No se envía el PAN en claro.


Cuándo usar

Sistemas de transporte donde el pasajero paga una tarifa fija por viaje. Ejemplos: bus urbano con tarifa plana, metro con tarifa única por estación de origen, peaje con tarifa fija.


Flujo

El flujo es simple — un solo paso:

  1. El pasajero acerca su tarjeta al lector contactless
  2. La terminal arma el track2_data + emv_data y el sistema envía una autorización por el monto exacto de la tarifa
  3. Se recibe la respuesta (aprobada o denegada)
  4. Si se aprueba, el pasajero viaja. Si se deniega, la tarjeta entra en la deny list del operador

Mastercard

POST /pos/payments/authorizations
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: {uuid-v4-único-por-request}

{
    "id": "ride-7f3a9c01",
    "intent": "authorization",
    "order_type": "purchase",
    "entry_mode": "contactless",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "terminal_id": "trm-d49abonq5g3h7p5qnpbb",
    "amount": {
        "value": 2950,
        "currency": "COP"
    },
    "instrument": {
        "emv_data": {
            "sequence_number": 0,
            "tags": [
                { "tag": "82",   "length": "2",  "value": "1980" },
                { "tag": "84",   "length": "7",  "value": "a0000000041010" },
                { "tag": "95",   "length": "5",  "value": "0000048001" },
                { "tag": "9A",   "length": "3",  "value": "260626" },
                { "tag": "9C",   "length": "1",  "value": "00" },
                { "tag": "5F2A", "length": "2",  "value": "0170" },
                { "tag": "9F02", "length": "6",  "value": "000000002950" },
                { "tag": "9F03", "length": "6",  "value": "000000000000" },
                { "tag": "9F1A", "length": "2",  "value": "0170" },
                { "tag": "9F10", "length": "18", "value": "0210a040032400000000ffffffffffffffff" },
                { "tag": "9F26", "length": "8",  "value": "5e746608800d2b55" },
                { "tag": "9F27", "length": "1",  "value": "80" },
                { "tag": "9F33", "length": "3",  "value": "004088" },
                { "tag": "9F34", "length": "3",  "value": "1f0302" },
                { "tag": "9F36", "length": "2",  "value": "01e5" },
                { "tag": "9F37", "length": "4",  "value": "20c1bd34" }
            ]
        },
        "track2_data": {
            "data": "5383040000000002D30122011000000000000",
            "encrypted": false
        }
    }
}

Notas sobre Mastercard:

  • intent: "authorization" con capture.mode: "AUTOMATIC" — autorización + captura en tiempo real (venta directa).
  • instrument.emv_data.tags lleva los tags de la lectura contactless (AID Mastercard a0000000041010 en el tag 84). El 9F34 (CVM Results) refleja "No CVM" porque tránsito no pide PIN ni firma.
  • track2_data.encrypted indica si la pista viaja cifrada. Si va cifrada, se acompaña del ksn de la llave; si el cliente la envía en claro (false), Akua la ofusca internamente.
  • No se envía CVV ni pin_block — las terminales de tránsito no los solicitan.
  • El MCC del comercio (resuelto por terminal_id) debe ser 4111, 4112 o 4131.

Visa

El request tiene la misma estructura que Mastercard; Akua resuelve la red por el BIN de la tarjeta. Solo cambian los datos propios de la tarjeta y el AID (tag 84 = a0000000031010 para Visa).

POST /pos/payments/authorizations
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: {uuid-v4-único-por-request}

{
    "id": "ride-7f3a9c02",
    "intent": "authorization",
    "order_type": "purchase",
    "entry_mode": "contactless",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "terminal_id": "trm-d49abonq5g3h7p5qnpbb",
    "amount": {
        "value": 2950,
        "currency": "COP"
    },
    "instrument": {
        "emv_data": {
            "sequence_number": 0,
            "tags": [
                { "tag": "82",   "length": "2",  "value": "1980" },
                { "tag": "84",   "length": "7",  "value": "a0000000031010" },
                { "tag": "95",   "length": "5",  "value": "0000048001" },
                { "tag": "9A",   "length": "3",  "value": "260626" },
                { "tag": "9C",   "length": "1",  "value": "00" },
                { "tag": "5F2A", "length": "2",  "value": "0170" },
                { "tag": "9F02", "length": "6",  "value": "000000002950" },
                { "tag": "9F03", "length": "6",  "value": "000000000000" },
                { "tag": "9F1A", "length": "2",  "value": "0170" },
                { "tag": "9F10", "length": "7",  "value": "06010a03a00000" },
                { "tag": "9F26", "length": "8",  "value": "a1b2c3d4e5f60718" },
                { "tag": "9F27", "length": "1",  "value": "80" },
                { "tag": "9F33", "length": "3",  "value": "e0f8c8" },
                { "tag": "9F34", "length": "3",  "value": "1f0302" },
                { "tag": "9F36", "length": "2",  "value": "00c7" },
                { "tag": "9F37", "length": "4",  "value": "8e2f1a44" }
            ]
        },
        "track2_data": {
            "data": "4761120000000148D30122011000000000000",
            "encrypted": false
        }
    }
}

Respuesta esperada

La respuesta sigue la estructura estándar de autorización POS (HTTP 201):

{
    "terminal": {
        "id": "trm-d49abonq5g3h7p5qnpbb",
        "batch_id": "2500011"
    },
    "payment_id": "pay-dggb2i4h3gkiv2a3adf7",
    "transaction": {
        "id": "trx-d54i8900icdm50jdldvj",
        "type": "AUTHORIZATION",
        "amount": "2950",
        "status": "APPROVED",
        "issuer_data": {
            "emv_tags": [
                { "tag": "91", "length": "0A", "value": "625A65E467ABB0470012" }
            ]
        },
        "network_data": {
            "approval_code": "772886",
            "response_code": "00",
            "response_code_description": "Approved or completed successfully",
            "financial_network_code": "MCC",
            "system_trace_audit_number": "621157"
        },
        "status_detail": "SUCCESS"
    },
    "instrument_id": "ins-hj4i86u64q0ma1v5phh6",
    "response_code": "00",
    "response_code_description": "Approved or completed successfully"
}

El issuer_data.emv_tags devuelve los tags de respuesta del emisor (p. ej. 91 — Issuer Authentication Data) que la terminal debe entregar al chip para completar la transacción.

Si la transacción es denegada, el operador de transporte debe agregar la tarjeta a su deny list local para evitar que se use en viajes posteriores hasta que se resuelva la deuda (ver guía de Recuperación de Deuda).

¿Te resultó útil?

Agrupación PAYG (Pay-As-You-Go)

Modelo para cuando la tarifa no es conocida al momento del tap. El monto final se calcula después, una vez que el pasajero finaliza su viaje o su período de uso. El operador agrupa los viajes del período y envía una autorización final con el monto total acumulado.

Este modelo tiene dos fases: una al inicio del viaje (intradía) y otra al finalizar el período de agrupación.

Recordatorio card-present: la Fase 1 (primer tap) es tarjeta presente, por lo que el instrument lleva track2_data + emv_data y terminal_id. La Fase 2 de Visa (autorización diferida) y los ajustes/capturas operan sobre el pago ya creado, así que usan instrument.id o el payment_id, sin volver a leer la tarjeta.


Cuándo usar

Sistemas de transporte donde la tarifa depende de la distancia, el tiempo o la cantidad de viajes. Ejemplos: metro con tarifas por zonas, tren con tarifa por distancia, sistemas con tope diario (fare capping).


Flujo general

Fase 1 — Primer tap (intradía)
    ↓
El pasajero viaja durante el día (puede hacer múltiples taps)
    ↓
Fase 2 — Finalizar período (el back-office calcula el total)
    ↓
Se cobra el monto acumulado real

El operador asume el First Ride Risk: el pasajero viaja antes de que se confirme si la tarjeta es válida y tiene fondos. Si la autorización inicial es denegada, la tarjeta va a la deny list y la deuda se intenta recuperar posteriormente.


Fase 1 — Intradía (primer tap del período)

Mastercard — Pre-autorización

Se envía una pre-autorización con un monto nominal (equivalente a 1-3 viajes típicos). Esto reserva fondos iniciales y valida la tarjeta. Es card-present: lleva track2_data + emv_data.

POST /pos/payments/authorizations
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: {uuid-v4-único-por-request}

{
    "id": "payg-mc-7f3a9c10",
    "intent": "pre-authorization",
    "order_type": "purchase",
    "entry_mode": "contactless",
    "capture": {
        "mode": "MANUAL"
    },
    "terminal_id": "trm-d49abonq5g3h7p5qnpbb",
    "amount": {
        "value": 8850,
        "currency": "COP"
    },
    "instrument": {
        "emv_data": {
            "sequence_number": 0,
            "tags": [
                { "tag": "82",   "length": "2",  "value": "1980" },
                { "tag": "84",   "length": "7",  "value": "a0000000041010" },
                { "tag": "95",   "length": "5",  "value": "0000048001" },
                { "tag": "9A",   "length": "3",  "value": "260626" },
                { "tag": "9C",   "length": "1",  "value": "00" },
                { "tag": "5F2A", "length": "2",  "value": "0170" },
                { "tag": "9F02", "length": "6",  "value": "000000008850" },
                { "tag": "9F03", "length": "6",  "value": "000000000000" },
                { "tag": "9F1A", "length": "2",  "value": "0170" },
                { "tag": "9F10", "length": "18", "value": "0210a040032400000000ffffffffffffffff" },
                { "tag": "9F26", "length": "8",  "value": "5e746608800d2b55" },
                { "tag": "9F27", "length": "1",  "value": "80" },
                { "tag": "9F33", "length": "3",  "value": "004088" },
                { "tag": "9F34", "length": "3",  "value": "1f0302" },
                { "tag": "9F36", "length": "2",  "value": "01e5" },
                { "tag": "9F37", "length": "4",  "value": "20c1bd34" }
            ]
        },
        "track2_data": {
            "data": "5383040000000002D30122011000000000000",
            "encrypted": false
        }
    }
}

El monto de la pre-autorización es un estimado nominal — no es el cobro final. Típicamente se usa el valor de 1 a 3 viajes como referencia. El capture.mode: "MANUAL" deja el pago pre-autorizado para finalizarlo en la Fase 2.

Importante: guardar el payment_id de la respuesta. Se necesita para la Fase 2 (adjust o capture).

Visa — Account Status (verificación de monto cero)

Visa usa un enfoque distinto: en lugar de pre-autorizar un monto, se envía una verificación de cuenta con monto cero. Esto valida que la tarjeta exista y esté activa sin reservar fondos. Sigue siendo card-present (la tarjeta está físicamente en el lector), por lo que también lleva track2_data + emv_data.

POST /pos/payments/authorizations
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: {uuid-v4-único-por-request}

{
    "id": "payg-visa-7f3a9c11",
    "intent": "account-status",
    "order_type": "purchase",
    "entry_mode": "contactless",
    "terminal_id": "trm-d49abonq5g3h7p5qnpbb",
    "amount": {
        "value": 0,
        "currency": "COP"
    },
    "instrument": {
        "emv_data": {
            "sequence_number": 0,
            "tags": [
                { "tag": "82",   "length": "2",  "value": "1980" },
                { "tag": "84",   "length": "7",  "value": "a0000000031010" },
                { "tag": "95",   "length": "5",  "value": "0000008000" },
                { "tag": "9A",   "length": "3",  "value": "260626" },
                { "tag": "9C",   "length": "1",  "value": "00" },
                { "tag": "5F2A", "length": "2",  "value": "0170" },
                { "tag": "9F02", "length": "6",  "value": "000000000000" },
                { "tag": "9F03", "length": "6",  "value": "000000000000" },
                { "tag": "9F1A", "length": "2",  "value": "0170" },
                { "tag": "9F10", "length": "7",  "value": "06010a03a00000" },
                { "tag": "9F26", "length": "8",  "value": "a1b2c3d4e5f60718" },
                { "tag": "9F27", "length": "1",  "value": "80" },
                { "tag": "9F33", "length": "3",  "value": "e0f8c8" },
                { "tag": "9F34", "length": "3",  "value": "1f0302" },
                { "tag": "9F36", "length": "2",  "value": "00c7" },
                { "tag": "9F37", "length": "4",  "value": "8e2f1a44" }
            ]
        },
        "track2_data": {
            "data": "4761120000000148D30122011000000000000",
            "encrypted": false
        }
    }
}

El amount.value es 0: es una verificación de estatus de cuenta, no un cobro. No se envía capture (no hay fondos que capturar). Guardar el instrument_id de la respuesta — se usa en la Fase 2 para la autorización diferida.


Fase 2 — Finalizar período (cobro del monto acumulado)

Una vez que el back-office del operador calcula el monto total del período de viaje, hay dos opciones para cobrar el monto real: ajuste (adjust) o captura (capture). Cada una tiene ventajas y limitaciones distintas.

Opción A: Ajuste (/pos/payments/{id}/adjust)

El ajuste genera una nueva autorización por la diferencia entre el monto pre-autorizado y el monto real. Es la opción más flexible porque permite cobrar cualquier monto, sin importar cuánto exceda la pre-autorización original. Sin embargo, al ser una nueva autorización, puede ser denegada si el tarjetahabiente no tiene fondos suficientes.

Mastercard — Adjust

Se ajusta la pre-autorización original al monto real acumulado, referenciando el payment_id de la Fase 1. El cuerpo usa amount.value (string) y currency.

POST /pos/payments/{id}/adjust
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: {uuid-v4-único-por-request}

{
    "amount": {
        "value": "17700",
        "currency": "COP"
    }
}

Donde {id} es el payment_id obtenido en la Fase 1. El value es el monto total real del ciclo de viajes y va como string. Este valor puede ser mayor o menor que la pre-autorización original — en tránsito está permitido que el monto final supere la pre-autorización.

Visa — Autorización diferida (deferred)

Visa usa una nueva autorización completa con order_type: "deferred" e initiator: "merchant", ya que el cobro se hace sin presencia del pasajero. Por eso usa instrument.id (el instrumento almacenado en la Fase 1) y no lleva track2_data ni emv_data.

POST /pos/payments/authorizations
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: {uuid-v4-único-por-request}

{
    "id": "payg-visa-final-7f3a9c12",
    "intent": "authorization",
    "order_type": "deferred",
    "entry_mode": "contactless",
    "initiator": "merchant",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "terminal_id": "trm-d49abonq5g3h7p5qnpbb",
    "amount": {
        "value": 17700,
        "currency": "COP"
    },
    "instrument": {
        "id": "ins-cuq7trf79diafopu1rog"
    }
}

Se usa instrument.id (el instrumento devuelto por el account-status) porque la tarjeta no está presente. El initiator: "merchant" indica que es una transacción MIT vinculada al account-status original.


Opción B: Captura (/pos/payments/{id}/captures)

La captura confirma el cobro directamente sobre la pre-autorización original, sin generar una nueva autorización. Esto significa que no puede ser denegada — el cobro se ejecuta siempre. La limitación es que el monto de la captura no puede exceder el 120% del monto pre-autorizado original (es decir, hasta un 20% por encima).

Mastercard y Visa — Capture

El request es el mismo para ambas redes. A diferencia del ajuste, la captura usa amount.value (número) y currency:

POST /pos/payments/{id}/captures
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: {uuid-v4-único-por-request}

{
    "amount": {
        "value": 10200,
        "currency": "COP"
    }
}

Donde {id} es el payment_id obtenido en la Fase 1. El amount.value es el monto total real del ciclo. Si el monto real es igual al pre-autorizado, se puede enviar la captura sin amount (captura por el monto completo pre-autorizado).

Regla del 20%: si la pre-autorización fue por $8,850 COP, la captura permite cobrar hasta $10,620 COP (8,850 × 1.20). Si el monto real del ciclo supera ese límite, se debe usar el ajuste en lugar de la captura.


¿Cuándo usar cada opción?

CriterioAjuste (adjust)Captura (capture)
Campo de montoamount.value (string)amount.value (número)
Monto real vs. pre-autorizaciónSin límite — puede ser cualquier montoHasta 120% del monto pre-autorizado
¿Puede fallar?Sí — es una nueva autorizaciónNo — confirma el cobro sin nueva autorización
Caso de uso idealEl monto real excede significativamente la pre-autorizaciónEl monto real es cercano a la pre-autorización
Si no se hace nadaAuto-captura a los 2 días por el monto original

Recomendación: usar captura cuando el monto acumulado esté dentro del 120% de la pre-autorización original (caso más común en viajes diarios). Usar ajuste cuando el monto real exceda ese umbral (viajes atípicos, acumulaciones de varios días).


Resumen del flujo por red

FaseMastercardVisa
1 — Primer tapPre-autorización con monto nominal (card-present)Account-status con monto cero (card-present)
Endpoint Fase 1POST /pos/payments/authorizationsPOST /pos/payments/authorizations
2A — AjusteAdjust al monto real (value)Autorización diferida (deferred) con monto real
Endpoint Fase 2APOST /pos/payments/{id}/adjustPOST /pos/payments/authorizations
2B — CapturaCaptura por monto real (value, ≤120% pre-auth)Captura por monto real (value, ≤120% pre-auth)
Endpoint Fase 2BPOST /pos/payments/{id}/capturesPOST /pos/payments/{id}/captures
Plazo máximo14 días calendario desde el primer tapSegún las reglas de Visa Urban Mobility
Auto-captura2 días si no se envía ajuste ni captura2 días si no se envía ajuste ni captura

Escenario completo: ejemplo de un día de viajes

Un pasajero toma el metro a las 7:00 AM (tarifa por zona, desconocida al tap), hace dos transbordos, y termina su último viaje a las 8:30 PM. El operador agrupa los viajes del día.

7:00 AM — Primer tap (Fase 1)

  • Mastercard: pre-autorización por $8,850 COP (3 viajes nominales)
  • Visa: account-status por $0

Durante el día

  • El pasajero viaja normalmente. Los taps intermedios se registran localmente en el sistema del operador, no generan autorizaciones adicionales.

11:00 PM — Cierre del día (Fase 2)

  • El back-office calcula: 5 viajes × $2,950 = $14,750 COP (con fare capping aplicado)

Opción A — Ajuste (monto real $14,750 excede el 120% de $8,850 = $10,620):

  • Mastercard: adjust con value: "14750" sobre la pre-autorización original
  • Visa: autorización diferida por $14,750

Opción B — Captura (solo si el monto real estuviera dentro del 120%):

  • Si el monto acumulado fuera $10,200 (dentro de $10,620), se podría usar captura con value: 10200 sobre la pre-autorización original — sin riesgo de denegación

En este ejemplo, como $14,750 supera el 120% de la pre-autorización ($10,620), el operador debe usar el ajuste.

¿Te resultó útil?

Recuperación de Deuda

Proceso para cobrar tarifas pendientes cuando una autorización de tránsito fue denegada y la tarjeta está en la deny list del operador. Aplica tanto para autorizaciones denegadas en Retail-Like como en Agrupación PAYG.

Endpoint: POST /payments/authorizations (e-commerce, no POS)

Card-not-present (excepción al patrón /pos/): este es el único modelo MTT que no es card-present. La tarjeta no está en el lector al momento del cobro, por lo que se usa el endpoint de e-commerce y el instrumento se referencia con instrument.id (la credencial almacenada en la bóveda de Akua). No se envía track2_data, emv_data, CVV ni terminal_id.


Cuándo usar

Cuando un pasajero acumuló deuda de tránsito porque su tarjeta fue denegada en uno o más viajes. El operador necesita recuperar ese monto. Esto puede ocurrir por fondos insuficientes, tarjeta expirada, o cualquier otro motivo de denegación.


Flujo

  1. Una autorización de tránsito es denegada (ya sea Retail-Like o PAYG)
  2. El operador agrega la tarjeta a la deny list — el pasajero no puede volver a usar esa tarjeta en el sistema de tránsito
  3. El operador intenta la recuperación de deuda periódicamente (automático diario, o cuando el pasajero se presenta en un punto de atención)
  4. Si la recuperación es aprobada, el operador debe remover la tarjeta de la deny list para permitir su uso nuevamente

Canales de recuperación típicos: cobro automático periódico (batch diario), tap en terminal atendido, o pago del pasajero vía call center / portal web.


Diferencias clave vs. autorización de tránsito normal

La recuperación de deuda se envía por el endpoint de e-commerce (no POS), porque la tarjeta no está físicamente presente al momento del cobro. Esto cambia varios campos importantes:

CampoValor en tránsito normal (POS)Valor en recuperación de deuda (e-commerce)
Endpoint/pos/payments/authorizations/payments/authorizations
entry_modecontactlessnot-present
order_typepurchaseresubmission
initiator(no se envía)merchant
instrumenttrack2_data + emv_datainstrument.id

Mastercard

POST /payments/authorizations
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: {uuid-v4-único-por-request}

{
    "intent": "authorization",
    "order_type": "resubmission",
    "entry_mode": "not-present",
    "initiator": "merchant",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "merchant_id": "mer-csuvatde7f1jb0qgqjvg",
    "amount": {
        "value": 14750,
        "currency": "COP"
    },
    "instrument": {
        "id": "ins-cuq7trf79diafopu1rog"
    },
    "parent_transaction_data": {
        "network_data": {
            "mastercard_economic_tlid": "AABB1234CCDD5678EEFF01"
        }
    }
}

Visa

POST /payments/authorizations
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: {uuid-v4-único-por-request}

{
    "intent": "authorization",
    "order_type": "resubmission",
    "entry_mode": "not-present",
    "initiator": "merchant",
    "capture": {
        "mode": "AUTOMATIC"
    },
    "merchant_id": "mer-csuvatde7f1jb0qgqjvg",
    "amount": {
        "value": 14750,
        "currency": "COP"
    },
    "instrument": {
        "id": "ins-cuq7trf79diafopu1rog"
    },
    "parent_transaction_data": {
        "network_data": {
            "visa_initial_transaction_identifier": "012345678901234"
        }
    }
}

Notas importantes

Sobre la deny list: al aprobarse la recuperación de deuda, el operador debe remover la tarjeta de la deny list lo antes posible para que el pasajero pueda volver a usar el servicio de transporte.

Sobre resubmission: este order_type indica a la red que es un reintento de una transacción previamente denegada. Solo es válido como MIT (initiator: "merchant"). El parent_transaction_data vincula este cobro con la transacción original que generó la deuda.

Sobre el instrumento: se usa instrument.id (el instrumento almacenado en la bóveda de Akua) ya que la tarjeta no está presente al momento del cobro. No se envía CVV ni datos crudos de la tarjeta (track2_data / emv_data).

¿Te resultó útil?

ATC Counter Update (soon...)

Mecanismo para sincronizar el Application Transaction Counter (ATC) de una tarjeta con el emisor. Aplica solo para Mastercard — Visa no define un mecanismo equivalente.

Endpoint: POST /pos/payments/authorizations

Recordatorio card-present: aunque es una transacción de monto cero, va por el endpoint /pos/ como tarjeta presente: lleva terminal_id e instrument con track2_data + emv_data. El tag clave es el 9F36 (Application Transaction Counter), que es justamente el contador que se quiere sincronizar.


Cuándo usar

Cuando una tarjeta se usa múltiples veces en el sistema de tránsito sin pasar por autorización online (por ejemplo, viajes offline aprobados por la terminal), el contador ATC de la tarjeta avanza localmente pero el emisor no lo ve. Esto puede causar que el emisor decline transacciones futuras por "secuencia fuera de orden".

El ATC Counter Update envía una transacción de monto cero para informar al emisor del valor actual del contador, evitando denegaciones innecesarias.


Mastercard

POST /pos/payments/authorizations
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: {uuid-v4-único-por-request}

{
    "id": "atc-sync-7f3a9c20",
    "intent": "atc-update",
    "entry_mode": "contactless",
    "terminal_id": "trm-d49abonq5g3h7p5qnpbb",
    "amount": {
        "value": 0,
        "currency": "COP"
    },
    "instrument": {
        "emv_data": {
            "sequence_number": 0,
            "tags": [
                { "tag": "82",   "length": "2",  "value": "1980" },
                { "tag": "84",   "length": "7",  "value": "a0000000041010" },
                { "tag": "95",   "length": "5",  "value": "0000008000" },
                { "tag": "9A",   "length": "3",  "value": "260626" },
                { "tag": "9C",   "length": "1",  "value": "00" },
                { "tag": "5F2A", "length": "2",  "value": "0170" },
                { "tag": "9F02", "length": "6",  "value": "000000000000" },
                { "tag": "9F1A", "length": "2",  "value": "0170" },
                { "tag": "9F10", "length": "18", "value": "0210a040032400000000ffffffffffffffff" },
                { "tag": "9F26", "length": "8",  "value": "5e746608800d2b55" },
                { "tag": "9F27", "length": "1",  "value": "80" },
                { "tag": "9F36", "length": "2",  "value": "01f4" },
                { "tag": "9F37", "length": "4",  "value": "20c1bd34" }
            ]
        },
        "track2_data": {
            "data": "5383040000000002D30122011000000000000",
            "encrypted": false
        }
    }
}

Es una transacción de monto cero (amount.value: 0). El intent: "atc-update" le indica a Akua que el propósito es exclusivamente sincronizar el contador, no realizar un cobro. El valor actual del contador viaja en el tag 9F36 de los emv_data.


Visa

Visa no define un mensaje ATC Update explícito en su framework de Urban Mobility. Sin embargo, los emisores Visa deben estar preparados para recibir contadores ATC fuera de secuencia y no declinar transacciones únicamente por ese motivo.

¿Te resultó útil?

3DS

9

Browser Flow — 3D Secure 2.0

3DS2 es un protocolo de autenticación que agrega una capa de seguridad a las transacciones con tarjeta en línea. Permite al banco emisor verificar la identidad del titular durante el proceso de compra, reduciendo el fraude y protegiendo tanto al comerciante como al consumidor.

El flujo Browser es el proceso que se ejecuta cuando el cliente realiza una compra desde un navegador web.


¿Qué permite el flujo 3DS Browser?

CapacidadDescripción
Verificación de soporteConfirma si la tarjeta soporta 3DS y qué versión
Device fingerprintingRecolecta información del dispositivo del usuario
Autenticación frictionlessAutentica sin interacción del usuario cuando es posible
Autenticación con challengeSolicita OTP, biometría u otro factor cuando es necesario

Pasos del flujo

PasoAcción
1. CheckoutEl usuario completa el formulario de pago en el sitio
2. Version RequestSe verifica si la tarjeta soporta 3DS y se obtiene la versión disponible
3. Method Request (opcional)Se recolecta información del dispositivo (device fingerprinting)
4. Authenticate RequestSe solicita autenticación 3DS al emisor
5. Resultado de autenticaciónEl emisor responde con uno de tres resultados (ver tabla)
6. Challenge RequestSi se requiere challenge, se presenta al usuario (OTP, biometría, etc.)
7. Result RequestSe obtiene el resultado final tras el challenge
8. Autorizar pagoSe usa el authentication_value (CAVV) para autorizar la transacción

Resultados de autenticación

ResultadoCódigoAcción a seguir
SuccessYAutenticación frictionless exitosa → proceder a autorización
ChallengeCSe requiere interacción del usuario → continuar con Challenge Request
FailedN / U / RAutenticación fallida o rechazada → no autorizar

¿Te resultó útil?

Recolección de Información del Navegador

Antes de iniciar el flujo 3DS, es necesario recolectar datos del navegador del usuario. Esta información se envía en el campo browser_data del Authenticate Request.


Función GetBrowserData()

La librería JavaScript de Akua recolecta estos datos automáticamente:

function GetBrowserData() {
    const browserData = {}
    if (window) {
        if (window.screen) {
            browserData.color_depth = String(window.screen.colorDepth);
            browserData.screen_height = String(window.screen.height);
            browserData.screen_width = String(window.screen.width);
        }
        if (window.navigator) {
            browserData.user_agent = window.navigator.userAgent;
            browserData.java_enabled = window.navigator.javaEnabled();
            browserData.language = window.navigator.language ||
                                   window.navigator.browserLanguage ||
                                   window.navigator.userLanguage;
        }
    }
    browserData.tz = String((new Date()).getTimezoneOffset());
    browserData.javascript_enabled = true;
    return browserData;
}

Campos de browser_data

Requeridos cuando device_channel = "02" (Browser).

CampoTipoRequeridoDescripciónEjemplo
accept_headerstringHeader Accept HTTP"text/html,application/xml"
javascript_enabledbooleanSi JavaScript está habilitadotrue
languagestringIdioma del navegador"es-UY"
user_agentstringUser agent del navegador"Mozilla/5.0..."
ip_addressstringIP del cliente — no obligatorio pero recomendado para la evaluación de riesgo"192.168.1.100"
color_depthstringProfundidad de color de pantalla"24"
screen_heightstringAlto de pantalla en píxeles"1080"
screen_widthstringAncho de pantalla en píxeles"1920"
java_enabledbooleanSi Java está habilitadofalse
tznumberZona horaria (offset en minutos)180

Ejemplo de objeto browserData

{
  "accept_header": "text/html,application/xhtml+xml,application/xml",
  "javascript_enabled": true,
  "language": "es-UY",
  "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
  "ip_address": "192.168.1.100",
  "color_depth": "24",
  "screen_height": "1080",
  "screen_width": "1920",
  "java_enabled": false,
  "tz": 180
}

¿Te resultó útil?

Method Request — 3DS

El Method Request recolecta información adicional del navegador en un iframe oculto para mejorar la evaluación de riesgo del emisor y aumentar la probabilidad de autenticación frictionless (sin challenge).

Este paso solo se realiza si el Version Response incluye un threeds_method_url. Si el campo está vacío o ausente, se omite.


Función SendMethodRequest()

function SendMethodRequest(threeDSMethodURL, threeDSServerTransID, methodNotificationURL) {
    let frameContainer = document.getElementById('methodFrameContainer');
    const threeDSMethodData = {
        threeDSServerTransID: threeDSServerTransID,
        threeDSMethodNotificationURL: methodNotificationURL
    }
    const threeDSMethodDataBase64 = encode(JSON.stringify(threeDSMethodData))
    const methodIframeName = 'methodIframe'
    const methodIframe = createIframe(frameContainer, methodIframeName, methodIframeName, 0, 0)
    const methodForm = createForm('threeDSMethodForm', threeDSMethodURL, methodIframe.name)
    const input = createInput('threeDSMethodData', threeDSMethodDataBase64)
    methodForm.appendChild(input);
    methodIframe.appendChild(methodForm);
    methodForm.submit();
}

URL de notificación

Debe implementar un endpoint en su servidor para recibir la notificación cuando el Method Request se complete:

https://su-dominio.com/api/3ds/method-notification
RequisitoDetalle
AccesibilidadDebe ser públicamente accesible — el ACS del emisor hará POST a esta URL
Parámetro recibidothreeDSMethodData codificado en base64 URL-safe
Respuesta esperadaHTTP 200
Notificación al frontendVia WebSocket, Server-Sent Events o postMessage

Formato de threeDSMethodData

Objeto JSON codificado en base64 URL-safe que se envía al ACS:

{
  "threeDSServerTransID": "8a880dc0-1234-5678-9abc-def012345678",
  "threeDSMethodNotificationURL": "https://su-dominio.com/api/3ds/method-notification"
}

Codificación base64 URL-safe

function encode(str) {
    return btoa(str)
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '')
}

Campo threeds_comp_ind

Requerido en el Authenticate Request cuando device_channel = "02" (Browser).

ValorCuándo enviarlo
"Y"El Method Request se completó exitosamente
"N"No había threeds_method_url, o el request no se completó (timeout o error)

Timeout recomendado: 10 segundos. Si el ACS no responde en ese tiempo, continuar el flujo con threeds_comp_ind: "N".

¿Te resultó útil?

Version Request — 3DS

POST https://api.akua.la/v1/3ds/version

Request

{
  "merchant_id": "string (requerido)",
  "instrument_id": "string (opcional)",
  "card_number": "string (opcional)",
  "card_expiry_date": "string (opcional, formato MMYY)"
}
CampoTipoRequeridoDescripción
merchant_idstringIdentificador único del comercio en Akua
instrument_idstringID del instrumento tokenizado (alternativa a card_number)
card_numberstringNúmero de tarjeta (PAN)
card_expiry_datestringFecha de expiración en formato MMYY (ej: "1226" para Dic 2026)

Debe enviar instrument_id o bien card_number + card_expiry_date. Ver cuándo usar cada opción.


Response

{
  "timestamp": 1706543210000,
  "card_scheme": "VISA",
  "data": {
    "transaction_id": "akua-txn-12345",
    "threeds_server_trans_id": "8a880dc0-1234-5678-9abc-def012345678",
    "threeds_method_url": "https://acs.example.com/method",
    "version_recommendation": "2.2.0",
    "available_version": ["2.1.0", "2.2.0"],
    "acs_start_protocol_version": "2.1.0",
    "acs_end_protocol_version": "2.2.0",
    "ds_start_protocol_version": "2.1.0",
    "ds_end_protocol_version": "2.2.0",
    "acs_info_id": ["01", "02"],
    "instrument_id": "ins-abc123xyz"
  }
}
CampoTipoDescripción
timestampintegerTimestamp Unix en milisegundos
card_schemestringEsquema de la tarjeta (VISA, MASTERCARD)
data.transaction_idstringID de la transacción generado por Akua
data.threeds_server_trans_idstringID único para esta transacción 3DS (UUID)
data.threeds_method_urlstringURL para el Method Request (puede estar vacío)
data.version_recommendationstringVersión 3DS recomendada para usar
data.available_versionarrayVersiones 3DS disponibles
data.acs_start_protocol_versionstringVersión mínima soportada por el ACS
data.acs_end_protocol_versionstringVersión máxima soportada por el ACS
data.ds_start_protocol_versionstringVersión mínima soportada por el Directory Server
data.ds_end_protocol_versionstringVersión máxima soportada por el Directory Server
data.acs_info_idarrayIDs de información del ACS
data.instrument_idstringID del instrumento tokenizado (si aplica)

threeds_server_trans_id — campo clave

Este ID vincula todos los pasos del flujo 3DS para una misma transacción. Debe guardarse y reutilizarse en los pasos siguientes:

PasoUso
Method RequestParámetro threeDSServerTransID
Authenticate RequestCampo opcional threeds_server_trans_id
Result RequestCampo requerido threeds_server_trans_id

instrument_id vs card_number

OpciónCuándo usarla
instrument_idYa existe un token del instrumento de una transacción previa — más seguro y cumple PCI DSS
card_number + card_expiry_datePrimera vez que se procesa la tarjeta y aún no se tiene token

¿Te resultó útil?

Authenticate Request — 3DS

POST https://api.akua.la/v1/3ds/authenticate

Request

{
  "merchant_id": "string (requerido)",
  "customer_id": "string (opcional)",
  "transaction_id": "string (opcional)",
  "data": {
    "device_channel": "string (requerido: 01, 02, 03)",
    "message_version": "string (opcional, ej: 2.2.0)",
    "threeds_server_trans_id": "string (opcional, del Version Response)",
    "message_category": "string (requerido: 01, 02)",
    "notification_url": "string (requerido, URL de webhook)",
    "purchase_amount": "string (opcional, ej: 10000 para $100.00)",
    "purchase_currency": "string (opcional, código numérico ISO 4217)",
    "purchase_exponent": "string (opcional, ej: 2 para centavos)",
    "purchase_date": "string (opcional, formato YYYYMMDDHHmmss)",
    "recurring_expiry": "string (opcional, formato YYYYMMDD)",
    "recurring_frequency": "string (opcional, días entre cargos)",
    "purchase_instal_data": "string (opcional, número máximo de cuotas)",
    "trans_type": "string (requerido cuando message_category es 01; valores: 01, 03, 10, 11, 28)",
    "threeds_requestor_url": "string (requerido, URL de su sitio)",
    "threeds_requestor_authentication_ind": "string (requerido: 01-07)",
    "threeds_comp_ind": "string (Y, N)",
    "threeds_requestor_challenge_ind": "string (opcional: 01-09, 90)",
    "threeds_requestor_dec_max_time": "string (opcional, minutos)",
    "threeds_requestor_dec_req_ind": "string (opcional: Y, N)",
    "threeds_requestor_authentication_info": {
      "threeds_req_auth_method": "string (opcional: 01-08)",
      "threeds_req_auth_timestamp": "string (opcional, formato YYYYMMDDHHmmss)",
      "threeds_req_auth_data": "string (opcional)"
    },
    "threeds_requestor_prior_authentication_info": {
      "threeds_req_prior_auth_method": "string (opcional: 01-04)",
      "threeds_req_prior_auth_timestamp": "string (opcional, formato YYYYMMDDHHmm)",
      "threeds_req_prior_ref": "string (opcional)",
      "threeds_req_prior_auth_data": "string (opcional)"
    },
    "merchant_risk_indicator": {
      "delivery_email_address": "string (opcional)",
      "delivery_time_frame": "string (opcional: 01-04)",
      "gift_card_amount": "string (opcional)",
      "gift_card_count": "string (opcional)",
      "gift_card_curr": "string (opcional)",
      "pre_order_purchase_ind": "string (opcional: 01, 02)",
      "pre_order_date": "string (opcional, formato YYYYMMDD)",
      "reorder_items_ind": "string (opcional: 01, 02)",
      "ship_indicator": "string (opcional: 01-07)"
    },
    "card_data": {
      "instrument_id": "string (opcional)",
      "card_number": "string (opcional)",
      "card_expiry_date": "string (opcional, formato MMYY)"
    },
    "cardholder": {
      "cardholder_name": "string (opcional)",
      "acct_type": "string (opcional: 01, 02, 03)",
      "email": "string (opcional)",
      "addr_match": "string (opcional: Y, N)",
      "bill_addr_line1": "string (opcional)",
      "bill_addr_city": "string (opcional)",
      "bill_addr_state": "string (opcional)",
      "bill_addr_zip_code": "string (opcional)",
      "bill_addr_country": "string (opcional, código numérico ISO 3166)",
      "ship_addr_line1": "string (opcional)",
      "ship_addr_city": "string (opcional)",
      "ship_addr_state": "string (opcional)",
      "ship_addr_zip_code": "string (opcional)",
      "ship_addr_country": "string (opcional, código numérico ISO 3166)"
    },
    "browser_data": {
      "accept_header": "string",
      "javascript_enabled": true,
      "language": "string",
      "user_agent": "string",
      "ip_address": "string (opcional, recomendado)",
      "java_enabled": false,
      "color_depth": "string (opcional)",
      "screen_height": "string (opcional)",
      "screen_width": "string (opcional)",
      "tz": "string (opcional)"
    }
  }
}

Campos de nivel superior

CampoTipoRequeridoDescripción
merchant_idstringID del comercio en Akua
customer_idstringID del cliente en su sistema
transaction_idstringID de la transacción en su sistema

Valores de campos clave

device_channel

ValorDescripción
"01"App-based (SDK)
"02"Browser
"03"3DS Requestor Initiated (3RI)

message_category

ValorDescripción
"01"Payment Authentication (PA)
"02"Non-Payment Authentication (NPA)

threeds_requestor_authentication_ind

ValorDescripción
"01"Pago — bienes o servicios
"02"Sin pago (enrollment, validación de cuenta)
"03"Transacción recurrente
"04"Transacción con cuotas
"05"Agregar tarjeta (sin pago)
"06"Mantener tarjeta (verificación)
"07"Verificación de cuenta de tarjeta

cardholder.acct_type

ValorDescripción
"01"Sin cuenta (invitado)
"02"Cuenta creada durante la transacción
"03"Cuenta existente

Validaciones condicionales

Identificador de tarjeta — requerido uno de los dos

OpciónCamposFormato
Tarjeta tokenizadacard_data.instrument_idAlfanumérico, puede incluir - y _
Tarjeta sin tokenizarcard_data.card_number + card_data.card_expiry_dateSolo dígitos / exactamente 4 dígitos MMYY

Si se envían ambos, se usa instrument_id y se ignora card_number.

Campos requeridos según device_channel = "02" (Browser)

CampoTipo
browser_data.accept_headerstring
browser_data.javascript_enabledboolean (true/false, no string)
browser_data.languagestring
browser_data.user_agentstring
threeds_comp_ind"Y" o "N"

browser_data.ip_address no es obligatorio pero es altamente recomendado para la evaluación de riesgo.

Campos requeridos según message_category = "01" (Payment Authentication)

CampoFormato
purchase_amountEntero en centavos (ej: "10000" para $100.00)
purchase_currencyCódigo numérico ISO 4217 — exactamente 3 dígitos (ej: "858")
purchase_exponentEj: "2" para centavos
purchase_dateYYYYMMDDHHmmss — exactamente 14 dígitos
trans_type01, 03, 10, 11 o 28

Campos adicionales para threeds_requestor_authentication_ind = "02" o "03" (recurrente / cuotas)

Los campos de purchase_* de la tabla anterior también son requeridos. Si además message_category = "01":

CampoFormato
recurring_expiryYYYYMMDD — exactamente 8 dígitos
recurring_frequencyNúmero de días entre cargos

Formatos estrictos

CampoFormatoEjemplo
card_numberSolo dígitos, sin espacios"4532015112830366"
card_expiry_date4 dígitos MMYY"1226"
purchase_currency3 dígitos numéricos ISO 4217"858"
purchase_date14 dígitos YYYYMMDDHHmmss"20260129153045"
recurring_expiry8 dígitos YYYYMMDD"20261231"
bill_addr_country / ship_addr_country3 dígitos numéricos ISO 3166"858"

Response

CampoTipoDescripción
timestampintegerTimestamp Unix en milisegundos
statusintegerCódigo de estado HTTP
card_schemestringEsquema de la tarjeta
transaction_idstringID de transacción de Akua
data.message_versionstringVersión del protocolo 3DS usado
data.threeds_server_trans_idstringID de transacción 3DS
data.acs_trans_idstringID de transacción del ACS
data.trans_statusstringEstado de la autenticación (ver tabla)
data.authentication_valuestringCAVV — valor de autenticación para autorización
data.ecistringElectronic Commerce Indicator
data.acs_urlstringURL del ACS para challenge (si aplica)
data.acs_challenge_mandatedstringSi el challenge es mandatorio
data.authentication_typestringTipo de autenticación realizada
data.trans_status_reasonstringRazón del estado
data.instrument_idstringID del instrumento tokenizado

Estados de autenticación — trans_status

CódigoEstadoDescripciónAcción
YAuthenticated SuccessfullyAutenticación frictionless exitosaProceder a autorización con CAVV
CChallenge RequiredSe requiere interacción del usuarioIniciar Challenge Request
AAttempts Processing PerformedAutenticación intentada pero no completadaAutorizar con ECI (riesgo del merchant)
NNot AuthenticatedAutenticación fallidaNo autorizar
RAuthentication RejectedRechazada por el emisorNo autorizar
UCould Not Be PerformedError técnicoDecisión de negocio según política de riesgo
DDecoupled AuthenticationAutenticación desacoplada confirmadaEsperar resultado
IInformation OnlySolo información, sin autenticaciónDecisión de negocio

Flujos según trans_status

Frictionless — Y o A

La respuesta incluye authentication_value (CAVV) y eci. No habrá acs_url. Proceder directamente a autorizar.

if (authResponse.data.trans_status === 'Y' || authResponse.data.trans_status === 'A') {
    await authorizePayment({
        cavv: authResponse.data.authentication_value,
        eci: authResponse.data.eci,
        threeDSServerTransID: authResponse.data.threeds_server_trans_id
    });
}

Challenge — C

La respuesta incluye acs_url. No habrá authentication_value aún. Iniciar el Challenge Request y luego obtener el resultado con el Result Request.

if (authResponse.data.trans_status === 'C') {
    const challengeRequest = {
        messageType: 'CReq',
        messageVersion: authResponse.data.message_version,
        threeDSServerTransID: authResponse.data.threeds_server_trans_id,
        acsTransID: authResponse.data.acs_trans_id,
        challengeWindowSize: '05'
    };
    SendChallengeRequest(
        authResponse.data.acs_url,
        challengeRequest,
        { transactionId: authResponse.transaction_id }
    );
}

Rechazo — N o R

No autorizar la transacción. Informar al usuario que la autenticación falló.

Incertidumbre — U, D, I

Requieren una decisión de negocio según la política de riesgo del comerciante.

¿Te resultó útil?

Challenge — 3DS

El Challenge permite al emisor verificar la identidad del titular cuando la autenticación frictionless no es suficiente. Se activa cuando el Authenticate Request retorna trans_status: "C".

Casos de uso: OTP vía SMS, aprobación en app del banco, biometría u otros factores adicionales para transacciones de alto riesgo.


Función SendChallengeRequest()

function SendChallengeRequest(acsURL, creq, sessionData) {
    let frameContainer = document.getElementById('challengeFrameContainer');
    const windowSize = getWindowSize(creq.challengeWindowSize)
    const creqBase64 = encode(JSON.stringify(creq));
    const sessionDataBase64 = encode(JSON.stringify(sessionData))
    const challengeIframeName = 'challengeIframe'
    const challengeIframe = createIframe(
        frameContainer,
        challengeIframeName,
        challengeIframeName,
        windowSize[0],
        windowSize[1]
    )
    const form = createForm('threeDSCReqForm', acsURL, challengeIframe.name)
    const creqInput = createInput('creq', creqBase64)
    const sessionDataInput = createInput('threeDSSessionData', sessionDataBase64)
    form.appendChild(creqInput);
    form.appendChild(sessionDataInput);
    challengeIframe.appendChild(form);
    form.submit();
}

Estructura del CReq

{
  "messageType": "CReq",
  "messageVersion": "2.2.0",
  "threeDSServerTransID": "8a880dc0-1234-5678-9abc-def012345678",
  "acsTransID": "d7c1ee99-9478-44a6-b1f2-391e29c6b340",
  "challengeWindowSize": "05"
}
CampoRequeridoDescripciónOrigen
messageTypeSiempre "CReq"
messageVersionVersión del protocoloAuthenticate Response
threeDSServerTransIDID de transacción 3DSAuthenticate Response
acsTransIDID del ACSAuthenticate Response
challengeWindowSizeTamaño del iframe (ver tabla)

Tamaños de ventana disponibles

CódigoDimensionesUso recomendado
"01"250px × 400pxMóvil — pantalla pequeña
"02"390px × 400pxMóvil — pantalla mediana
"03"500px × 600pxTablet o desktop
"04"600px × 400pxDesktop — ventana ancha
"05"100% × 100%Pantalla completa — responsive

Usar "05" para una experiencia que se adapte a cualquier dispositivo.


Contenedor del Challenge

El iframe del challenge se renderiza dentro de un contenedor HTML. Se recomienda usar un modal para mejor experiencia de usuario:

<!-- Opción básica -->
<div id="challengeFrameContainer"></div>

<!-- Opción recomendada: modal con overlay -->
<div id="challengeModal" class="modal">
  <div class="modal-content">
    <div id="challengeFrameContainer"></div>
  </div>
</div>

URL de notificación del Challenge

El ACS envía el resultado del challenge a su endpoint configurado:

POST https://su-dominio.com/api/3ds/challenge-notification
Content-Type: application/x-www-form-urlencoded

Parámetros recibidos:

ParámetroDescripción
cresChallenge Response en base64 URL-safe
threeDSSessionDataDatos de sesión enviados en el CReq, en base64 URL-safe

Decodificación de los parámetros

function decodeBase64Url(str) {
    let base64 = str.replace(/-/g, '+').replace(/_/g, '/');
    const padding = base64.length % 4;
    if (padding) base64 += '='.repeat(4 - padding);
    return atob(base64);
}

const cresDecoded = JSON.parse(decodeBase64Url(cres));
const sessionDataDecoded = JSON.parse(decodeBase64Url(threeDSSessionData));

Comunicación backend → frontend

Tras recibir la notificación, el backend debe avisar al frontend que el challenge se completó. Usar window.postMessage() para comunicación segura entre iframes:

Desde la página de notificación (dentro del iframe):

window.parent.postMessage({
    challengeCompleted: true,
    threeDSServerTransID: sessionDataDecoded.transactionId,
    status: 'SUCCESS'
}, '*');

Desde la página principal (que contiene el iframe):

window.addEventListener('message', (event) => {
    if (event.data.challengeCompleted) {
        closeChallengeModal();
        await getResultAndAuthorize(event.data.threeDSServerTransID);
    }
});

Flujo completo de Challenge

async function handleCheckout() {
    // 1. Hacer Authenticate Request
    const authResponse = await fetch('/v1/3ds/authenticate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(authenticateRequest)
    });
    const authData = await authResponse.json();

    // 2. Evaluar resultado
    if (authData.data.trans_status === 'Y') {
        // Frictionless — proceder directamente
        await authorizePayment(authData);

    } else if (authData.data.trans_status === 'C') {
        // Challenge requerido
        const challengeRequest = {
            messageType: 'CReq',
            messageVersion: authData.data.message_version,
            threeDSServerTransID: authData.data.threeds_server_trans_id,
            acsTransID: authData.data.acs_trans_id,
            challengeWindowSize: '05'
        };
        // 3. Abrir modal y enviar challenge
        openChallengeModal();
        SendChallengeRequest(
            authData.data.acs_url,
            challengeRequest,
            { transactionId: authData.transaction_id }
        );
    }
}

// 4. Escuchar el completado del challenge
window.addEventListener('message', async (event) => {
    if (event.data.challengeCompleted) {
        closeChallengeModal();

        // 5. Obtener resultado final
        const resultResponse = await fetch('/v1/3ds/result', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                merchant_id: 'merchant_12345',
                threeds_server_trans_id: event.data.threeDSServerTransID
            })
        });
        const resultData = await resultResponse.json();

        // 6. Autorizar si la autenticación fue exitosa
        if (resultData.data.trans_status === 'Y') {
            await authorizePayment(resultData);
        }
    }
});

Timeout del Challenge

A diferencia del Method Request, no debe establecer un timeout para el Challenge. El usuario puede tomar el tiempo que necesite para completar la autenticación. El emisor puede tener su propio timeout, pero desde su lado debe esperar la notificación sin interrumpir el flujo.

¿Te resultó útil?

Result Request — 3DS

Obtiene el resultado final de la autenticación después de completado el Challenge. Requiere el threeds_server_trans_id generado en el Authenticate Response.

POST https://api.akua.la/v1/3ds/result

Request

{
  "merchant_id": "string (requerido)",
  "threeds_server_trans_id": "string (requerido)"
}
CampoTipoRequeridoDescripción
merchant_idstringID del comercio en Akua
threeds_server_trans_idstringID de transacción 3DS del Authenticate Response

Response

{
  "timestamp": 1706543210000,
  "card_scheme": "VISA",
  "transaction_id": "akua-txn-12345",
  "data": {
    "message_version": "2.2.0",
    "threeds_server_trans_id": "8a880dc0-1234-5678-9abc-def012345678",
    "trans_status": "Y",
    "trans_status_reason": "",
    "eci": "05",
    "authentication_value": "AAABCZIhcQAAAABZlyFxAAAAAAA=",
    "authentication_type": "01",
    "whitelist_status": "",
    "whitelist_status_source": "",
    "interaction_counter": "",
    "challenge_cancel": ""
  }
}
CampoTipoDescripción
timestampintegerTimestamp Unix en milisegundos
card_schemestringEsquema de la tarjeta
transaction_idstringID de transacción de Akua
data.message_versionstringVersión del protocolo 3DS
data.threeds_server_trans_idstringID de transacción 3DS
data.trans_statusstringEstado final de la autenticación
data.trans_status_reasonstringRazón del estado (si aplica)
data.ecistringElectronic Commerce Indicator
data.authentication_valuestringCAVV — valor para autorización
data.authentication_typestringTipo de autenticación realizada
data.whitelist_statusstringEstado de whitelist del tarjetahabiente
data.whitelist_status_sourcestringFuente del estado de whitelist
data.interaction_counterstringContador de intentos de challenge
data.challenge_cancelstringCódigo de cancelación (si aplica)

Estados — trans_status

CódigoEstadoAcción
YAuthentication SuccessfulAutorizar el pago con el CAVV
AAttempts ProcessingAutorizar bajo riesgo propio usando el ECI
NNot AuthenticatedRechazar la transacción
UAuthentication UnavailableDecisión de negocio según política de riesgo
RRejectedRechazar la transacción

Códigos de challenge_cancel

Si el usuario cancela o el ACS interrumpe el challenge, este campo indica la razón:

CódigoDescripción
01El tarjetahabiente canceló
02Transacción reservada (cardholder reserved)
03Transacción rechazada por el ACS
04ACS reconoció al tarjetahabiente del Directory Server
05Timeout en el ACS
06Error en el ACS
07Desconocido

¿Te resultó útil?

Tarjetas de Prueba — 3DS Sandbox

Usá estas tarjetas en el ambiente sandbox para simular diferentes escenarios de autenticación 3DS. Todas son válidas con cualquier fecha de expiración futura (MMYY, ej: 1226) y cualquier CVV de 3 dígitos.

Estas tarjetas solo funcionan en sandbox. No usarlas en producción.


Tarjetas disponibles

Frictionless (sin challenge)

PANRedtrans_statusEscenario
4242424242424242VisaYFrictionless exitoso
5555555555554444MastercardYFrictionless exitoso
4111111111111111VisaAAttempted — sin Method URL
5424180011113336MastercardAAttempted
4264281511112228VisaNAutenticación fallida
5424180000000171MastercardNAutenticación fallida
5405001111111165MastercardUAutenticación no disponible
5405001111111116MastercardRAutenticación rechazada

Con Challenge

PANRedResultado finalEscenario
4000020000000000VisaYChallenge exitoso
4005562231212123VisaYChallenge exitoso — sin Method URL
4761369980320253VisaYChallenge mandatorio
4000000000000341VisaYChallenge out-of-band
5200000000001104MastercardYChallenge mandatorio
4005571701111111VisaAChallenge con resultado Attempted
4055011111111111VisaNChallenge fallido
5427660064241339MastercardNChallenge fallido

Errores y casos especiales

PANRedEscenario
4264281500003339VisaError en Directory Server
4264281500001119VisaError en 3DS Server
5424180011110001Mastercard3DS2 no soportado

Notas para testing

AspectoDetalle
Fecha de expiraciónCualquier fecha futura en formato MMYY (ej: 1226)
CVVCualquier valor de 3 dígitos (ej: 123)
Código de challengeIngresar 1234 cuando el challenge lo solicite
MontoNo afecta el comportamiento — usar cualquier monto válido

Estado A (Attempted): cuando lo recibas, tu sistema debe decidir si acepta el riesgo y autoriza la transacción. Es una decisión de negocio configurable según el apetito de riesgo del comerciante.

Tarjetas de error: útiles para probar el manejo de excepciones y la resiliencia de la integración ante fallos del sistema.

¿Te resultó útil?

Apéndice

Referencia completa de todos los valores y enumeraciones usados en el flujo 3DS.


A. trans_status — Estado de autenticación

CódigoEstadoDescripción
YAuthenticated SuccessfullyEl tarjetahabiente fue autenticado exitosamente
NNot AuthenticatedLa autenticación falló o fue declinada
UCould Not Be PerformedNo pudo realizarse por problemas técnicos
AAttempts Processing PerformedSe intentó pero el tarjetahabiente no está enrollado o el banco no soporta 3DS
CChallenge RequiredSe requiere autenticación adicional
DDecoupled Authentication ConfirmedSe confirmó autenticación desacoplada
RAuthentication RejectedRechazada por el emisor
IInformation OnlySolo información, sin autenticación

B. device_channel — Canal del dispositivo

CódigoCanalDescripción
01App-basedAplicación móvil nativa usando SDK
02BrowserNavegador web (desktop o móvil)
033DS Requestor InitiatedIniciado por el comercio sin participación del tarjetahabiente

C. message_category — Categoría del mensaje

CódigoCategoríaDescripción
01Payment Authentication (PA)Autenticación para una transacción de pago
02Non-Payment Authentication (NPA)Autenticación sin pago (agregar tarjeta, validación)

D. threeds_requestor_authentication_ind — Propósito de la autenticación

CódigoIndicadorDescripción
01Payment transactionPago de bienes o servicios
02Recurring transactionPrimera transacción de una serie recurrente
03Installment transactionPrimera transacción de una serie de cuotas
04Add cardAgregar tarjeta sin transacción
05Maintain cardMantener información de tarjeta
06Verify cardholderVerificación de cuenta de tarjeta
07Billing agreementAcuerdo de facturación

E. acct_type — Tipo de cuenta

CódigoTipoDescripción
01Not applicableNo aplica
02CreditCrédito
03DebitDébito

F. trans_type — Tipo de transacción

CódigoTipoDescripción
01Goods / Service PurchaseCompra de bienes o servicios
03Check AcceptanceAceptación de cheque
10Account FundingFinanciamiento de cuenta
11Quasi-Cash TransactionTransacción cuasi-efectivo
28Prepaid Activation and LoadActivación y carga de prepago

G. ship_indicator — Indicador de envío

CódigoDescripción
01Envío a dirección de facturación del tarjetahabiente
02Envío a otra dirección verificada
03Envío a dirección diferente a la de facturación
04Recoger en tienda
05Bienes digitales (sin envío físico)
06Tickets de viaje o eventos
07Otro

H. delivery_time_frame — Marco de tiempo de entrega

CódigoDescripción
01Entrega electrónica
02Envío el mismo día
03Envío nocturno
04Envío de dos días o más

I. pre_order_purchase_ind — Indicador de pre-orden

CódigoDescripción
01Mercancía disponible
02Disponibilidad futura (pre-orden)

J. reorder_items_ind — Indicador de re-orden

CódigoDescripción
01Primera vez ordenando
02Re-ordenado (ya comprado antes)

K. threeds_req_auth_method — Método de autenticación

CódigoMétodoDescripción
01No authenticationSin autenticación (invitado)
02Login to merchant accountLogin con credenciales
03Federated IDID federado (SSO)
04Issuer credentialsCredenciales del emisor
05Third-party authenticationAutenticación de terceros
06FIDO authenticatorAutenticador FIDO
07FIDO authenticator (signed)FIDO con firma de garantía
08SRC Assurance DataDatos de garantía SRC

L. threeds_req_prior_auth_method — Método de autenticación previa

CódigoMétodoDescripción
01FrictionlessAutenticación sin fricción
02ChallengeChallenge (ACS)
03AVS verifiedVerificado por AVS
04Other issuer methodsOtros métodos del emisor

M. Códigos ECI — Electronic Commerce Indicator

Visa

ECIDescripción
05Authenticated (VERes y CAVV)
06Attempts (VERes sin CAVV)
07Transacción sin 3DS

Mastercard

ECIDescripción
02Authenticated (UCAF o CAVV)
01Merchant only (SSL)
00Attempts

N. threeds_requestor_challenge_ind — Preferencia de challenge

CódigoDescripción
01Sin preferencia
02No se solicita challenge
03Se solicita challenge (preferencia del requestor)
04Se solicita challenge (mandato — ej: PSD2)
05No se solicita (análisis de riesgo ya realizado)
06No se solicita (solo intercambio de datos)
07No se solicita (autenticación fuerte ya realizada)
08No se solicita (usar exención de whitelist si aplica)
09Se solicita (solicitar aviso de whitelist si aplica)
90Habilitar scoring de Cartes Bancaires (solo Cartes Bancaires)

O. trans_status_reason — Razón del estado

CódigoDescripción
01Autenticación de la tarjeta fallida
02Dispositivo desconocido
03Dispositivo no soportado
04Se excedió el límite de frecuencia de autenticación
05Tarjeta vencida
06Número de tarjeta inválido
07Transacción inválida
08No existe registro de la tarjeta
09Falla de seguridad
10Tarjeta robada
11Fraude sospechado
12Transacción no permitida para el titular
13Titular no enrolado en el servicio
14Timeout en el ACS
15Baja confianza
16Confianza media
17Alta confianza
18Confianza muy alta
19Se excedió el máximo de challenges del ACS
20Transacción NPA no soportada
21Transacción 3RI no soportada
22Problema técnico del ACS
23Autenticación desacoplada requerida pero no solicitada
24Se excedió el tiempo máximo para autenticación desacoplada
25Tiempo insuficiente para autenticación desacoplada
26Autenticación intentada pero no completada por el titular

P. authentication_type — Tipo de autenticación

CódigoTipoDescripción
01StaticContraseña o código de acceso
02DynamicOTP (contraseña de un solo uso)
03Out-of-bandApp móvil del banco emisor
04DecoupledAutenticación desacoplada

Q. whitelist_status — Estado de whitelist

CódigoDescripción
YEl comercio es confiable para el titular
NEl comercio aún no ha sido marcado como confiable
ENo elegible según lo determinado por el emisor
PPendiente de confirmación por parte del titular
REl titular rechazó la solicitud
UDesconocido o no aplica

R. whitelist_status_source — Fuente del estado de whitelist

CódigoSistemaDescripción
013DS ServerServidor 3DS
02DSDirectory Server
03ACSAccess Control Server

S. challenge_cancel — Razón de cancelación del challenge

CódigoDescripción
01El titular seleccionó "Cancelar"
02El requestor 3DS canceló la autenticación
03Transacción abandonada
04Timeout en el ACS
05ACS timeout — la primera CReq no fue recibida
06Error en la transacción
07Desconocido

T. Códigos SDK y ACS UI

sdk_interface — Tipo de interfaz del SDK

CódigoTipoDescripción
01NativeInterfaz nativa
02HTMLInterfaz HTML
03BothAmbas

sdk_ui_type — Tipos de UI soportados por el dispositivo

CódigoTipoDescripción
01TextCampo de texto
02Single SelectSelección única
03Multi SelectSelección múltiple
04OOBOut-of-Band
05HTML OtherHTML otro (solo para UI HTML)

acs_interface — Interfaz que el ACS usará para el challenge

CódigoTipo
01Nativa
02HTML

acs_ui_template — Plantilla de UI del ACS

CódigoTipoDescripción
01TextCampo de texto
02Single SelectDesplegable
03Multi SelectCheckbox
04OOBApp del banco emisor
05HTML OtherHTML otro

U. error_component — Componente donde ocurrió el error

CódigoComponente
S3DS Server
DDirectory Server
AACS
CTarjeta

V. Formatos de fecha y hora

CampoFormatoEjemploDescripción
card_expiry_dateMMYY1226Diciembre 2026
purchase_dateYYYYMMDDHHmmss2026012915304529 Enero 2026, 15:30:45
recurring_expiryYYYYMMDD2026123131 Diciembre 2026
pre_order_dateYYYYMMDD2026061515 Junio 2026
threeds_req_auth_timestampYYYYMMDDHHmmss2026012915304529 Enero 2026, 15:30:45
threeds_req_prior_auth_timestampYYYYMMDDHHmm20260129153029 Enero 2026, 15:30

W. Códigos de país — ISO 3166-1 numérico

CódigoPaís
032Argentina
076Brasil
152Chile
170Colombia
484México
604Perú
858Uruguay
862Venezuela
840Estados Unidos

X. Códigos de moneda — ISO 4217

CódigoMonedaExponente
032ARS — Peso Argentino2
986BRL — Real Brasileño2
152CLP — Peso Chileno0
170COP — Peso Colombiano2
840USD — Dólar Estadounidense2
978EUR — Euro2
484MXN — Peso Mexicano2
604PEN — Sol Peruano2
858UYU — Peso Uruguayo2

Exponente: indica el número de decimales. Exponente 2 → $100.00 se envía como "10000". Exponente 0 → $100 se envía como "100".


Y. Errores HTTP comunes

CódigoErrorCausaSolución
400Bad RequestRequest mal formado o campos faltantesVerificar estructura del JSON y campos requeridos
400browser_data is requiredFalta browser_data en flujo browserIncluir browser_data completo cuando device_channel = "02"
400accept_header is requiredFalta accept_header en browser_dataIncluir el header Accept del navegador
400javascript_enabled is requiredFalta javascript_enabledIncluir como booleano (true/false)
400language is requiredFalta language en browser_dataIncluir el idioma del navegador
400user_agent is requiredFalta user_agent en browser_dataIncluir el user agent del navegador
400threeds_comp_ind is requiredFalta en flujo browserEnviar "Y" o "N"
400purchase_currency is requiredFalta en pagoCódigo ISO 4217 numérico de 3 dígitos
400purchase_amount is requiredFalta en pagoEj: "10000" para $100.00
400purchase_date is requiredFalta en pagoFormato YYYYMMDDHHmmss
400purchase_exponent is requiredFalta en pagoEj: "2" para centavos
401UnauthorizedCredenciales inválidasVerificar Client ID y API key
403ForbiddenPermisos insuficientesContactar a Akua para verificar permisos
404Not FoundRecurso no encontradoVerificar el endpoint y los IDs enviados
422Unprocessable EntityValidación de campos fallidaRevisar valores y formatos de los campos
500Internal Server ErrorError del servidorContactar soporte de Akua

¿Te resultó útil?

SUSCRIPCIONES

1

Planes de Suscripción

Propósito

Pantalla para administrar las plantillas de facturación que después se aplican a las suscripciones. Un plan define el tipo de orden (recurrente, orden permanente o no programado), la periodicidad, el monto, los reintentos ante fallo de cobro y los días de prueba gratuita.

Es el punto de partida del módulo: las suscripciones se crean a partir de un plan (o, opcionalmente, de forma independiente). Cada plan también puede emitir links de management para sus suscriptores.

Screenshot 2026-05-07 at 22.59.45@2x.png

Estadísticas (cards superiores)

  • Total Plans — cantidad de planes disponibles.
  • Active Subscribers — suscripciones activas en este momento.
  • Total MRR — ingreso recurrente mensual del módulo.
  • Avg Revenue / Plan — MRR dividido por la cantidad de planes.

Tabla de planes

Screenshot 2026-05-08 at 10.13.29@2x.png

Columnas: Plan Name, Order Type, Periodicity, Amount, Free Trial, Max Retries, Status, Subscribers.

Acciones por fila:

  • Generate management link — abre un drawer para emitir un link de gestión a un suscriptor del plan. Sólo se habilita si el plan tiene suscriptores; si no, queda deshabilitado en gris.
  • Ojo (vista detalle) — abre la pantalla de detalle del plan (/subscriptions/plans/{id}).
  • Tacho rojo — abre el modal de confirmación de eliminación.

Acciones del header

  • Generate Link — atajo a la creación de un link multi-plan (mismo flujo que la pestaña Links).
  • + Create Plan — abre el modal de creación.

Crear plan

Click en + Create Plan abre el modal:

Screenshot 2026-05-08 at 10.14.34@2x.png

Campos

CampoTipoNotas
Plan Name *textoObligatorio. Placeholder e.g. Pro Monthly.
DescriptiontextareaOpcional.
Order Type *selectRecurring, Standing Order, Unscheduled.
PeriodicityselectWeekly, Bi-Weekly, Monthly, Quarterly, Semi-Annual, Annual. No aplica a Unscheduled.
Amount *númeroObligatorio. Acepta decimales.
CurrencyselectLimitada a las monedas habilitadas en la organización (en sandbox: COP).
Free TrialtoggleAl activar, aparece Free Trial Days (entero, mínimo 0).
Max RetriesnúmeroDefault 3. Cantidad de reintentos automáticos ante fallo de cobro.
Retry PeriodicityselectDaily, Every 3 Days, Weekly.

Tipos de orden disponibles

  • Recurring — mismo monto, misma periodicidad (ej. Netflix).
  • Standing Order — monto variable, misma periodicidad (ej. servicios públicos).
  • Unscheduled — cobros bajo demanda, sin agenda fija (ej. Uber, Rappi).

Validaciones visibles

  • Los campos con asterisco rojo (Plan Name, Order Type, Amount) son obligatorios.
  • El botón Save queda habilitado cuando se completan los obligatorios.

Ver detalle del plan

Click en el ícono de ojo de la fila.

Screenshot 2026-05-08 at 10.16.52@2x.png

Bloques:

  • Plan Information — nombre, descripción, order type, periodicity, amount, free trial, max retries, status, fecha de creación.
  • Active Subscribers — contador.
  • Avg Duration — duración promedio de las suscripciones del plan.
  • Subscribers — tabla con Merchant, Instrument, Status, Start Date, Amount. Si no hay suscriptores: estado vacío "No subscribers".

Click en Generate management link en la fila (sólo planes con suscriptores).

Screenshot 2026-05-08 at 10.19.43@2x.png

Campos:

  • Plan Information — preview del plan (read-only).
  • Badge violeta MANAGE SUBSCRIPTION indicando el tipo de link.
  • Subscription * — selector entre las suscripciones del plan.
  • Payment Link Expiration — número + unidad (Days, Hours, etc.).
  • Botones Cancel / Generate Link.

El link generado permite al suscriptor actualizar tarjeta o cancelar la suscripción desde una página whitelabel.


Estados visibles

  • ACTIVE (badge verde) — único estado observado para planes en sandbox. Los planes no se cancelan: se eliminan.

¿Te resultó útil?

ALTERNATIVE PAYMENT METHODS (APMS))

5

Pagos instantáneos en Colombia

Akua admite cuatro rails de pago instantáneo para Colombia: Bre-B, Nequi, Daviplata y PSE. Los cuatro se inician a través del mismo endpoint — POST /api/v1/payments/intents — y el rail se determina mediante el campo rail.id en el cuerpo de la solicitud.


Visión general

RailTipoMecanismoPaso de confirmaciónCaso de uso típico
BRE_BBANK_TRANSFEREscaneo de QR o alias desde cualquier app bancariaNoPresencial, e-commerce, alta interoperabilidad
NEQUIWALLETNotificación push a la app de NequiNoE-commerce, usuarios de Nequi
DAVIPLATAWALLETOTP enviado por SMSE-commerce, sin necesidad de app
PSEBANK_TRANSFERRedirección al portal de internet bankingNoMontos altos, B2B, preferencia por débito bancario directo

Ciclo de vida de la solicitud

Todos los intentos pasan por el mismo puente asíncrono-a-síncrono:

  1. Tu servidor llama a POST /api/v1/payments/intents.
  2. Akua valida la solicitud, se suscribe a un canal interno de resultado y publica un evento de comando al procesador de pagos.
  3. El procesador ejecuta la lógica específica del rail y publica el resultado de vuelta.
  4. Akua responde de forma síncrona con una respuesta HTTP 201 que contiene el estado inicial de la transacción.
  5. El resultado final (aprobado, rechazado, fallido) se entrega de forma asíncrona mediante webhook.

Nunca uses la respuesta inicial 201 para confirmar un pedido. Solo el webhook (o una llamada de consulta) transporta el estado final autoritativo.

Idempotencia

Todas las solicitudes de intento pasan por un bloqueo distribuido respaldado por Redis con un TTL configurable (~40 segundos). La idempotencia se controla mediante el header Idempotency-Key: enviar una solicitud con la misma clave mientras una anterior sigue en curso devuelve HTTP 409.

Usa el campo id con tu referencia interna del pedido para poder rastrear la transacción y evitar cargos duplicados desde tu plataforma.


Autenticación

Todas las solicitudes requieren tus credenciales de API en los headers de la solicitud. Contacta a tu ejecutivo de cuenta de Akua para obtener tu Client-Id y tu API key.

Client-Id: cli-xxxxxxxxxxxxxxxxxxxx
Authorization: Bearer <your-api-key>
Content-Type: application/json

Estados del pago

EstadoDescripción
CREATEDRegistro de pago creado; el procesamiento aún no ha iniciado
PENDING_CUSTOMEREsperando acción del cliente (Daviplata: ingreso del OTP; otros rails: esperando la aprobación del cliente)
PENDING_PROVIDEREsperando a que el proveedor complete el procesamiento (p. ej. redirección al portal bancario en curso)
AUTHORIZEDPago aprobado; fondos confirmados
REJECTEDPago rechazado de forma definitiva
FAILEDError técnico durante el procesamiento

Bre-B

Bre-B es el sistema nacional de pagos instantáneos de Colombia, operado por el Banco de la República. Es interoperable: el cliente puede pagar desde cualquier entidad financiera conectada. Los pagos se liquidan de inmediato a través del sistema CUD y son irrevocables.

Cómo funciona

  1. Tu servidor crea un intento de pago con rail.id: "BRE_B".
  2. Akua responde de inmediato con un código QR, un alias y una llave alfanumérica.
  3. El cliente escanea el QR o ingresa manualmente la llave (alias) desde cualquier app bancaria y autoriza la transferencia.
  4. Akua envía un webhook cuando el pago se confirma.

Sin redirección, sin paso de confirmación separado.

Crear un intento

POST /api/v1/payments/intents

Cuerpo de la solicitud

{
  "id": "order-12345",
  "amount": {
    "value": 150000,
    "currency": "COP"
  },
  "description": "Compra Online",
  "merchant_id": "mer-xxxxxxxxxxxxxxxxxxxx",
  "rail": {
    "id": "BRE_B",
    "type": "BANK_TRANSFER"
  }
}

Campos de la solicitud

CampoTipoRequeridoDescripción
idstringNoTu referencia interna del pedido. Si se omite, Akua genera una. Máx. 255 caracteres.
amount.valuedecimalMonto del pago en COP. Debe ser mayor a cero. Mínimo: 1.000 COP.
amount.currencystringDebe ser COP.
descriptionstringNoDescripción del pago que se muestra al cliente. Máx. 255 caracteres.
merchant_idstringTu ID de comercio en Akua.
rail.idstringDebe ser BRE_B.
rail.typestringDebe ser BANK_TRANSFER.
return_urlstringNoURL HTTPS a la que redirigir al cliente tras completar el flujo del enlace de pago.
customer_data.emailstringNoCorreo del cliente.
customer_data.phone_numberstringNoNúmero de teléfono del cliente.
customer_data.first_namestringNoNombre del cliente.
customer_data.last_namestringNoApellido del cliente.

Respuesta — HTTP 201

{
  "payment_id": "pay-xxxxxxxxxxxxxxxxxxxx",
  "transaction": {
    "id": "trx-xxxxxxxxxxxxxxxxxxxx",
    "type": "PURCHASE",
    "status": "IN_PROGRESS",
    "status_detail": "PENDING",
    "amount": 150000
  },
  "rail": {
    "id": "BRE_B",
    "alias": "@STORE7X",
    "qr": {
      "image": "data:image/png;base64,...",
      "content": "00020101021226310014CO.COM.ACH.LLA..."
    },
    "payment_link": "https://pay.breb.com.co/t/abc123xyz"
  }
}

Muestra al cliente rail.qr.image y/o rail.payment_link. rail.alias es un código corto que el cliente puede escribir manualmente si no puede escanear el QR.

Webhooks

EventoSignificadoAcción recomendada
payment.purchase.pendingQR generado; el cliente aún no ha pagadoMostrar una pantalla de espera con el QR y el alias
payment.purchase.succeededEl cliente completó el pagoConfirmar el pedido y liberar el producto o servicio
payment.purchase.rejectedPago rechazado o QR expirado sin pagoNotificar al cliente; ofrecer un método de pago alternativo
payment.purchase.failedError técnicoRegistrar el error; contactar a soporte si persiste

Límites y reglas

ParámetroValor
MonedaCOP únicamente
Monto mínimo1.000 COP
Monto máximoSin límite de red; aplican los límites del banco del pagador
Vigencia del intento (QR / enlace de pago)15 minutos
Disponibilidad24/7/365 incluyendo festivos
LiquidaciónEn tiempo real (CUD)
Acreditación en AkuaT+1
ContracargosNo aplican — los pagos Bre-B son irrevocables
Captura separadaNo aplica — los fondos se mueven al momento del pago

Errores comunes

ErrorCausa probableResolución
amount must be greater than zeroamount.value es 0 o negativoAsegúrate de que amount.value > 0
rail.type inválidoSe envió un tipo de rail incorrectoDebe ser BANK_TRANSFER para Bre-B
merchant_id no encontradoEl ID de comercio no existe o está inactivoVerifica el merchant_id en tu panel de Akua
Webhook no recibidoLa URL de callback no está configurada o no devuelve HTTP 200Asegúrate de que tu endpoint responde en menos de 5 segundos

Nequi

Nequi es la billetera digital de Bancolombia, con aproximadamente 18 millones de usuarios en Colombia. Akua usa el flujo de cobro push: tu plataforma inicia el cobro, el cliente recibe una notificación push en la app de Nequi y aprueba o rechaza con su PIN.

Cómo funciona

  1. Tu servidor crea un intento de pago con rail.id: "NEQUI" y el número de celular del cliente.
  2. Nequi envía una notificación push al dispositivo del cliente.
  3. El cliente abre la app, revisa el cobro y aprueba o rechaza.
  4. Akua envía un webhook con el resultado final.

El cliente tiene 45 minutos para responder. Si no lo hace, el intento expira y Akua envía un webhook payment.purchase.rejected.

Crear un intento

POST /api/v1/payments/intents

Cuerpo de la solicitud

{
  "id": "order-12345",
  "amount": {
    "value": 50000,
    "currency": "COP"
  },
  "description": "Compra Online",
  "merchant_id": "mer-xxxxxxxxxxxxxxxxxxxx",
  "rail": {
    "id": "NEQUI",
    "type": "WALLET"
  },
  "customer_data": {
    "phone_number": "3001234567"
  }
}

Campos de la solicitud

CampoTipoRequeridoDescripción
idstringNoTu referencia interna del pedido. Máx. 255 caracteres.
amount.valuedecimalMonto del cobro en COP. Debe ser mayor a cero.
amount.currencystringDebe ser COP.
descriptionstringNoDescripción del pago visible para el cliente. Máx. 255 caracteres.
merchant_idstringTu ID de comercio en Akua.
rail.idstringDebe ser NEQUI.
rail.typestringDebe ser WALLET.
customer_data.phone_numberstringNúmero de celular colombiano registrado en Nequi. Acepta 3001234567 o +573001234567. Los caracteres no numéricos (excepto un + inicial) se eliminan automáticamente.
return_urlstringNoURL HTTPS de redirección tras completar el pago.

Respuesta — HTTP 201

{
  "payment_id": "pay-xxxxxxxxxxxxxxxxxxxx",
  "transaction": {
    "id": "trx-xxxxxxxxxxxxxxxxxxxx",
    "type": "PURCHASE",
    "status": "IN_PROGRESS",
    "status_detail": "PENDING",
    "amount": 50000
  }
}

IN_PROGRESS significa que la solicitud de cobro se envió correctamente a Nequi y el cliente ya recibió (o recibirá pronto) la notificación. No significa que el pago fue aprobado.

Webhooks

EventoSignificadoAcción recomendada
payment.purchase.pendingNotificación enviada; el cliente aún no respondeMostrar una pantalla de "esperando aprobación"
payment.purchase.succeededEl cliente aprobó; fondos debitadosConfirmar el pedido y liberar el producto o servicio
payment.purchase.rejectedEl cliente rechazó, o el intento expiró (TTL de 45 min)Notificar al cliente; ofrecer alternativa
payment.purchase.failedError del proveedor o técnicoRegistrar; no reintentar sin verificar el estado del intento

Límites y reglas

ParámetroValor
MonedaCOP únicamente
Límite por transacción~12.000.000 COP (definido por Bancolombia)
Límite mensual del pagador~7.000.000 COP (definido por Bancolombia)
TTL del intento45 minutos
Disponibilidad24/7
Acreditación en AkuaT+1
ContracargosNo aplican — los pagos Nequi son irrevocables una vez aprobados
Reenvío de notificaciónNo es posible; una notificación por intento
Reintento de un intento expiradoNo es posible; crear un nuevo intento

Errores comunes

ErrorCausa probableResolución
phone_number is required when rail.id is NEQUINo se envió customer_data.phone_numberIncluir el número de celular del cliente
Número no registrado en NequiNo hay cuenta Nequi activa para ese númeroOfrecer un método de pago alternativo
Notificación no recibidaNotificaciones push desactivadas o dispositivo sin conexiónIndicar al cliente que habilite las notificaciones de Nequi
Fondos insuficientesEl saldo de Nequi es menor al monto solicitadoEl cliente debe recargar o usar otro método
Cuenta bloqueadaBancolombia suspendió la cuentaEl intento falla en la creación; ofrecer una alternativa
Intento expirado (TTL)El cliente no respondió en 45 minutosCrear un nuevo intento si el cliente desea reintentar

Daviplata

Daviplata es la billetera digital de Davivienda. Funciona completamente por SMS — sin necesidad de app. Akua usa un flujo de dos pasos con OTP: tu plataforma crea el intento (lo que dispara un SMS al cliente) y luego confirma el OTP que el cliente ingresa en tu checkout.

Cómo funciona

  1. Tu servidor crea un intento de pago con rail.id: "DAVIPLATA" y el número de celular del cliente.
  2. Davivienda valida que el número corresponde a una cuenta Daviplata activa.
  3. Si es válido, Daviplata envía un OTP por SMS al celular del cliente. El SMS incluye el nombre del comercio, el monto y el código de confirmación.
  4. El cliente ingresa el OTP en tu checkout.
  5. Tu servidor llama a POST /api/v1/payments/intents/{payment_id}/confirm con el OTP.
  6. Akua valida el OTP y, si es correcto, ejecuta el débito de forma atómica.
  7. Akua envía un webhook con el resultado final.

El OTP es válido durante 15 minutos. Si expira, crea un nuevo intento — no hay mecanismo de reenvío.

Paso 1 — Crear un intento

POST /api/v1/payments/intents

Cuerpo de la solicitud

{
  "id": "order-12345",
  "amount": {
    "value": 75000,
    "currency": "COP"
  },
  "description": "Online store purchase",
  "merchant_id": "mer-xxxxxxxxxxxxxxxxxxxx",
  "rail": {
    "id": "DAVIPLATA",
    "type": "WALLET"
  },
  "customer_data": {
    "phone_number": "3001234567",
    "document": "1234567890",
    "document_type": "CC"
  }
}

Campos de la solicitud

CampoTipoRequeridoDescripción
idstringNoTu referencia interna del pedido. Máx. 255 caracteres.
amount.valuedecimalMonto del cobro en COP. Debe ser mayor a cero. Máximo: 3.000.000 COP por transacción.
amount.currencystringDebe ser COP.
descriptionstringNoConcepto del pago que aparece en el SMS. Máx. 255 caracteres.
merchant_idstringTu ID de comercio en Akua.
rail.idstringDebe ser DAVIPLATA.
rail.typestringDebe ser WALLET.
customer_data.phone_numberstringNúmero de celular colombiano registrado en Daviplata. Acepta 3001234567 o +573001234567. Los caracteres no numéricos (excepto un + inicial) se eliminan automáticamente.
customer_data.documentstringNoNúmero de documento del cliente. Recomendado para aumentar la tasa de aprobación.
customer_data.document_typestringNoTipo de documento. Valores válidos: CC, CE, TI.

Respuesta — HTTP 201

{
  "payment_id": "pay-xxxxxxxxxxxxxxxxxxxx",
  "transaction": {
    "id": "trx-xxxxxxxxxxxxxxxxxxxx",
    "type": "PURCHASE",
    "status": "IN_PROGRESS",
    "status_detail": "PENDING",
    "amount": 75000
  }
}

Guarda el payment_id — lo necesitarás para confirmar el OTP.

Paso 2 — Confirmar el OTP

Una vez que el cliente proporciona el OTP que recibió por SMS, envíalo a Akua:

POST /api/v1/payments/intents/{payment_id}/confirm

Cuerpo de la solicitud

{
  "otp": "123456"
}
CampoTipoRequeridoDescripción
otpstringEl OTP ingresado por el cliente.

Respuesta — HTTP 200

{
  "payment_id": "pay-xxxxxxxxxxxxxxxxxxxx",
  "transaction": {
    "id": "trx-xxxxxxxxxxxxxxxxxxxx",
    "type": "PURCHASE",
    "status": "IN_PROGRESS",
    "status_detail": "PENDING",
    "amount": 75000
  }
}

El HTTP 200 indica que Akua recibió y procesó la solicitud de confirmación — no garantiza que el pago fue aprobado. El resultado final llega por webhook.

Webhooks

EventoSignificadoAcción recomendada
payment.purchase.confirm.processedOTP validado; débito ejecutado con éxitoConfirmar el pedido y liberar el producto o servicio
payment.purchase.confirm.rejectedPago rechazado de forma definitiva por el proveedor (cuenta bloqueada, fondos insuficientes, etc.)Notificar al cliente; ofrecer alternativa — este intento no puede reintentarse
payment.purchase.confirm.failed.retryableOTP incorrecto; el intento sigue activo (PENDING_CUSTOMER)Mostrar un mensaje de "OTP incorrecto"; permitir que el cliente vuelva a ingresar el código y llame de nuevo a confirm con el mismo payment_id
payment.purchase.succeededEl pago alcanzó el estado AUTHORIZED (se emite junto con confirm.processed)Usar como señal adicional de autorización si se necesita
payment.purchase.failedError técnico durante el procesamientoRegistrar el error; contactar a soporte si persiste

Límites y reglas

ParámetroValor
MonedaCOP únicamente
Límite por transacción3.000.000 COP
Límites diarios/mensualesDefinidos por Davivienda según regulación (SFC)
Validez del OTP15 minutos
Disponibilidad24/7
Acreditación en AkuaT+1
EjecuciónAtómica: se debita el monto completo o nada
ContracargosNo aplican — los pagos Daviplata son irrevocables
Reenvío del OTPNo es posible; crear un nuevo intento

Errores comunes

EscenarioCausaResolución
Número no registrado en DaviplataNo hay cuenta Daviplata activa para ese teléfonoError devuelto en la creación del intento; ofrecer una alternativa
OTP incorrecto (confirm.failed.retryable)El cliente ingresó el código equivocadoMostrar el error; permitir reingreso con el mismo payment_id
OTP expirado (15 min)El cliente no ingresó el OTP a tiempoCrear un nuevo intento
Fondos insuficientesEl saldo de Daviplata es menor al monto solicitadoEl cliente debe recargar o usar otro método
Cuenta bloqueadaDavivienda restringió la cuentaError en la creación del intento; ofrecer una alternativa
Monto excede el límiteMonto > 3.000.000 COPReducir el monto o usar un método de pago diferente

PSE

PSE (Pagos Seguros en Línea) es la red interbancaria de pagos en línea de Colombia, operada por ACH Colombia. El cliente es redirigido al portal de internet banking de su propio banco, se autentica y autoriza el débito directamente. Tu plataforma nunca maneja credenciales bancarias.

Cómo funciona

  1. Muestra una lista de bancos disponibles obtenida dinámicamente desde la API de Akua. El cliente selecciona su banco.
  2. Tu servidor crea un intento de pago con rail.id: "PSE", el bank_id seleccionado y una return_url.
  3. Akua responde con un rail.payment_link — redirige al cliente a esta URL de inmediato.
  4. El cliente se autentica en su banco y autoriza el pago.
  5. El banco redirige de vuelta a tu return_url. Esto no confirma la aprobación.
  6. Verifica el estado final mediante webhook o una llamada de consulta antes de confirmar el pedido.

Paso 1 - Obtener los bancos disponibles

Antes de crear un intento, obtén la lista de bancos disponibles desde la API de Akua para mostrarla al cliente. Obtén siempre esta lista dinámicamente en tiempo de ejecución — no la codifiques de forma fija. La disponibilidad de los bancos cambia con el tiempo.

GET /api/banks?country=COL&rail_id=PSE

Ambos parámetros de query son obligatorios: country=COL y rail_id=PSE.

Respuesta

[
  { "id": "1007", "name": "BANCOLOMBIA" },
  { "id": "1051", "name": "DAVIVIENDA" },
  ...
]

Usa el id de la entidad seleccionada como customer_data.bank_id al crear el intento. Obtén esta lista en tiempo de ejecución cada vez; la disponibilidad de bancos cambia con el tiempo.

Paso 2 - Crear un intento

POST /api/v1/payments/intents

Cuerpo de la solicitud

{
  "id": "order-12345",
  "amount": {
    "value": 200000,
    "currency": "COP"
  },
  "description": "Invoice payment #2025-1001",
  "merchant_id": "mer-xxxxxxxxxxxxxxxxxxxx",
  "rail": {
    "id": "PSE",
    "type": "BANK_TRANSFER"
  },
  "return_url": "https://yoursite.com/payments/result",
  "customer_data": {
    "bank_id": "1007",
    "document": "1234567890",
    "document_type": "CC",
    "first_name": "Juan",
    "last_name": "Pérez",
    "email": "juan@example.com"
  }
}

Campos de la solicitud

CampoTipoRequeridoDescripción
idstringNoTu referencia interna del pedido. Máx. 255 caracteres.
amount.valuedecimalMonto del pago en COP. Debe ser mayor a cero.
amount.currencystringDebe ser COP.
descriptionstringNoDescripción del pago que se muestra en el comprobante bancario. Máx. 255 caracteres.
merchant_idstringTu ID de comercio en Akua.
rail.idstringDebe ser PSE.
rail.typestringDebe ser BANK_TRANSFER.
return_urlstringURL HTTPS pública a la que el banco redirige tras completar el paso bancario.
customer_data.bank_idstringID del banco seleccionado por el cliente. Obtén la lista desde la API de Akua.
customer_data.documentstringNúmero de documento del cliente.
customer_data.document_typestringTipo de documento. Valores válidos: CC, CE, NIT, PASSPORT.
customer_data.first_namestringNombre del cliente.
customer_data.last_namestringApellido del cliente.
customer_data.emailstringCorreo del cliente. ACH Colombia envía el comprobante a esta dirección.

Respuesta — HTTP 201

{
  "payment_id": "pay-xxxxxxxxxxxxxxxxxxxx",
  "transaction": {
    "id": "trx-xxxxxxxxxxxxxxxxxxxx",
    "type": "PURCHASE",
    "status": "IN_PROGRESS",
    "status_detail": "PENDING",
    "amount": 200000
  },
  "rail": {
    "id": "PSE",
    "payment_link": "https://pse.onepay.com/pay/session-abc123xyz"
  }
}

Redirige al cliente a rail.payment_link de inmediato. Esta URL tiene un tiempo de expiración definido por el banco — no la almacenes para uso posterior.

Estados del pago

EstadoSignificadoAcción recomendada
IN_PROGRESS / PENDINGEl cliente está en el portal bancario o no ha iniciadoMostrar una pantalla de "procesando"
APPROVEDEl banco autorizó el débito; fondos en tránsitoConfirmar el pedido
REJECTEDEl banco rechazó la autorizaciónNotificar al cliente; ofrecer reintentar o alternativa
PENDING_PROVIDERLa transacción llegó al banco pero el resultado aún no está resueltoHacer polling cada 15–30 segundos hasta un estado terminal
FAILEDError técnicoRegistrar el error; no reintentar sin verificar el estado actual

Importante: El retorno del cliente a tu return_url no es una confirmación de aprobación. Verifica siempre el estado del pago vía webhook o API antes de confirmar el pedido.

Webhooks

EventoSignificadoAcción recomendada
payment.purchase.pendingIntento creado; el cliente está siendo redirigido al bancoMostrar una pantalla de "procesando" mientras el cliente completa el paso bancario
payment.purchase.succeededEl banco aprobó el débitoConfirmar el pedido
payment.purchase.rejectedEl banco rechazó la transacciónNotificar al cliente; ofrecer una alternativa
payment.purchase.failedError técnicoRegistrar; contactar a soporte si persiste

Límites y reglas

ParámetroValor
MonedaCOP únicamente
Monto mínimoSin mínimo de red; los comercios pueden definir el suyo
Monto máximoSin límite de red; aplican los límites del banco del pagador
Vigencia del intento (enlace de pago)21 minutos
Bancos disponiblesMás de 30 bancos y cooperativas financieras colombianas
Pagos recurrentesNo soportados — cada pago requiere autenticación activa del cliente
Acreditación en AkuaT+1
ContracargosNo aplican — PSE es una transferencia bancaria autorizada explícitamente
DevolucionesSin reversión nativa; procesar como una transferencia bancaria separada (desembolso)
PollingObligatorio — la return_url por sí sola no es un mecanismo de confirmación confiable

Errores comunes

ErrorCausaResolución
bank_id is required when rail.id is PSENo se envió customer_data.bank_idIncluir el banco seleccionado por el cliente
return_url inválidaLa URL no es pública o no es accesibleAsegúrate de que la URL sea pública, válida y devuelva HTTP 200
PENDING_PROVIDER persistenteDemora de ACH Colombia o del bancoHacer polling con una espera máxima (p. ej. 30 minutos); marcar como fallido si no se resuelve
El cliente abandona el portal bancarioEl cliente cierra la pestaña o la sesión expiraEl estado puede quedar PENDING o REJECTED; esperar el webhook o hacer polling
Webhook no recibidoTu URL de callback no está activa o expiróImplementar un job de reconciliación que consulte periódicamente los estados de pago abiertos

Referencia de webhooks

Los cuatro rails de pago entregan los resultados finales como eventos webhook. Tu endpoint debe devolver HTTP 200 en menos de 5 segundos.

Estructura del payload del webhook

{
  "id": "evt-xxxxxxxxxxxxxxxxxxxx",
  "type": "payment.purchase.succeeded",
  "version": "1.0",
  "source": "payments-service",
  "time": "2025-10-15T14:32:00Z",
  "data": {
    "payment": {
      "id": "pay-xxxxxxxxxxxxxxxxxxxx",
      "currency": "COP",
      "current_amount": 150000,
      "merchant": {
        "id": "mer-xxxxxxxxxxxxxxxxxxxx"
      },
      "instrument": {
        "type": "WALLET"
      },
      "transaction": {
        "id": "trx-xxxxxxxxxxxxxxxxxxxx",
        "type": "PURCHASE",
        "status": "APPROVED",
        "status_detail": "SUCCESS"
      }
    }
  },
  "metadata": {
    "client_id": "cli-xxxxxxxxxxxxxxxxxxxx"
  }
}

Todos los tipos de evento

EventoRailsSignificado
payment.purchase.pendingBre-B, Nequi, PSEIntento creado y despachado al rail; esperando acción del cliente (PENDING_CUSTOMER)
payment.purchase.pending.providerPSEIntento despachado; esperando a que el proveedor (portal bancario) complete el procesamiento (PENDING_PROVIDER)
payment.purchase.succeededBre-B, Nequi, PSE, DaviplataPago aprobado; fondos confirmados
payment.purchase.rejectedBre-B, Nequi, PSEPago rechazado o intento expirado
payment.purchase.failedTodosError técnico durante el procesamiento
payment.purchase.confirm.processedDaviplataOTP confirmado y débito ejecutado
payment.purchase.confirm.rejectedDaviplataOTP rechazado de forma definitiva (problema de cuenta, etc.)
payment.purchase.confirm.failed.retryableDaviplataOTP incorrecto; el intento sigue activo y es reintentable

Confiabilidad de los webhooks

Los webhooks se entregan al menos una vez. Para manejar posibles duplicados, haz que tu handler de webhooks sea idempotente — usa el campo id como clave de deduplicación.

Si no se recibe un webhook:

  • Para Bre-B, Nequi, PSE: implementa un job de polling que consulte los intentos abiertos a intervalos regulares.
  • Para Daviplata: la respuesta del endpoint de confirmación es síncrona — si devuelve 200, la solicitud de confirmación fue procesada y el webhook llegará después.

Formato de respuesta de error

Los errores de validación y las fallas de solicitud devuelven un cuerpo de error estructurado:

{
  "code": "INVALID_REQUEST",
  "type": "VALIDATION",
  "message": "phone_number is required when rail.id is NEQUI",
  "processor_code": "30",
  "processor_message": "Format error"
}
Estado HTTPSignificado
201Intento creado; con el estado inicial de la transacción
200Solicitud de confirmación recibida (solo Daviplata)
400Error de validación — revisa el campo message
409Solicitud duplicada en curso (bloqueo de idempotencia activo)
423Ya hay una operación en curso para este pago (conflicto de concurrencia)
500Error interno

Devoluciones

Ninguno de los rails de pago instantáneo de Colombia admite reversiones nativas. Las devoluciones deben procesarse como desembolsos bancarios separados. Contacta a tu ejecutivo de cuenta de Akua para habilitar los desembolsos en tu integración.


Pruebas en Sandbox

El entorno sandbox simula el flujo completo de pago sin conectarse a redes de proveedores reales.

Activar el mock

Envía un monto cuyo valor entero termine en 00. Ejemplos: 35000, 75000, 100000, 1200. El sistema detecta este sufijo automáticamente y activa el mock para el canal seleccionado.

Cualquier otro monto envía la solicitud al proveedor real en staging. En el entorno sandbox no hay proveedores reales, por lo que los montos sin mock generalmente agotarán el tiempo de espera.

Comportamiento por método

MétodoComportamiento del mock
Bre-BDevuelve una imagen QR y un payment_link. Dispara el webhook payment.purchase.succeeded automáticamente en segundos.
NequiSimula la aprobación de una notificación push. Dispara el webhook payment.purchase.succeeded automáticamente en segundos.
Daviplata (paso 1)Simula el envío del OTP. Devuelve 202 IN_PROGRESS. Espera la llamada de confirmación.
Daviplata (paso 2)Acepta cualquier valor de OTP. Dispara el webhook payment.purchase.succeeded automáticamente en segundos.
PSEDevuelve un payment_link de sandbox. Dispara el webhook payment.purchase.succeeded automáticamente — no se necesita redirección al portal.

¿Te resultó útil?

PSE en Akua: pagos directos desde cuenta bancaria

Acepta pagos con PSE (Pagos Seguros en Línea) a través de Akua. El cliente es redirigido a su propio banco, se autentica, y autoriza el débito directamente desde su cuenta bancaria.


Antes de empezar

  • URL base: https://sandbox.akua.la (pruebas) o https://api.akua.la (producción).
  • Autenticación: OAuth 2.0 client-credentials. Obtén un token con POST /oauth/token y envíalo como Authorization: Bearer <access_token> en cada llamada. Ver la guía maestra Pagos instantáneos en Colombia → Autenticación.
  • Redirección obligatoria: PSE lleva al cliente al portal de su banco; siempre debes enviar un return_url.

¿Qué es PSE?

PSE (Pagos Seguros en Línea) es la red de pagos interbancarios en línea de Colombia, operada por ACH Colombia — un consorcio propiedad de los principales bancos del país. Es el método de pago dominante para transacciones electrónicas directas desde cuentas bancarias en Colombia, presente en más de 30 entidades financieras, incluyendo Bancolombia, Davivienda, BBVA Colombia, Banco de Bogotá y Scotiabank Colpatria, entre otras.

A diferencia de las billeteras digitales o las tarjetas, PSE no pertenece a un emisor único: es infraestructura compartida del sistema financiero colombiano. Esto le da una cobertura institucional sin igual y un nivel de confianza consolidado entre los usuarios colombianos.

El mecanismo central de PSE es una redirección bancaria: el cliente es enviado desde tu checkout al portal de internet banking de su propio banco, donde se autentica y autoriza el débito directamente. Tu plataforma nunca accede a las credenciales bancarias del cliente.

PSE es particularmente adecuado para pagos de monto mediano y alto, pagos B2B, servicios públicos, seguros y cualquier contexto donde el cliente prefiera pagar directamente desde su cuenta bancaria.


¿Cómo funciona un pago con PSE en Akua?

Paso 1 — El cliente selecciona su banco

En tu checkout, el cliente elige PSE como método de pago y selecciona su banco de la lista. Esta lista debe obtenerse dinámicamente desde la API de Akua (GET /api/banks?country=COL&rail_id=PSE) para garantizar que solo se muestren las entidades actualmente disponibles. No codifiques la lista de bancos en tu integración — puede cambiar.

Paso 2 — Crear el intento de pago

Tu plataforma llama a POST /api/v1/payments/intents con el banco seleccionado, los datos del cliente y la URL de retorno (return_url). Akua crea el intento y devuelve un payment_link — la URL de redirección al portal bancario del cliente.

Paso 3 — Redirigir al cliente al banco

Tu checkout redirige el navegador del cliente a la URL recibida en rail.payment_link. El cliente entra al portal de internet banking de su banco, donde el banco controla completamente la experiencia de autenticación (usuario, contraseña, token, biometría, etc.).

Tu plataforma no tiene visibilidad de lo que ocurre dentro del portal bancario. El banco puede solicitar pasos de autenticación adicionales según sus propias políticas de seguridad.

Paso 4 — El cliente autoriza el pago en su banco

Dentro del portal bancario, el cliente ve los detalles de la transacción (comercio, monto, referencia) y confirma el débito. El banco procesa la autorización y redirige al cliente de vuelta a tu return_url.

Si el cliente abandona el portal bancario (cierra la pestaña, cierra sesión, se acaba el tiempo de la sesión bancaria), la transacción puede quedar en estado IN_PROGRESS con status_detail PENDING o pasar a DECLINED, según si el banco registró alguna acción antes del abandono.

Paso 5 — Retorno al checkout y verificación de estado

La redirección de vuelta a tu return_url no confirma que el pago fue aprobado. Solo indica que el cliente completó (o abandonó) el paso bancario. Inmediatamente al recibir al cliente de vuelta, tu plataforma debe consultar el estado del pago para obtener el resultado definitivo.

Si el estado es APPROVED, el pedido puede confirmarse. Si es DECLINED, el cliente debe ser notificado. Si el status_detail es PENDING o PENDING_VALIDATION, es necesario implementar un mecanismo de sondeo (polling) hasta recibir un estado terminal.

Paso 6 — Confirmación vía webhook

Akua también envía un webhook cuando el pago es confirmado. Usa el webhook como el mecanismo principal de notificación, pero no dependas de él exclusivamente — implementa igualmente el polling para los estados no terminales.


Obtener la lista de bancos

Antes de crear el intento, obtén la lista de bancos disponibles para mostrarla al cliente.

GET /api/banks?country=COL&rail_id=PSE

Ambos parámetros de query son obligatorios: country=COL y rail_id=PSE.

Respuesta

[
  { "id": "1007", "name": "BANCOLOMBIA" },
  { "id": "1051", "name": "DAVIVIENDA" },
  ...
]

Usa el id de la entidad seleccionada como customer_data.bank_id al crear el intento. Obtén esta lista en tiempo de ejecución cada vez; la disponibilidad de bancos cambia con el tiempo.


Cómo crear un pago con PSE

Endpoint

POST /api/v1/payments/intents

Cuerpo de la solicitud

{
  "id": "orden-12345",
  "amount": {
    "value": 200000,
    "currency": "COP"
  },
  "description": "Pago de factura #2025-1001",
  "merchant_id": "mer-xxxxxxxxxxxxxxxxxxxx",
  "rail": {
    "id": "PSE",
    "type": "BANK_TRANSFER"
  },
  "return_url": "https://mitienda.com/pagos/resultado",
  "customer_data": {
    "bank_id": "1007",
    "document": "1234567890",
    "document_type": "CC",
    "first_name": "Juan",
    "last_name": "Pérez",
    "email": "juan@ejemplo.com"
  }
}
CampoTipoRequeridoDescripción
idstringNoTu identificador interno del pedido. Máx. 255 caracteres.
amount.valuedecimalMonto del pago en COP. Debe ser mayor a cero.
amount.currencystringDebe ser COP. PSE no procesa monedas extranjeras.
descriptionstringNoDescripción del pago. Aparece en el comprobante del cliente. Máx. 255 caracteres.
merchant_idstringID del comercio en Akua.
rail.idstringDebe ser PSE.
rail.typestringDebe ser BANK_TRANSFER.
return_urlstringURL a la que el banco redirige al cliente tras completar el paso bancario. Debe ser una URL pública y válida.
customer_data.bank_idstringID de la entidad bancaria seleccionada por el cliente. Obtén esta lista desde GET /api/banks?country=COL&rail_id=PSE.
customer_data.documentstringNúmero de documento del pagador.
customer_data.document_typestringTipo de documento. Valores válidos: CC, CE, NIT, PASSPORT.
customer_data.first_namestringNombre(s) del pagador.
customer_data.last_namestringApellido(s) del pagador.
customer_data.emailstringCorreo electrónico del pagador. ACH Colombia envía el comprobante a esta dirección.

Respuesta exitosa (HTTP 202)

{
  "payment_id": "pay-xxxxxxxxxxxxxxxxxxxx",
  "transaction": {
    "id": "trx-xxxxxxxxxxxxxxxxxxxx",
    "type": "PURCHASE",
    "status": "IN_PROGRESS",
    "status_detail": "PENDING",
    "amount": 200000
  },
  "rail": {
    "id": "PSE",
    "payment_link": "https://pse.onepay.com/pay/session-abc123xyz"
  }
}

Debes redirigir inmediatamente al cliente a la URL indicada en rail.payment_link. Esta URL tiene un tiempo de expiración definido por el banco — no la almacenes para uso posterior.


Estados del pago

status / status_detailSignificadoAcción recomendada
IN_PROGRESS / PENDINGEl cliente aún está en el portal bancario o no ha iniciado el procesoEspera; muestra un mensaje de "procesando" en tu checkout
IN_PROGRESS / PENDING_PROVIDEREl intento fue despachado y el proveedor (portal bancario) está procesandoMuestra "procesando"; espera el webhook
APPROVED / SUCCESSEl banco autorizó el débito; los fondos están en tránsitoConfirmar el pedido y liberar el producto o servicio
DECLINEDEl banco rechazó la autorización (fondos insuficientes, credenciales incorrectas, cliente canceló)Notificar al cliente; ofrecer reintentar con otro banco o método de pago
IN_PROGRESS / PENDING_VALIDATIONLa transacción llegó al banco pero el resultado aún no está resueltoImplementar polling cada 15–30 segundos hasta obtener un estado terminal
FAILEDError técnico en el flujoRegistrar el error; no reintentar sin verificar el estado actual

Importante: La redirección del cliente de vuelta a tu return_url no es una garantía de aprobación. Siempre consulta el estado del pago vía API o espera el webhook antes de confirmar el pedido.


Webhooks

EventoSignificadoAcción recomendada
payment.purchase.pendingEl intento fue creado; el cliente está siendo redirigido al bancoMostrar pantalla de "procesando" mientras el cliente completa el paso bancario
payment.purchase.pending.providerEl intento fue despachado; el proveedor (portal bancario) está completando el procesamientoMantener pantalla de "procesando"; esperar el resultado
payment.purchase.succeededEl banco aprobó el débito; los fondos están en tránsitoConfirmar el pedido
payment.purchase.rejectedEl banco rechazó la transacciónNotificar al cliente y ofrecer alternativa
payment.purchase.failedError técnico en el procesamientoRegistrar; contactar soporte si persiste

Ejemplo de webhook de pago exitoso

{
  "id": "evt-xxxxxxxxxxxxxxxxxxxx",
  "type": "payment.purchase.succeeded",
  "version": "1.0",
  "source": "payments-service",
  "time": "2025-10-15T15:10:00Z",
  "data": {
    "payment": {
      "id": "pay-xxxxxxxxxxxxxxxxxxxx",
      "currency": "COP",
      "current_amount": 200000,
      "merchant": { "id": "mer-xxxxxxxxxxxxxxxxxxxx" },
      "instrument": { "type": "BANK_TRANSFER" },
      "transaction": {
        "id": "trx-xxxxxxxxxxxxxxxxxxxx",
        "type": "PURCHASE",
        "status": "APPROVED",
        "status_detail": "SUCCESS"
      }
    }
  },
  "metadata": {
    "client_id": "cli-xxxxxxxxxxxxxxxxxxxx"
  }
}

Reglas y límites

ParámetroValor
MonedaCOP únicamente
Monto mínimoSin mínimo a nivel de red; los comercios pueden definir uno propio
Monto máximoSin límite de red; aplican límites del banco del pagador para su portal de internet banking
Entidades disponiblesMás de 30 bancos y cooperativas financieras colombianas
Credenciales almacenadasNo aplica. PSE es completamente basado en sesión; no hay tokenización ni cobros recurrentes
Acreditación en AkuaT+1
ContracargosNo aplican. PSE es una transferencia bancaria autorizada explícitamente por el usuario
DevolucionesNo hay reversión nativa. Las devoluciones se procesan como transferencias bancarias separadas (desembolsos)
Polling obligatorioSí. Las integraciones que dependen solo del return_url tendrán confirmaciones poco confiables
Moneda extranjeraNo soportada

Nota: PSE no soporta pagos recurrentes ni suscripciones. Cada cobro requiere que el cliente complete un nuevo proceso de autenticación en su banco.


Errores frecuentes y cómo resolverlos

EscenarioCausaSolución
bank_id is required when rail.id is PSENo se envió customer_data.bank_idIncluir el banco seleccionado por el cliente en la solicitud
return_url inválidaLa URL no es válida o no es accesible públicamenteVerificar que la URL sea pública, válida y devuelva HTTP 200
Estado PENDING_VALIDATION persistenteDemora de ACH Colombia o del banco en resolver la transacciónImplementar polling con espera máxima (ej. 30 minutos); registrar como fallido si no se resuelve
Cliente abandona el bancoEl cliente cierra la pestaña o la sesión bancaria expiraEl estado puede quedar PENDING o DECLINED; espera el webhook o haz polling
Banco incorrecto seleccionadoEl cliente eligió un banco donde no tiene cuenta activaLa autenticación falla en el portal bancario; el resultado será DECLINED
Webhook no recibidoTu URL de callback no está activa o no responde en tiempoImplementar un job de reconciliación que consulte estados abiertos periódicamente
Credenciales bancarias incorrectasEl cliente falla la autenticación en su bancoEl banco devuelve DECLINED; notificar al cliente para que reintente con las credenciales correctas
Cliente sin internet banking habilitadoEl cliente tiene cuenta bancaria pero no tiene acceso configurado al portal de su bancoInformar al cliente; ofrecer método de pago alternativo

Pruebas en sandbox

Prueba PSE de punta a punta en https://sandbox.akua.la antes de producción. Casos mínimos recomendados: pago aprobado, pago rechazado por el banco, abandono del portal bancario y PENDING_VALIDATION persistente.

Por confirmar con tu ejecutivo de cuenta: los bancos de prueba y el mecanismo para forzar cada desenlace en sandbox se entregan junto con tus credenciales. (Pendiente de estandarizar en el ambiente unificado.)


Preguntas frecuentes

¿Tengo que mostrar todos los bancos disponibles en el checkout? Debes obtener la lista de entidades activas desde GET /api/banks?country=COL&rail_id=PSE en tiempo de ejecución para garantizar que solo muestras los bancos actualmente disponibles. No codifiques la lista de bancos en tu integración — puede cambiar.

¿El cliente puede pagar con PSE sin tener internet banking habilitado? No. PSE requiere que el cliente tenga activo el acceso al portal de internet banking de su banco. Si no lo tiene, la autenticación fallará.

¿Puedo usar PSE para pagos recurrentes? No. PSE no soporta almacenamiento de credenciales ni cobros automáticos. Cada pago requiere la participación activa del cliente en una nueva sesión bancaria.

¿Qué pasa si el webhook no llega? Implementa un job de reconciliación que consulte el estado de los pagos en estado IN_PROGRESS o con status_detail PENDING_VALIDATION al menos una vez al día. No dependas exclusivamente del webhook para confirmar pedidos.

¿Puedo hacer devoluciones con PSE? PSE no tiene mecanismo de reversión nativo. Las devoluciones se procesan como desembolsos (transferencias bancarias) separados. Consulta el artículo sobre devoluciones en Akua para más detalle.


Artículos relacionados: Pagos instantáneos en Colombia (guía maestra) · Ciclo de vida de un pago en Akua · Bre-B en Akua · Nequi en Akua · Daviplata en Akua · Webhooks y notificaciones

¿Te resultó útil?

Bre-B en Akua: pagos instantáneos interoperables

Acepta pagos en tiempo real a través de Bre-B, el sistema de pagos instantáneos de Colombia, directamente desde la API de Akua.


¿Qué es Bre-B?

Bre-B es el sistema de pagos instantáneos e interoperables de Colombia, creado y operado por el Banco de la República. Funciona de manera similar a PIX en Brasil o UPI en India: una infraestructura nacional que permite transferencias de dinero en tiempo real entre cualquier entidad financiera del país, sin importar cuál sea el banco del pagador o del receptor.

Bre-B opera a través de una red de nodos interconectados (entre ellos Transfiya, Entrecuentas y Visionamos) y utiliza el sistema CUD del Banco de la República para la liquidación final. Cada transacción se liquida de forma individual e inmediata — no hay lotes ni compensación al final del día.

El sistema comenzó a operar en septiembre de 2025 y está disponible 24 horas al día, 7 días a la semana, los 365 días del año, incluyendo fines de semana y festivos.


Conceptos clave

ConceptoDescripción
Llave (Key)Alias digital registrado en el directorio centralizado de Bre-B. Puede ser un número de cédula, número de celular, correo electrónico o un código alfanumérico. Cada llave apunta a una cuenta bancaria específica.
QR Bre-BCódigo QR que el cliente escanea para iniciar el pago. Contiene la información de la llave del comercio. Akua lo genera automáticamente al crear el intento de pago.
AliasCódigo corto (p.ej. @COMERCIO7X) que el cliente puede usar para pagar manualmente si no puede escanear el QR.
LiquidaciónEl movimiento real de fondos, que ocurre en tiempo real a través del CUD. Una vez liquidada, la transacción es irrevocable.
IrrevocabilidadA diferencia de los pagos con tarjeta, las transacciones Bre-B no tienen contracargos. Una vez que el cliente paga, el pago es definitivo.

¿Cómo funciona un pago con Bre-B en Akua?

El flujo completo ocurre en dos etapas: tu plataforma crea el intento de pago, y el cliente lo ejecuta desde su aplicación bancaria escaneando el QR o usando el alias.

Paso 1 — Crear el intento de pago

Tu plataforma llama a POST /api/v1/payments/intents con los datos del pago y el rail BRE_B. Akua responde de inmediato con un código QR y un alias que debes mostrar al cliente en el checkout.

Paso 2 — El cliente escanea y paga

El cliente abre su aplicación bancaria, escanea el QR o ingresa el alias, confirma el monto y autoriza el pago. El pago se ejecuta en tiempo real directamente desde su cuenta bancaria.

Paso 3 — Confirmación vía webhook

En cuanto el pago es confirmado, Akua envía un webhook a tu URL de callback con el estado final del pago. Tu plataforma debe escuchar este evento para confirmar la transacción y liberar el pedido.

Importante: Bre-B no tiene un paso de captura separado. A diferencia de los pagos con tarjeta, el dinero se mueve en el momento en que el cliente paga. No uses el flujo de autorización/captura para este método.


Cómo crear un pago con Bre-B

Endpoint

POST /api/v1/payments/intents

Cuerpo de la solicitud

{
  "id": "orden-12345",
  "amount": {
    "value": 150000,
    "currency": "COP"
  },
  "description": "Compra en tienda online",
  "merchant_id": "mer-xxxxxxxxxxxxxxxxxxxx",
  "rail": {
    "id": "BRE_B",
    "type": "BANK_TRANSFER"
  }
}
CampoTipoRequeridoDescripción
idstringNoTu identificador interno del pedido. Si no se envía, Akua genera uno automáticamente. Máx. 255 caracteres.
amount.valuedecimalMonto del pago. Debe ser mayor a cero. Mínimo: 1.000 COP.
amount.currencystringCódigo de moneda ISO 4217. Para Colombia: COP.
descriptionstringNoDescripción del pago. Máx. 255 caracteres.
merchant_idstringID del comercio en Akua.
rail.idstringDebe ser BRE_B.
rail.typestringDebe ser BANK_TRANSFER.

Respuesta exitosa (HTTP 201)

{
  "payment_id": "pay-xxxxxxxxxxxxxxxxxxxx",
  "transaction": {
    "id": "trx-xxxxxxxxxxxxxxxxxxxx",
    "type": "PURCHASE",
    "status": "IN_PROGRESS",
    "status_detail": "PENDING",
    "amount": 150000
  },
  "rail": {
    "id": "BRE_B",
    "alias": "@COMERCIO7X",
    "qr": {
      "image": "data:image/png;base64,...",
      "content": "00020101021226310014CO.COM.ACH.LLA..."
    }
  }
}

Debes mostrar al cliente tanto el QR (rail.qr.image) como el alias (rail.alias). El cliente puede usar cualquiera de los dos para completar el pago. Mostrar ambas opciones es requerido para cumplir con la experiencia de usuario de Bre-B.


Webhooks

Akua envía un webhook a tu URL de callback cuando el estado del pago cambia. Debes implementar el manejo de estos eventos para confirmar o rechazar pedidos en tu plataforma.

EventoSignificadoAcción recomendada
payment.purchase.processedEl cliente completó el pago exitosamenteConfirmar el pedido y liberar el producto o servicio
payment.purchase.rejectedEl pago fue rechazado o el cliente cancelóNotificar al cliente y ofrecer un método alternativo
payment.purchase.failedError del proveedor o falla técnicaRegistrar el error y contactar a soporte si persiste

Ejemplo de webhook de pago exitoso

{
  "id": "evt-xxxxxxxxxxxxxxxxxxxx",
  "type": "payment.purchase.processed",
  "version": "1.0",
  "source": "payments-service",
  "time": "2025-10-15T14:32:00Z",
  "data": {
    "payment": {
      "id": "pay-xxxxxxxxxxxxxxxxxxxx",
      "currency": "COP",
      "current_amount": 150000,
      "merchant": { "id": "mer-xxxxxxxxxxxxxxxxxxxx" },
      "instrument": { "type": "BANK_TRANSFER" },
      "transaction": {
        "id": "trx-xxxxxxxxxxxxxxxxxxxx",
        "type": "PURCHASE",
        "status": "APPROVED",
        "status_detail": "SUCCESS"
      }
    }
  },
  "metadata": {
    "client_id": "cli-xxxxxxxxxxxxxxxxxxxx"
  }
}

No confirmes pedidos basándote únicamente en la respuesta del POST /api/v1/payments/intents. La respuesta inicial solo indica que el QR fue generado. El webhook es la única señal confiable de que el pago fue completado.


Reglas y límites

ParámetroValor
MonedaCOP únicamente
Monto mínimo1.000 COP
Monto máximoSin límite a nivel de red; aplican límites del banco del pagador
Disponibilidad24/7/365, incluyendo festivos
Tiempo de liquidaciónInmediato (real-time gross settlement vía CUD)
Acreditación en AkuaT+1
Reversiones / contracargosNo aplican. Los pagos Bre-B son irrevocables una vez liquidados
Captura separadaNo aplica. El dinero se mueve en el momento del pago

Errores frecuentes

ErrorCausa probableCómo resolverlo
amount must be greater than zeroEl valor enviado es 0 o negativoVerifica que amount.value sea mayor a cero
amount.currency inválidaEl código de moneda no es ISO 4217Usa COP para pagos en Colombia
rail.type inválidoEl tipo de rail no correspondePara Bre-B debe ser BANK_TRANSFER
merchant_id no encontradoEl ID del comercio no existe o no está activoVerifica el merchant_id en tu configuración de Akua
Webhook no recibidoTu URL de callback no está configurada o no respondeAsegúrate de que tu endpoint responde con HTTP 200 en menos de 5 segundos

Preguntas frecuentes

¿El cliente necesita tener una cuenta en un banco específico? No. Bre-B es interoperable: el cliente puede pagar desde cualquier entidad financiera colombiana que esté conectada al sistema, sin importar cuál sea su banco.

¿Qué pasa si el cliente no paga el QR? El intento de pago queda en estado IN_PROGRESS hasta que el cliente pague o expire el tiempo definido por el proveedor. Si el QR expira sin pago, recibirás un webhook con estado payment.purchase.rejected.

¿Se pueden hacer devoluciones? Las transacciones Bre-B son irrevocables por diseño del sistema. Las devoluciones deben procesarse como transferencias bancarias separadas. Consulta el artículo sobre devoluciones en Akua para más detalle.


¿Te resultó útil?

Nequi en Akua: cobro push a billetera digital

Acepta pagos con Nequi directamente desde la API de Akua. El cliente recibe una notificación push en su app y aprueba el cobro con su PIN, sin redirecciones ni datos de tarjeta.


¿Qué es Nequi?

Nequi es la billetera digital de Bancolombia, con aproximadamente 18 millones de usuarios en Colombia. Es uno de los métodos de pago digitales con mayor penetración en el país.

El flujo que Akua implementa se conoce en el mercado como cobro push o pago push: tu plataforma es quien inicia el cobro, y el cliente simplemente aprueba o rechaza desde la app de Nequi. No hay redirección a páginas externas ni necesidad de ingresar datos bancarios en el checkout.

Nequi es ideal para flujos de pago donde el cliente ya proporcionó su número de celular registrado en Nequi y quieres ofrecerle una experiencia de aprobación rápida y sin fricción.


¿Cómo funciona un pago con Nequi en Akua?

Paso 1 — Crear el intento de pago

Tu plataforma llama a POST /api/v1/payments/intents con el número de celular del cliente y el rail NEQUI. Akua envía la solicitud de cobro a Bancolombia, que la registra en su sistema y empieza el contador de tiempo de espera.

Paso 2 — El cliente recibe la notificación

Nequi envía una notificación push al celular del cliente. La notificación muestra el nombre del comercio, el monto solicitado en COP y un botón para abrir la app.

Nota: Nequi envía una sola notificación por intento de pago. Si el cliente no tiene habilitadas las notificaciones de la app, no la recibirá. Si su dispositivo está sin conexión, la notificación llegará cuando se reconecte — pero el contador de tiempo sigue corriendo.

Paso 3 — El cliente aprueba o rechaza en la app

El cliente abre Nequi, ve los detalles del cobro (comercio, monto, referencia) y decide:

  • Aprobar: selecciona la fuente de fondos (saldo disponible) y confirma con su PIN. El débito se ejecuta en tiempo real.
  • Rechazar: descarta la solicitud. El intento pasa a estado REJECTED de inmediato.

Paso 4 — Confirmación vía webhook

Akua envía un webhook a tu URL de callback con el resultado final. Tu plataforma debe escuchar este evento para confirmar o cancelar el pedido.

Paso 5 — Tiempo de espera (TTL)

El cliente tiene 45 minutos para responder desde que se crea el intento. Si no hay respuesta en ese tiempo, el intento expira y recibirás un webhook con estado payment.purchase.rejected.


Cómo crear un pago con Nequi

Endpoint

POST /api/v1/payments/intents

Cuerpo de la solicitud

{
  "id": "orden-12345",
  "amount": {
    "value": 50000,
    "currency": "COP"
  },
  "description": "Compra en tienda online",
  "merchant_id": "mer-xxxxxxxxxxxxxxxxxxxx",
  "rail": {
    "id": "NEQUI",
    "type": "WALLET"
  },
  "customer_data": {
    "phone_number": "3001234567"
  }
}
CampoTipoRequeridoDescripción
idstringNoTu identificador interno del pedido. Si no se envía, Akua genera uno automáticamente. Máx. 255 caracteres.
amount.valuedecimalMonto del cobro en COP. Debe ser mayor a cero.
amount.currencystringDebe ser COP. Nequi no procesa monedas extranjeras.
descriptionstringNoDescripción del pago visible para el cliente. Máx. 255 caracteres.
merchant_idstringID del comercio en Akua.
rail.idstringDebe ser NEQUI.
rail.typestringDebe ser WALLET.
customer_data.phone_numberstringNúmero de celular colombiano registrado en Nequi. Formato: 10 dígitos sin prefijo de país (p.ej. 3001234567).

Respuesta exitosa (HTTP 201)

{
  "payment_id": "pay-xxxxxxxxxxxxxxxxxxxx",
  "transaction": {
    "id": "trx-xxxxxxxxxxxxxxxxxxxx",
    "type": "PURCHASE",
    "status": "IN_PROGRESS",
    "status_detail": "PENDING",
    "amount": 50000
  }
}

El estado IN_PROGRESS indica que la solicitud de cobro fue enviada correctamente a Nequi y el cliente ya recibió (o recibirá) la notificación. No implica que el pago fue aprobado. El resultado definitivo llega por webhook.


Webhooks

EventoSignificadoAcción recomendada
payment.purchase.processedEl cliente aprobó el cobro; el débito fue ejecutado en su billeteraConfirmar el pedido y liberar el producto o servicio
payment.purchase.rejectedEl cliente rechazó la solicitud, o el intento expiró sin respuestaNotificar al cliente y ofrecer un método de pago alternativo
payment.purchase.failedError del proveedor o falla técnica en el procesamientoRegistrar el error; no reintentar sin verificar el estado del intento

Ejemplo de webhook de pago exitoso

{
  "id": "evt-xxxxxxxxxxxxxxxxxxxx",
  "type": "payment.purchase.processed",
  "version": "1.0",
  "source": "payments-service",
  "time": "2025-10-15T14:32:00Z",
  "data": {
    "payment": {
      "id": "pay-xxxxxxxxxxxxxxxxxxxx",
      "currency": "COP",
      "current_amount": 50000,
      "merchant": { "id": "mer-xxxxxxxxxxxxxxxxxxxx" },
      "instrument": { "type": "WALLET" },
      "transaction": {
        "id": "trx-xxxxxxxxxxxxxxxxxxxx",
        "type": "PURCHASE",
        "status": "APPROVED",
        "status_detail": "SUCCESS"
      }
    }
  },
  "metadata": {
    "client_id": "cli-xxxxxxxxxxxxxxxxxxxx"
  }
}

Reglas y límites

ParámetroValor
MonedaCOP únicamente
Límite mensual del pagador~7.000.000 COP (límite estándar de Bancolombia para cuentas Nequi)
Límite por transacción~12.000.000 COP
TTL del intento45 minutos
Disponibilidad24/7
Acreditación en AkuaT+1
ContracargosNo aplican. Los pagos Nequi son irreversibles una vez aprobados
Captura separadaNo aplica. El débito ocurre en el momento de la aprobación
Reintento del mismo intentoNo es posible. Un intento expirado o rechazado es terminal; debes crear uno nuevo
Reenvío de notificaciónNo es posible. Nequi envía una sola notificación por intento

Nota sobre límites del pagador: Los límites de transacción y mensuales son definidos por Bancolombia a nivel de cuenta de usuario, no por Akua. Los clientes con cuenta completa verificada pueden tener límites más altos. Si un pago es rechazado por límite excedido, el cliente debe usar otro método de pago o contactar a Nequi.


Errores frecuentes y cómo resolverlos

EscenarioCausaSolución
phone_number is required when rail.id is NEQUINo se envió el campo customer_data.phone_numberIncluir el número de celular del cliente en la solicitud
Número no registrado en NequiEl celular no tiene una cuenta Nequi activaValidar antes del checkout que el número esté registrado; ofrecer método alternativo
Notificación no recibidaNotificaciones desactivadas o dispositivo sin conexiónIndicar al cliente en el checkout que tenga habilitadas las notificaciones de Nequi
Fondos insuficientesEl saldo disponible en Nequi es menor al monto solicitadoEl intento llega a estado REJECTED; notificar al cliente para que recargue su saldo o use otro método
Cuenta bloqueada o restringidaBancolombia ha suspendido la cuenta del usuarioEl intento falla en creación; ofrecer método de pago alternativo
Intento expirado (TTL vencido)El cliente no respondió en 45 minutosEl webhook llega con estado payment.purchase.rejected; crear un nuevo intento si el cliente quiere reintentar
Límite de transacción excedidoEl monto supera el tope por transacción del usuarioInformar al cliente; no es posible procesar el monto con Nequi

Preguntas frecuentes

¿El cliente necesita tener la app de Nequi instalada? Sí. El flujo de cobro push requiere que el cliente tenga la app de Nequi instalada en su dispositivo con notificaciones habilitadas.

¿Qué pasa si el cliente rechaza el cobro? El intento pasa a estado terminal REJECTED de inmediato. No es posible retomar el mismo intento; debes crear uno nuevo si el cliente desea intentar de nuevo.

¿Puedo hacer devoluciones? Los cobros Nequi no tienen un mecanismo de devolución nativo dentro del rail. Las devoluciones deben procesarse como transferencias bancarias separadas. Consulta el artículo sobre devoluciones en Akua para más detalle.

¿Qué pasa si creo dos intentos para el mismo cliente al mismo tiempo? Cada intento es independiente. El cliente recibirá dos notificaciones. Usa el campo id con tu referencia interna y controla la idempotencia desde tu plataforma para evitar cargos duplicados.


¿Te resultó útil?

Daviplata en Akua: cobro con OTP por SMS

Acepta pagos con Daviplata a través de Akua. El cliente recibe un código de un solo uso por SMS y lo ingresa en tu checkout para autorizar el débito, sin necesidad de instalar ninguna app.


¿Qué es Daviplata?

Daviplata es la billetera digital de Davivienda. A diferencia de otros métodos de pago digitales, funciona únicamente por SMS: no requiere que el cliente tenga la app instalada, ni acceso a internet en su dispositivo. Esto lo hace accesible para un segmento amplio de usuarios.

El flujo que Akua implementa es el de cobro push con OTP: tu plataforma inicia el cobro, Daviplata envía un código de un solo uso (OTP) al celular del cliente por SMS, y el cliente lo ingresa en el checkout para confirmar el pago. El débito se ejecuta inmediatamente al validar el OTP.

Este método es especialmente efectivo para transacciones de bajo a mediano monto y contextos donde reducir la fricción del cliente importa, sin sacrificar la confirmación explícita del pago.


¿Cómo funciona un pago con Daviplata en Akua?

El flujo es de dos pasos: primero creas el intento de pago (lo que dispara el SMS), y luego confirmas el OTP que el cliente recibió.

Paso 1 — Crear el intento de pago

Tu plataforma llama a POST /api/v1/payments/intents con el número de celular del cliente y el rail DAVIPLATA. Davivienda valida que el número corresponde a una cuenta Daviplata activa. Si la validación falla, el intento se rechaza de inmediato y no se envía ningún SMS.

Paso 2 — El cliente recibe el OTP por SMS

Si la validación es exitosa, Daviplata envía un SMS al celular del cliente con el OTP. El mensaje incluye el nombre del comercio, el monto y el código de confirmación. No se requiere app ni internet en el dispositivo del cliente.

Tiempo de validez del OTP: El OTP es válido durante 15 minutos desde que se envía. Si el cliente no lo usa en ese tiempo, el intento completo expira y deberás crear uno nuevo.

Paso 3 — El cliente ingresa el OTP en tu checkout

Tu checkout debe mostrar un campo para que el cliente ingrese el OTP que recibió por SMS. Esta interacción ocurre completamente dentro de tu interfaz — Akua no tiene visibilidad de este paso hasta que envíes el OTP en el siguiente.

Paso 4 — Confirmar el OTP

Tu backend llama a POST /api/v1/payments/intents/{payment_id}/confirm con el OTP que el cliente ingresó. Akua lo reenvía al procesador, que valida el código y ejecuta el débito de forma atómica. Si el OTP es correcto y está dentro del tiempo de validez, el pago se completa en ese momento.

Paso 5 — Confirmación vía webhook

Akua envía un webhook con el resultado de la confirmación. Recibirás payment.purchase.confirm.processed si el pago fue exitoso, payment.purchase.confirm.rejected si el OTP fue rechazado de forma definitiva o la cuenta fue rechazada por el proveedor, o payment.purchase.confirm.failed.retryable si el OTP ingresado fue incorrecto pero el intento sigue activo y puede reintentarse.


Paso 1: Crear el intento de pago

Endpoint

POST /api/v1/payments/intents

Cuerpo de la solicitud

{
  "id": "orden-12345",
  "amount": {
    "value": 75000,
    "currency": "COP"
  },
  "description": "Compra en tienda online",
  "merchant_id": "mer-xxxxxxxxxxxxxxxxxxxx",
  "rail": {
    "id": "DAVIPLATA",
    "type": "WALLET"
  },
  "customer_data": {
    "phone_number": "3001234567",
    "document": "1234567890",
    "document_type": "CC"
  }
}
CampoTipoRequeridoDescripción
idstringNoTu identificador interno del pedido. Máx. 255 caracteres.
amount.valuedecimalMonto del cobro. Debe ser mayor a cero. Máximo: 3.000.000 COP por transacción.
amount.currencystringDebe ser COP. Daviplata no procesa monedas extranjeras.
descriptionstringNoConcepto del pago. Aparece en el SMS enviado al cliente. Máx. 255 caracteres.
merchant_idstringID del comercio en Akua.
rail.idstringDebe ser DAVIPLATA.
rail.typestringDebe ser WALLET.
customer_data.phone_numberstringNúmero de celular colombiano registrado en Daviplata. Acepta 3001234567 o +573001234567. Los caracteres no numéricos (excepto + al inicio) se eliminan automáticamente.
customer_data.documentstringNoNúmero de documento del titular de la cuenta Daviplata. Recomendado para aumentar la tasa de aprobación.
customer_data.document_typestringNoTipo de documento. Valores válidos: CC, CE, TI.

Respuesta exitosa (HTTP 201)

{
  "payment_id": "pay-xxxxxxxxxxxxxxxxxxxx",
  "transaction": {
    "id": "trx-xxxxxxxxxxxxxxxxxxxx",
    "type": "PURCHASE",
    "status": "IN_PROGRESS",
    "status_detail": "PENDING",
    "amount": 75000
  }
}

El payment_id que recibes aquí es el que usarás en el siguiente paso para confirmar el OTP. Guárdalo en tu sesión de checkout.


Paso 2: Confirmar el OTP

Una vez que el cliente te proporciona el OTP que recibió por SMS, tu backend debe enviarlo a Akua para completar el pago.

Endpoint

POST /api/v1/payments/intents/{payment_id}/confirm

Reemplaza {payment_id} con el valor de payment_id recibido en el paso anterior.

Cuerpo de la solicitud

{
  "otp": "123456"
}
CampoTipoRequeridoDescripción
otpstringEl código OTP ingresado por el cliente.

Respuesta exitosa (HTTP 200)

{
  "payment_id": "pay-xxxxxxxxxxxxxxxxxxxx",
  "transaction": {
    "id": "trx-xxxxxxxxxxxxxxxxxxxx",
    "type": "PURCHASE",
    "status": "IN_PROGRESS",
    "status_detail": "PENDING",
    "amount": 75000
  }
}

Importante: La respuesta HTTP 200 del endpoint de confirmación indica que la solicitud fue recibida y procesada por Akua, pero no garantiza que el pago fue aprobado. El resultado definitivo llega por webhook.


Webhooks

EventoSignificadoAcción recomendada
payment.purchase.confirm.processedEl OTP fue validado y el débito fue ejecutado exitosamenteConfirmar el pedido y liberar el producto o servicio
payment.purchase.confirm.rejectedEl pago fue rechazado de forma definitiva por el proveedor (cuenta bloqueada, fondos insuficientes, etc.)Informar al cliente del error; ofrecer método alternativo — no es posible reintentar con el mismo payment_id
payment.purchase.confirm.failed.retryableEl OTP ingresado fue incorrecto; el intento sigue activo en estado PENDING_CUSTOMERMostrar un mensaje de OTP incorrecto al cliente; permitirle ingresar el código nuevamente llamando otra vez al endpoint de confirmación con el mismo payment_id
payment.purchase.succeededEl pago alcanzó estado AUTORIZADO. Se emite automáticamente justo después de payment.purchase.confirm.processed cuando el débito es exitosoPuedes usarlo como señal adicional de autorización; no es necesario esperar a este evento para confirmar el pedido si ya recibiste confirm.processed
payment.purchase.failedError técnico en el procesamientoRegistrar el error; contactar soporte si persiste

Ejemplo de webhook de pago exitoso

{
  "id": "evt-xxxxxxxxxxxxxxxxxxxx",
  "type": "payment.purchase.confirm.processed",
  "version": "1.0",
  "source": "payments-service",
  "time": "2025-10-15T14:35:00Z",
  "data": {
    "payment": {
      "id": "pay-xxxxxxxxxxxxxxxxxxxx",
      "currency": "COP",
      "current_amount": 75000,
      "merchant": { "id": "mer-xxxxxxxxxxxxxxxxxxxx" },
      "instrument": { "type": "WALLET" },
      "transaction": {
        "id": "trx-xxxxxxxxxxxxxxxxxxxx",
        "type": "PURCHASE",
        "status": "APPROVED",
        "status_detail": "SUCCESS"
      }
    }
  },
  "metadata": {
    "client_id": "cli-xxxxxxxxxxxxxxxxxxxx"
  }
}

Reglas y límites

ParámetroValor
MonedaCOP únicamente
Límite por transacción3.000.000 COP
Límites adicionalesAplican límites diarios y mensuales definidos por Davivienda según regulación de depósitos de bajo monto (SFC)
TTL del intento y del OTP15 minutos (comparten el mismo tiempo de expiración)
Disponibilidad24/7
Acreditación en AkuaT+1
EjecuciónAtómica. Se débita el monto completo o no se débita nada. No hay capturas parciales
ContracargosNo aplican. Los pagos Daviplata son irreversibles una vez confirmados
Reenvío de OTPNo es posible reenviar el OTP del mismo intento. Si expira, debes crear un nuevo intento
Moneda extranjeraNo soportada

Errores frecuentes y cómo resolverlos

EscenarioCausaSolución
Número no registrado en DaviplataEl celular no tiene una cuenta Daviplata activaError devuelto en la creación del intento; ofrecer método alternativo
OTP incorrectoEl cliente ingresó el código equivocadoAkua devuelve el evento payment.purchase.confirm.failed.retryable; el pago queda en PENDING_CUSTOMER con el bloqueo liberado. Muestra el error al cliente y permítele volver a llamar al endpoint de confirmación con el mismo payment_id — no es necesario crear un nuevo intento
OTP expirado (15 min)El cliente no ingresó el OTP antes de que venciera el tiempoNotificar al cliente; crear un nuevo intento si desea reintentar
Fondos insuficientesEl saldo de Daviplata es menor al monto solicitadoEl pago falla en la confirmación; notificar al cliente para que recargue su saldo
Cuenta bloqueada o suspendidaDavivienda ha restringido la cuenta del usuarioError en la creación; no se envía SMS; ofrecer método alternativo
Monto supera el límite por transacciónEl monto excede 3.000.000 COPReducir el monto o usar un método de pago diferente
SMS no entregadoFalla en el operador de telecomunicaciones o número con formato incorrectoVerificar el formato del número (10 dígitos, sin +57); reintentar con un nuevo intento
Intento duplicadoSe crearon dos intentos para el mismo usuario en poco tiempoCada intento genera un SMS independiente; implementa idempotencia con el campo id

Preguntas frecuentes

¿El cliente necesita tener la app de Daviplata instalada? No. El flujo funciona completamente por SMS. El cliente solo necesita un celular con cobertura de red.

¿Puedo reenviar el OTP si el cliente no lo recibió? No es posible reenviar el OTP de un intento existente. Si el cliente no recibió el SMS (por falla del operador, número incorrecto, etc.), debes crear un nuevo intento.

¿Qué pasa si el cliente ingresa el OTP después de que expiró? La confirmación será rechazada. El intento completo queda en estado terminal y deberás crear uno nuevo.

¿Puedo hacer devoluciones? Los pagos Daviplata no tienen un mecanismo de devolución nativo. Las devoluciones deben procesarse como transferencias bancarias separadas. Consulta el artículo sobre devoluciones en Akua para más detalle.


¿Te resultó útil?

NANO Y MICRO MERCHANTS

3

Comercios Nano y Micro: criterios de elegibilidad

Algunos comercios pequeños acceden a tarifas de intercambio reducidas cuando se clasifican como Nano Comercio o Micro Comercio. Los criterios dependen de la franquicia: Visa maneja dos categorías (Nano y Micro) y Mastercard solo una (Micro). A continuación se explican los requisitos de cada una.

Visa

Visa clasifica al comercio según su volumen de transacciones Visa, sin importar el rubro o la actividad del negocio.

El punto de partida es el volumen mensual promedio, es decir, el volumen anual estimado de transacciones Visa dividido entre 12. Ese promedio mensual se compara contra los topes vigentes:

CategoríaVolumen mensual promedio (2026)
Nanohasta COP 11.417.532
Microhasta COP 50.383.788
Regularpor encima de COP 50.383.788

Si el promedio mensual supera el tope de Micro, el comercio se clasifica como Regular y no accede a tarifa reducida. Los topes se actualizan una vez al año, así que conviene confirmar los valores vigentes en cada periodo.

Tarifas resultantes (Visa)

CategoríaDébitoPrepagoCrédito
Nano0.30%0.30%0.60%
Micro0.70%0.70%1.00%

Mastercard

Mastercard solo ofrece la categoría de Micro Comercio. Para acceder a la tarifa reducida, el comercio debe cumplir las dos condiciones siguientes:

  1. Estar registrado con identificación personal (Cédula de Ciudadanía o de Extranjería, y documentos equivalentes para población migrante), no con NIT. Un comercio registrado con NIT no califica como micro comercio.
  2. Tener un volumen anual de transacciones Mastercard de hasta COP 130.000.000.

Adicionalmente, la actividad del comercio (MCC) no debe estar dentro de la lista de rubros excluidos, como aerolíneas, hoteles, universidades, estaciones de servicio, telecomunicaciones y entidades de gobierno. Las transacciones Maestro no participan del programa.

Tarifas resultantes (Mastercard Micro Comercio)

ProductoTarifa
Débito y Prepago, Consumer0.60%
Débito y Prepago, Commercial0.65%
Crédito Standard y Gold1.15%
Crédito Platinum1.19%
Crédito Black1.24%
Crédito Commercial1.29%

En resumen

  • Visa evalúa solo el volumen y ofrece dos niveles: Nano y Micro.
  • Mastercard combina el tipo de identificación (Cédula) y el volumen anual, y ofrece un solo nivel: Micro.
  • En ambos casos, superar los topes de volumen lleva al comercio a la categoría Regular, con tarifa estándar.

¿Te resultó útil?

Comercio Micro en Brasil (Mastercard)

En Brasil, Mastercard ofrece una tarifa de intercambio reducida a los comercios pequeños a través de la categoría de Micro Comercio (Microestabelecimento Comercial). A diferencia de otros países, Brasil maneja una sola categoría (Micro, sin Nano) y la tarifa reducida aplica únicamente a pagos sin cuotas.

Criterios de elegibilidad

Para acceder a la tarifa reducida como Micro Comercio, el comercio debe cumplir lo siguiente:

  1. Estar registrado con CPF (identificación de persona física), no con CNPJ.
  2. Tener un volumen anual de transacciones Mastercard dentro del umbral que Mastercard define para micro comercios.
  3. La transacción debe ser un pago sin cuotas, es decir, en un solo pago. Los pagos en cuotas no acceden a la tarifa de micro comercio.

El umbral de volumen lo administra y verifica Mastercard, por lo que la calificación por volumen la determina la franquicia.

Tarifas resultantes

ProductoTarifaMáximo por transacción
Débito Mastercard0.25%BRL 0.30
Prepago0.30%BRL 0.30

En resumen

  • Brasil tiene una sola categoría reducida: Micro Comercio (no hay Nano).
  • El comercio debe estar registrado con CPF, no con CNPJ.
  • La tarifa reducida aplica solo a pagos sin cuotas.
  • El cumplimiento del volumen anual lo verifica Mastercard.

¿Te resultó útil?

Comercios Micro y Nano en Perú (Mastercard)

En Perú, Mastercard ofrece tarifas de intercambio reducidas a los comercios pequeños a través de dos categorías: Micro Comercio y Nano Comercio. La clasificación depende del volumen anual de transacciones Mastercard del comercio y, en el caso de Nano, también del canal por el que recibe los pagos.

Criterios de elegibilidad

Como requisito general, el comercio debe estar identificado con un documento tributario válido: Cédula o RUC.

Además, debe cumplir el umbral de volumen de su categoría y, en el caso de Nano, recibir los pagos por el canal correspondiente:

CategoríaVolumen anual de transacciones MastercardCanal
Nanohasta PEN 9.600Solo QR o Tap on Phone (el celular del comercio funciona como terminal)
Microhasta PEN 90.000Presencial (con tarjeta) o no presencial (en línea)

Puntos clave:

  • Nano es la categoría de menor volumen y solo aplica cuando el pago se recibe por QR o por Tap on Phone. Si un comercio con volumen de nivel Nano recibe el pago por otro canal, esa transacción no entra como Nano.
  • Micro cubre los pagos presenciales y no presenciales hasta el umbral de PEN 90.000 al año.
  • Un comercio cuyo volumen supere PEN 90.000 al año se clasifica como Regular y no accede a tarifa reducida.

Tarifas resultantes

Débito Mastercard:

CategoríaStandard y GoldPlatinum, World y Commercial
Micro0.85%0.90%
Nano0.15%0.15%

Prepago:

CategoríaTarifa
Micro1.40%
Nano0.15%

Crédito:

CategoríaStandardGoldPlatinumBlack y Commercial
Micro1.20%1.25%1.40%1.65%
Nano0.90%0.90%1.00%1.00%

En resumen

  • La clasificación depende del volumen anual de transacciones Mastercard del comercio.
  • Nano exige volumen muy bajo y solo aplica a pagos por QR o Tap on Phone.
  • Micro aplica a pagos presenciales y en línea hasta PEN 90.000 al año.
  • Superar el umbral de Micro lleva al comercio a la categoría Regular, con tarifa estándar.

¿Te resultó útil?