Unified Error Catalog — Kushki ONE Connect

Kushki ONE Connect returns a structured JSON payload on any failure, whether the problem started at the terminal, in a validation, in authentication or at the acquirer. That lets you build robust integrations, automate recovery flows and stop depending solely on HTTP status codes.

This manual is your diagnostic tool: the data model structure, the catalogs by category, how we map third-party rejections and a quick guide for the common cases.

1. Error models

There are two error envelopes. Which one you get depends on whether the failure arrives in an HTTP response or in an async event.

1.1 HTTP responses: LinkFailure

Every error response shares this structure. Evaluate the type field first to classify the source of the failure, then look up the matching code.

FieldTypeAlways presentDescription
typestringError category. Identifies the source of the failure. See Section 2
codestringPrefix plus number for Kushki ONE’s own families (PAR-003, TER-004, AUTH-001, NF-001, CONF-4007, MAN-30005). Acquirer codes are the processor’s own, unprefixed
paramstringThe exact request field that caused the error. Present only when the failure is attributable to a field — see below
messagestringHuman-readable description of the failure
objectobjectTraceability data: client_transaction_id, terminal_id and serial_number where applicable

On payment endpoints the HTTP status is always 200, whatever happened: it confirms that the terminal processed your request, not that the operation succeeded. Always evaluate the body. The print endpoints are the exception and return real codes — 404 when the job does not exist, 409 while the queue is busy.

The five fields above sit at the root of the body. The two envelopes older builds returned, {"success": false, "data": {…}} and {"failure": {…}}, no longer exist. And object.terminal_id may arrive empty on TER-003 — do not depend on it.

{
"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 Async events: failure_reason

When you integrate over async mode, failures do not arrive in an HTTP response but inside the webhook event, in the failure_reason object.

FieldTypeDescription
typestringError category, with the same values as Section 2
codestringUnique error code
messagestringHuman-readable description of the failure
{
"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."
}
}

When param is present, and when it is not

param is not an optional field that happens to be missing sometimes. It is omitted deliberately whenever the error was not caused by a field of your request. The rule in one line: param appears only when the error is attributable to a request field.

Comes with paramWhy
PAR-003, TER-003, AUTH-001Data validation errors — there is a field at fault
NF-001Carries the identifier that was not found
Comes without paramWhy
TER-004Printer busy, or the cardholder cancelled. The request was valid; the hardware or the person was not
MAN-30005Card or PIN timeout. Same reason
ACQUIRERThe transaction was valid and the bank declined it
CONF-4007Terminal provisioning, not the call
PAR-002 with unreadable JSONThe parser fails before deserializing, so there is no field to point at

Without this rule an integrator reads the catalog, sees param among the fields, and codes assuming it always arrives.

2. Error categories

typeSourceDescription
PARAMETERValidationIncorrectly sent fields: required fields empty, wrong type or invalid format
TERMINALTerminalState of the physical terminal: busy, offline, not linked, incompatible mode
AUTHSecurityCredentials cannot be authenticated, or permissions are insufficient
NOT_FOUNDRoutingService or endpoint not found. Invalid URL
ACQUIRERAcquirerProcessing or authorization of the transaction by the Kushki acquirer. Native code, unprefixed
INTERNALApplicationUnexpected errors: services down, internal failures
CONFIGURATIONTerminal capabilityThe operation is not enabled, or it exceeds the limits configured for the terminal
TERMINAL-PRINTERHardwareErrors from the built-in thermal printer: out of paper, cover open, paper jam
TERMINAL-SUNMIManufacturer SDKErrors from the Sunmi or Landi SDK. MAN- prefix

3. Validation errors — type: “PARAMETER”

These are generated when the request contains fields with the wrong format, values out of range or missing required fields. The param field identifies the specific field. All of them are preventable by validating the payload in your POS system before you call the API.

codeDescriptionMessage templateExample
PAR-001Required field not sentField {{field}} is requiredField amount.subtotal_iva0 is required
PAR-002Field of the wrong typeField {{field}} must be a/an {{type}}Field amount.subtotal_iva must be an integer
PAR-003Wrong format or invalid valueField {{field}} must satisfy: {{condition}}Field amount.iva must satisfy: value >= 0

When type is PARAMETER, the code can also be a numeric code in the 2002 to 2021 range, plus the BAD_FORMAT format code.

3.1 System codes

codeDescription
BAD_FORMATJSON parsing error. The request body is not valid JSON or contains a wrong data type

3.2 Amount and payment field validators

codeFieldMessageApplies to
2002amount.ivaamount.iva cannot be negativeAll
2003amount.subtotal_ivaamount.subtotal_iva cannot be negativeAll
2004amount.subtotal_iva0amount.subtotal_iva0 cannot be negativeAll
2005amount.tipamount.tip cannot be negative/charge and /authorization, plus /pos_tip where the tip is the amount
2006amount.extra_taxes.airport_taxamount.extra_taxes.airport_tax cannot be negativeAll
2007amount.extra_taxes.iacamount.extra_taxes.iac cannot be negativeAll
2008amount.extra_taxes.iceamount.extra_taxes.ice cannot be negativeAll
2009amount.extra_taxes.travel_agencyamount.extra_taxes.travel_agency cannot be negativeAll

3.3 Installment validators (deferred)

Installments travel in the deferred object in every market except Mexico, which uses the boolean query_deferred. The two are mutually exclusive and never travel together. These validations have no numeric code assigned yet:

ConditionResult
deferred.months out of range for the countryPARAMETER error on deferred.months
deferred.credit_type sent outside ChilePARAMETER error — credit_type exists only in Chile
deferred and query_deferred sent togetherPARAMETER error — the two are mutually exclusive
query_deferred sent outside MexicoPARAMETER error — the field is Mexico only

The ceiling depends on the market: Mexico sends query_deferred as a boolean, Chile allows up to 12 months with credit_type: "03" or up to 48 without it, Colombia up to 48, and Peru 2 to 48 for every card network. The full contract, country by country, is in Accept payments with Kushki One.

3.4 Transaction identifier validators

codeFieldMessage
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 Pagination and date validators

codeFieldMessage
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. Terminal errors — type: “TERMINAL”

These are generated when the physical terminal cannot accept the operation. Unlike hardware errors, they point to a state or connectivity problem, not a component failure.

codeDescriptionMessage template
TER-001Terminal not linked to the merchant accountTerminal {{serial_number}} does not exist, or is not linked to your account
TER-002Terminal not responding: offline or off the networkTerminal {{serial_number}} is not responding. It may be offline or not connected to the local network
TER-003Terminal busy processing a transactionTerminal {{serial_number}} is busy processing transaction (client_transaction_id: {{id}})
TER-004Printer busy, or cardholder cancellation. See the section on this code belowTerminal {{serial_number}} is busy executing action {{action}}
TER-005Terminal in a mode incompatible with the operationThe terminal is in {{mode}} mode and does not allow the requested action
TER-006Terminal not enabled for that operation typeThe terminal is not allowed to process {{type}}

5. Authentication errors — type: “AUTH”

These are generated when credentials are invalid or do not carry enough permissions for the requested action.

codeDescriptionMessage
AUTH-001Credentials cannot be authenticatedInvalid or expired credentials
AUTH-002Valid credentials without permission for the resourceYour credentials are valid but do not grant access to this resource
{
"type": "AUTH",
"code": "AUTH-001",
"message": "Invalid or expired credentials"
}

6. Routing and internal errors

type: “NOT_FOUND”

codeDescriptionMessage template
NF-001Service or endpoint not foundService not found: {{url}}

type: “INTERNAL”

codeDescriptionMessage
INT-001Unexpected server or application errorInternal server error

7. Acquirer errors — type: “ACQUIRER”

Errors from the Kushki acquirer are wrapped under type: "ACQUIRER" with this mapping rule:

  • code: the acquirer’s native code, unchanged and unprefixed. E020 is returned as E020. Authorization codes are native to the processing network and are left intact to preserve the ISO 8583 traceability the card brands require — do not expect an ACQ- prefix, it never arrives.
  • message: identical to Kushki’s original message.
  • object: includes client_transaction_id, terminal_id and serial_number where applicable.
  • HTTP status: we keep the one Kushki originally returned.

Original Kushki error:

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

Error mapped by Kushki ONE Connect, with the same 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. Manufacturer errors — type: “TERMINAL-SUNMI”

Errors from the manufacturer SDK are wrapped with the MAN- prefix — a single hyphen — followed by the number. The code confirmed in real responses is MAN-30005: the card read or the PIN entry timed out, which you treat as an expected cancellation rather than a failure. For the full Sunmi catalog by functional range, ask your Kushki integration team.

{
"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. Configuration errors — type: “CONFIGURATION”

These are generated when the operation is not enabled for that terminal, or when the amount exceeds the configured limits. Unlike PARAMETER errors, they are not fixed by changing the payload.

codeCauseRecommended action
CONF-4001Tipping is not enabled on the terminalRequest it at soporte@kushkipagos.com
CONF-4002Cashback is not enabled on the terminalRequest it at soporte@kushkipagos.com
CONF-4003The cashback amount exceeds the configured limitTell the customer the available limit. Do not retry with the same amount. To raise it, write to soporte@kushkipagos.com
CONF-4006The transaction amount exceeds the configured limitTell the customer. To raise the limit, write to soporte@kushkipagos.com
CONF-4007Terminal provisioning problem — not caused by your callEscalate to soporte@kushkipagos.com with the 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. Kushki Printer errors — type: “TERMINAL-PRINTER”

Errors from the printing hardware. They are standardized regardless of the terminal manufacturer.

codeCauseAction for the operator
OUT_OF_PAPERNo paper rollInsert a new roll and retry
COVER_OPENPaper compartment cover openClose the cover firmly
COVER_INCOMPLETECover badly closed or roller without pressureOpen and close making sure the roller seats
PAPER_JAMPaper jammed in the mechanismRemove the jammed paper and insert a new roll
PRINTER_HOTThermal print head overheatedWait 2 or 3 minutes and retry
MOTOR_HOTFeed motor overheatedWait for it to cool down
CUTTER_ERRORCutter blade jammedRequires technical service intervention
OFFLINEThe module is not responding to the Android systemRestart the terminal
UNKNOWN_ERRORUnclassified hardware failureLog the case and escalate to technical support

11. Quick diagnostic guide

If type is…And codeThen
AUTHAUTH-001Check that you sign with the Business-Code and that the timestamp unit is correct
AUTHAUTH-002Credentials are valid but permissions are missing. Contact integrations
PARAMETERanyCheck the field named in param. Add validation in your POS before calling the API
PARAMETER2002 to 2009You most likely sent amounts with decimals instead of integers
INTERNALMQTT_REQUEST_FAILEDThe Cloud relay could not reach the terminal. Check it is online and retry. Cloud only
TERMINALTER-002The terminal is offline. Check network connectivity
TERMINALTER-003The terminal is busy with a transaction. Wait or use abort
TERMINALTER-004On a print endpoint the printer is busy: retry. On a payment endpoint the cardholder cancelled: do not retry
TERMINALTER-006Capability not enabled for this terminal. Write to soporte@kushkipagos.com
TERMINAL-PRINTERanyPhysical hardware condition. Show the message to the operator
TERMINAL-SUNMIMAN-30005Card or PIN timeout. Treat it as an expected cancellation
ACQUIRERanyProcessor decline. Show the message to the customer and log the code
CONFIGURATIONanyDo not retry with the same payload. Write to soporte@kushkipagos.com
INTERNAL or NOT_FOUNDanyLog the full payload and escalate to Kushki technical support

To debug a signature failure, this is the minimum logging pattern:

  • 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,
transaction: data.object?.client_transaction_id,
signaturePresent: Boolean(headers.Authorization),
});
}
} catch (e) {
logger.error("kushki_one_network", { message: 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"),
"transaction": data.get("object", {}).get("client_transaction_id"),
"signature_present": "Authorization" in headers,
})
except requests.RequestException as e:
logger.error("kushki_one_network", extra={"message": str(e)})
Request authentication

Resolve AUTH errors by reviewing the two signing mechanisms and their differences.

Async services and webhooks

Interpret the failure_reason object inside the transaction lifecycle.