The Adyen Node.js API Library now includes the Cloud device API, a modern replacement for the Terminal (Cloud) API for In-Person Payments cloud integrations.
The Terminal (Cloud) API (TerminalCloudAPI) uses hand-crafted models in the src/typings/terminal package. The Cloud device API (CloudDeviceAPI) is generated from the Cloud device API OpenAPI specification, just like all other services in this library. This means the models and service classes are always in sync with the API, follow the same patterns as the rest of the library (ObjectSerializer serialization, attributeTypeMap, etc.), and benefit from the automated update process.
Because the Cloud device API models (src/typings/tapi) are generated from the spec rather than hand-crafted, there are differences in class names, enum naming conventions, field types, and properties. This guide describes these differences and what to be aware of when adopting the Cloud device API.
The Cloud device API introduces several improvements over the Terminal (Cloud) API:
- API logs in the Customer Area: troubleshoot errors using the API logs available in your Customer Area.
- Versioned endpoints: the API uses a version strategy for controlled and safer rollouts.
- Improved security: supports OAuth authentication alongside API key authentication.
- Device management endpoints: query connected devices and check their status directly from your integration.
- New features: new In-Person Payments features and products are released exclusively on the Cloud device API.
- New integrations: use the Cloud device API from the start. See the Cloud device API documentation.
- Updating your cloud integration: consider migrating to the Cloud device API to benefit from the improvements listed above.
- Not making changes: you can continue using the Terminal (Cloud) API. It remains functional, but you will miss out on the benefits of the Cloud device API.
Before you start using the Cloud device API, make sure the following are in place.
Your API key must have the Cloud device API user role assigned. You can manage roles in the Customer Area under Developers > API credentials.
On the TEST environment, no region configuration is needed. On the LIVE environment, you must configure region to the region closest to your terminals:
import { Client, Config, EnvironmentEnum, RegionEnum, CloudDeviceAPI } from "@adyen/api-library";
const client = new Client(new Config({
apiKey: "YOUR_API_KEY",
environment: EnvironmentEnum.LIVE,
region: RegionEnum.EU, // set to the region closest to your terminals
}));
const cloudDeviceAPI = new CloudDeviceAPI(client);See the Terminal API cloud documentation for available regions.
The following sections describe the key differences between the Terminal (Cloud) API and the Cloud device API.
The Cloud device API uses the CloudDeviceAPI service class instead of TerminalCloudAPI:
| Terminal (Cloud) API | Cloud device API | |
|---|---|---|
| Service class | TerminalCloudAPI |
CloudDeviceAPI (exposes .CloudDeviceApi) |
| Request wrapper | terminal.TerminalAPIRequest (SaleToPOIRequest) |
clouddevice.CloudDeviceApiRequest |
| Response wrapper | terminal.TerminalApiResponse |
clouddevice.CloudDeviceApiResponse |
| Async response | string ("ok") or TerminalApiResponse |
clouddevice.CloudDeviceApiAsyncResponse |
The Cloud device API sync and async methods require merchantAccount and deviceId as parameters, in addition to the request body. Make sure the POIID in the MessageHeader matches the deviceId.
Cloud device API:
// make a sync request
const response = await cloudDeviceAPI.CloudDeviceApi.sync("myMerchant", "P400Plus-123456789", cloudDeviceApiRequest);
// get the list of connected devices for a given merchant account
const devices = await cloudDeviceAPI.CloudDeviceApi.getConnectedDevices("myMerchant");The Terminal (Cloud) API uses hand-crafted models in src/typings/terminal. The Cloud device API uses models generated from the OpenAPI specification in src/typings/tapi.
Terminal (Cloud) API (terminal) |
Cloud device API (tapi) |
|---|---|
SaleToPOIRequest |
SaleToPOIRequest |
MessageHeader |
MessageHeader |
MessageCategoryType |
MessageCategory (renamed, see below) |
PaymentRequest |
PaymentRequest |
AmountsReq |
AmountsReq |
Several enum classes are named differently in the Cloud device API to match the OpenAPI specification. The Type suffix has been dropped:
Old name (terminal) |
New name (tapi) |
|---|---|
AlignmentType |
Alignment |
CharacterHeightType |
CharacterHeight |
CharacterStyleType |
CharacterStyle |
CharacterWidthType |
CharacterWidth |
DeviceType |
Device |
DocumentQualifierType |
DocumentQualifier |
ErrorConditionType |
ErrorCondition |
EventToNotifyType |
EventToNotify |
GlobalStatusType |
GlobalStatus |
IdentificationSupportType |
IdentificationSupport |
InfoQualifyType |
InfoQualify |
InputCommandType |
InputCommand |
LoyaltyHandlingType |
LoyaltyHandling |
MenuEntryTagType |
MenuEntryTag |
MessageCategoryType |
MessageCategory |
MessageClassType |
MessageClass |
OutputFormatType |
OutputFormat |
PeriodUnitType |
PeriodUnit |
PINFormatType |
PINFormat |
PrinterStatusType |
PrinterStatus |
ResponseModeType |
ResponseMode |
ResultType |
Result |
ReversalReasonType |
ReversalReason |
SoundActionType |
SoundAction |
SoundFormatType |
SoundFormat |
TrackFormatType |
TrackFormat |
TransactionActionType |
TransactionAction |
Note: enums that already end with Type in the spec (for example, MessageType, TokenRequestedType, AccountType) are not renamed.
Some classes are also renamed to adopt the name of the model in the OpenAPI specification.
Terminal (Cloud) API (terminal) |
Cloud device API (tapi) |
|---|---|
CheckTypeCodeType |
TypeCode |
TransactionIdentification |
TransactionIDType |
CardholderPIN |
CardHolderPIN |
SignaturePoint |
Point |
LoyaltyAccountId |
LoyaltyAccountID |
StoredValueAccountId |
StoredValueAccountID |
TerminalApiRequest |
TerminalAPIRequest |
TerminalApiResponse |
TerminalAPIResponse |
Some field types differ in the generated models.
The Cloud device API models use Date for timestamp fields (DateTime, ExpiryDateTime, TimeStamp), whereas the Terminal (Cloud) API models used a generic { [key: string]: any } type. Always provide a Date:
Terminal (Cloud) API:
SaleTransactionID: {
TransactionID: "001",
TimeStamp: new Date().toISOString(),
}Cloud device API:
SaleTransactionID: {
TransactionID: "001",
TimeStamp: new Date(),
}More than 40 properties that were previously inline enums (for example, Response.ErrorConditionEnum) are now standalone enum classes (for example, ErrorCondition). Import the enum from src/typings/tapi/models instead of accessing it through the parent class.
Several fields changed from string to number in the Cloud device API, including AcquirerID, POIReconciliationID, CardCountryCode, PAN, and IMEI.
ContentInformation->stringforProtectedCardData,ProtectedSignature,Password,ProtectedMobileDataSaleToAcquirerData(class) ->stringonsaleData
ForceEntryMode, ServicesEnabled, and AuthenticationMethod are single values instead of arrays.
Some properties were renamed, added, or removed. The most relevant renames:
| File | Terminal (Cloud) API | Cloud device API |
|---|---|---|
iCCResetData |
AtrValue |
ATRValue |
soundContent |
Value |
Text |
storedValueAccountID |
Value |
StoredValueID |
trackData |
Value |
TrackValue |
paymentResult |
InstalmentType |
Instalment |
New properties in the Cloud device API include PaymentReceipt (balanceInquiryResponse, storedValueResponse), HostReconciliationID (paymentAcquirerData), ProtectedCardData and StoredValueAccountID (paymentInstrumentData), and TokenRequestStatus (loginResponse).
| Enum | Removed values | Added values |
|---|---|---|
CharacterStyle |
Underlined |
Underline |
EventToNotify |
NetworkConnected, NetworkDisconnected |
UseAnotherCardForPreauth |
MessageCategory |
Batch, CardReaderAPDU, CardReaderInit, CardReaderPowerOff, PIN, Sound, Transmit |
None |
TrackFormat |
JisI, JisIi |
(none) |
The async response handling differs between the two APIs. The Terminal (Cloud) API async method returns a plain string ("ok") on success, or a TerminalApiResponse on failure. The Cloud device API wraps the response in CloudDeviceApiAsyncResponse.
Terminal (Cloud) API:
const response = await terminalCloudAPI.async(terminalAPIRequest);
if (typeof response === "string") {
// success ("ok")
} else {
// failed: response.SaleToPOIRequest?.EventNotification
}Cloud device API:
const response = await cloudDeviceAPI.CloudDeviceApi.async("myMerchant", "P400Plus-123456789", cloudDeviceApiRequest);
if (response.Result === "ok") {
// success
} else {
// request failed: check EventNotification for error details
const eventNotification = response.SaleToPOIRequest?.EventNotification;
}The Cloud device API includes endpoints for device management that are not available in the Terminal (Cloud) API:
// List connected devices for a merchant account
const devices = await cloudDeviceAPI.CloudDeviceApi.getConnectedDevices("myMerchant");
console.log(devices.uniqueDeviceIds);
// Check the status of a specific device
const status = await cloudDeviceAPI.CloudDeviceApi.getDeviceStatus("myMerchant", "P400Plus-123456789");
console.log(status.status);import { Client, Config, EnvironmentEnum, TerminalCloudAPI } from "@adyen/api-library";
import {
MessageCategoryType,
MessageClassType,
MessageType,
SaleToPOIRequest,
} from "@adyen/api-library/lib/src/typings/terminal/models";
const client = new Client(new Config({ apiKey: "YOUR_API_KEY", environment: EnvironmentEnum.TEST }));
const terminalCloudAPI = new TerminalCloudAPI(client);
const paymentRequest: SaleToPOIRequest = {
MessageHeader: {
ProtocolVersion: "3.0",
MessageClass: MessageClassType.Service,
MessageCategory: MessageCategoryType.Payment,
MessageType: MessageType.Request,
SaleID: "001",
ServiceID: "001",
POIID: "P400Plus-123456789",
},
PaymentRequest: {
SaleData: {
SaleTransactionID: {
TransactionID: "001",
TimeStamp: new Date().toISOString(),
},
},
PaymentTransaction: {
AmountsReq: { Currency: "EUR", RequestedAmount: 1 },
},
},
};
const response = await terminalCloudAPI.sync({ SaleToPOIRequest: paymentRequest });import { Client, Config, EnvironmentEnum, CloudDeviceAPI } from "@adyen/api-library";
import {
MessageCategory,
MessageClass,
MessageType,
SaleToPOIRequest,
} from "@adyen/api-library/lib/src/typings/tapi/models";
import { CloudDeviceApiRequest } from "@adyen/api-library/lib/src/typings/clouddevice/models";
const client = new Client(new Config({ apiKey: "YOUR_API_KEY", environment: EnvironmentEnum.TEST }));
const cloudDeviceAPI = new CloudDeviceAPI(client);
const request: CloudDeviceApiRequest = {
SaleToPOIRequest: {
MessageHeader: {
ProtocolVersion: "3.0",
MessageClass: MessageClass.Service,
MessageCategory: MessageCategory.Payment,
MessageType: MessageType.Request,
SaleID: "001",
ServiceID: "001",
POIID: "P400Plus-123456789",
},
PaymentRequest: {
SaleData: {
SaleTransactionID: {
TransactionID: "001",
TimeStamp: new Date(),
},
},
PaymentTransaction: {
AmountsReq: { Currency: "EUR", RequestedAmount: 1 },
},
},
},
};
// Note: make sure POIID matches the deviceId parameter
const response = await cloudDeviceAPI.CloudDeviceApi.sync("myMerchant", "P400Plus-123456789", request);Some models present in the terminal package are not available in the tapi package because they are not part of the current OpenAPI specification. These represent features that were never supported by the Terminal (Cloud) API:
BatchRequest/BatchResponseLoyaltyRequestPINRequest/PINResponseCardReaderInitRequest/CardReaderInitResponseCardReaderPowerOffRequest/CardReaderPowerOffResponseSoundRequest/SoundResponseTransmitRequest/TransmitResponseContentInformation
The terminal message-level security and crypto types (for example, SecurityKey, EnvelopedData, SignedData) are also absent from the tapi package. To secure cloud communication with the Cloud device API, use EncryptedCloudDeviceApi instead (see Protect cloud communication).
If your integration requires these models, please create a new issue, so we can understand your needs and provide you with the necessary help.
Perform a thorough validation of the migration.
- Verify that your request objects serialize to the same JSON structure with the new models. Compare with the expected JSON payloads from your existing test data.
- Pay special attention to the renamed fields and type changes described above.
- Point the
CloudDeviceAPIto the test environment (EnvironmentEnum.TEST). - Run your most common payment flows: payment, reversal, refund, and reconciliation.
- Verify that the response structure is parsed correctly, especially the fields with type changes (
Date,number). - Test your async flow to confirm event notifications are received and can be parsed.
- Test with a POS terminal.
- Check that
PaymentResponse,ReversalResponse, and other response models deserialize without errors. - Confirm that boolean field handling works correctly without the old default-value helpers.
- Use
getConnectedDevices()andgetDeviceStatus()to validate your terminal connectivity before running transaction tests.
- Consider running the Cloud device API integration in parallel with your existing Terminal (Cloud) API integration.
- Observe traffic (with the Customer Area API Logs or your own observability tools) to validate the API requests and responses.
- Compare the results of both integrations to ensure functional equivalence.