Structuring and validating Terminal API messages

Learn how to structure Terminal API messages based on the Nexo standard.


Adyen’s Terminal API is based on the Nexo retailer standard implemented in JSON messages transmitted via long-timeout HTTPS request-response pairs.

Adyen has only implemented a subset of the Nexo standard. If you use messages from the Nexo standard that Adyen has not implemented, the terminal will return an error. If you use unsupported elements in supported messages, Adyen will process the message but return a warning that some fields were not used.

JSON messages will be checked and return errors if the JSON is not valid.

Terminology

Sale system - This is another name for cash register or POS.

POI - Point of Interaction. This is an alternate name for a a payment terminal or PED.

URL

The URL used to send Terminal API messages depends on your type of implementation. For more information, see our Local and Cloud architectures.

Data types

Most base data types used in the Terminal API are common in other languages such as Enumerations, Strings, Integers, etc.

One data type that is often used in the Terminal API, but is less common outside of nexo, is a cluster. A cluster is an unordered list of 0 to n enumerated values.

For example, a cluster called EntryMode may contain values: ICCKeyedMagStripeScanned. A valid instance of EntryMode can then be: [], or [ICC, Keyed] or [Keyed].

Terminal API message structure

Terminal API messages consist of 3 components:

  • a message envelope
  • a message header
  • a message body

Main envelope

There are 2 types of envelopes: SaleToPOIRequest and SaleToPOIResponse.

The header and body of a message submitted in a HTTPS request will always be enveloped in a SaleToPOIRequest, and the message within the HTTPS response will always be enveloped in a SaleToPOIResponse.

{
   "SaleToPOIRequest" : {
                                           ...
                      }
}


{
   "SaleToPOIResponse" : {
                                           ...
                      }
}

Header

A header consists of 7 elements. ProtocolVersion  is conditional. If messages are being sent in a session between a login and logout of a particular Sale system, only the login requires a ProtocolVersion field. All other elements are mandatory for every request and response.

The SaleID and ServiceID in the MessageHeader should be unique. SaleID and ServiceID combinations are rejected if used recently, within 48 hours.

Name Type Description

ProtocolVersion

String

Version of Terminal API used. The default value is: 3.0

MessageClass

Enum

Enumeration: Service, Device, Event.

MessageCategory

Enum

Enumeration: Payment, TransactionStatus, Reversal, Abort. See Nexo documentation for full list.

MessageType

Enum

Enumeration: Request, Response, Notification.

ServiceID

String

A string that uniquely identifies request response pair. Must be unique. Maximum number of characters = 10.

POIID

String

Uniquely Identifies PED for POS. This is the Adyen terminal ID and must match the Terminal ID of the terminal receiving the message. Example: P400-123456789.

SaleID

String

Uniquely Identifies POS for PED. Example: YourSaleSystemID001.

Header example

  "MessageHeader" : {
         "SaleID" : “POSSystemID12345",
         "MessageClass" : "Service",
         "POIID" : "POITerm1",
         "ServiceID" : "7975",
         "MessageType" : "Request",
         "ProtocolVersion" : "3.0",
         "MessageCategory" : "Reversal"
      },

Body

The body holds different content for each MessageType. The content is further specified for various use cases throughout the documentation.

All response message types contain a result.

Name Type Description
Result Enum: Success or failure Mandatory for all responses
ErrorCondition Enum, see error management section for a complete overview Mandatory if result is failure. Optional otherwise
AdditionalResponse String: log for fault finding Optional

Body example

  "SaleToPOIResponse" :
      "TransactionStatusResponse" : {
         "Response" : {
            "ErrorCondition" : "NotFound",
            "Result" : "Failure",
            "AdditionalResponse" : "Message not Found, last PaymentRequest has ID 2"
         }}}


Validating HTTP requests

After you submit a HTTP request, the nexo application validates incoming JSON and sends a response.

Invalid JSON

If the message is not a valid JSON object, the nexo application will respond with a HTTP Reply body, for example:

["Bad JSON:[line]: [message]"]


[line] and [message] will contain details of the error

Valid JSON Invalid Nexo Request

If the incoming message is valid JSON but not a valid Nexo request, a HTTP Reply body is generated according to nexo specifications, for example:

{ 
   "SaleToPOIResponse" : {
      "PaymentResponse" : {
         "SaleData" : {},
         "Response" : {
            "Result" : "Failure",
            "ErrorCondition" : "MessageFormat",
            "AdditionalResponse" : "At toplevel, field SaleToPOIRequest: Missing"
         },
         "POIData" : {
            "POITransactionID" : {
               "TimeStamp" : "2017-06-02T12:23:53.000Z",
               "TransactionID" : "oLkO001496406233000.9815033996072250"
            }
         }
      },
      "MessageHeader" : {
         "MessageType" : "Response",
         "MessageCategory" : "Payment",
         "MessageClass" : "Service",
         "ProtocolVersion" : "3.0"
      }
   }
}

Request issued, not implemented

If a request is issued that is not implemented. A message is generated, for example:

{
   "SaleToPOIResponse" : {
      "MessageHeader" : {
         "MessageType" : "Response",
         "SaleID" : "POSSystemID12345",
         "MessageClass" : "Service",
         "ProtocolVersion" : "3.0",
         "MessageCategory" : "StoredValue",
         "POIID" : "MX925-123456789",
         "ServiceID" : "11605"
      },
      "StoredValueResponse" : {
         "Response" : {
            "ErrorCondition" : "UnavailableService",
            "AdditionalResponse" : "Unavailable Device Service",
            "Result" : "Failure"
         }
      }
   }
}