Terminal API

July 10, 2026 ยท View on GitHub

With the Terminal API you can send and receive Terminal API messages in the following ways:

  • Local communications: using your local network, your POS system sends the request directly to the IP address of the terminal, and receives the result synchronously.
  • Cloud communications: using the internet to access the cloud /sync and /async endpoints.

Note: For In-Person Payments cloud integrations, the recommended solution is the Cloud device API. Consider migrating to the Cloud device API to benefit from API logs in the Customer Area, versioned endpoints, and improved security.

Using the Cloud Terminal API

For In-Person Payments integrations with the Cloud Terminal API, you must initialize the Client setting the closest Region:

// Step 1: Require the parts of the module you want to use
import { Client, TerminalCloudAPI, Config, EnvironmentEnum, RegionEnum, Types } from "@adyen/api-library";

// Step 2: Initialize the client object
const config = new Config({
    apiKey: "YOUR_API_KEY",
    environment: EnvironmentEnum.LIVE,
    region: RegionEnum.US
});
const client = new Client(config);

// Step 3: Initialize the API object
const terminalCloudAPI = new TerminalCloudAPI(client);

// Step 4: Create the request object
const serviceID = "123456789";
const saleID = "POS-SystemID12345";
const POIID = "Your Device Name(eg V400m-123456789)";

// Use a unique transaction for every transaction you perform
const transactionID = "TransactionID";
const paymentRequest: Types.terminal.SaleToPOIRequest = {
    MessageHeader: {
        MessageClass: Types.terminal.MessageClassType.Service,
        MessageCategory: Types.terminal.MessageCategoryType.Payment,
        MessageType: Types.terminal.MessageType.Request,
        ProtocolVersion: "3.0",
        ServiceID: serviceID,
        SaleID: saleID,
        POIID: POIID
    },
    PaymentRequest: {
        SaleData: {
            SaleTransactionID: {
                TransactionID: transactionID,
                TimeStamp: new Date().toISOString()
            },

            SaleToAcquirerData: {
                applicationInfo: {
                    merchantApplication: {
                        version: "1",
                        name: "test",
                    }
                }
            }
        },
        PaymentTransaction: {
            AmountsReq: {
                Currency: "EUR",
                RequestedAmount: 1000
            }
        }
    }
};

// Step 5: Make the request
const terminalAPIResponse: Types.terminal.TerminalApiResponse = await terminalCloudAPI.sync(paymentRequest);

Optional: perform an abort request

To perform an abort request you can use the following example:

const abortRequest: Types.terminal.SaleToPOIRequest = {
    MessageHeader: {
        MessageClass: Types.terminal.MessageClassType.Service,
        MessageCategory: Types.terminal.MessageCategoryType.Abort,
        MessageType: Types.terminal.MessageType.Request,
        ProtocolVersion: "3.0",
        // Different serviceID than the one you're aborting
        ServiceID: "Different service ID",
        SaleID: saleID,
        POIID: POIID
    },
    AbortRequest: {
        AbortReason: "MerchantAbort",
        MessageReference: {
            MessageCategory: Types.terminal.MessageReference.MessageCategoryEnum.Payment,
            SaleID: saleID,
            // Service ID of the payment you're aborting
            ServiceID: serviceID,
            POIID: POIID
        }

    }
};
const terminalAPIResponse: Types.terminal.TerminalApiResponse = await terminalCloudAPI.sync(abortRequest);

Optional: perform a status request

To perform a status request you can use the following example:

const statusRequest: Types.terminal.SaleToPOIRequest = {
    MessageHeader: {
        MessageClass: Types.terminal.MessageClassType.Service,
        MessageCategory: Types.terminal.MessageCategoryType.TransactionStatus,
        MessageType: Types.terminal.MessageType.Request,
        ProtocolVersion: "3.0",
        ServiceID: "Different service ID",
        SaleID: saleID,
        POIID: POIID
    },
    TransactionStatusRequest: {
        ReceiptReprintFlag: true,
        DocumentQualifier: [Types.terminal.TransactionStatusRequest.DocumentQualifierEnum.CashierReceipt, Types.terminal.TransactionStatusRequest.DocumentQualifierEnum.CustomerReceipt],
        MessageReference: {
            SaleID: saleID,
            // serviceID of the transaction you want the status update for
            ServiceID: serviceID,
            MessageCategory: Types.terminal.MessageReference.MessageCategoryEnum.Payment
        }
    }
};
const terminalAPIResponse: Types.terminal.TerminalApiResponse = await terminalCloudAPI.sync(statusRequest);

Using the Cloud Terminal API Integration (async)

If you choose to integrate Terminal API over Cloud asynchronously, you need to follow similar steps to initialize the client and prepare the request object. However the response will be asynchronous:

  • a successful request will return 200 status code and ok as response body. Make sure to setup the event notifications
  • a request that fails will return 200 status code and the TerminalApiResponse as response body
// Step 1: Require the parts of the module you want to use
import { Client, TerminalCloudAPI, EnvironmentEnum, Types } from "@adyen/api-library";

// Step 2: Initialize the client object
const client = new Client({apiKey: "YOUR_API_KEY", environment: EnvironmentEnum.TEST}); 


// Step 3: Initialize the API object
const terminalCloudAPI = new TerminalCloudAPI(client);

// Step 4: Create the request object
const serviceID = "123456789";
const saleID = "POS-SystemID12345";
const POIID = "Your Device Name(eg V400m-123456789)";

// Use a unique transaction for every transaction you perform
const transactionID = "TransactionID";
const paymentRequest: Types.terminal.SaleToPOIRequest = {
    MessageHeader: {
        MessageClass: Types.terminal.MessageClassType.Service,
        MessageCategory: Types.terminal.MessageCategoryType.Payment,
        MessageType: Types.terminal.MessageType.Request,
        ProtocolVersion: "3.0",
        ServiceID: serviceID,
        SaleID: saleID,
        POIID: POIID
    },
    PaymentRequest: {
        SaleData: {
            SaleTransactionID: {
                TransactionID: transactionID,
                TimeStamp: new Date().toISOString()
            },

            SaleToAcquirerData: {
                applicationInfo: {
                    merchantApplication: {
                        version: "1",
                        name: "test",
                    }
                }
            }
        },
        PaymentTransaction: {
            AmountsReq: {
                Currency: "EUR",
                RequestedAmount: 1000
            }
        }
    }
};

// Step 5: Make the request
const response = await terminalCloudAPI.async(paymentRequest);
// handle both `string` and `TerminalApiResponse`
if (typeof response === "string") {
  // request was successful
  console.log("response:", response); // should be 'ok'
} else {
  // request failed: see details in the EventNotification object
  console.log("EventToNotify:", response.SaleToPOIRequest?.EventNotification?.EventToNotify);
  console.log("EventDetails:", response.SaleToPOIRequest?.EventNotification?.EventDetails);
}

Helper classes

Use PredefinedContentHelper to parse Display notification types which you find in PredefinedContent->ReferenceID:

import { PredefinedContentHelper } from "@adyen/api-library/lib/src/typings/terminal/predefinedContentHelper";

// Parse ReferenceID (i.e. key1=value1&key2=value2)
const helper = new PredefinedContentHelper(predefinedContent.ReferenceID);
const event = helper.getEvent();

Using the Local Terminal API Integration

The procedure to send In-Person requests using Terminal API over Local Connection is similar to the Cloud Terminal API one, however, additional encryption details are required to perform the requests. Make sure to install the certificate as described here

// Step 1: Require the parts of the module you want to use
import { Client, TerminalLocalAPI, Config, Types } from "@adyen/api-library";

// Step 2: Add your Certificate Path and Local Endpoint to the config path. Install the certificate and save it in your project folder as "cert.cer"
const config: Config = new Config();
config.certificatePath = "./cert.cer";
config.terminalApiLocalEndpoint = "The IP of your terminal (eg https://192.168.47.169)";
config.apiKey = "YOUR_API_KEY_HERE";

// Step 3: Setup a security password for your terminal in CA, and import the security key object:
const securityKey: SecurityKey = {
    AdyenCryptoVersion: 1,
    KeyIdentifier: "keyIdentifier",
    KeyVersion: 1,
    Passphrase: "passphrase",
};

// Step 4 Initialize the client and the API objects
const client = new Client({ config });
const terminalLocalAPI = new TerminalLocalAPI(client);

// Step 5: Create the request object
const paymentRequest: Types.terminal.SaleToPOIRequest = {
// Similar to the saleToPOIRequest used for Cloud API
}

// Step 6: Make the request
const terminalApiResponse: Types.terminal.TerminalApiResponse = await terminalLocalAPI.request(paymentRequest, securityKey);

Using the Local Terminal API Integration without Encryption (Only on TEST)

If you wish to develop the Local Terminal API integration parallel to your encryption implementation, you can opt for the unencrypted version. Be sure to remove any encryption details from the CA terminal config page.

// Step 1: Require the parts of the module you want to use
import { Client, TerminalLocalAPIUnencrypted, Config, Types } from "@adyen/api-library";

// Step 2: Add your Certificate Path and Local Endpoint to the config path. Install the certificate and save it in your project folder as "cert.cer"
const config: Config = new Config();
config.terminalApiLocalEndpoint = "The IP of your terminal (eg https://192.168.47.169)";
config.apiKey = "YOUR_API_KEY_HERE";

// Step 3 Initialize the client and the API objects
const client = new Client({ config });
const terminalLocalAPI = new TerminalLocalAPIUnencrypted(client);

// Step 4: Create the request object
const paymentRequest: Types.terminal.SaleToPOIRequest = {
// Similar to the saleToPOIRequest used for Cloud API
}

// Step 5: Make the request
const terminalApiResponse: Types.terminal.TerminalApiResponse = await terminalLocalAPI.request(paymentRequest);