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
codetextoCódigo único. Formato prefijo más número, por ejemplo PAR-001, TER-002, ACQ-13
paramtextoCampo o parámetro exacto que causó el error. Se usa sobre todo en errores PARAMETER
messagetextoDescripción legible del motivo del fallo
objectobjetoDatos de trazabilidad: client_transaction_id, terminal_id y serial_number cuando corresponda

El código de estado HTTP es coherente con el type del cuerpo. Para errores ACQUIRER se conserva el estado que devolvió originalmente Kushki.

{
"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."
}
}

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
AUTHENTICATIONSeguridadNo 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. Prefijo ACQ-
INTERNALAplicaciónErrores inesperados: servicios caídos, fallos internos
CONFIGURATIONConfiguración DMSLa 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
MANUFACTURERSDK 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 2001 a 2037, además de dos códigos especiales de formato.

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
BUSYLa terminal está procesando otra solicitud. Reintenta cuando quede disponible

3.2 Validadores de monto y campos de pago

codeCampoMensajeAplica a
2001amount.currencyInvalid currency: {valor}. Expected one of: [MXN, CLP, PEN, COP]Ver nota
2002amount.ivaamount.iva cannot be negativeTodos
2003amount.subtotalIvaamount.subtotalIva cannot be negativeTodos
2004amount.subtotalIva0amount.subtotalIva0 cannot be negativeTodos
2005amount.tipamount.tip cannot be negative/charge y /pos_tip
2006airportTaxairportTax cannot be negativeTodos
2007iaciac cannot be negativeTodos
2008iceice cannot be negativeTodos
2009travelAgencytravelAgency cannot be negativeTodos
2012deferredMonthsdeferredMonths must be > 0 when isDeferred is true/charge
2013cashbackAmountcashbackAmount must be > 0 when isCashback is true/charge

3.3 Validadores de identificadores de transacción

codeCampoMensaje
2010clientTransactionIdclientTransactionId must be a valid UUID format
2011clientTransactionIdclientTransactionId is required
2014transactionReferencetransactionReference must be a valid UUID format
2015transactionReferencetransactionReference is required

3.4 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

3.5 Validadores de configuración

codeCampoMensaje
2022envenv is required
2023privateCredentialIdprivateCredentialId is required
2024countrycountry is required
2025pinTimeOutpinTimeOut cannot be negative
2026cardDetectTimeOutcardDetectTimeOut cannot be negative
2027pinKeyIndexpinKeyIndex cannot be negative
2028dataKeyIndexdataKeyIndex cannot be negative
2029timeoutSecondstimeoutSeconds cannot be negative
2030maxChipRetriesmaxChipRetries cannot be negative
2031countryCodecountryCode must be 3 uppercase letters or 3-4 digits (ISO 3166-1)
2032currencyCodecurrencyCode must be 3 uppercase letters or 3-4 digits (ISO 4217)
2033merchantIdmerchantId cannot be blank
2034terminalIdterminalId cannot be blank
2035terminalTypeterminalType cannot exceed 2 characters
2036CardInputAt least one card input method (ICC, NFC, MSR) must be enabled
2037timeoutSecondstimeoutSeconds cannot exceed 300 seconds (5 minutes)

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-004Terminal ocupada con una acción distinta a un pagoTerminal {{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: “AUTHENTICATION”

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": "AUTHENTICATION",
"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: código Kushki original con el prefijo ACQ-. El código 13 se convierte en ACQ-13.
  • 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": "13",
"message": "Either Invalid amount or Currency conversion field overflow"
}

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

{
"type": "ACQUIRER",
"code": "ACQ-13",
"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: “MANUFACTURER”

Los errores del SDK del fabricante se encapsulan con el prefijo MAN- seguido del código original. El código -2001 de Sunmi se convierte en MAN--2001.

{
"type": "MANUFACTURER",
"code": "MAN--2001",
"message": "Have no card",
"object": {
"client_transaction_id": "c5a3f3be-9d6f-4d39-8af5-58dbb589af69",
"terminal_id": "172653",
"serial_number": "SN816265"
}
}

Códigos de Sunmi más frecuentes

codeDescripciónAcción recomendada
MAN--2001Have no cardEl cliente no presentó la tarjeta. Solicita un reintento
MAN--2002Multiple cardsHay más de una tarjeta en el campo NFC. Pide retirar las adicionales
MAN--2581User canceledEl cliente canceló. Trátalo como cancelación esperada
MAN--2582MSR or IC interruptedLectura interrumpida. Pide no retirar la tarjeta hasta que la terminal lo indique
MAN--3023DUKPT overflowContador DUKPT agotado. Requiere reinyección de clave. Contacta a soporte
MAN--4104Card is lockedTarjeta bloqueada. El cliente debe contactar a su banco
MAN--4111Card expiredTarjeta vencida. Informa al cliente
MAN--4120Amount exceeds contactless limitEl monto supera el límite NFC. Usa chip
MAN--50020PIN entry cancelEl cliente canceló la entrada de PIN. Trátalo como cancelación
MAN--60001Input PIN timeoutEl cliente no ingresó el PIN a tiempo. Solicita un reintento

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

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

codeCausaAcción recomendada
-4001La propina no está habilitada en la terminalContacta a Operaciones Kushki para habilitarla en el DMS
-4002El cashback no está habilitado en la terminalContacta a Operaciones Kushki para habilitarlo en el DMS
-4003El monto de cashback supera el límite configuradoInforma al cliente el límite disponible. No reintentes con el mismo monto
-4006El monto de la transacción supera el límite configuradoInforma al cliente. Contacta a Operaciones Kushki si el límite necesita ajuste
{
"type": "CONFIGURATION",
"code": "-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
BUSYCola de impresión ocupada con skipIfBusy: trueReintenta en unos segundos
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
AUTHENTICATIONAUTH-001Verifica que firmas con el Business-Code y que la unidad del timestamp es la correcta
AUTHENTICATIONAUTH-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
TERMINALTER-002La terminal está fuera de línea. Verifica la conectividad de red
TERMINALTER-003 o TER-004La terminal está ocupada. Espera o usa abort
TERMINALTER-006Funcionalidad no habilitada. Contacta a Operaciones Kushki
TERMINAL-PRINTERcualquieraCondición física del hardware. Muestra el message al operador
MANUFACTURERempieza en MAN--200Problema de lectura de tarjeta. Solicita un reintento al cliente
MANUFACTURERMAN--50020 o MAN--60001El cliente canceló o no ingresó el 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. Requiere ajuste en el DMS
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 AUTHENTICATION 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.