|
| 1 | +# Cloud Device API |
| 2 | + |
| 3 | +The [Cloud Device API](https://docs.adyen.com/api-explorer/cloud-device-api/1/overview) is our solution to create best-in-class In-person Payments integrations. |
| 4 | + |
| 5 | +With the Cloud device API you can: |
| 6 | + |
| 7 | +- Send Terminal API requests to a cloud endpoint. You can use this communication method when it is not an option to send Terminal API requests over your local network directly to a payment terminal. |
| 8 | +- Check the cloud connection of a payment terminal or of a device used in a Mobile solution for in-person payments. |
| 9 | + |
| 10 | +## Benefits of the Cloud Device API |
| 11 | + |
| 12 | +The Cloud Device API offers the following benefits: |
| 13 | +- access to API logs in the Customer Area for troubleshooting errors |
| 14 | +- using a version strategy for the API endpoints for controlled and safer rollouts |
| 15 | +- improved reliability and security (OAuth support) |
| 16 | + |
| 17 | +New features and products will be released exclusively on the Cloud Device API |
| 18 | + |
| 19 | +## Use the Cloud Device API |
| 20 | + |
| 21 | +### Setup |
| 22 | + |
| 23 | +First you must initialise the Client **setting the closest** [Region](https://docs.adyen.com/point-of-sale/design-your-integration/terminal-api/#cloud): |
| 24 | +``` javascript |
| 25 | +// Step 1: Require the parts of the module you want to use |
| 26 | +const {Client, TerminalCloudAPI} from "@adyen/api-library"; |
| 27 | +const { Config, EnvironmentEnum, RegionEnum } = require("@adyen/api-library"); |
| 28 | + |
| 29 | +// Step 2: Initialize the client object |
| 30 | +const config = new Config({ |
| 31 | + apiKey: "YOUR_API_KEY", |
| 32 | + environment: EnvironmentEnum.LIVE, |
| 33 | + region: RegionEnum.US |
| 34 | +}); |
| 35 | +const client = new Client(config); |
| 36 | + |
| 37 | +// Step 3: Initialize the Cloud Device API service |
| 38 | +const cloudDeviceAPI = new CloudDeviceAPI(client); |
| 39 | +``` |
| 40 | + |
| 41 | +### Send a payment request |
| 42 | + |
| 43 | +```javascript |
| 44 | + |
| 45 | +// define the messageHeader |
| 46 | +const messageHeader: MessageHeader = { |
| 47 | + MessageCategory: MessageCategoryType.Payment, |
| 48 | + MessageClass: MessageClassType.Service, |
| 49 | + MessageType: MessageType.Request, |
| 50 | + POIID: "V400m-123456789", |
| 51 | + ProtocolVersion: "3.0", |
| 52 | + SaleID: "POS-123", // Your unique ID for the system where you send this request from |
| 53 | + ServiceID: "abvc-efgh", // Your unique ID for this request |
| 54 | +}; |
| 55 | + |
| 56 | +// define the paymentRequest |
| 57 | +const paymentRequest: PaymentRequest = { |
| 58 | + PaymentTransaction: { |
| 59 | + AmountsReq: { |
| 60 | + Currency: "EUR", |
| 61 | + RequestedAmount: 1, |
| 62 | + }, |
| 63 | + }, |
| 64 | + SaleData: { |
| 65 | + SaleTransactionID: { |
| 66 | + TimeStamp: "2025-09-11T08:51:30.698Z", |
| 67 | + TransactionID: "abc1234567890", |
| 68 | + }, |
| 69 | + SaleToAcquirerData: { |
| 70 | + applicationInfo: { |
| 71 | + merchantApplication: { |
| 72 | + version: "1", |
| 73 | + name: "test" |
| 74 | + } |
| 75 | + }, |
| 76 | + metadata: { |
| 77 | + someMetaDataKey1: "YOUR_VALUE", |
| 78 | + someMetaDataKey2: "YOUR_VALUE" |
| 79 | + }, |
| 80 | + } |
| 81 | + }, |
| 82 | +}; |
| 83 | + |
| 84 | +// define the request |
| 85 | +const cloudDeviceApiRequest: CloudDeviceApiRequest = { |
| 86 | + SaleToPOIRequest: { |
| 87 | + MessageHeader: messageHeader, |
| 88 | + PaymentRequest: paymentRequest, |
| 89 | + }, |
| 90 | +}; |
| 91 | + |
| 92 | +// perform the sync call |
| 93 | +const response = await cloudDeviceAPI.sendSync( |
| 94 | + "YOUR_MERCHANT_ACCOUNT", |
| 95 | + "V400m-123456789", |
| 96 | + cloudDeviceApiRequest |
| 97 | +); |
| 98 | +``` |
| 99 | + |
| 100 | + |
| 101 | +### Send a payment ASYNC request |
| 102 | + |
| 103 | +If you choose to receive the response asynchronously, you only need to use a different method (`sendAsync()`). |
| 104 | +Don't forget to set up [event notifications](https://docs.adyen.com/point-of-sale/design-your-integration/notifications/event-notifications/) in the CA to be able to receive the Cloud Device API responses. |
| 105 | + |
| 106 | +```javascript |
| 107 | + |
| 108 | +// define the request |
| 109 | +const cloudDeviceApiRequest: CloudDeviceApiRequest = { |
| 110 | + SaleToPOIRequest: { |
| 111 | + MessageHeader: messageHeader, |
| 112 | + PaymentRequest: paymentRequest, |
| 113 | + }, |
| 114 | +}; |
| 115 | + |
| 116 | +// perform the async call |
| 117 | +const response = await cloudDeviceAPI.sendAsync( |
| 118 | + "YOUR_MERCHANT_ACCOUNT", |
| 119 | + "V400m-123456789", |
| 120 | + cloudDeviceApiRequest |
| 121 | +); |
| 122 | + |
| 123 | +// handle both `string` and `CloudDeviceApiResponse` |
| 124 | +if (typeof response === "string") { |
| 125 | + // request was successful |
| 126 | + console.log("response:", response); // should be 'ok' |
| 127 | +} else { |
| 128 | + // request failed: see details in the EventNotification object |
| 129 | + console.log("EventToNotify:", response.SaleToPOIRequest?.EventNotification?.EventToNotify); |
| 130 | + console.log("EventDetails:", response.SaleToPOIRequest?.EventNotification?.EventDetails); |
| 131 | +} |
| 132 | +``` |
| 133 | +
|
| 134 | +### Verity the status of the terminals |
| 135 | +
|
| 136 | +The Cloud Device API allows your integration to check the status of the terminals. |
| 137 | +
|
| 138 | +```javascript |
| 139 | + |
| 140 | +// list of payment terminals or SDK mobile installation IDs |
| 141 | +const connectedDevices: ConnectedDevicesResponse = await cloudDeviceAPI.getConnectedDevices("YOUR_MERCHANT_ACCOUNT"); |
| 142 | +console.log(connectedDevices.uniqueDeviceIds); |
| 143 | + |
| 144 | +// check the payment terminal or SDK mobile installation ID |
| 145 | +const deviceStatus: DeviceStatusResponse = await cloudDeviceAPI.getDeviceStatus("YOUR_MERCHANT_ACCOUNT", "V400m-123456789"); |
| 146 | +console.log(deviceStatus.status); |
| 147 | + |
| 148 | +``` |
| 149 | +
|
| 150 | +### Error handling |
| 151 | +
|
| 152 | +In case of error try-catch the `CloudDeviceApiError` to understand what went wrong. |
| 153 | +
|
| 154 | +```javascript |
| 155 | +try { |
| 156 | + const response = await client.sendSync("YOUR_MERCHANT_ACCOUNT", "V400m-123456789", cloudDeviceApiRequest); |
| 157 | + console.log("response:", response); |
| 158 | + } catch (err) { |
| 159 | + if (err instanceof CloudDeviceApiError) { |
| 160 | + console.error("CloudDevice API failed:", err.message); |
| 161 | + console.error("Cause:", err.cause); |
| 162 | + } |
| 163 | + } |
| 164 | +``` |
| 165 | +
|
| 166 | +### Protect cloud communication |
| 167 | +
|
| 168 | +The Adyen Node.js library supports encrypting request and response payloads, allowing you to secure communication between your integration and the cloud. |
| 169 | +
|
| 170 | +```javascript |
| 171 | + |
| 172 | +// Encryption credentials from the Terminal configuration on CA |
| 173 | +const encryptionCredentialDetails: EncryptionCredentialDetails = { |
| 174 | + AdyenCryptoVersion: 1, |
| 175 | + KeyIdentifier: "myKeyIdentifier", |
| 176 | + KeyVersion: "myKeyVersion", |
| 177 | + Passphrase: "myPassphrase" |
| 178 | +}; |
| 179 | + |
| 180 | +const response: CloudDeviceApiResponse = await cloudDeviceAPI.sendEncryptedSync("YOUR_MERCHANT_ACCOUNT", "V400m-123456789", cloudDeviceApiRequest, encryptionCredentialDetails); |
| 181 | +console.log("response:", response); |
| 182 | +``` |
| 183 | +
|
| 184 | +In case of asynchronous integration, you can decrypt the payload of the event notification using `decryptNotification()` method. |
| 185 | +
|
| 186 | +```javascript |
| 187 | + |
| 188 | +const response: string = await cloudDeviceAPI.decryptNotification("", encryptionCredentialDetails); |
| 189 | +console.log("response:", response); |
| 190 | + |
| 191 | +``` |
0 commit comments