This guide takes you from zero to a first approved payment over the Local API (HTTP) in about ten minutes. It uses curl so you can verify the flow before writing any code.
Prerequisites
- A provisioned terminal on your local network (see Connect your terminal to POS) and its IP address.
- The terminal in integrated mode, reachable on port
8080.
Step 1 — Open a session
Every Local API integration starts with a Login. Send it once when your POS starts, not per transaction.
curl -X POST http://TERMINAL_IP:8080/login \
-H "Content-Type: application/json" \
-d '{
"MessageHeader": {"ProtocolVersion":"3.1","MessageClass":"Service","MessageCategory":"Login","MessageType":"Request","ServiceID":"1","SaleID":"POS_01","POIID":"POI_01"},
"LoginRequest": {"DateTime":"2026-07-06T10:00:00.0+02:00","OperatorID":"Cashier_01","OperatorLanguage":"EN","SaleSoftware":[{"ApplicationName":"MyPOS","ProviderIdentification":"POS_ID","SoftwareVersion":"1.0.0"}]}
}'A successful response contains LoginResponse.Response.Result = "Success". Store the POISerialNumber it returns — see Session and login lifecycle for why.
Step 2 — Send a payment
curl -X POST http://TERMINAL_IP:8080/payment \
-H "Content-Type: application/json" \
-d '{
"MessageHeader": {"ProtocolVersion":"3.1","MessageClass":"Service","MessageCategory":"Payment","MessageType":"Request","ServiceID":"2","SaleID":"POS_01","POIID":"POI_01"},
"PaymentRequest": {
"PaymentData": {"PaymentType":"Normal"},
"PaymentTransaction": {"AmountsReq":{"Currency":"EUR","RequestedAmount":"11.99"}},
"SaleData": {"OperatorID":"Cashier_01","SaleTransactionID":{"TimeStamp":"2026-07-06T10:01:00.0+02:00","TransactionID":"1001"}}
}
}'The terminal replies 202 Accepted immediately — the payment has started, not finished. The ServiceID changed (2): the terminal does not require or check this, but varying it per request makes logs far easier to correlate.
Step 3 — Poll for the result
curl http://TERMINAL_IP:8080/paymentWhile the cardholder is presenting their card you receive 206 — keep polling (once per second is fine). When the transaction completes you receive 200 with the PaymentResponse. Check:
Response.Result—SuccessorFailurePaymentResult.AmountsResp.AuthorizedAmount— may be lower than requested (partial authorisation)POIData.POITransactionID— store this; you need it for reversals and refunds
Warning
Never treat 206 as a failure and never re-send the payment while polling. Set your HTTP client timeout above 90 seconds — see Transport bindings for the full rules.
Step 4 — Close the session
curl -X POST http://TERMINAL_IP:8080/logout \
-H "Content-Type: application/json" \
-d '{"MessageHeader":{"ProtocolVersion":"3.1","MessageClass":"Service","MessageCategory":"Logout","MessageType":"Request","ServiceID":"3","SaleID":"POS_01","POIID":"POI_01"},"LogoutRequest":{}}'Where to go next
- How the message model works — the rules behind ServiceID, transaction IDs and error conditions.
- Transport bindings — HTTP & TCP/IP — the polling contract in full, plus the socket transport.
- Taking a payment — the complete payment guide: partial authorisation, signature, receipts.
- Testing & certification — validate against the Dummy Server before go-live.