The Terminal API allows you to make payments, perform refunds, collect shopper information, and other shopper-terminal interactions.
Our Terminal API is based on the nexo Retailer Protocol.
Before you make any point of sale payments, it is important to understand how our Terminal API works and how requests and responses are structured.
Here we describe:
- The endpoints.
- How to get an API key.
- How to enable Terminal API.
- The API structure.
- Making requests.
- Receiving responses.
- How to receive webhooks.
- How to handle errors.
Endpoints
The endpoints you need to use, and how you authenticate requests depends on how your integration connects to the Adyen payments platform:
Local communications
If your integration uses local communications, all your API requests are made from a cash register directly to a terminal's IP address. Alternatively, if you assign a hostname to your terminal, you can make requests to the resolvable hostname of the terminal.
The terminal listens for POST requests to /nexo
on port 8443. For example, if your terminal has the IP address 198.51.100.1 you would make API requests to: https://198.51.100.1:8443/nexo
Fix each terminal's MAC address to a static IP address. This helps to prevent connection issues when the terminal or your network reboots.
To protect local communications, you need to add Adyen's certificate to your cash register, and encrypt your messages.
Cloud communications
If your integration uses cloud communications, your cash register makes API requests to the Adyen payments platform. Our platform then forwards the request to the terminal.
The endpoint you need to use depends on two things:
- Whether your integration will receive transaction results synchronously or asynchronously.
- Whether you are making test transactions or live transactions.
Test endpoints - for all test transactions | |
---|---|
Synchronous result: | https://terminal-api-test.adyen.com/sync |
Asynchronous result: | https://terminal-api-test.adyen.com/async |
When you're ready to go live, you need to switch to a live transaction endpoint that's geographically closest to the location of your store.
Live endpoints - Europe | |
---|---|
Synchronous result: | https://terminal-api-live.adyen.com/sync |
Asynchronous result: | https://terminal-api-live.adyen.com/async |
Live endpoints - Australia | |
---|---|
Synchronous result: | https://terminal-api-live-au.adyen.com/sync |
Asynchronous result: | https://terminal-api-live-au.adyen.com/async |
Live endpoints - US | |
---|---|
Synchronous result: | https://terminal-api-live-us.adyen.com/sync |
Asynchronous result: | https://terminal-api-live-us.adyen.com/async |
Get your API key
To authenticate your requests you need to include an Adyen API key in the header of each Terminal API request. To get an API key for your test environment:
- Log in to your Customer Area.
- Go to Account > API credentials, and select the credential for your integration, for example ws@Company.[YourCompanyAccount].
- Under Authentication, select Generate New API Key.
- Copy and securely store the API key in your system — you won't be able to restore it later.
If your API key is lost or compromised, you need to generate a new one. - Select Save at the bottom of the page.
When you switch to your live environment, follow the same steps in your live Customer Area.
Add the value of the API key to the request header using the key: x-API-key
Enable Terminal API
Before you can use Terminal API in your test environment, you need to enable it:
- Log in to your test Customer Area.
- Go to Point of sale > Terminal settings and select Integrations.
- Select the option to Enable Terminal API.
- Select Save.
When you switch to your live environment, follow the same steps in your live Customer Area.
API structure
Our Terminal API communicates with the terminal using JSON messages. All requests and responses have the following message header-body structure:
- Message header: Identifies the type of transaction, the terminal being used, and unique transaction identifiers.
- Body: A request or response object, depending on the type of transaction. For example, when you make a payment request this is a
PaymentRequest
object, and when you receive a payment response this is aPaymentResponse
object.
The message header and body of Terminal API requests and responses are described in more detail below.
Requests
Each Terminal API request you make is contained in a SaletoPOIRequest
object. In this, you need to provide a:
MessageHeader
object.- Request body object corresponding to the type of transaction. For example, this is a
PaymentRequest
object when you are making a payment, or anInputRequest
object when you are requesting shopper input.
Request MessageHeader
In each request MessageHeader
, specify the following:
Name | Required | Type | Description |
---|---|---|---|
ProtocolVersion |
![]() |
String | Version of Adyen's Terminal API. The current version is 3.0 |
MessageClass |
![]() |
Enum | This is almost always Service, but it can also be Device or Event. We will specify which MessageClass is required throughout our documentation. |
MessageCategory |
![]() |
Enum | The type of transaction. For example, Payment for a payment request. We will specify which MessageCategory is required throughout our documentation. |
MessageType |
![]() |
Enum | This is always Request. |
SaleID |
![]() |
String | Your unique ID for your cash register. |
ServiceID |
![]() |
String | Your unique ID for the transaction attempt, consisting of 1-10 alphanumeric characters. This value needs to be unique within the last 48 hours. |
POIID |
![]() |
String | The unique ID of the terminal, in the format [device model]-[serial number]. For example, P400-123456789. You can find the device model and serial number of a terminal in your Customer Area, under Point of sale > Terminals. The serial number (or s/n) is also printed on the underside of each terminal. |
The example below shows the header you would provide if you wanted to make a payment.
{
"SaleToPOIRequest":{
"MessageHeader":{
"ProtocolVersion":"3.0",
"MessageClass":"Service",
"MessageCategory":"Payment",
"MessageType":"Request",
"SaleID":"POSSystemID12345",
"ServiceID":"0207111104",
"POIID":"V400m-324688179"
},
"PaymentRequest":{...}
}
}
Request body
The values you need to include in the request body depends on the type of transaction you are making. We provide examples and reference information for each transaction type throughout our point of sale documentation.
Responses
Each terminal API response you receive is contained in a SaletoPOIResponse
object, and includes a:
MessageHeader
object: Echoes the MessageHeader values you provided in the API request.- Response body object: Corresponds to the type of transaction request you made.
For example, when you make aPaymentRequest
you receive aPaymentResponse
object.
If you're using a cloud integration that receives results asynchronously, you will only receive an ok
response from the Terminal API. The MessageHeader
and response body are sent in a display notification instead.
Response MessageHeader
The MessageHeader
you receive in the response will echo the values you provided in the request. The only exception is the MessageType
, which will be Response.
The following example shows the header you would receive in response to the example payment request provided above.
{
"SaleToPOIResponse":{
"MessageHeader":{
"ProtocolVersion":"3.0",
"MessageClass":"Service",
"MessageCategory":"Payment",
"MessageType":"Response",
"SaleID":"POSSystemID12345",
"ServiceID":"0207111104",
"POIID":"V400m-324688179"
},
"PaymentResponse":{...}
}
}
Response body
The values you receive in the response body depends on the type of transaction request you made. We provide examples and reference information for each transaction type throughout our point of sale documentation.
The response body will often include a unique transaction identifier, and data you can use to generate your receipts.
Transaction identifier
Every API request that creates a transaction or interacts with your money flow (such as a payment or refund) returns a unique transaction identifier in the POITransactionID.TransactionID
:
This identifier contains two values, separated by a dot:
- Tender reference: Unique value generated by the terminal for the transaction.
- PSP reference: Unique value generated by the Adyen payments platform for the transaction.
If you're using Adyen for online payments or Unified Commerce, the PSP reference is the equivalent of the
pspReference
that you receive for transactions made online.
You should store each transaction identifier you receive, as you will need it to:
- Make a refund.
- Make a payment with acquired card details.
- Identify the transaction in your Customer Area, or in reports generated by Adyen.
Transaction identifiers for offline payments
If your integration uses local communications, your terminals will be able to make Offline EMV and store-and-forward transactions. When you experience a network issue, an Approved payment will only generate a transaction identifier with the tender reference:
Once the terminal is able to connect to the internet again, the Adyen payments platform will process the payment and generate a PSP reference. The PSP reference and tender reference can be found in your Customer Area, and in reports generated by Adyen.
Receipt data
When you make a transaction such as a payment, the payment result contains a PaymentReceipt
object. You can add the key-value pairs from this object to the receipt that you print, display, or email to your shopper.
For more information, see our receipts documentation.
Receiving webhooks
As you perform payments and other interactions with your integration, your terminal will generate notifications. These are JSON formatted webhooks that can be sent to endpoints on your cash register, and used to inform your store staff of important events.
There are two types of notifications that can be sent to your cash register:
- Display notifications: Inform your store staff of events that relate to a transaction, such as indicating whether the shopper is interacting with the terminal, or the result of the payment.
If your integration uses cloud communications with an asynchronous result, you will need to integrate display notifications to receive the result of your transactions.
- Event notifications: Inform your store staff of a terminal's availability and state, including when terminal is beginning maintenance, or shutting down.
In addition to these, Adyen can send platform notifications to your back office server. You can use these to help automate business processes, such as reporting and reconciliation, or to keep your Order Management System (OMS) up to date.
Handling errors
As you integrate, you may receive an error message in the API response. For information on these errors and how to resolve them, see Error scenarios.
If you do not receive a response to an API request, your connection may have dropped after the request was sent. For more information on how to handle this scenario, refer to verifying a transaction status.
Now that you understand the fundamentals of our Terminal API, you can start making payments.