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.
| Field | Type | Always present | Description |
|---|---|---|---|
type | string | ✅ | Error category. Identifies the source of the failure. See Section 2 |
code | string | ✅ | Unique code. Prefix plus number, for example PAR-001, TER-002, ACQ-13 |
param | string | — | The exact field or parameter that caused the error. Used mostly in PARAMETER errors |
message | string | ✅ | Human-readable description of the failure |
object | object | — | Traceability data: client_transaction_id, terminal_id and serial_number where applicable |
The HTTP status code is consistent with the type in the body. For ACQUIRER errors we keep the status Kushki originally returned.
{"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.
| Field | Type | Description |
|---|---|---|
type | string | Error category, with the same values as Section 2 |
code | string | Unique error code |
message | string | Human-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."}}
2. Error categories
type | Source | Description |
|---|---|---|
PARAMETER | Validation | Incorrectly sent fields: required fields empty, wrong type or invalid format |
TERMINAL | Terminal | State of the physical terminal: busy, offline, not linked, incompatible mode |
AUTHENTICATION | Security | Credentials cannot be authenticated, or permissions are insufficient |
NOT_FOUND | Routing | Service or endpoint not found. Invalid URL |
ACQUIRER | Acquirer | Processing or authorization of the transaction by the Kushki acquirer. ACQ- prefix |
INTERNAL | Application | Unexpected errors: services down, internal failures |
CONFIGURATION | DMS configuration | The operation is not enabled, or it exceeds the limits configured for the terminal |
TERMINAL-PRINTER | Hardware | Errors from the built-in thermal printer: out of paper, cover open, paper jam |
MANUFACTURER | Manufacturer SDK | Errors 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.
code | Description | Message template | Example |
|---|---|---|---|
PAR-001 | Required field not sent | Field {{field}} is required | Field amount.subtotal_iva0 is required |
PAR-002 | Field of the wrong type | Field {{field}} must be a/an {{type}} | Field amount.subtotal_iva must be an integer |
PAR-003 | Wrong format or invalid value | Field {{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 2001 to 2037 range, plus two special format codes.
3.1 System codes
code | Description |
|---|---|
BAD_FORMAT | JSON parsing error. The request body is not valid JSON or contains a wrong data type |
BUSY | The terminal is processing another request. Retry once it becomes available |
3.2 Amount and payment field validators
code | Field | Message | Applies to |
|---|---|---|---|
2001 | amount.currency | Invalid currency: {value}. Expected one of: [MXN, CLP, PEN, COP] | See note |
2002 | amount.iva | amount.iva cannot be negative | All |
2003 | amount.subtotalIva | amount.subtotalIva cannot be negative | All |
2004 | amount.subtotalIva0 | amount.subtotalIva0 cannot be negative | All |
2005 | amount.tip | amount.tip cannot be negative | /charge and /pos_tip |
2006 | airportTax | airportTax cannot be negative | All |
2007 | iac | iac cannot be negative | All |
2008 | ice | ice cannot be negative | All |
2009 | travelAgency | travelAgency cannot be negative | All |
2012 | deferredMonths | deferredMonths must be > 0 when isDeferred is true | /charge |
2013 | cashbackAmount | cashbackAmount must be > 0 when isCashback is true | /charge |
3.3 Transaction identifier validators
code | Field | Message |
|---|---|---|
2010 | clientTransactionId | clientTransactionId must be a valid UUID format |
2011 | clientTransactionId | clientTransactionId is required |
2014 | transactionReference | transactionReference must be a valid UUID format |
2015 | transactionReference | transactionReference is required |
3.4 Pagination and date validators
code | Field | Message |
|---|---|---|
2016 | page | page must be greater than 0 |
2017 | size | size must be greater than 0 |
2018 | size | size must not exceed 500 |
2019 | start_date | start_date cannot be negative |
2020 | end_date | end_date cannot be negative |
2021 | start_date | start_date must be before end_date |
3.5 Configuration validators
code | Field | Message |
|---|---|---|
2022 | env | env is required |
2023 | privateCredentialId | privateCredentialId is required |
2024 | country | country is required |
2025 | pinTimeOut | pinTimeOut cannot be negative |
2026 | cardDetectTimeOut | cardDetectTimeOut cannot be negative |
2027 | pinKeyIndex | pinKeyIndex cannot be negative |
2028 | dataKeyIndex | dataKeyIndex cannot be negative |
2029 | timeoutSeconds | timeoutSeconds cannot be negative |
2030 | maxChipRetries | maxChipRetries cannot be negative |
2031 | countryCode | countryCode must be 3 uppercase letters or 3-4 digits (ISO 3166-1) |
2032 | currencyCode | currencyCode must be 3 uppercase letters or 3-4 digits (ISO 4217) |
2033 | merchantId | merchantId cannot be blank |
2034 | terminalId | terminalId cannot be blank |
2035 | terminalType | terminalType cannot exceed 2 characters |
2036 | CardInput | At least one card input method (ICC, NFC, MSR) must be enabled |
2037 | timeoutSeconds | timeoutSeconds cannot exceed 300 seconds (5 minutes) |
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.
code | Description | Message template |
|---|---|---|
TER-001 | Terminal not linked to the merchant account | Terminal {{serial_number}} does not exist, or is not linked to your account |
TER-002 | Terminal not responding: offline or off the network | Terminal {{serial_number}} is not responding. It may be offline or not connected to the local network |
TER-003 | Terminal busy processing a transaction | Terminal {{serial_number}} is busy processing transaction (client_transaction_id: {{id}}) |
TER-004 | Terminal busy with an action other than a payment | Terminal {{serial_number}} is busy executing action {{action}} |
TER-005 | Terminal in a mode incompatible with the operation | The terminal is in {{mode}} mode and does not allow the requested action |
TER-006 | Terminal not enabled for that operation type | The terminal is not allowed to process {{type}} |
5. Authentication errors — type: “AUTHENTICATION”
These are generated when credentials are invalid or do not carry enough permissions for the requested action.
code | Description | Message |
|---|---|---|
AUTH-001 | Credentials cannot be authenticated | Invalid or expired credentials |
AUTH-002 | Valid credentials without permission for the resource | Your credentials are valid but do not grant access to this resource |
{"type": "AUTHENTICATION","code": "AUTH-001","message": "Invalid or expired credentials"}
6. Routing and internal errors
type: “NOT_FOUND”
code | Description | Message template |
|---|---|---|
NF-001 | Service or endpoint not found | Service not found: {{url}} |
type: “INTERNAL”
code | Description | Message |
|---|---|---|
INT-001 | Unexpected server or application error | Internal server error |
7. Acquirer errors — type: “ACQUIRER”
Errors from the Kushki acquirer are wrapped under type: "ACQUIRER" with this mapping rule:
code: the original Kushki code with theACQ-prefix. Code13becomesACQ-13.message: identical to Kushki’s original message.object: includesclient_transaction_id,terminal_idandserial_numberwhere applicable.- HTTP status: we keep the one Kushki originally returned.
Original Kushki error:
{"code": "13","message": "Either Invalid amount or Currency conversion field overflow"}
Error mapped by Kushki ONE Connect, with the same 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. Manufacturer errors — type: “MANUFACTURER”
Errors from the manufacturer SDK are wrapped with the MAN- prefix followed by the original code. Sunmi’s -2001 becomes 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"}}
Most frequent Sunmi codes
code | Description | Recommended action |
|---|---|---|
MAN--2001 | Have no card | The customer did not present the card. Ask for a retry |
MAN--2002 | Multiple cards | More than one card is in the NFC field. Ask them to remove the extras |
MAN--2581 | User canceled | The customer canceled. Treat it as an expected cancellation |
MAN--2582 | MSR or IC interrupted | Reading interrupted. Ask them not to remove the card until the terminal says so |
MAN--3023 | DUKPT overflow | DUKPT counter exhausted. Requires key reinjection. Contact support |
MAN--4104 | Card is locked | Card blocked. The customer must contact their bank |
MAN--4111 | Card expired | Expired card. Let the customer know |
MAN--4120 | Amount exceeds contactless limit | The amount exceeds the NFC limit. Use chip instead |
MAN--50020 | PIN entry cancel | The customer canceled PIN entry. Treat it as a cancellation |
MAN--60001 | Input PIN timeout | The customer did not enter the PIN in time. Ask for a retry |
9. Configuration errors — type: “CONFIGURATION”
These are generated when the operation is not enabled for that terminal in the DMS, or when the amount exceeds the configured limits. Unlike PARAMETER errors, they are not fixed by changing the payload.
code | Cause | Recommended action |
|---|---|---|
-4001 | Tipping is not enabled on the terminal | Contact Kushki Operations to enable it in the DMS |
-4002 | Cashback is not enabled on the terminal | Contact Kushki Operations to enable it in the DMS |
-4003 | The cashback amount exceeds the configured limit | Tell the customer the available limit. Do not retry with the same amount |
-4006 | The transaction amount exceeds the configured limit | Tell the customer. Contact Kushki Operations if the limit needs adjusting |
{"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. Kushki Printer errors — type: “TERMINAL-PRINTER”
Errors from the printing hardware. They are standardized regardless of the terminal manufacturer.
code | Cause | Action for the operator |
|---|---|---|
OUT_OF_PAPER | No paper roll | Insert a new roll and retry |
COVER_OPEN | Paper compartment cover open | Close the cover firmly |
COVER_INCOMPLETE | Cover badly closed or roller without pressure | Open and close making sure the roller seats |
PAPER_JAM | Paper jammed in the mechanism | Remove the jammed paper and insert a new roll |
BUSY | Print queue busy with skipIfBusy: true | Retry in a few seconds |
PRINTER_HOT | Thermal print head overheated | Wait 2 or 3 minutes and retry |
MOTOR_HOT | Feed motor overheated | Wait for it to cool down |
CUTTER_ERROR | Cutter blade jammed | Requires technical service intervention |
OFFLINE | The module is not responding to the Android system | Restart the terminal |
UNKNOWN_ERROR | Unclassified hardware failure | Log the case and escalate to technical support |
11. Quick diagnostic guide
If type is… | And code… | Then |
|---|---|---|
AUTHENTICATION | AUTH-001 | Check that you sign with the Business-Code and that the timestamp unit is correct |
AUTHENTICATION | AUTH-002 | Credentials are valid but permissions are missing. Contact integrations |
PARAMETER | any | Check the field named in param. Add validation in your POS before calling the API |
PARAMETER | 2002 to 2009 | You most likely sent amounts with decimals instead of integers |
TERMINAL | TER-002 | The terminal is offline. Check network connectivity |
TERMINAL | TER-003 or TER-004 | The terminal is busy. Wait or use abort |
TERMINAL | TER-006 | Capability not enabled. Contact Kushki Operations |
TERMINAL-PRINTER | any | Physical hardware condition. Show the message to the operator |
MANUFACTURER | starts with MAN--200 | Card reading problem. Ask the customer for a retry |
MANUFACTURER | MAN--50020 or MAN--60001 | The customer canceled or did not enter the PIN. Treat it as an expected cancellation |
ACQUIRER | any | Processor decline. Show the message to the customer and log the code |
CONFIGURATION | any | Do not retry with the same payload. Requires a DMS adjustment |
INTERNAL or NOT_FOUND | any | Log 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 AUTHENTICATION errors by reviewing the two signing mechanisms and their differences.
Async services and webhooks
Interpret the failure_reason object inside the transaction lifecycle.
Chile
Colombia
Ecuador
Peru