Catálogo Unificado de Errores — Kushki ONE Connect

Kushki ONE Connect devuelve un payload JSON estructurado ante cualquier fallo, sin importar si el problema se originó en la terminal, en una validación, en la autenticación o en el adquirente. Eso te permite construir integraciones robustas, automatizar flujos de recuperación y dejar de depender exclusivamente de los códigos de estado HTTP.

Este manual es tu herramienta de diagnóstico: la estructura del modelo de datos, los catálogos por categoría, cómo mapeamos los rechazos de terceros y una guía rápida para resolver los casos frecuentes.

1. Modelos de errores

Existen dos envolturas de error. Cuál recibes depende de si el fallo llega en una respuesta HTTP o en un evento asíncrono.

1.1 Respuestas HTTP: LinkFailure

Toda respuesta de error comparte esta estructura. Evalúa primero el campo type para clasificar la fuente del fallo y luego consulta el code correspondiente.

CampoTipoSiempre presenteDescripción
typetextoCategoría del error. Identifica la fuente del fallo. Ver Sección 2
codetextoPrefijo más número para las familias propias de Kushki ONE (PAR-003, TER-004, AUTH-001, NF-001, CONF-4007, MAN-30005). Los códigos del adquirente son los suyos, sin prefijo
paramtextoCampo exacto del request que causó el error. Aparece solo cuando la falla es atribuible a un campo — ver abajo
messagetextoDescripción legible del motivo del fallo
objectobjetoDatos de trazabilidad: client_transaction_id, terminal_id y serial_number cuando corresponda

En los endpoints de pago el status HTTP es siempre 200, pase lo que pase: confirma que la terminal procesó tu petición, no que la operación haya salido bien. Evalúa siempre el cuerpo. Los endpoints de impresión son la excepción y devuelven códigos reales — 404 si el job no existe, 409 mientras la cola está ocupada.

Los cinco campos de arriba están en la raíz del cuerpo. Las dos envolturas que devolvían las versiones viejas, {"success": false, "data": {…}} y {"failure": {…}}, ya no existen. Y object.terminal_id puede llegar vacío en TER-003 — no dependas de él.

{
"type": "PARAMETER",
"code": "PAR-003",
"param": "amount",
"message": "Amount must be a value greater than 0",
"object": {
"client_transaction_id": "1018282",
"terminal_id": "172653",
"serial_number": "PJ715652"
}
}

1.2 Eventos asíncronos: failure_reason

Cuando integras por el modo asíncrono, los fallos no llegan en una respuesta HTTP sino dentro del evento del webhook, en el objeto failure_reason.

CampoTipoDescripción
typetextoCategoría del error, con los mismos valores de la Sección 2
codetextoCódigo único del error
messagetextoDescripción legible del motivo
{
"status": "TERMINAL_REJECTED",
"previous_status": "CARD_PRESENTED",
"client_transaction_id": "c5a3f3be-9d6f-4d39-8af5-58dbb589af79",
"failure_reason": {
"type": "TERMINAL",
"code": "TER-172",
"message": "The maximum operation time was exceeded."
}
}

Cuándo viene param y cuándo no

param no es un campo opcional que a veces falta. Se omite deliberadamente cuando el error no lo causó un campo de tu request. La regla en una línea: param aparece solo cuando el error es atribuible a un campo del request.

Sí trae paramPor qué
PAR-003, TER-003, AUTH-001Errores de validación de datos — hay un campo culpable
NF-001Trae el identificador que no se encontró
No trae paramPor qué
TER-004Impresora ocupada, o cancelación del tarjetahabiente. El request era válido; falló el hardware o la persona
MAN-30005Timeout de tarjeta o PIN. Misma razón
ACQUIRERLa transacción fue válida y el banco la rechazó
CONF-4007Aprovisionamiento de la terminal, no la llamada
PAR-002 con JSON ilegibleEl parser falla antes de deserializar, así que no hay campo que señalar

Sin esta regla un integrador lee el catálogo, ve param entre los campos y programa asumiendo que siempre llega.

2. Categorías de error

typeOrigenDescripción
PARAMETERValidaciónEnvío incorrecto de campos: requeridos vacíos, tipo incorrecto o formato inválido
TERMINALTerminalEstado de la terminal física: ocupada, fuera de línea, no vinculada, modo incompatible
AUTHSeguridadNo es posible autenticar las credenciales o no alcanzan los permisos
NOT_FOUNDEnrutamientoServicio o endpoint no encontrado. URL inválida
ACQUIRERAdquirenteProcesamiento o autorización de la transacción por parte del adquirente Kushki. Código nativo, sin prefijo
INTERNALAplicaciónErrores inesperados: servicios caídos, fallos internos
CONFIGURATIONCapacidad de la terminalLa operación no está habilitada o supera los límites configurados para la terminal
TERMINAL-PRINTERHardwareErrores de la impresora térmica integrada: sin papel, tapa abierta, atasco
TERMINAL-SUNMISDK del fabricanteErrores del SDK de Sunmi o Landi. Prefijo MAN-

3. Errores de validación — type: “PARAMETER”

Se generan cuando el request contiene campos con formato incorrecto, valores fuera de rango o campos requeridos ausentes. El campo param identifica el campo específico. Todos son prevenibles validando el payload en tu sistema de caja antes de llamar a la API.

codeDescripciónPlantilla del mensajeEjemplo
PAR-001Campo requerido no enviadoField {{field}} is requiredField amount.subtotal_iva0 is required
PAR-002Campo de tipo incorrectoField {{field}} must be a/an {{type}}Field amount.subtotal_iva must be an integer
PAR-003Formato incorrecto o valor no válidoField {{field}} must satisfy: {{condition}}Field amount.iva must satisfy: value >= 0

Cuando el type es PARAMETER, el code también puede ser un código numérico del rango 2002 a 2021, además del código de formato BAD_FORMAT.

3.1 Códigos de sistema

codeDescripción
BAD_FORMATError de parseo JSON. El cuerpo del request no es un JSON válido o contiene un tipo de dato incorrecto

3.2 Validadores de monto y campos de pago

codeCampoMensajeAplica a
2002amount.ivaamount.iva cannot be negativeTodos
2003amount.subtotal_ivaamount.subtotal_iva cannot be negativeTodos
2004amount.subtotal_iva0amount.subtotal_iva0 cannot be negativeTodos
2005amount.tipamount.tip cannot be negative/charge y /authorization, más /pos_tip donde la propina es el monto
2006amount.extra_taxes.airport_taxamount.extra_taxes.airport_tax cannot be negativeTodos
2007amount.extra_taxes.iacamount.extra_taxes.iac cannot be negativeTodos
2008amount.extra_taxes.iceamount.extra_taxes.ice cannot be negativeTodos
2009amount.extra_taxes.travel_agencyamount.extra_taxes.travel_agency cannot be negativeTodos

3.3 Validadores de cuotas (deferred)

Las cuotas viajan en el objeto deferred en todos los mercados salvo México, que usa el booleano query_deferred. Los dos son mutuamente excluyentes y nunca viajan juntos. Estas validaciones todavía no tienen código numérico asignado:

CondiciónResultado
deferred.months fuera del rango del paísError PARAMETER en deferred.months
deferred.credit_type enviado fuera de ChileError PARAMETERcredit_type solo existe en Chile
deferred y query_deferred juntosError PARAMETER — son mutuamente excluyentes
query_deferred enviado fuera de MéxicoError PARAMETER — el campo es solo de México

El techo depende del mercado: México envía query_deferred como booleano, Chile admite hasta 12 meses con credit_type: "03" o hasta 48 sin él, Colombia hasta 48, y Perú de 2 a 48 para todas las redes. El contrato completo, país por país, está en Acepta pagos con Kushki One.

3.4 Validadores de identificadores de transacción

codeCampoMensaje
2010client_transaction_idclient_transaction_id must be a valid UUID format
2011client_transaction_idclient_transaction_id is required
2014transaction_referencetransaction_reference must be a valid UUID format
2015transaction_referencetransaction_reference is required

3.5 Validadores de paginación y fechas

codeCampoMensaje
2016pagepage must be greater than 0
2017sizesize must be greater than 0
2018sizesize must not exceed 500
2019start_datestart_date cannot be negative
2020end_dateend_date cannot be negative
2021start_datestart_date must be before end_date

4. Errores de terminal — type: “TERMINAL”

Se generan cuando la terminal física no puede aceptar la operación. A diferencia de los errores de hardware, indican un problema de estado o conectividad, no un fallo de componente.

codeDescripciónPlantilla del mensaje
TER-001Terminal no vinculada al comercioTerminal {{serial_number}} does not exist, or is not linked to your account
TER-002Terminal no responde: fuera de línea o fuera de redTerminal {{serial_number}} is not responding. It may be offline or not connected to the local network
TER-003Terminal ocupada procesando una transacciónTerminal {{serial_number}} is busy processing transaction (client_transaction_id: {{id}})
TER-004Impresora ocupada, o cancelación del tarjetahabiente. Ver la sección de este código más abajoTerminal {{serial_number}} is busy executing action {{action}}
TER-005Terminal en un modo incompatible con la operaciónThe terminal is in {{mode}} mode and does not allow the requested action
TER-006Terminal no habilitada para ese tipo de operaciónThe terminal is not allowed to process {{type}}

5. Errores de Autenticación — type: “AUTH”

Se generan cuando las credenciales son inválidas o no alcanzan los permisos para la acción solicitada.

codeDescripciónMensaje
AUTH-001No es posible autenticar las credencialesInvalid or expired credentials
AUTH-002Credenciales válidas pero sin permiso para el recursoYour credentials are valid but do not grant access to this resource
{
"type": "AUTH",
"code": "AUTH-001",
"message": "Invalid or expired credentials"
}

6. Errores de enrutamiento e internos

type: “NOT_FOUND”

codeDescripciónPlantilla del mensaje
NF-001Servicio o endpoint no encontradoService not found: {{url}}

type: “INTERNAL”

codeDescripciónMensaje
INT-001Error inesperado del servidor o de la aplicaciónInternal server error

7. Errores del adquirente — type: “ACQUIRER”

Los errores del adquirente Kushki se encapsulan bajo type: "ACQUIRER" con esta regla de mapeo:

  • code: el código nativo del adquirente, sin cambios y sin prefijo. E020 se devuelve como E020. Los códigos de autorización son nativos de la red procesadora y se dejan intactos para mantener la trazabilidad ISO 8583 que exigen las franquicias — no esperes un prefijo ACQ-, nunca llega.
  • message: idéntico al mensaje original de Kushki.
  • object: incluye client_transaction_id, terminal_id y serial_number cuando corresponda.
  • Estado HTTP: se conserva el que devolvió originalmente Kushki.

Error original de Kushki:

{
"code": "E020",
"message": "Either Invalid amount or Currency conversion field overflow"
}

Error mapeado por Kushki ONE Connect, con el mismo 400 Bad Request:

{
"type": "ACQUIRER",
"code": "E020",
"param": "",
"message": "Either Invalid amount or Currency conversion field overflow",
"object": {
"client_transaction_id": "1018282",
"terminal_id": "172653",
"serial_number": "PJ715652"
}
}

8. Errores del fabricante — type: “TERMINAL-SUNMI”

Los errores del SDK del fabricante se encapsulan con el prefijo MAN-un solo guión — seguido del número. El código confirmado en respuestas reales es MAN-30005: se venció el tiempo de lectura de la tarjeta o de ingreso del PIN, y se trata como una cancelación esperada, no como una falla. Para el catálogo Sunmi completo por rango funcional, pídelo al equipo de integraciones de Kushki.

{
"type": "TERMINAL-SUNMI",
"code": "MAN-30005",
"message": "Input PIN timeout",
"object": {
"client_transaction_id": "c5a3f3be-9d6f-4d39-8af5-58dbb589af69",
"terminal_id": "172653",
"serial_number": "SN816265"
}
}

9. Errores de configuración — type: “CONFIGURATION”

Se generan cuando la operación no está habilitada para esa terminal, o cuando el monto supera los límites configurados. A diferencia de los errores PARAMETER, no se corrigen modificando el payload.

codeCausaAcción recomendada
CONF-4001La propina no está habilitada en la terminalSolicítala en soporte@kushkipagos.com
CONF-4002El cashback no está habilitado en la terminalSolicítalo en soporte@kushkipagos.com
CONF-4003El monto de cashback supera el límite configuradoInforma al cliente el límite disponible. No reintentes con el mismo monto. Para ampliarlo, escribe a soporte@kushkipagos.com
CONF-4006El monto de la transacción supera el límite configuradoInforma al cliente. Para ampliar el límite, escribe a soporte@kushkipagos.com
CONF-4007Problema de aprovisionamiento de la terminal — no lo causó tu llamadaEscala a soporte@kushkipagos.com con el serial_number
{
"type": "CONFIGURATION",
"code": "CONF-4001",
"message": "Tip is not enabled",
"object": {
"client_transaction_id": "c5a3f3be-9d6f-4d39-8af5-58dbb589af69",
"terminal_id": "172653",
"serial_number": "SN816265"
}
}

10. Errores de Impresora Kushki — type: “TERMINAL-PRINTER”

Errores del hardware de impresión. Están estandarizados sin importar el fabricante de la terminal.

codeCausaAcción para el operador
OUT_OF_PAPERSin rollo de papelInserta un rollo nuevo y reintenta
COVER_OPENTapa del compartimento abiertaCierra firmemente la tapa
COVER_INCOMPLETETapa mal cerrada o rodillo sin presiónAbre y cierra asegurando el encaje del rodillo
PAPER_JAMAtasco de papel en el mecanismoRetira el papel atascado e inserta un rollo nuevo
PRINTER_HOTCabezal térmico sobrecalentadoEspera 2 o 3 minutos y reintenta
MOTOR_HOTMotor de arrastre sobrecalentadoEspera a que se enfríe
CUTTER_ERRORGuillotina de corte bloqueadaRequiere intervención de servicio técnico
OFFLINEEl módulo no responde al sistema AndroidReinicia la terminal
UNKNOWN_ERRORFallo no clasificado del hardwareRegistra el caso y escala a soporte técnico

11. Guía rápida de diagnóstico

Si el type es…Y el codeEntonces
AUTHAUTH-001Verifica que firmas con el Business-Code y que la unidad del timestamp es la correcta
AUTHAUTH-002Las credenciales son válidas pero faltan permisos. Contacta a integraciones
PARAMETERcualquieraRevisa el campo indicado en param. Agrega validación en tu caja antes de llamar a la API
PARAMETER2002 a 2009Muy probablemente enviaste montos con decimales en lugar de enteros
INTERNALMQTT_REQUEST_FAILEDEl relay de Nube no pudo llegar a la terminal. Verifica que esté en línea y reintenta. Solo en Nube
TERMINALTER-002La terminal está fuera de línea. Verifica la conectividad de red
TERMINALTER-003La terminal está ocupada con una transacción. Espera o usa abort
TERMINALTER-004En un endpoint de impresión la impresora está ocupada: reintenta. En un endpoint de pago el tarjetahabiente canceló: no reintentes
TERMINALTER-006Funcionalidad no habilitada para esta terminal. Escribe a soporte@kushkipagos.com
TERMINAL-PRINTERcualquieraCondición física del hardware. Muestra el message al operador
TERMINAL-SUNMIMAN-30005Se venció la lectura de tarjeta o el ingreso del PIN. Trátalo como cancelación esperada
ACQUIRERcualquieraRechazo del procesador. Muestra el message al cliente y registra el code
CONFIGURATIONcualquieraNo reintentes con el mismo payload. Escribe a soporte@kushkipagos.com
INTERNAL o NOT_FOUNDcualquieraRegistra el payload completo y escala a soporte técnico de Kushki

Para depurar un fallo de firma, este es el patrón mínimo de registro:

  • Javascript
  • Python
try {
const res = await fetch(url, { method: "POST", headers, body });
const data = await res.json();
if (!res.ok) {
logger.error("kushki_one_error", {
http: res.status,
type: data.type,
code: data.code,
transaccion: data.object?.client_transaction_id,
firma_presente: Boolean(headers.Authorization),
});
}
} catch (e) {
logger.error("kushki_one_red", { mensaje: e.message });
}
try:
res = requests.post(url, headers=headers, json=payload, timeout=30)
data = res.json()
if not res.ok:
logger.error("kushki_one_error", extra={
"http": res.status_code,
"type": data.get("type"),
"code": data.get("code"),
"transaccion": data.get("object", {}).get("client_transaction_id"),
"firma_presente": "Authorization" in headers,
})
except requests.RequestException as e:
logger.error("kushki_one_red", extra={"mensaje": str(e)})
Autenticación de requests

Resuelve los errores AUTH revisando los dos mecanismos de firma y sus diferencias.

Servicios asíncronos y webhooks

Interpreta el objeto failure_reason dentro del ciclo de vida de la transacción.