NEXO Retailer Protocol
Nexo nexo nexo nexo
## Nexo HTTPS Integration Guide for ECR Developers Table of Contents
- Nexo HTTPS Integration Guide for ECR Developers Table of Contents
- 1. Overview
- 2. Connection Setup
- 2.1 Terminal Configuration
- 2.2 ECR Requirements
- 3. Message Structure
- 3.1 Request Payload
- 3.2 Response Payload
- 4. X-Callback-Url Header
- 5. Request/Response Examples
- 5.1 Login Request
- 5.2 Logout Request
- 5.3 Payment Request
- 5.4 Reversal Request
- 5.5 Admin Request
- 6. Callback Messages
- 6.1 Display Request
- 6.2 Input Request
- 6.3 Event Notification
- 7. Response Result Codes........................................................................................
- 7.1 Success
- 7.2 Failure
- 7.3 Common Error Conditions
- 8. HTTP Status Codes
- 9. TLS and Certificates
- 10. Timeouts
### 1. Overview
This guide covers integrating an ECR with a Nexo payment terminal over HTTPS. The terminal
acts as an HTTPS server; the ECR sends POST requests and receives JSON responses.
Key Points:
- Endpoint: POST https://terminal-ip:8443/nexo
- Message format: JSON
- Encryption: TLS 1.
- Timeout: 130 seconds for payment requests
- Callbacks: Optional for real-time updates
### 2. Connection Setup
#### 2.1 Terminal Configuration
- IP Address: Terminal's network IP address
- Port: 8443 (default, may be configurable)
- Protocol: HTTPS (TLS 1.2)
- Certificate: The terminal uses a server certificate (PFX format, default: TestKey.pfx) for
TLS. It presents this certificate to the ECR during the TLS handshake. ECR clients
should validate the certificate.
#### 2.2 ECR Requirements
- HTTPS client supporting TLS 1.
- JSON serialization/deserialization
- Callback Server (Optional): An HTTPS server on the ECR to receive real-time updates
from the terminal.
### 3. Message Structure
```
All messages (requests and responses) during communication follow this structure.
```
#### 3.1 Request Payload
#### 3.2 Response Payload
{
"SaleToPOIRequest": {
[Request Type]: { ... },
"MessageHeader": {
"ProtocolVersion": "3.1",
"MessageClass": "Service",
"MessageCategory": "Payment",
"MessageType": "Request",
"ServiceID": "service-id",
"POIID": "terminal-id"
}
}
}
{
" SaleToPOIResponse": {
[Response Type]: { ... },
"MessageHeader": {
"ProtocolVersion": "3.1",
"MessageClass": "Service",
"MessageCategory": "Payment",
"MessageType": "Response",
"ServiceID": "service-id",
}
}
}
**MessageHeader Fields**
- ProtocolVersion: **_3._**
- MessageClass: **_Service_**
- MessageCategory: **_Login_** , **_Payment_** , **_Reversal_** , **_Admin_** , **_Logout_**
- MessageType: **_Request_** or **_Response_**
- ServiceID: Unique identifier for the service session
- POIID: Terminal identifier
**RequestType** : One of **_LoginRequest_** , **_PaymentRequest_** , **_ReversalRequest_** , **_AdminRequest_** ,
**_LogoutRequest_**
**ResponseType** : One of **_LoginResponse_** , **_PaymentResponse_** , **_ReversalResponse_** ,
**_AdminResponse_** , **_LogoutResponse_**
### 4. X-Callback-Url Header
Include the **_X-Callback-Url_** header to receive asynchronous updates during long operations:
If the ECR provides an **_X-Callback-Url_** header, the terminal sends **Display** notifications to that
URL during payment processing. The server should accept **POST** requests with **JSON**
payloads and respond with **HTTP 200 OK**. If no callback URL is provided, the terminal will not
send intermediate updates.
```
POST /nexo HTTP/1.
Host: 192.168.1.100:
Content-Type: application/json
X-Callback-Url: https://ecr-ip:port/callback
```
### 5. Request/Response Examples
#### 5.1 Login Request
**Purpose:** Establish a session with the terminal.
**Request:**
```
{
"SaleToPOIRequest": {
"LoginRequest": {
"OperatorLanguage": "en",
"OperatorID": "Nisse",
"DateTime": "2026- 01 - 08T14:19:03.5303520+05:30",
"ConfigData": {
"TxnHostAddress": "...",
"ConfigHostAddress": "..."
},
"SaleSoftware": {
"ProviderIdentification": "Westpay AB",
"ApplicationName": "Westpay NEXO ECR",
"SoftwareVersion": "1.0.0.0"
}
},
"MessageHeader": {
"ProtocolVersion": "3.1",
"MessageClass": "Service",
"MessageCategory": "Login",
"MessageType": "Request",
"ServiceID": "225",
"POIID": "..."
}
}
}
```
**Response:**
```
{
"SaleToPOIResponse": {
"LoginResponse": {
"Response": {
"Result": "Success"
},
"POISystemData": {
"DateTime": "2026- 01 - 08T09:49:11.2303772+01:00",
"POISoftware": [{
"ProviderIdentification": "Westpay AB",
"ApplicationName": "Westpay Payment Application",
"SoftwareVersion": "1.0.0",
"ComponentType": "APPL"
}]
}
},
"MessageHeader": {
"ProtocolVersion": "3.1",
"MessageClass": "Service",
"MessageCategory": "Login",
"MessageType": "Response",
"ServiceID": "225"
}
}
}
```
#### 5.2 Logout Request
**Purpose:** Terminate the session.
**Request:**
```
{
"SaleToPOIRequest": {
"LogoutRequest": {
"MaintenanceAllowed": "False"
},
"MessageHeader": {
"ProtocolVersion": "3.1",
"MessageClass": "Service",
"MessageCategory": "Logout",
"MessageType": "Request",
"ServiceID": "226",
"POIID": "..."
}
}
}
```
**Response:**
```
{
"SaleToPOIResponse": {
"LogoutResponse": {
"Response": {
"Result": "Success"
}
},
"MessageHeader": {
"ProtocolVersion": "3.1",
"MessageClass": "Service",
"MessageCategory": "Logout",
"MessageType": "Response",
"ServiceID": "226"
}
}
}
```
#### 5.3 Payment Request
_5.3.1 Purchase_
**Purpose:** To process a financial transaction, including Purchase (Normal), Refund, or Cashback.
**Request:**
```
{
"SaleToPOIRequest": {
"PaymentRequest": {
"SaleData": {
"OperatorID": "",
"SaleTransactionID": {
"TransactionID": "149",
"TimeStamp": "2026- 01 - 08T12:26:56.4596945+05:30"
}
},
"PaymentData": {
"PaymentType": "Normal"
},
"PaymentTransaction": {
"AmountsReq": {
"Currency": "SEK",
"RequestedAmount": "200.00",
"CashBackAmount": "0.00",
"TipAmount": "0.00"
},
"TransactionConditions": {
"DisableTip": "true"
}
}
},
"MessageHeader": {
...
"MessageCategory": "Payment",
...
}
}
}
```
- **_PaymentType:_** Supports **_Normal_** and **_Refund_** transactions. **_Normal_** represents a Purchase
and supports tipping and cashback, if provided.
**12 |** Pa g e
**Response:**
```
{
"SaleToPOIResponse": {
"PaymentResponse": {
"Response": {
"Result": "Success"
},
"SaleData": {...},
"POIData": {...},
"PaymentResult": {
"PaymentType": "Normal",
"CardData": {...},
"AmountsResp": {
"AuthorizedAmount": "200.00",
"CashBackAmount": "0.00",
"TipAmount": "0.00"
}
},
"PaymentReceipt": [
{
"DocumentQualifier": "CashierReceipt",
"IntegratedPrintFlag": "False",
"RequiredSignatureFlag": "False",
"OutputContent": {
"OutputFormat": "Text",
"OutputText": [{"Text": "..."}]
}
},
{
"DocumentQualifier": "CustomerReceipt",
...
}
]
},
"MessageHeader": {
"MessageCategory": "Payment",
"MessageType": "Response",
...
}
}
}
```
**Sample Failure Response:**
```
{
"SaleToPOIResponse": {
"PaymentResponse": {
"Response": {
"Result": "Failure",
"ErrorCondition": "Refusal",
"AdditionalResponse": "Cashback not permitted for card"
},
"SaleData": {...},
"POIData": {...},
"PaymentResult": {
"PaymentType": "Normal"
},
"PaymentReceipt": [
{
"DocumentQualifier": "CustomerReceipt",
"IntegratedPrintFlag": "False",
"RequiredSignatureFlag": "False",
"OutputContent": {
"OutputFormat": "Text",
"OutputText": [{"Text": "..."}]
}
}
]
},
"MessageHeader": {
"MessageCategory": "Payment",
"MessageType": "Response",
...
}
}
}
```
#### 5.4 Reversal Request
**Purpose:** Reverse/Cancel a previous transaction.
**Request:**
Reversal Reasons:
- **_CustCancel_** - Customer cancellation
- **_MerchantCancel_** - Cashier cancellation
- **_Malfunction_** - Suspected malfunction
- **_Unable2Compl_** - Device unable to complete transaction
```
{
"SaleToPOIRequest": {
"ReversalRequest": {
"ReversalReason": "CustCancel",
"OriginalPOITransaction": {
"POITransactionID": {
"TransactionID": "800052501091",
"TimeStamp": "2026- 01 - 08T14:23:24.1522980+05:30"
}
}
},
"MessageHeader": {
"ProtocolVersion": "3.1",
"MessageClass": "Service",
"MessageCategory": "Reversal",
"MessageType": "Request",
"ServiceID": "232",
"POIID": "..."
}
}
}
```
**Response:**
```
{
"SaleToPOIResponse": {
"ReversalResponse": {
"Response": {
"Result": "Success"
},
"PaymentReceipt": [
{
"DocumentQualifier": "CashierReceipt",
"IntegratedPrintFlag": "False",
"RequiredSignatureFlag": "False",
"OutputContent": {
"OutputFormat": "Text",
"OutputText": [{"Text": "..."}]
}
},
{
"DocumentQualifier": "CustomerReceipt",
...
}
]
},
"MessageHeader": {
"MessageCategory": "Reversal",
"MessageType": "Response",
...
}
}
}
```
#### 5.5 Admin Request
**Purpose:** Administrative functions
**Request:**
```
{
"SaleToPOIRequest": {
"AdminRequest": {
"ServiceIdentification": "HostLogin",
"MerchantId": ""
},
"MessageHeader": {
"ProtocolVersion": "3.1",
"MessageClass": "Service",
"MessageCategory": "Admin",
"MessageType": "Request",
"ServiceID": "234",
"POIID": "..."
}
}
}
```
**Response:**
The following admin service identifications are supported:
- **_HostLogin_** – Login as an admin
- **_ResetMerchantPassword_** - Reset merchant password
- **_PrintLastEMVTransaction_** - Print last EMV transaction
- **_PrintTerminalConfig_** - Print terminal configuration
- **_ExtractLogFiles_** - Extract log files
- **_SetLogLevel_** - Set log level (requires LogLevel field: 0-4)
All follow the same request/response structure as shown above, with the appropriate
**_ServiceIdentification_** value in the **_AdminRequest_**.
```
{
"SaleToPOIResponse": {
"AdminResponse": {
"Response": {
"Result": "Success"
}
},
"MessageHeader": {
"ProtocolVersion": "3.1",
"MessageClass": "Service",
"MessageCategory": "Admin",
"MessageType": "Response",
"ServiceID": "234"
}
}
}
```
### 6. Callback Messages
When **_X-Callback-Url_** is provided, the terminal may send these messages to the ECR:
#### 6.1 Display Request
**Purpose:** Update ECR display with status messages.
```
{
"SaleToPOIRequest": {
"DisplayRequest": {
"DisplayOutput": [
{
"Device": "CashierDisplay",
"InfoQualify": "POIReplication",
"OutputContent": {
"OutputFormat": "Text",
"OutputText": [
{
"Text": "Please wait"
}
]
}
}
]
},
"MessageHeader": {
"ProtocolVersion": "3.1",
"MessageClass": "Device",
"MessageCategory": "Display",
"MessageType": "Request",
"ServiceID": "249",
"DeviceID": "..."
}
}
}
```
#### 6.2 Input Request
**Purpose:** Request input from Cashier/Customer.
```
{
"SaleToPOIRequest": {
"InputRequest": {
"PromptId": "105",
"DisplayOutput": {
"Device": "CashierDisplay",
"InfoQualify": "POIReplication",
"OutputContent": {
"OutputFormat": "Text",
"OutputText": [
{
"Text": "Adjust amount?"
}
]
},
"MenuEntry": [...]
},
"InputData": {...}
},
"MessageHeader": {
"ProtocolVersion": "3.1",
"MessageClass": "Device",
"MessageCategory": "Input",
"MessageType": "Request",
"ServiceID": "249",
"DeviceID": "..."
}
}
}
```
#### 6.3 Event Notification
**Purpose:** Notify ECR of terminal events.
**Event Types:**
- **_BeginMaintenance_** : Indicates the start of POI maintenance mode.
- **_EndMaintenance_** : Indicates the end of POI maintenance mode and return to normal
operation.
- **_Shutdown_** : The POI terminal or POI system is shutting down.
- **_Initialised_** : The POI terminal or POI system has completed initialization and is ready for
operation.
- **_OutOfOrder_** : The POI terminal or POI system is unable to operate.
- **_Completed_** : An Abort request was received for a message that had already completed
processing.
- **_Abort_** : One or more device requests were issued by the POI during service processing and
were cancelled by the customer or stopped by the POI. If device responses are not
received, an event is sent to instruct the Sale system to abort the related device requests
internally.
```
{
"SaleToPOIRequest": {
"EventNotification": {
"TimeStamp": "2026- 01 - 09T07:55:15.0936334+01:00",
"EventToNotify": "CardInserted",
"EventDetails": "Card tapped"
},
"MessageHeader": {
"MessageClass": "Event",
"MessageCategory": "Event",
"MessageType": "Notification"
}
}
}
```
- **_SaleWakeUp_** : The POI requests the Sale system to initiate payment processing for the
```
transaction identified in the EventDetails.
```
- **_SaleAdmin_** : The POI has performed or intends to perform an automatic administrative
```
process (e.g., end-of-day reports).
```
- **_CustomerLanguage_** : The customer has selected a different language on the POI terminal.
- **_KeyPressed_** : The customer has pressed a specific key on the POI terminal.
- **_SecurityAlarm_** : A security-related issue or alert has been detected by the POI.
- **_StopAssistance_** : Customer assistance has stopped because the customer has completed
```
their input.
```
- **_CardInserted_** : A card has been inserted into the card reader.
- **_CardRemoved_** : A card has been removed from the card reader.
- **_Reject_** : A message request has been rejected. Details of the error and the rejected message
```
are provided in the EventDetails field.
```
### 7. Response Result Codes........................................................................................
All responses include a _Response_ object.
#### 7.1 Success
#### 7.2 Failure
#### 7.3 Common Error Conditions
- **_Aborted_** : The request initiator sent an aborted message, which was accepted and
processed successfully.
- **_Busy_** : The system is currently busy and cannot process the request. Retry later.
- **_Cancel_** : The user manually aborted the transaction on the PED (e.g., during PIN entry).
- **_DeviceOut_** : The device is out of order and cannot process requests.
- **_InsertedCard_** : A card was inserted while an input request was pending (with
_NotifyCardInputFlag_ enabled). The POI aborted the input processing and returned this
error.
- **_InProgress_** : A transaction is already in progress, so the requested command cannot be
processed.
- **_LoggedOut_** : The system is not logged in.
- **_MessageFormat_** : The request message has an invalid format. AdditionalResponse
contains the data identifier and a clear-text reason.
- **_NotAllowed_** : The requested service or service combination is not permitted in the current
context (e.g., incompatible service request or protected card entered during initialization).
```
{
"Result": "Success"
}
```
```
{
"Result": "Failure",
"ErrorCondition": "Refusal",
"AdditionalResponse": "Transaction declined by issuer"
}
```
- **_NotFound_** : The referenced transaction was not found (e.g., reversal or repeat request).
- **_PaymentRestriction_** : One or more sale items cannot be paid using the customer’s card.
- **_Refusal_** : The transaction was refused by the host or card rules and cannot be repeated.
- **_UnavailableDevice_** : The required hardware is unavailable (missing, not configured, or
offline).
- **_UnavailableService_** : The requested service is unavailable (not implemented, not
configured, or unsupported protocol version).
- **_InvalidCard_** : The card entered is not supported or configured in the system.
- **_UnreachableHost_** : The acquirer or host is unreachable or did not respond. The request
may be retried depending on the sale context.
- **_WrongPIN_** : The PIN entered by the user failed verification.
- **_PrinterPaperOut_** : The printer is out of paper.
- **_PrinterFailure_** : The printer has encountered technical failure.
### 8. HTTP Status Codes
- **200 OK** - Request processed successfully
- **400 Bad Request** - Invalid JSON or message format
- **408 Request Timeout** - Response timeout
- **500 Internal Server Error** - Processing error
- **503 Service Unavailable** - Terminal busy processing another request
### 9. TLS and Certificates
- **TLS Version**
o TLS 1.2 is required for all HTTPS communications.
- **Certificate Handling**
o The terminal presents a server certificate during the TLS handshake.
o Testing / Development:
▪ The ECR may accept self-signed certificates.
o Production:
▪ Proper certificate validation must be enforced using trusted Certificate
Authorities (CA).
- **Certificate Validation**
o In testing and development environments, configure the HTTPS client to trust
self-signed certificates.
o In production environments, implement full certificate validation to ensure secure
communication.
## 10. Timeouts
- **Request Timeout**
o 120+ seconds recommended for payment-related requests.
o Allows sufficient time for card processing and authorization.
- **Callback Timeout**
o 30 seconds for terminal-initiated callbacks to the ECR.
o Designed for quick delivery of status updates and notifications.
- **Connection Handling**
o Each request must use a new HTTPS connection.
o Connections are closed after the response.
o Persistent (keep-alive) connections are not required.