--- title: "Terminal API" description: "Learn about our Terminal API, including the endpoints and structure." url: "https://docs.adyen.com/point-of-sale/design-your-integration/terminal-api" source_url: "https://docs.adyen.com/point-of-sale/design-your-integration/terminal-api.md" canonical: "https://docs.adyen.com/point-of-sale/design-your-integration/terminal-api" last_modified: "2023-07-11T11:17:00+02:00" language: "en" --- # Terminal API Learn about our Terminal API, including the endpoints and structure. [View source](/point-of-sale/design-your-integration/terminal-api.md) Our Terminal API is based on the [nexo Retailer Protocol](https://www.nexo-standards.org/standards/nexo-retailer-protocol).\ See our official [Terminal API](https://docs.adyen.com/api-explorer/terminal-api/latest/overview) reference. The Adyen Terminal API lets you make payments, issue refunds, collect shopper information, and perform other shopper-terminal interactions using a payment terminal supplied by Adyen. Before you make any point-of-sale payments, it is important to understand how Terminal API works and how requests and responses are structured. ## Enable Terminal API Before you can use Terminal API in your test environment, you need to enable it: 1. Log in to your [test Customer Area](https://ca-test.adyen.com/). 2. Go to **Devices** > **Device settings** > **Integrations**. 3. At **Terminal API**, turn on the **Enable terminal API** toggle. 4. Select **Save**. When you switch to your live environment, follow the same steps in your [live Customer Area](https://ca-live.adyen.com/). ## 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 a `PaymentResponse` object. The message header and body of Terminal API [requests](#requests) and [responses](#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-message-header). * [Request body object](#request-body) corresponding to the type of transaction. For example, this is a `PaymentRequest` object when you are making a payment, or an `InputRequest` object when you are requesting shopper input. ### Request MessageHeader In each request `MessageHeader`, specify the following: | Name | Required | Type | Description | | ----------------- | ------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ProtocolVersion` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | String | Version of the Nexo protocol that Terminal API is based on.The current protocol version is **3.0** | | `MessageClass` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | 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` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | Enum | The type of transaction. For example, `Payment` for a payment request. We will specify which `MessageCategory` is required throughout our documentation. | | `MessageType` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | Enum | This is always **Request**. | | `ServiceID` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | String | Your unique ID for this request, consisting of 1-10 alphanumeric characters. Must be unique within the last 48 hours for the terminal (`POIID`) being used. | | `SaleID` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | String | Your unique ID for the system where you send this request from. | | `POIID` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | String | The unique ID of the terminal that you send this request to. Format: *\[device model]-\[serial number]*. For example, **P400‑123456789**.To find the POIID, see [Get the terminal ID](/point-of-sale/design-your-integration/terminal-api/get-the-terminal-id/). | The example below shows the header for making a payment. **Request MessageHeader** ```JSON { "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. ## Sending Terminal API requests Sending Terminal API requests and how you authenticate requests depends on how your integration connects to the Adyen payments platform: * [Local communications](/point-of-sale/design-your-integration/choose-your-architecture/local).\ With a local Terminal API integration, your POS system communicates directly with the terminal over your local network. To make a payment, you make an API request directly to the IP address of the terminal, for the shopper to complete the transaction. You receive the result of the payment synchronously.\ ![Diagram showing local communications flow: POS app sends request directly to terminal over local network](/user/pages/reuse/pos-reuse/local-communication/local-comms.svg?decoding=auto\&fetchpriority=auto) * [Cloud communications](/point-of-sale/design-your-integration/choose-your-architecture/cloud).\ With a Terminal API integration using cloud communications, your POS system communicates with the terminal over the internet. To make a payment, you send your Terminal API requests to an endpoint on the Adyen payments platform. This request is forwarded to the terminal, for the shopper to complete the transaction. You can choose whether you want to receive the result of the payments synchronously or asynchronously.\ ![Diagram showing cloud communications flow: POS app sends request to Adyen cloud, which forwards to terminal](/user/pages/reuse/pos-reuse/cloud-communication/cloud-comms.svg?decoding=auto\&fetchpriority=auto) ## Responses Each terminal API response you receive is contained in a `SaleToPOIResponse` object, and includes a: * [`MessageHeader` object](#response-message-header): echoes the **MessageHeader** values you provided in the [API request](#request-message-header). * [Response body object](#response-body): corresponds to the type of transaction request you made.\ For example, when you make a `PaymentRequest` you receive a `PaymentResponse` object. In a cloud integration that receives results asynchronously, you only receive an `ok` response from the Terminal API. The `MessageHeader` and response body are sent in an [event notification](/point-of-sale/design-your-integration/notifications/event-notifications) instead. ### Response MessageHeader The `MessageHeader` you receive in the response echoes the values you provided in the request. The only exception is the `MessageType`, which is **Response**. The following example shows the header you would receive in response to the [example payment request provided above](#request-message-header). **Response MessageHeader** ```JSON { "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](#transaction-identifier), and data you can use to [generate your receipts](#receipt-data). #### 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`: ![Transaction identifier](/user/pages/docs/03.point-of-sale/04.design-your-integration/08.terminal-api/ReferenceForOnline.svg?decoding=auto\&fetchpriority=auto) This identifier contains two values, separated by a dot: * **Tender reference**: a unique value generated by the terminal for the transaction. * **PSP reference**: a unique alphanumeric value generated by the Adyen payments platform for the transaction. If you use Adyen for [online payments](/online-payments) or an omnichannel strategy, 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](https://ca-test.adyen.com/), or in [reports](/reporting) generated by Adyen. #### Transaction identifiers for offline payments If your integration uses [local communications](/point-of-sale/design-your-integration/choose-your-architecture/local), 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: ![Transaction identifier for offline payments](/user/pages/docs/03.point-of-sale/04.design-your-integration/08.terminal-api/ReferenceForOffline.svg?decoding=auto\&fetchpriority=auto) When the terminal is able to connect to the internet again, the Adyen payments platform will process the payment and generate an alphanumeric PSP reference. The PSP reference and tender reference can be found in your [Customer Area](https://ca-test.adyen.com/), and in [reports](/reporting) 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](/point-of-sale/basic-tapi-integration/generate-receipts). ## Next steps [Payment flow](/point-of-sale/basic-tapi-integration) [Implement the Terminal API requests needed in a basic integration.](/point-of-sale/basic-tapi-integration) [Handle responses](/point-of-sale/error-scenarios) [Resolve Terminal API errors and handle declined payments.](/point-of-sale/error-scenarios) [Terminal API reference](https://docs.adyen.com/api-explorer/terminal-api/1/overview) [View our implementation of the nexo standard.](https://docs.adyen.com/api-explorer/terminal-api/1/overview) [Get the terminal ID](/point-of-sale/design-your-integration/terminal-api/get-the-terminal-id) [Get the unique identifier of the payment terminal to include in your Terminal API requests.](/point-of-sale/design-your-integration/terminal-api/get-the-terminal-id)