Integration

Looking for a simpler integration path?

The Nexi OPI Proxy turns raw TCP and XML terminal integration into a local HTTP and JSON API, while keeping the terminal-side OPI handling inside the proxy.

Explore the OPI Proxy

OPI is the low-level integration model for direct communication between a POS or ECR and a Nexi terminal. In this model, your checkout system talks directly to the terminal over TCP/IP and exchanges XML messages for payments, refunds, status requests, receipt handling, and device interactions.

What OPI Means in Practice

At a high level, a direct OPI integration means:

  • your POS opens a TCP connection to the terminal
  • your POS sends XML requests in the OPI message format
  • the terminal answers with XML responses
  • the terminal may also call back into the POS for display, receipt, journal, or input handling

That last part matters. OPI is not only "send amount, get result". It is a conversation between the POS and the terminal. The POS must therefore be able to handle both sides of the exchange: requests initiated by the POS and device interactions initiated by the terminal.

At a Glance

  • Transport: TCP/IP
  • Payload format: XML
  • Encoding: UTF-8
  • Framing: 4-byte message length prefix in network byte order
  • Main message families:
    • CardServiceRequest / CardServiceResponse
    • ServiceRequest / ServiceResponse
    • DeviceRequest / DeviceResponse
  • Typical responsibilities:
    • payment and refund requests
    • terminal status and info requests
    • receipt and journal handling
    • device request handling
    • unknown-result recovery

TCP Connection and Message Framing

OPI uses a normal TCP/IP connection, but the XML payload is not sent as a raw unframed stream. Each message uses a 4-byte length prefix in network byte order, followed by the UTF-8 XML payload.

[4-byte big-endian length][utf-8 xml payload]

That means your POS needs to:

  • keep the socket open for the full exchange
  • read the length prefix first
  • then read the exact XML payload length
  • avoid assuming that one socket read always equals one full XML message
  • handle partial reads, delayed packets, and connection timeouts correctly

This is one of the reasons OPI integrations can feel more low-level than a modern API.

The Two-Channel Model

Direct OPI uses two logical communication directions:

  • Channel 0: POS to terminal for payment and service requests
  • Channel 1: terminal to POS for device interactions

A typical flow looks like this:

  1. The POS sends a CardServiceRequest or ServiceRequest.
  2. The terminal starts processing the request.
  3. During the flow, the terminal may send one or more DeviceRequest messages back to the POS.
  4. The POS must answer each DeviceRequest with a matching DeviceResponse.
  5. The flow finishes with a CardServiceResponse or ServiceResponse.

This is the part many new integrations underestimate. If the POS does not handle DeviceRequest correctly, the overall integration is not complete even if the original payment request itself is valid.

Channel 1 is commonly used for terminal-driven interactions such as:

  • cashier display output
  • receipt output
  • journal output
  • e-journal output
  • input requests
  • status or device prompts

What Your POS Owns

In a direct OPI integration, your system is responsible for the local integration layer. This includes:

  • opening and managing the TCP connection
  • writing and reading framed XML messages
  • building valid OPI request XML
  • parsing OPI response XML
  • correlating request and response identifiers
  • handling DeviceRequest messages
  • replying with matching DeviceResponse messages
  • printing, storing, or acknowledging receipts and journals where required
  • dealing with unknown-result recovery after communication problems
  • enforcing your own business rules such as refund permissions or transaction lookup

The POS is also responsible for keeping its own transaction state consistent. For example, if a connection is interrupted during a payment, the POS must not simply assume that the payment failed. The result may be unknown and must be recovered.

What Nexi and Terminal Parameters Own

Not everything is decided by the POS implementation alone. Some behaviour is configured on the terminal, host, merchant setup, or acquirer side.

Examples include:

  • which payment methods are enabled
  • whether DCC is enabled
  • whether tipping is enabled
  • receipt layout and receipt copies
  • login or logoff behaviour
  • submission behaviour
  • terminal software and parameter updates
  • whether specific request types are available on a given terminal model
  • whether a terminal is configured for attended or unattended use
  • whether offline payment capabilities are enabled

This is why an OPI integration should stay flexible. The XML message model is standardised, but not every terminal or merchant setup behaves the same way. Your POS should therefore avoid hard-coding assumptions that only apply to one terminal, one merchant, or one parameter setup.

Standard EMV offline processing is configured on the acquiring side and is not something the POS enables with an OPI field. Forced Acceptance is different: if the approved merchant setup supports it, the POS may intentionally request it with the Force Acceptance indicator. See Offline Payments for more.

Network Model

For a local OPI setup, the POS and the terminal are typically on the same local network.

The POS usually needs to know:

  • the terminal IP address
  • the terminal port for payment and service traffic
  • the POS listener address and port for DeviceRequest

Recommended network approach:

  • keep the POS and terminal on a stable local network
  • prefer DHCP reservation or a static IP for the terminal
  • make sure local firewalls allow the configured OPI ports
  • make sure the terminal can reach the POS listener for device callbacks
  • avoid network setups where the terminal IP address changes unpredictably

The POS-to-terminal connection and the terminal-to-POS callback path are both important. A payment can start correctly and still fail later if the terminal cannot send required device requests back to the POS.

Required Local Ports

In a typical TCP/IP OPI setup, two local communication paths must work:

Direction Typical port Purpose
POS or proxy to terminal 4100 OPI payment and service requests, also called channel 0
Terminal to POS or proxy 4102 OPI DeviceRequest callbacks, also called channel 1

The exact ports can be changed by terminal parameters or local integration configuration, but both directions must be allowed by the network and host firewall. It is common to verify the POS-to-terminal path first and miss the callback path. That can lead to confusing behaviour: the terminal receives the payment request, but receipt, display, journal, input, or unattended delivery callbacks cannot be acknowledged.

For Docker-based deployments, publish the device callback port on the Docker host. The terminal must be able to reach the host IP and callback port directly on the local network.

Onboarding and Provisioning

Once a merchant is onboarded, terminal setup usually includes:

  • a TID
  • an activation code
  • parameter configuration
  • remote parameter download if required

An internet connection is typically needed for:

  • first activation
  • parameter download
  • updates
  • normal host communication during transaction processing

The POS-to-terminal OPI communication itself is then local, using the terminal IP address and configured OPI ports.

The Main OPI Message Families

CardService

CardServiceRequest and CardServiceResponse cover card-related transaction flows such as:

  • payment
  • reservation / preauthorisation
  • refund
  • reversal
  • reprint

Service

ServiceRequest and ServiceResponse cover terminal-side service actions such as:

  • status
  • info
  • close day
  • transmit
  • configuration refresh / initialisation where relevant
  • login / logout
  • restart

Device

DeviceRequest and DeviceResponse handle terminal-driven interaction with the POS.

Examples include:

  • cashier display output
  • receipt printer output
  • journal output
  • e-journal output
  • cashier keyboard input
  • customer display output

Every DeviceRequest must be answered with a matching DeviceResponse.

What the POS Should Implement First

A robust OPI implementation does not need every optional field on day one. A strong first milestone is:

  • CardPayment
  • PaymentRefund
  • TicketReprint
  • GetInfo
  • GetStatus
  • CloseDay
  • TransmitTrx if the merchant setup uses it
  • full DeviceRequest / DeviceResponse handling
  • receipt and journal handling
  • unknown-result recovery

That gives you a practical production baseline before you add more specialised flows.

If you do not want to build that full direct OPI baseline yourself, the Nexi OPI Proxy packages the same terminal-side model behind a smaller local HTTP API and a Docker-first runtime.

The Most Important Implementation Rules

Always keep identifiers clean

Use unique RequestID values and keep WorkstationID, RequestID, and RequestType consistent across the full flow.

The POS must be able to correlate requests, responses, and device interactions reliably.

Always answer DeviceRequest

Every DeviceRequest needs a matching DeviceResponse.

Do not treat device requests as optional. They are part of the terminal flow and may be required before the terminal can complete the transaction.

Treat receipt handling as part of the payment flow

Receipt and journal handling are not optional in practice.

If the terminal cannot complete receipt handling, the next transaction may be blocked until the last receipt is reprinted, acknowledged, or otherwise handled correctly.

Do not assume communication failure means payment failure

If the connection breaks, the transaction result may still be unknown.

The POS must support recovery logic and should be able to check, reconcile, or otherwise resolve transactions that were interrupted during processing.

Handle Forced Acceptance explicitly

If Forced Acceptance is supported for the merchant, the POS or ECR can intentionally trigger that Own Risk flow by sending the Force Acceptance indicator in POSdata:

<ForceAcceptance>true</ForceAcceptance>

Use this only for approved merchant setups. The merchant should be able to see when Own Risk acceptance is being used, and the POS should expose pending submission or transmission states after connectivity returns. The detailed behaviour is documented in Offline Payments.

Do not send this as a standing default. The POS or ECR should use normal online authorisation first and only send Force Acceptance after OPI indicates that the authorisation host or payment server cannot be reached.

Forced Acceptance is a payment-only flow. Do not use it for refunds.

Relevant OPI response codes include:

Code Meaning
1 System error
569, 579 No connection to payment server

When one of these codes is returned, the integration may treat authorisation connectivity as unavailable for the purpose of Force Acceptance.

Once normal online authorisation is available again, the POS or ECR is responsible for stopping Force Acceptance and returning to normal online processing. Integrations may either process a controlled number of Force Acceptance transactions and then disable it manually, or preferably stop sending ForceAcceptance automatically once the terminal indicates that normal authorisation is available again, for example with terminalDeclineReason value 0.

Only send fields that are valid for the selected message model

Do not add fields simply because they appear in receipt output or examples from another integration.

Keep requests aligned with the actual OPI schema and the terminal profile in use.

Keep terminal-specific behaviour configurable

Avoid building an integration that only works with one terminal model or one merchant setup.

Payment methods, receipts, tipping, DCC, service functions, and available request types may differ depending on terminal parameters and merchant configuration.

Minimal Example

<?xml version="1.0" encoding="utf-8"?>
<CardServiceRequest WorkstationID="POS-1"
                    RequestID="1001"
                    RequestType="CardPayment"
                    ReferenceNumber="ORDER-1001"
                    xmlns="http://www.nrf-arts.org/IXRetail/namespace">
  <POSdata LanguageCode="en">
    <POSTimeStamp>2026-04-08T10:15:00+02:00</POSTimeStamp>
    <ShiftNumber>1</ShiftNumber>
    <ClerkID>12</ClerkID>
  </POSdata>
  <TotalAmount Currency="CHF">25.00</TotalAmount>
</CardServiceRequest>

Unattended Terminals

Unattended behaviour is an additional layer on top of the normal OPI model. Most direct OPI integrations do not need DeliveryBox at all, and many unattended estates are designed either around a dedicated OPI controller or MDB rather than the standard attended POS path.

If your terminal profile does require unattended handling, your controller must be able to:

  • handle DeliveryBox callbacks from the terminal
  • trigger delivery only after the correct payment step
  • return the real delivery result to the terminal
  • keep payment and delivery state linked
  • handle timeouts and recovery evidence cleanly

The detailed unattended flow, XML examples, and testing guidance live on Unattended Terminals.

OPI Proxy as an Alternative

If you want to avoid raw TCP, XML framing, DeviceRequest handling, terminal-specific recovery logic, and optional unattended DeliveryBox handling in your POS, consider using the Nexi OPI Proxy instead.

The proxy turns the OPI integration into a simpler local HTTP API and keeps the OPI complexity inside the proxy service.