Point-of-sale icon

Handle responses

Learn how to resolve Terminal API errors and handle declined payments.

To be able to resolve issues with your requests, you need to know how Terminal API informs you of the processing status of your request. This is communicated in the Response object of the API response, which has:

  • Result: one of the following values:

    • Success: the request succeeded / the transaction was approved on the terminal.
    • Partial: the transaction amount has been partially approved.
    • Failure: the request or transaction didn't succeed. The remaining Response fields provide more information about the error, to enable you to determine how to handle it.

  • ErrorCondition: this field is included when the request or transaction fails, and indicates the cause of the failure.

  • AdditionalResponse: more information about the error condition. You'll receive either a string of form-encoded key-value pairs or a Base64 string that you need to decode to get a JSON object.

Now let's see what you can do when:

  • The request failed because it was invalid.
  • You made a payment request but didn't receive a result.
  • The result of your payment request indicates the transaction failed.

Invalid message format

A Response object with Result Failure and ErrorCondition MessageFormat indicates there was a mistake in the request you sent. Proceed as follows:

  1. Determine what caused the error, based on the message, warnings, or errors in the AdditionalResponse. For example, a missing required field or an unexpected field.

    The following example is for a response indicating that the Currency field is missing from the payment request:

    {
    ...
       "Response":{
          "Result":"Failure",
          "AdditionalResponse": "errors=At%20SaleToPOIRequest.PaymentRequest.PaymentTransaction.AmountsReq%2c%20field%20Currency%3a%20Missing",
          "ErrorCondition":"MessageFormat"
       }
    ...
    }
  2. Refer to the Terminal API reference if necessary, then manually fix your request and try again.

Invalid JSON format

If your API request does not contain a valid JSON object, you receive a Bad JSON HTTP reply that specifies the line number and a description of the issue:

["Bad JSON:LINE_NUMBER: DESCRIPTION"]
  • Manually fix the JSON error on the line mentioned in the HTTP reply and try again.

Unavailable service

A Response object with Result Failure and ErrorCondition UnavailableService indicates we were unable to implement your request. Proceed as follows:

  1. Determine what caused the error, based on the message, warnings, or errors in the AdditionalResponse. For example:

    • You tried to use functionality that the payment terminal doesn't support.
    • You tried to use a ProtocolVersion that the terminal can't manage.
    • You tried to use functionality that we don't support.

    The following example is for a response indicating that there's a mismatch between the protocol versions (2.0 in the request and 3.0 on the terminal):

    {
    ...
       "Response": {
          "Result": "Failure",
          "AdditionalResponse": "message=Sale%20Protocol%20Version%202.0%20mismatch%2c%20Version%20implemented%3a%203.0",
          "ErrorCondition": "UnavailableService"
       }
    ...
    }
  2. Depending on the cause of the error, manually fix your request and send it again. For example, after receiving the above failure response you'd specify the same protocol version that the terminal supports.

No result received

We recommend that your integration automatically checks the status of a transaction any time it fails to receive a transaction response.

Payment requests time out after a while. If you do not receive a payment response (or you receive a response indicating a time-out) after 120 seconds (local integration) or 150 seconds (cloud integration), and the internet connection hasn't dropped, your integration should automatically check the transaction status.

If you do not receive a transaction result, neither synchronously nor asynchronously, proceed as follows:

  1. Make a TransactionStatusRequest (see Verify transaction status for details).

  2. Determine your next action based on the TransactionStatusResponse.Response:

    Response Description Action
    Result Success The transaction was processed. Use the RepeatedResponseMessageBody to determine how to process the transaction.
    ErrorCondition InProgress The payment terminal is waiting for a response from the shopper, or there is a delay with the card issuer. Continue making a transaction status request for this transaction every five seconds until you receive a response indicating the transaction was processed.
    ErrorCondition NotFound Possible causes:
    • The details you specified in the transaction status request are incorrect.
    • We did not receive your request; maybe your connection dropped after sending the request.
    Possible actions:
    • Provide the details of the original transaction in the MessageReference of your transaction status request.
    • Retry the original transaction.

Terminal unavailable (cloud integration)

When you send a PaymentRequest to a payment terminal that is unavailable, the payment can't be processed. In a cloud integration, the Terminal API generates a Reject event notification.

Note that event notifications are always presented as a SaleToPOIRequest.

The EventNotification body contains:

  • RejectedMessage: a Base64 string containing the payment request that couldn't be processed. Decode this to get the original payment request as a JSON object.
  • EventToNotify: Reject
  • EventDetails: a message indicating why the payment terminal is unavailable.

Here's an example event notification for an unavailable payment terminal in a cloud integration:

{
   "SaleToPOIRequest": {
      "EventNotification": {
         "EventToNotify": "Reject",
         "EventDetails": "message=Did+not+receive+a+response+from+the+POI.",
         "RejectedMessage": "ewoi...0KfQo=",
         "TimeStamp": "2020-03-31T10:28:39.515Z"
      },
      "MessageHeader": {
         "DeviceID": "666568147",
         "MessageCategory": "Event",
         "MessageClass": "Event",
         "MessageType": "Notification",
         "POIID": "P400Plus-123456789",
         "ProtocolVersion": "3.0",
         "SaleID": "saleid-4c32759faaa7",
         "ServiceID": "31122609"
      }
   }
}

The steps that you can take, relate to the EventDetails message you receive:

Did not receive a response

"message=Did+not+receive+a+response+from+the+POI."

This message indicates that the request was sent but the payment terminal didn't respond, possibly because the WebSocket is down at the terminal.

Failed to send message

"message=Failed+to+send+message+to+POI.+There+may+be+a+network+issue+or+it+may+not+have+the+websocket+connected."

This message indicates that probably the WebSocket for the payment terminal is not available on the cloud Terminal API router.

  • Check the WebSocket connection:

    • The terminal display should have a cloud icon in the top row.
    • Check the cloud connection from your Customer Area, using an API request, or on the terminal itself.

Unknown POIID

"message=Unknown+POIID+P400Plus-123456789"

This message indicates that the terminal ID (POIID) in the payment request is incorrect, or that the terminal is in the inventory of the Company account and hasn't been assigned to a merchant account or store that allows processing payments.

  1. On the payment terminal, open the terminal information (press 5 and then the Confirm button or see the instructions for your payment terminal model) and verify that the terminal ID in the format [device model]-[serial number] matches the POIID that you specified in the payment request. For example, P400Plus-123456789.
    If the POIID matches, go to the next step.
  2. Verify that the payment terminal is assigned to a merchant account or store. You can do this using a /getTerminalsUnderAccount request, or using your Customer Area.

Declined payment

When a PaymentRequest results in a Response object with Result Failure and one of the error conditions listed below, the transaction was declined.
The AdditionalResponse has more information about why the transaction was declined in the refusalReason and message fields. These fields are our mapping of the response we receive from acquirers and issuers.

Here's an example failure response for a declined payment:

{
...
   "Response": {
      "Result": "Failure",
      "AdditionalResponse": "refusalReason=214%Declined%20online...&message=CANCELLED...",
      "ErrorCondition": "Refusal"
   }
...
}

When your payment request is declined, you need to determine whether you can retry it:

  1. Check the ErrorCondition in the PaymentResponse.Response, because in many cases this already indicates whether you can retry the transaction.

    Error condition Retry?
    Aborted -white_check_mark-
    Busy See next step
    Cancel See next step
    DeviceOut -white_check_mark-
    InvalidCard See next step
    NotAllowed -x-
    Refusal See next step
    UnreachableHost -white_check_mark-
    WrongPIN -white_check_mark-
  2. For the error conditions Cancel, InvalidCard, and Refusal, check the AdditionalResponse for the refusalReason and message. For the error condition Busy, check the response for a serviceId. You can use this if you want to cancel the transaction.

    You can use the ErrorCondition to code your POS app. The refusalReason and Message fields are included for additional insight, and should not be coded against.
    The serviceId can be used by the POS app to cancel a transaction.

    Select the tabs for details.

    ErrorCondition refusalReason message Retry?
    Cancel Approved APPROVED -x-
    Cancel (all other refusalReasons) (all other messages) -white_check_mark-

    The ErrorCondition Cancel can be caused by a device time-out.

    For more information, see our reference documentation for refusal reasons. If you enabled receiving the refusalReasonRaw field in the AdditionalResponse, also see our reference documentation for raw acquirer responses.

    The refusalReasonRaw provides additional information. But if you base your code on it, that might break your integration because acquirers and issuers sometimes change their raw responses without notice.

  3. If applicable, retry the transaction.

Time-out

If a time-out occurs during a payment, the transaction is declined. The Response object includes Result Failure.

  • A processing time-out returns the ErrorCondition Communication timeout.
  • A device time-out returns the ErrorCondition Cancel and mentions the type of time-out in the AdditionalResponse.

Error condition comparison

The table below compares error conditions and troubleshooting steps specific to making a PaymentRequest, TransactionStatusRequest, or ReversalRequest (a referenced refund).

Error condition PaymentRequest TransactionStatusRequest ReversalRequest
Aborted Retry not applicable Optionally retry
Cancel See Declined payment not applicable not applicable
DeviceOut Wait and retry Wait and retry Wait and retry
InProgress not applicable See No result received not applicable
InvalidCard See Declined payment not applicable not applicable
Invalid message format
NotAllowed Don't retry Wait and retry Wait and retry or Retry different device
NotFound Manual recovery See No result received Manual recovery
Refusal See Declined payment not applicable Manual recovery
Unavailable service
UnreachableHost Retry Retry Retry
WrongPIN Retry not applicable not applicable

See also