Skip to content

Dotypay - Payment Protocol

The purpose of this document is to provide the POS (ECR) with a single API to communicate with external POI devices. We will use the Nexo standard as the API. This document will describe the Nexo messages that will be used in our solution. We will not copy here the entire Nexo standard spec. For further information you could refer to and learn the official Nexo document.

NEW! We prepared example requests for the Postman application, you can download them here.

Payment Protocol Version: 1 (based on Nexo protocol v3.1)

Dotypay version: 2.1.160

Changes

Date Author Version Description
11.05.2020 PO v1.3.0 HTTPS implementation, POIID verification in requests
19.05.2020 PO v1.3.2 Implicit authentication for certified POSes, new request to get the list of supported POIIDs
18.06.2020 PO v1.3.7 Added request result codes
21.07.2020 PO v1.3.10 Added flag ECRPrint to ProprietaryTags in response to indicate whether the POS should print the receipt
31.07.2020 PO v1.4.0-RC1 Receipt data in response, if flag ECRPrint is set to true; mandatory authorization in the Intent communication
17.08.2020 PO v1.4.0-RC2 Added information about mockup build
22.09.2020 MM v1.4.0-RC3 Extension of POI Terminal list - specification for more terminals
27.10.2020 PO v1.4.4 0 Added variable symbol to sale request and response
18.11.2020 PO v1.4.60 Added enumerated values to receipt images
01.12.2020 PO v1.5.40 Added reconciliation support
09.12.2020 PO v1.5.50 Added ResultCode for TransactionStatus reponse body
12.01.2021 PO v2.0.0 Added support for tips
12.01.2021 PO v2.0.1 Added ResultCode for failed signature verification; retrospectively added ResultCode for Place call.
17.02.2021 MM v2.0.20 Changed to bearer authorization in request examples
01.03.2021 MM v2.0.30 Example requests for Postman
02.03.2021 MM v2.0.40 Variable symbol request
01.06.2021 PO v2.1.80 ECRPrint in requests
14.06.2021 PO v2.1.90 Token communication, ECRPrint changes, added new Result Codes
16.08.2021 SK v2.1.160 Added the description of the Abort Request
17.08.2021 HT v2.2.0 Cloud terminal authorization

Overview

Glossary

Term Description
POS Point of Sale. This is the cash register (ECR), AKA Sale system. This term may refer to the hardware or the software of the POS.
POI Point of Interaction. This is the payment terminal, AKA PED.
PED PIN Entry Device. Same as POI.
Nexo The nexo Retailer protocol defines a set of interfaces between a card payment application and a retail point of sale system.
JSON JavaScript Object Notation.
HTTP HyperText Transfer Protocol. The Nexo messages will be sent using HTTP over TCP
HTTPS An extension of HTTP that is used for secure communication over a computer network
POIID A logical number that identifies the POI.
TID Terminal ID. This is a unique logical number of the payment terminal. TID will be used as the POIID.
CNP Card not present

General Requirements and Limitations

  1. The POI must be able to listen for TCP/HTTP connections (i.e. the POI is the server).
  2. The POS is the client. It creates the TCP/HTTP connection to the POI and sends the request to the POI using HTTP over TCP. The POS keeps the TCP/HTTP connection open until it gets the response.
  3. The request/response protocol between the POS and the POI will be based on HTTP over TCP.
  4. The HTTP body will be of Nexo format. This document will focus on the Nexo messages that are sent in the HTTP body. For more information about Nexo, please refer to Nexo official specification.
  5. For the communication of POS and POI on the same device, it is possible to communicate using Android Intents.
  6. The POI communicates with POS through a HTTPS protocol with self-signed certificate. This certificate is used just to enable an encrypted communication, not to verify POI's identity.

Default values

Default port number for STPay is set to 7500 for production release and 6999 for mock release. Default basic authentication values are user:pass (only for version 1.2-1.5). For versions 2.0.x and above please use bearer authorization. Please contact integrace@dotypay.com for mock device and token.

HTTP Format

Mandatory HTTP Request Headers

The following HTTP headers are mandatory:

Content-Type:application/json Content-Length: <the length of the JSON request string (the HTTP body)>

The POS (ECR) may send more headers, but they will be ignored by the POI.

Authentication

In order to secure the NEXO calls, every request needs to be authorized.

Authentication for cloud-based communication

Requests are authorized with an API key obtained via the Dotypay Portal - every user can create (and delete) their own API key on their profile.

Authorization: ApiKey <apiKey>

Each request must also contain two additional headers:

  1. X-Cloud-Identifier to specify the device the request is meant for. This identifier can be created on a device's edit page on the Dotypay Portal. In order for authorization to be successful, the API key provided in the Authorization header must belong to a user who has access to the specified device.

    X-Cloud-Identifier: 085c4fbf-b838-45c2-b648-92ffd0c9bd91

  2. X-Terminal-Authorization with the bearer token described below (see "Authentication for versions 2.0 and newer").

    X-Terminal-Authorization: Bearer <token>

Authentication for versions 2.0 and newer

Requests are authorized with a bearer token, which can be obtained through a POS certification process. Each request must contain a header field with the token: Authorization: Bearer <token>

Tokens have limited validity and they need to be periodically renewed. For development purposes, you can apply for a token, which will work on mockup devices.

Token environment

The token environment is bound to an application build type, which restricts its usage in certain application builds.

There are three environment tiers:

  1. MOCK - A token with this environment can be used only on MOCK application builds.
  2. MODEL - A token with this environment can be used on MODEL and MOCK application builds.
  3. PRODUCTION - This token can be used in every application build.
Token modules

Each token contains a set of modules, which authorizes the ECR to do certain actions.

  • BASE module - Basic functionality. Allows Sale and Reversal transactions, TransactionStatusRequest, AbortRequest and PoiTermList.
  • PRINTS module - Allows printing on ECR. If the token doesn't contain this module, printing will always be done on the POI.
  • SETTLEMENT module - Allows creating X and Z reports (reconciliations) from ECR.
  • REFUND module - Allows Refund transactions.
The Certification process

Every third party integrator can apply for a MOCK environment token. With this token, they implement all the functions needed to certify their application. Then Dotypay assigns them a token for the MODEL environment, which they embed into their application. Application with this token type will be used during the certification process in Dotypay. If all required tests pass, Dotypay will issue a PRODUCTION environment token to the integrator.

Authentication for versions 1.2 - 1.5

Requests are authorized with HTTP Basic Authentication. Basic Authentication is a method for an HTTP user agent to provide a username and password when making a request. This method request contains a header field in the form Authorization: Basic <credentials>, where credentials is the base64 encoding of username and password joined by a single colon : . For more information visit https://en.wikipedia.org/wiki/Basic_access_authentication.

The certified Point Of Sale systems such as Dotykacka, Markeeta, ProfiUctenka and SmartPOS can use the hardcoded username and password, these have been assigned during the certification process.

First request

If the POS runs on the same device as POI, it is recommended to check if the Nexo server is running. If the server is not running, you can start it programmatically using an Intent.

Request intent must target the launch intent for STPAY package (com.stpos.a8pos).

        PackageManager pm = activity.getPackageManager();

        // throws an Exception if STPAY is not installed
        pm.getPackageInfo("com.stpos.a8pos", PackageManager.GET_ACTIVITIES);
        Intent intent = pm.getLaunchIntentForPackage("com.stpos.a8pos");
        if (intent != null) {
            intent.setFlags(0);
            intent.putExtra("START_NEXO_SERVER", true);
            activity.startActivityForResult(intent, REQUEST_CODE);
        }

After STPAY starts the server, it will return back to the Activity, which sent the Intent.

Intent based communication

If the POS (ECR) is running on the same device as POI, the POS can call POI’s activity and receive result after the request is complete without any HTTP communication whatsoever.

First, the POS should check if the Payment Application is running.

  • If the Payment App isn’t running, the request intent should be the launch intent for it’s package (com.stpos.a8pos).
  • If the Payment App is running, the request intent should target it’s Main View (com.stpos.a8pos.main.MainView).

The Intent should be send with flags 0.

Request parameters

The request data in NEXO format must be placed as String Extra under key NEXO_REQUEST.

From version 1.4.0 are mandatory String extras USERNAME and PASSWORD, which will be checked when the request Intent arrives. These credentials are the same for both HTTP and Intent communication.

Response parameters

After the request is completed, the activity finishes and the result will be delivered through the onActivityResult() method in your Activity. The NEXO response payload will be available under the NEXO_RESPONSE key.

Nexo message structure

Nexo Message Structure consists of 3 main components: 1. a message envelope - SaleToPOIRequest/SaleToPOIResponse, depends if request or response 2. a message header - contains request metadata, consists of 7 elements 3. a message body - holds different content for each MessageType and MessageCategory

Request structure

 {
    "SaleToPOIRequest": {
        "MessageHeader": {
           ...header data...
        }
        ...body...
    }
}

POIID value in MessageHeader will be checked by the POI to identify the request recipient. If the POIID in the message header is not identical to the POIID as it is defined in the POI, then the POI will not accept the request and it will return an error. In the response, the POI will put its POIID in this tag (even if the POS sent the wrong POIID).

ECR Print in request

Each request, which may print a receipt, can contain ProprietaryTags element with an ECRPrint attribute in it. If the ECR has a PRINTS module in its token, the ECR is allowed to tell the POI, who will print the receipt. If the ECR doesn't have the module mentioned above, its usage is forbidden.

When ECRPrint in the request isn't used, the terminal will use it's own configuration to tell the ECR whether it must print the receipt or not.

Response structure

 {
    "ResultCode": 0,
    "SaleToPOIResponse": {
        "MessageHeader": {
           ...header data...
        }
        ...body...
    }
}

Each response object contains a result code in a ResultCode field to identify the request result.

Result code list

Name Code Description
UNDEFINED -1 Unclassified result.
OK 0 Success.
UNAUTHORIZED 100 The authorization failed. Check your credentials.
INVALID_CONTENT_TYPE 101 Request content-type has to be 'application/json'.
INVALID_JSON 102 The request JSON is not valid.
EMPTY_BODY 103 The request is empty.
UNKNOWN_REQUEST 104 The request is not valid or this request method is not implemented yet.
MANDATORY_DATA_MISSING 105 The request is missing required data.
ANOTHER_REQUEST_BEING_PROCESSED 106 The terminal is processing another transaction. Retry the request later.
HTTP_METHOD_NOT_ALLOWED 107 This HTTP method is not allowed.
REQUEST_TYPE_NOT_ALLOWED 108 The request type is not allowed on this terminal.
WRONG_TID 109 Terminal ID (TID, POIID) in the request doesn't correspond with the TID of this payment terminal.
CURRENCY_NOT_ALLOWED 110 Payment terminal does not allow to make transactions in this currency.
INVALID_AMOUNT 111 The request amount should be greater than zero.
TIMEOUT 200 Request timeout.
NOT_FOUND 201 Transaction with provided parameters was not found.
NO_REVERSIBLE_TRANSACTION_FOUND 202 Cannot reverse the transaction.
TRANSACTION_IS_NOT_REVERSIBLE 203 Cannot reverse the transaction.
CANCELED_BY_USER 204 The transaction was canceled by user.
CARD_READ_ERROR 205 The provided card could not be read.
ABORTED 206 The request was aborted externally.
CARD_READ_TIMEOUT 207 The card was not read in time.
NO_CONNECTION 208 The payment terminal cannot connect to the payment server.
NOT_ABORTABLE 209 Transaction with given parameters cannot be aborted.
HOST_REFUSED_GENERIC 300 Transaction was refused.
WRONG_PIN 301 Transaction was refused because the the customer PIN was incorrect.
EMPTY_HOST_RESPONSE 302 Payment authorization switch returned an empty answer.
TECHNICAL_REVERSAL 303 The request was sent to payment switch and the result could not be read. The transaction was successfully canceled afterwards.
PAYMENT_SWITCH_COMMUNICATION_ERROR 304 The request was sent to payment switch and the result could not be read. The transaction was not canceled due to another error. If you receive this result code, please call the support to verify the transaction result.
PLACE_CALL 305 The transaction requires a phone authorization. The staff member must call the authorization centre to complete the transaction.
SIGNATURE_NOT_VERIFIED 306 The transaction was successful and required a signature verification, which failed. The transaction was reversed afterwards.
CALL_SUPPORT 307 The transaction was sent to the payment switch and no response was received back. The staff member must call the technical support to discover the transaction result.
EMV_DECLINED 308 The transaction was declined by EMV kernel. If the transaction was successfully approved by the host, the transaction was reversed.

Concurrency

Only one request can be processed at the time. If there are more concurrent requests, only the first one will be processed and the other ones will return busy response (result code 106).

The same scenario is applied if the terminal processes a transaction locally.

ECR Print in response

The ECR must print the receipt if the ECRPrint attribute in ProprietaryTags element is set to true. If the ECR's token doesn't have the PRINTS module, ECRPrint will always be false. The location of ProprietaryTags varies depending on the type of Request (see individual Response examples). The ECRPrint is available in the app versions 1.4.0 and higher.

Nexo standards definies the location of the receipt data inside PaymentReceipt structure, which is located inside the particular response object (see the examples below).

For some reponse objects (ie. ReconciliationResponse) Nexo standards doesn't define PaymentReceipt structure, so the Receipt data will be located inside ProprietaryTags element.

Dotypay receipt format

If ECRPrint in Proprietary tags is set to true, the response object also contains the receipt data in Dotypay format and the ECR is obliged to print the receipt.

outputContent.OutputFormat determines the data format. Currently supported format is Dotypay (from version 2.1.0). The DotypayData tag contains an array of receipt lines. Each line is a JSON object with predefined format.

Line format types
  • text - The basic text to print. It is in the text property. The format is defined in format object, which consists of three format items:
    • size (int): Text size. Default value is 18. Bigger texts, like amount value, should have their value around 26.
    • bold (boolean): true if the text should be printed in bold. false otherwise.
    • align (string): One of the following values: start, center, end.
  • twocolumns - The text should be formatted into two colums, defined in properties left and right. Each column is text type with it's own format.
  • division - A horizontal division line for separating content on the receipt.
  • image - An image. If the image is from enumerated list, it will contain it's enumerated value, so the POS doesn't have to parse the binary data every time. The fields in the image line are:
    • data (string): BASE64 encoded bmp data. Flags for the encoding are NO_WRAP and NO_PADDING.
    • enumValue (string). Supported values are:
      • CLESS_LOGO: Logo for contactless transaction

The sample output is in the Sale response.

Mockup

Mockup version of STPAY app is shown as STPAY MOCK in the laucher.

This version of the app doesn't communicate with any server, thus the implementator can use production cards to test the transactions with.

Because the card data are not being verified online, transaction result is being set based on the requested amount.

If the reqested amount is:

  • greater or equal to 1000: transaction is declined,
  • greater or equal to 555 and less than 556: result is PLACE CALL,
  • greater or equal to 666 and less than 667: result is TECHNICAL REVERSAL FAIL,
  • greater or equal to 110 and less than 121: result contains additional food card data.

Supported Transaction Types [/]

Sale [POST]

A request combining the Auth and Completion transactions that instructs the Gateway to perform both actions, one after the other: query the bank for authorization and, upon approval, immediately complete the transaction. In Nexo, the Sale is done by using "PaymentType": "Normal"

ProprietaryTags in PaymentTransaction is optional.

The POS can set the tipping options by setting the value of AskForTip in ProprietaryTags. If the value is missing, the customer will be asked for a tip based on the POI configuration. If the user was asked for a tip, the POI performs the payment transaction for the RequestedAmount increased by the value of tip amount, and the TipAmount will be present in the response if the whole payment is authorised as following:

AmountsResp.AuthorizedAmount = AmountsReq.RequestedAmount + AmountsResp.TipAmount

The POS can also request the variable symbol prompt by setting the value of AskForVariableSymbol in ProprietaryTags to true. The VariableSymbol value overrides the AskForVariableSymbol - if the VariableSymbol is present, the POI will use the provided VS and won't ask the user for it.

  • Request (application/json)

    • Headers

      Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJlb...
      Content-Length: <calculated>
      
    • Body

      {
          "SaleToPOIRequest": {
              "MessageHeader": {
                  "MessageCategory": "Payment",
                  "MessageClass": "Service",
                  "MessageType": "Request",
                  "POIID": "POITerm1",
                  "ProtocolVersion": "3.1",
                  "SaleID": "POS_ID_1234",
                  "ServiceID": "123456"
              },
              "PaymentRequest": {
                  "PaymentData": {
                      "PaymentType": "Normal"
                  },
                  "PaymentTransaction": {
                      "AmountsReq": {
                          "Currency": "CZK",
                          "RequestedAmount": 10
                      },
                      "ProprietaryTags": {
                          "AskForTip": true,
                          "VariableSymbol": "123123",
                          "AskForVariableSymbol": false,
                          "ECRPrint": true
                      }
                  },
                  "SaleData": {
                      "SaleTransactionID": {
                          "TimeStamp": "2020-04-19T14:20:00+0100",
                          "TransactionID": "12345678-abcd-abcd-abcd-123456789abc"
                      }
                  }
              }
          }
      }
      
  • Response 200 (application/json)

    • Headers

    • Body

      {
          "ResultCode": 0,
          "SaleToPOIResponse": {
              "MessageHeader": {
                  "MessageCategory": "Payment",
                  "MessageClass": "Service",
                  "MessageType": "Response",
                  "POIID": "POITerm1",
                  "ProtocolVersion": "3.1",
                  "SaleID": "POS_ID_1234",
                  "ServiceID": "123456"
              },
              "PaymentResponse": {
                  "PaymentData": {
                      "PaymentType": "Normal"
                  },
                  "PaymentReceipt": {
                      "documentQualifier": "saleReceipt",
                      "integratedPrintFlag": true,
                      "outputContent": {
                          "OutputFormat": "Dotypay",
                          "DotypayData": [
                              {
                                  "format": {
                                      "align": "start",
                                      "bold": false,
                                      "size": 18
                                  },
                                  "text": "Basic text",
                                  "type": "text"
                              },
                              {
                                  "type": "division"
                              },
                              {
                                  "left": {
                                      "format": {
                                          "align": "start",
                                          "bold": false,
                                          "size": 18
                                      },
                                      "text": "Left column text",
                                      "type": "text"
                                  },
                                  "right": {
                                      "format": {
                                          "align": "end",
                                          "bold": false,
                                          "size": 18
                                      },
                                      "text": "Right column text",
                                      "type": "text"
                                  },
                                  "type": "twocolumns"
                              }
                          ]
                      },
                      "requiredSignatureFlag": false
                  }
                  "PaymentResult": {
                      "AmountsResp": {
                          "AuthorizedAmount": 11.0,
                          "TipAmount": 1.0,
                          "Currency": "CZK"
                      },
                      "PaymentInstrumentData": {
                          "CardData": {
                              "MaskedPan": "53xx-xxxx-xxxx-1234"
                          }
                      },
                      "ProprietaryTags": {
                          "Aid": "A0000000041010",
                          "ApplicationName": "DEBIT MASTERCARD",
                          "AuthorizationCode": "123456",
                          "Brand": "MASTER",
                          "CardExpiration": "20220731",
                          "CardPresentationMethod": "CLESS",
                          "ECRPrint": true,
                          "ReceiptDate": "2020-04-24T14:20:11+02:00",
                          "SequenceNumber": "1234567890",
                          "SignatureRequired": false,
                          "TerminalId": "POITerm1  ",
                          "VariableSymbol": "123123",
                          "VerifiedByDevice": false
                      }
                  },
                  "POIData": {
                      "POITransactionID": {
                          "TimeStamp": "2020-04-24T14:20:11+02:00",
                          "TransactionID": "79fe58f3-511f-4964-9e63-91609ae02273"
                      }
                  },
                  "Response": {
                      "Result": "Success"
                  }
              }
          }
      }
      

Reversal [POST]

A request initiated by the merchant, Technical Support, or Risk department, instructing the Gateway to cancel (delete) the last transaction before end of day. The reversed transaction can either be a Completion, Sale or Refund. The reversal transaction enables you to cancel an erroneous or problematic transaction before it is completed.

In Nexo, it is done by using "MessageCategory": "Reversal" in the message header.

Original transaction will be identified by data sent in OriginalPOITransaction.POITransactionID field.

  • Request (application/json)

    • Headers

      Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJlb...
      Content-Length: <calculated>
      
    • Body

      {
          "SaleToPOIRequest" : {
              "MessageHeader" : {
                    "MessageCategory" : "Reversal",
                    "MessageClass" : "Service",
                    "MessageType" : "Request",
                    "POIID" : "POITerm1",
                    "ProtocolVersion" : "3.1",
                    "SaleID" : "POS_ID_1234",
                    "ServiceID" : "12345678"
              },
              "ReversalRequest" : {
                  "OriginalPOITransaction" : {
                      "POITransactionID": {
                          "TimeStamp": "2020-04-24T14:20:11+02:00",
                          "TransactionID": "79fe58f3-511f-4964-9e63-91609ae02273"
                      }
                  },
                  "ReversalReason" : "MerchantCancel",
                  "ProprietaryTags": {
                      "ECRPrint": true
                  }
              }
          }
      }
      
  • Response 200 (application/json)

    • Headers

    • Body

      {
          "ResultCode": 0,
          "SaleToPOIResponse": {
              "MessageHeader": {
                  "MessageCategory": "Reversal",
                  "MessageClass": "Service",
                  "MessageType": "Response",
                  "POIID": "POITerm1",
                  "ProtocolVersion": "3.1",
                  "SaleID": "POS_ID_1234",
                  "ServiceID": "12345678"
              },
              "ReversalResponse": {
                  "PaymentReceipt": {
                      "documentQualifier": "saleReceipt",
                      "integratedPrintFlag": true,
                      "outputContent": {
                          "DotypayData": [
                              {
                                  "format": {
                                      "align": "start",
                                      "bold": false,
                                      "size": 24
                                  },
                                  "text": "Receipt data in Dotypay format",
                                  "type": "text"
                              }
                          ],
                          "OutputFormat": "Dotypay"
                      },
                      "requiredSignatureFlag": false
                  },
                  "POIData": {
                      "POITransactionID": {
                          "TimeStamp": "2020-04-24T14:30:45+02:00",
                          "TransactionID": "766b894f-4512-40ec-8505-82e13c795b0d"
                      }
                  },
                  "Response": {
                      "Result": "Success"
                  }
              }
          }
      }
      

Refund [POST]

A request instructing the Gateway to refund a previously completed transaction to the consumer. In Nexo, the refund is done by using "PaymentType": "Refund"

  • Request (application/json)

    • Headers

      Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJlb...
      Content-Length: <calculated>
      
    • Body

      {
          "SaleToPOIRequest": {
              "MessageHeader": {
                  "MessageCategory": "Payment",
                  "MessageClass": "Service",
                  "MessageType": "Request",
                  "POIID": "POITerm1",
                  "ProtocolVersion": "3.1",
                  "SaleID": "POS_ID_1234",
                  "ServiceID": "123456789"
              },
              "PaymentRequest": {
                  "PaymentData": {
                      "PaymentType": "Refund"
                  },
                  "PaymentTransaction": {
                      "AmountsReq": {
                          "Currency": "CZK",
                          "RequestedAmount": 10.00
                      },
                      "OriginalPOITransaction": {
                          "POITransactionID": {
                              "TimeStamp": "2020-04-24T15:57:48+02:00",
                              "TransactionID": "bfb7fab0-e777-416f-9d87-ab4065da01cc"
                          }
                      },
                      "ProprietaryTags": {
                          "ECRPrint": true
                      }
                  }, "SaleData": {
                      "SaleTransactionID": {
                          "TransactionID": "12345",
                          "TimeStamp": "2020-04-24T15:59:00+0100"
                      }
                  }
              }
          }
      }
      
  • Response 200 (application/json)

    • Headers

    • Body

      {
          "ResultCode": 0,
          "SaleToPOIResponse": {
              "MessageHeader": {
                  "MessageCategory": "Payment",
                  "MessageClass": "Service",
                  "MessageType": "Response",
                  "POIID": "POITerm1",
                  "ProtocolVersion": "3.1",
                  "SaleID": "POS_ID_1234",
                  "ServiceID": "123456789"
              },
              "PaymentResponse": {
                  "PaymentData": {
                      "PaymentType": "Refund"
                  },
                  "PaymentReceipt": {
                      "documentQualifier": "saleReceipt",
                      "integratedPrintFlag": true,
                      "outputContent": {
                          "DotypayData": [
                              {
                                  "format": {
                                      "align": "start",
                                      "bold": false,
                                      "size": 24
                                  },
                                  "text": "Receipt data in Dotypay format",
                                  "type": "text"
                              }
                          ],
                          "OutputFormat": "Dotypay"
                      },
                      "requiredSignatureFlag": false
                  },
                  "PaymentResult": {
                      "AmountsResp": {
                          "AuthorizedAmount": 10.0,
                          "Currency": "CZK"
                      },
                      "PaymentInstrumentData": {
                          "CardData": {
                              "MaskedPan": "53xx-xxxx-xxxx-1234"
                          }
                      },
                      "ProprietaryTags": {
                          "Aid": "A0000000041010",
                          "ApplicationName": "DEBIT MASTERCARD",
                          "AuthorizationCode": "123456",
                          "Brand": "MASTER",
                          "CardExpiration": "20220731",
                          "CardPresentationMethod": "CLESS",
                          "ECRPrint": false,
                          "ReceiptDate": "2020-04-24T15:59:24+02:00",
                          "SequenceNumber": "1234567890",
                          "SignatureRequired": false,
                          "TerminalId": "POITerm1  ",
                          "VerifiedByDevice": false
                      }
                  },
                  "POIData": {
                      "POITransactionID": {
                          "TimeStamp": "2020-04-24T15:59:24+02:00",
                          "TransactionID": "f21ba5ef-ed98-4aff-a184-08866707cfc0"
                      }
                  },
                  "Response": {
                      "Result": "Success"
                  }
              }
          }
      }
      

Transaction Status Request [POST]

The POS can recover the final status of a payment when the POS didn't receive the payment response from the POI. A TransactionStatusRequest is an error recovery mechanism. If the response of the payment request does not arrive within the predefined time limit, you can retrieve the final status of the transaction. Because the response didn't arrive, the POS cannot use the POI TransactionID because it doesn't know it. So the POS will use the ServiceID, SaleID and MessageCategory from previously sent MessageHeader.

POI will return a unique transaction from combination of ServiceID, SaleID and MessageCategory from MessageReference sent in the Body of the request. If the POI won't find exactly one transaction, an error will be returned.

Result code of the previous transaction is located in TransactionStatusResponse.

  • Request (application/json)

    • Headers

      Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJlb...
      Content-Length: <calculated>
      
    • Body

      {
          "SaleToPOIRequest": {
              "MessageHeader": {
                  "MessageCategory": "TransactionStatus",
                  "MessageClass": "Service",
                  "MessageType": "Request",
                  "POIID": "POITerm1",
                  "ProtocolVersion": "3.1",
                  "SaleID": "POS_ID_1234",
                  "ServiceID": "1234567"
              },
              "TransactionStatusRequest": {
                  "MessageReference": {
                      "MessageCategory": "Payment",
                      "ServiceID": "123456",
                      "SaleID": "POS_ID_1234"
                  }
              }
          }
      }
      
  • Response 200 (application/json)

    • Headers

    • Body

      {
          "ResultCode": 0,
          "SaleToPOIResponse": {
              "MessageHeader": {
                  "MessageCategory": "TransactionStatus",
                  "MessageClass": "Service",
                  "MessageType": "Response",
                  "POIID": "POITerm1",
                  "ProtocolVersion": "3.1",
                  "SaleID": "POS_ID_1234",
                  "ServiceID": "1234567"
              },
              "TransactionStatusResponse": {
                  "ResultCode": 0,
                  "RepeatedMessageResponse": {
                      "MessageHeader": {
                          "MessageCategory": "Payment",
                          "MessageClass": "Service",
                          "MessageType": "Response",
                          "POIID": "POITerm1",
                          "ProtocolVersion": "3.1",
                          "SaleID": "POS_ID_1234",
                          "ServiceID": "123456"
                      },
                      "RepeatedResponseMessageBody": {
                          "PaymentResponse": {
                              "PaymentData": {
                                  "PaymentType": "Normal"
                              },
                              "PaymentReceipt": {
                                  "documentQualifier": "saleReceipt",
                                  "integratedPrintFlag": true,
                                  "outputContent": {
                                      "OutputFormat": "Dotypay",
                                      "DotypayData": [
                                          {
                                              "format": {
                                                  "align": "start",
                                                  "bold": false,
                                                  "size": 18
                                              },
                                              "text": "Basic text",
                                              "type": "text"
                                          },
                                          {
                                              "type": "division"
                                          },
                                          {
                                              "left": {
                                                  "format": {
                                                      "align": "start",
                                                      "bold": false,
                                                      "size": 18
                                                  },
                                                  "text": "Left column text",
                                                  "type": "text"
                                              },
                                              "right": {
                                                  "format": {
                                                      "align": "end",
                                                      "bold": false,
                                                      "size": 18
                                                  },
                                                  "text": "Right column text",
                                                  "type": "text"
                                              },
                                              "type": "twocolumns"
                                          }
                                      ]
                                  },
                                  "requiredSignatureFlag": false
                              },
                              "PaymentResult": {
                                  "AmountsResp": {
                                      "AuthorizedAmount": 10.0,
                                      "Currency": "CZK"
                                  },
                                  "PaymentInstrumentData": {
                                      "CardData": {
                                          "MaskedPan": "53xx-xxxx-xxxx-1234"
                                      }
                                  },
                                  "ProprietaryTags": {
                                      "Aid": "A0000000041010",
                                      "ApplicationName": "DEBIT MASTERCARD",
                                      "AuthorizationCode": "123456",
                                      "Brand": "MASTER",
                                      "CardExpiration": "20220731",
                                      "CardPresentationMethod": "CLESS",
                                      "ReceiptDate": "2020-04-24T14:20:10+02:00",
                                      "SequenceNumber": "1234567890",
                                      "SignatureRequired": false,
                                      "TerminalId": "POITerm1  ",
                                      "VerifiedByDevice": false
                                  }
                              },
                              "POIData": {
                                  "POITransactionID": {
                                      "TimeStamp": "2020-04-24T14:20:10+02:00",
                                      "TransactionID": "79fe58f3-511f-4964-9e63-91609ae02273"
                                  }
                              },
                              "Response": {
                                  "Result": "Success"
                              }
                          }
                      }
                  },
                  "Response": {
                      "Result": "Success"
                  }
              }
          }
      }
      

Reconciliation Request [POST]

The reconciliation request is used to close the sale interval on the POI (Z Report) or calculate the subtotals (X Report).

The Reconciliation request message body is ReconciliationRequest and contains the ReconciliationType field, which determines the report type:

  • SaleReconciliation: Reconciliation of the current reconciliation period, without any closing nor synchronisation with Acquirer reconciliations. (X report)

  • AcquirerSynchronisation: Reconciliation and closure of the current period, with synchronisation of reconciliations between the POI and the Acquirer. (Z report)

The response contains data of transaction debit and credit counters and the terminal currency.

  • Request (application/json)

    • Headers

      Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJlb...
      Content-Length: <calculated>
      
    • Body

      {
          "SaleToPOIRequest": {
              "MessageHeader": {
                  "MessageCategory": "Reconciliation",
                  "MessageClass": "Service",
                  "MessageType": "Request",
                  "POIID": "POITerm1",
                  "ProtocolVersion": "3.1",
                  "SaleID": "POS_ID_1234",
                  "ServiceID": "1234567"
              },
              "ReconciliationRequest": {
                  "ReconciliationType": "SaleReconciliation",
                  "ProprietaryTags": {
                      "ECRPrint": true
                  }
              }
          }
      }
      
  • Response 200 (application/json)

    • Headers

    • Body

      {
          "SaleToPOIResponse": {
              "MessageHeader": {
                  "MessageCategory": "Reconciliation",
                  "MessageClass": "Service",
                  "MessageType": "Response",
                  "POIID": "POITerm1",
                  "ProtocolVersion": "3.1",
                  "SaleID": "POS_ID_1234",
                  "ServiceID": "1234567"
              },
              "ReconciliationResponse": {
                  "POIReconciliationID": 1,
                  "ProprietaryTags": {
                      "ECRPrint": true,
                      "ReceiptData": [
                          {
                              "format": {
                                  "align": "start",
                                  "bold": false,
                                  "size": 24
                              },
                              "text": "Receipt data in Dotypay format",
                              "type": "text"
                          }
                      ]
                  },
                  "ReconciliationType": "SaleReconciliation",
                  "TransactionTotals": [
                      {
                          "PaymentCurrency": "CZK",
                          "PaymentTotals": [
                              {
                                  "TransactionAmount": 123.25,
                                  "TransactionCount": 2,
                                  "TransactionType": "Credit"
                              },
                              {
                                  "TransactionAmount": 2535.98,
                                  "TransactionCount": 10,
                                  "TransactionType": "Debit"
                              }
                          ]
                      }
                  ],
                  "Response": {
                      "Result": "Success"
                  }
              }
          },
          "ResultCode": 0
      }
      

Abort Request [POST]

The Abort message allows to halt and prematurely terminate the processing of the currently processed message. This request is most commonly used when a processing of a message is taking too much time. At the moment only the Payment Request message can be aborted.

The POI will make an attempt to abort the processing of a message identified by the combination of the following attributes: ServiceID, SaleID and MessageCategory from MessageReference sent in the Body of the request. If any of these attributes is missing then the request is not processed and an Event Notification message with the attribute EventToNotify set to Reject is sent as a response. Reason of the abortion should be located in the attribute AbortReason of the AbortRequest object.

Attributes SaleID and POIID in the MessageReference object must match the SaleID and POIID attributes present in the message header of the Abort Request message otherwise an Event Notification message with an attribute EventToNotify set to Reject is sent as a response.

If the referenced message cannot be aborted (e.g., it has already been sent to the issuer) a simple response with result code set to NOT_ABORTABLE is sent and the referenced message is not aborted.

If the referenced message can be aborted then a simple response with result code set to OK is sent and the POI aborts the ongoing transaction. A message with an attribute ErrorCondition set to Aborted, attribute Result set to Failure and attribute AdditionalResponse containing the reason of abortion is sent as a response to the sender of the aborted Payment Request.

However, if the referenced message to be aborted has already been processed, an Event Notification message is sent as a response with the attribute EventToNotify set to CompletedMessage.

  • Request (application/json)

    • Headers

      Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJlb...
      Content-Length: <calculated>
      
    • Body

       {
          "SaleToPOIRequest": {
              "MessageHeader": {
                  "MessageCategory": "Abort",
                  "MessageClass": "Service",
                  "MessageType": "Request",
                  "ProtocolVersion": "3.1",
                  "ServiceID": "POS_ID_1234",
                  "SaleID": "1234567",
                  "POIID": "POITerm1"
              },
              "AbortRequest": {
                  "MessageReference": {
                      "MessageCategory": "Payment",
                      "ServiceID": "POS_ID_1234",
                      "SaleID": "1234567",
                      "POIID": "POITerm1"
      
                  },
                  "AbortReason": "The processing of the message is taking too long."
              }
          }
      }
      
  • Response 200 (application/json)

    • Headers

    • Body

      {
          "ResultCode": 0,
      }
      

Protocol extensions [/poitermlist]

POI Terminal List [GET]

A request to discover the available POIIDs on current terminal. It returns a POI Terminal list, which contains a list of available terminals on the device. The caller then uses this POIID in the MessageHeader object to identify the terminal, which is communicating with.

The first record of POI Terminal list contains information about the proprietor of the physical device. POS systems could use this record as a fallback in pairing procedure (e.g. when POIID can't be found by BusinessID and Currency).

  • Request (application/json)

    • Headers
      Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJlb...
      
  • Response 200 (application/json)

    • Headers

    • Body

      {
          "ResultCode": 0,
          "POITerminalList": [
              {
                  "POIID": "POITERM2",
                  "BusinessId": "25599051",
                  "MerchantName": "Dotypay s.r.o.",
                  "Currency": "EUR"
              },
              {
                  "POIID": "POITERM1",
                  "BusinessId": "25292498",
                  "MerchantName": "Smart software s.r.o.",
                  "Currency": "CZK"
              }
          ]
      }