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 | ✅ | Prefix 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 |
param | string | — | The exact request field that caused the error. Present only when the failure is attributable to a field — see below |
message | string | ✅ | Human-readable description of the failure |
object | object | — | Traceability 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.
| 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."}}
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 param | Why |
|---|---|
PAR-003, TER-003, AUTH-001 | Data validation errors — there is a field at fault |
NF-001 | Carries the identifier that was not found |
Comes without param | Why |
|---|---|
TER-004 | Printer busy, or the cardholder cancelled. The request was valid; the hardware or the person was not |
MAN-30005 | Card or PIN timeout. Same reason |
ACQUIRER | The transaction was valid and the bank declined it |
CONF-4007 | Terminal provisioning, not the call |
PAR-002 with unreadable JSON | The 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
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 |
AUTH | 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. Native code, unprefixed |
INTERNAL | Application | Unexpected errors: services down, internal failures |
CONFIGURATION | Terminal capability | 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 |
TERMINAL-SUNMI | 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 2002 to 2021 range, plus the BAD_FORMAT format code.
3.1 System codes
code | Description |
|---|---|
BAD_FORMAT | JSON parsing error. The request body is not valid JSON or contains a wrong data type |
3.2 Amount and payment field validators
code | Field | Message | Applies to |
|---|---|---|---|
2002 | amount.iva | amount.iva cannot be negative | All |
2003 | amount.subtotal_iva | amount.subtotal_iva cannot be negative | All |
2004 | amount.subtotal_iva0 | amount.subtotal_iva0 cannot be negative | All |
2005 | amount.tip | amount.tip cannot be negative | /charge and /authorization, plus /pos_tip where the tip is the amount |
2006 | amount.extra_taxes.airport_tax | amount.extra_taxes.airport_tax cannot be negative | All |
2007 | amount.extra_taxes.iac | amount.extra_taxes.iac cannot be negative | All |
2008 | amount.extra_taxes.ice | amount.extra_taxes.ice cannot be negative | All |
2009 | amount.extra_taxes.travel_agency | amount.extra_taxes.travel_agency cannot be negative | All |
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:
| Condition | Result |
|---|---|
deferred.months out of range for the country | PARAMETER error on deferred.months |
deferred.credit_type sent outside Chile | PARAMETER error — credit_type exists only in Chile |
deferred and query_deferred sent together | PARAMETER error — the two are mutually exclusive |
query_deferred sent outside Mexico | PARAMETER 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
code | Field | Message |
|---|---|---|
2010 | client_transaction_id | client_transaction_id must be a valid UUID format |
2011 | client_transaction_id | client_transaction_id is required |
2014 | transaction_reference | transaction_reference must be a valid UUID format |
2015 | transaction_reference | transaction_reference is required |
3.5 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 |
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 | Printer busy, or cardholder cancellation. See the section on this code below | 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: “AUTH”
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": "AUTH","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 acquirer’s native code, unchanged and unprefixed.E020is returned asE020. 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 anACQ-prefix, it never arrives.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": "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.
code | Cause | Recommended action |
|---|---|---|
CONF-4001 | Tipping is not enabled on the terminal | Request it at soporte@kushkipagos.com |
CONF-4002 | Cashback is not enabled on the terminal | Request it at soporte@kushkipagos.com |
CONF-4003 | The cashback amount exceeds the configured limit | Tell the customer the available limit. Do not retry with the same amount. To raise it, write to soporte@kushkipagos.com |
CONF-4006 | The transaction amount exceeds the configured limit | Tell the customer. To raise the limit, write to soporte@kushkipagos.com |
CONF-4007 | Terminal provisioning problem — not caused by your call | Escalate 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.
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 |
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 |
|---|---|---|
AUTH | AUTH-001 | Check that you sign with the Business-Code and that the timestamp unit is correct |
AUTH | 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 |
INTERNAL | MQTT_REQUEST_FAILED | The Cloud relay could not reach the terminal. Check it is online and retry. Cloud only |
TERMINAL | TER-002 | The terminal is offline. Check network connectivity |
TERMINAL | TER-003 | The terminal is busy with a transaction. Wait or use abort |
TERMINAL | TER-004 | On a print endpoint the printer is busy: retry. On a payment endpoint the cardholder cancelled: do not retry |
TERMINAL | TER-006 | Capability not enabled for this terminal. Write to soporte@kushkipagos.com |
TERMINAL-PRINTER | any | Physical hardware condition. Show the message to the operator |
TERMINAL-SUNMI | MAN-30005 | Card or PIN timeout. 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. Write to soporte@kushkipagos.com |
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 AUTH 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