--- title: "Third-party interactions" description: "Allow a third party to interact with your customers on your payment terminals." url: "https://docs.adyen.com/point-of-sale/shopper-engagement/third-party-interactions" source_url: "https://docs.adyen.com/point-of-sale/shopper-engagement/third-party-interactions.md" canonical: "https://docs.adyen.com/point-of-sale/shopper-engagement/third-party-interactions" last_modified: "2022-12-27T09:57:00+01:00" language: "en" --- # Third-party interactions Allow a third party to interact with your customers on your payment terminals. Apart from accepting payments, you can use your payment terminals to interact with your customers in other ways. For example, to get feedback on your service, engage customers in your loyalty program, or ask their details for sending a digital receipt. Typically, the data is collected through input requests, and forwarded to a back-end system that produces the intended result. You can set this up yourself. But you can also engage the services of companies specialized in surveys, customer loyalty, digital receipts, and so on. That is because we support **third-party interactions**, where another company can interact with your terminals directly without having to integrate with your POS system. Depending on what you want to achieve, third parties can: * Send non-payment requests to your terminals, like [input requests](/point-of-sale/shopper-engagement/shopper-input) for gathering answers from your customers, and [display requests](/point-of-sale/shopper-engagement/display-data) to show information like a 'Thank you' message. * Receive Terminal API display notifications.\ These notifications are generated by the terminal, are sent as webhooks, and contain updates on the progress of a payment on the terminal. * Receive standard webhooks.\ These webhooks are generated on the Adyen payments platform and contain transaction details. Third-party interaction with the terminal doesn't interrupt the payment process. Third-party interactions currently do not work with the OPI integration. ## Security and requirements Third parties cannot send payment or card acquisition requests to your terminals. If they try to send such a request, the request is refused with an HTTP status code of `010 Not Allowed`. Third-party interaction is possible: * In a Terminal API integration with WebSockets enabled.\ You can check the WebSockets setting in your [Customer Area](https://ca-test.adyen.com/), under **In-person payments** > **Terminal settings** > **Integrations**. * With specific terminal models: M400, P400 Plus, V210, V400m. ## How it works To enable third-party interactions you need to complete the setup as follows: 1. You [set up display notifications](#set-up-display-notifications) for the third party. For every step of the [tender](/get-started-with-adyen/adyen-glossary/#tender) process, the third party receives a display notification that contains: * The `POIID` of the terminal. This tells the third party where to send a request. * The `TransactionID`: the tender reference. When the payment is completed, the terminal sends a **TENDER\_FINAL** display notification. In this notification, the PSP reference is added in the format \`\[tender reference].\[PSP reference] is appended with the PSP reference: for cross-reference with a standard webhooks. 2. You [set up standard webhooks](#set-up-standard-webhooks) for the third party. For every payment, the third party will receive a webhook that includes the outcome of the payment, the amount, the PSP reference, and more. Based on the PSP reference, the third party can link the customer's transaction to their rating, for richer reporting. 3. You [set up an API credential](#set-up-the-third-party-api-credential) for the third party. This enables the third party to authenticate the input and display requests that they send. ## Third-party interaction flow The message flow with third-party interaction is as follows: 1. The POS app sends a payment request to the payment terminal. 2. The terminal sends display notifications to the third party for every step of the tender process, from [TENDER\_CREATED](/point-of-sale/design-your-integration/notifications/display-notifications#tender-created) when the payment starts, to [TENDER\_FINAL](/point-of-sale/design-your-integration/notifications/display-notifications#tender-final) when the payment is completed. 3. When the payment process is finished, the third party sends an input request to the terminal. 4. The customer provides their input on the terminal, and the third party receives the response. 5. To thank the customer, the third party sends a display request with an image. The image disappears after the time-out set in the request, or after a default time-out of three seconds. (This step is not shown in the diagram below.) 6. The third party receives a standard webhook for the payment from the Adyen payments platform. The following diagram illustrates the message flow for third-party interaction. In the diagram, the POS uses cloud communications, but with local communications the third-party interaction with the terminal is the same. ![](/user/pages/docs/03.point-of-sale/41.shopper-engagement/06.third-party-interactions/third-party-interaction-after-payment.svg?decoding=auto\&fetchpriority=auto) ## Set up third-party webhook endpoints To receive webhooks from Adyen terminals and the Adyen payments platform, the third party needs to configure their system. Then you need to set up third-party webhooks in your Customer Area. ### Configuration by the third-party 1. Inform the third party of the requirements for receiving webhooks: * Their system needs to have: * One or more endpoints that can receive webhooks in JSON format. They may get two kinds of webhooks: display notifications from the terminals, and standard webhooks from the Adyen payments platform. * For the test environment: an open TCP port for HTTP traffic (80, 8080, or 8888) or HTTPS traffic (443, 8443, or 8843) with TLSv1.2. * For the live environment: an open TCP port for HTTPS traffic (443, 8443, or 8843) with TLSv1.2. * Optional: a username and password for basic authentication. * If they want to receive standard webhooks, they should [verify the HMAC signature](/development-resources/webhooks/secure-webhooks/verify-hmac-signatures) of the standard webhook and they must [acknowledge](/development-resources/webhooks/configure-and-manage#accept-webhooks) every standard webhook with a [successful HTTP response status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#successful_responses), for example **200**. For instructions, refer the third party to our [development resources](/development-resources/webhooks) for webhooks. 2. Ask the third party for the endpoints and basic authentication credentials they set up for receiving webhooks.\ You need to provide those details in your Customer Area in the next steps. ### Set up display notifications To set up display notifications for the third party: 1. Make sure that you know the endpoint where the third party wants to receive display notifications, and the basic authentication credentials. 2. Log in to your [Customer Area](https://ca-test.adyen.com/) and switch to the account, store, or terminal that you want to set up notifications for. 3. Go to **In-person payments** > **Terminal settings** > **Integrations**. 4. In the **Terminal API** section, select **Decrypted**. 5. Under **Display URLs**, select the pencil icon **and then select **Add new**. 6. Select the pencil icon **next to the field that appears.\ The **Add URL** dialog opens. 7. Enter the details: * **URL**: the URL of the endpoint where the third party wants to receive display notifications. * **Username** and **Password** (optional): the basic authentication credentials that the third party set up on their server. * **Public**: select this option. Indicates that the specified URL is on a public network. * **Local**: do not select this option; not applicable for third-party interactions. 8. Select **Add URL** and then **Save**. 9. If your integration uses local communications, ask our [Support Team](https://ca-test.adyen.com/ca/ca/contactUs/support.shtml?form=other) to ensure display notifications are not encrypted.\ This step is necessary because with local communications the terminal generates encrypted notifications and the third party cannot decrypt those. ### Set up standard webhooks Currently there are no restrictions enforced on the details that third parties can receive in standard webhooks. We advise you to limit the details to the minimum required for your use case, by enabling as few additional settings as possible. To set up third-party standard webhooks: In your [Customer Area](https://ca-test.adyen.com/), enable and configure webhooks for your [company account](/account/account-structure/#company-account), [merchant account](/account/account-structure/#merchant-accounts), and [merchant account groups](/account/account-structure/#account-groups). However, we [recommend to configure webhooks for your company account](/development-resources/webhooks/configure-and-manage). To set up a webhook for a specific merchant account, create a webhook for your company account, and [configure merchant accounts](/development-resources/webhooks/configure-and-manage) for that webhook. * You can configure [Payments webhooks](/development-resources/webhooks/webhook-types#payments-webhooks) on the company, merchant account, and merchant account groups. * You can configure [Platforms webhooks](/development-resources/webhooks/webhook-types#platforms-webhooks) on the company account level only. **To configure a webhook:** 1\. Make sure that you know the endpoint where the third party wants to receive standard webhooks, and the basic authentication username and password of their webhook server. 2. If the payment terminals that the third party will interact with are boarded to one specific merchant account, switch to that merchant account. 1. In your [Customer Area](https://ca-test.adyen.com/), go to **Developers** > **Webhooks**.\ If you have a Balance Platform integration, select **Payments** or **Platforms** to view the webhooks available to you based on your integration. 2. Select ****Create new webhook**.\ If you are adding a webhook for your platform and have multiple platforms set up to run on Adyen, select the balance platform where you want to configure your new webhook. 3. From the list of webhooks, select **Add** for the one to add. 4. Under **General**, configure the following: | Setting | Description | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Enabled** | Select the toggle to enable or disable the webhook. | | **Version** | The webhook version. | | **Description** | Your description of the webhook. | | **Merchant accounts** | You can apply the webhook to all merchant accounts for a company account, include only specific merchant accounts, or exclude specific merchant accounts for your company account. | 5. Under **Server configuration**, configure the following: | Setting | Description | | ----------------------- | ------------------------------------------------------------------- | | **URL** | The URL of the third-party webhook server. It must be a public URL. | | **Method** | JSON, HTTP POST, or SOAP | | **Encryption protocol** | TLSv1.2 or TLSv1.3 | 6. Under **Security**, configure the following: | Setting | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **OAuth 2.0** | **Note:** OAuth 2.0 support is available for the **Standard webhook** type only. If you want to use OAuth 2.0 for access to your webhook endpoint, enter the following for your Identity Provider's OAuth 2.0 server:- **Client ID** - **Client secret** - **URL**: The location of your Identity Provider's OAuth 2.0 authorization server, where Adyen should request new access tokens. The time-to-live (TTL) setting of your access tokens must be 3599 seconds, at a minimum. - **Scope**: The **Scope** is optional. The permission level Adyen's webhook service needs to access to your webhook endpoint. | | **Basic authentication** | Enter the following for the third-party webhook server:- **username** - **password** | | **HMAC Key** | Generate a new HMAC Key or use an existing HMAC key. | 7. Under **Events** settings, select the [event types](/development-resources/webhooks/webhook-types/#event-codes) for this webhook. Some webhook types do not support more than one event type, so this setting does not appear. 8. If the **Additional settings** section is available, optionally select the additional information you want to receive in this webhook. Some webhook types do not support more than one event type, so this section does not appear. 9. Select **Save configuration**. ### **READY\_3RD\_PARTY** display notification #### JSON ```json { "SaleToPOIRequest":{ "DisplayRequest":{ "DisplayOutput":[ { "Device": "CashierDisplay", "InfoQualify": "Status", "OutputContent": { "OutputFormat": "MessageRef", "PredefinedContent": { "ReferenceID": "event=READY_3RD_PARTY" } }, "ResponseRequiredFlag": false } ] }, "MessageHeader":{ "SaleID":"POSSystemID12345", "ProtocolVersion":"3.0", "MessageType":"Request", "POIID":"V400m-324688179", "ServiceID":"0207111617", "MessageClass":"Device", "MessageCategory":"Display", "DeviceID":"1517998562" } } } ``` #### Java ```java String saleID = "YOUR_CASH_REGISTER_ID"; String POIID = "YOUR_TERMINAL_ID"; String serviceID = "YOUR_UNIQUE_ATTEMPT_ID"; SaleToPOIRequest saleToPOIRequest = new SaleToPOIRequest(); DisplayRequest displayRequest = new DisplayRequest(); DisplayOutput displayOutput = new DisplayOutput(); OutputContent outputContent = new OutputContent(); outputContent.setOutputFormat( OutputFormatType.MESSAGE_REF ); PredefinedContent predefinedContent = new PredefinedContent(); predefinedContent.setReferenceID("event=READY_3RD_PARTY"); outputContent.setPredefinedContent(predefinedContent); displayOutput.setOutputContent(outputContent); displayOutput.setInfoQualify( InfoQualifyType.STATUS ); displayOutput.setDevice( DeviceType.CASHIER_DISPLAY ); displayOutput.setResponseRequiredFlag( Boolean.FALSE ); displayRequest.setDisplayOutput(displayOutput); saleToPOIRequest.setDisplayRequest(displayRequest); MessageHeader messageHeader = new MessageHeader(); messageHeader.setSaleID(saleID); messageHeader.setProtocolVersion("3.0"); messageHeader.setMessageType( MessageType.REQUEST ); messageHeader.setPOIID(POIID); messageHeader.setServiceID(serviceID); messageHeader.setMessageClass( MessageClassType.DEVICE ); messageHeader.setMessageCategory( MessageCategoryType.DISPLAY ); messageHeader.setDeviceID("1517998562"); saleToPOIRequest.setMessageHeader(messageHeader); terminalAPIRequest.setSaleToPOIRequest(saleToPOIRequest); ``` ## Set up the third-party API credential If the third party wants to send Terminal API requests to your terminals, they must [authenticate their requests with an API key](/development-resources/api-authentication#api-key-authentication). This means you need to create a special third-party API credential for your account and share it with the third party. The third-party API credential has limited access and cannot be used to make payments. Like all API credentials, it consists of: * An API key. * API permissions: roles required for the type of request, and accounts that the API key is valid for. To be able to create the third-party API credential, you must have one of the following [user roles](/account/user-roles): * **Merchant admin** * **Manage API credentials** To create the third-party API credential: 1. Log in to your [Customer Area](https://ca-test.adyen.com/), and go to **Developers** > **API credentials**.\ This opens a list with all API credentials linked to your company account. 2. Select **Add standardized user**. 3. Select **thirdParty\_xxxxxx\@Company.****\[YourCompanyAccount]**.\ In this third-party API credential username, `xxxxxx` will be replaced with numbers. 4. Select **Add**. 5. In the list of API credentials, select the new third-party API credential username. 6. To generate an API key, under **Server settings** > **Authentication** select the **API key** tab. Select **Generate API key**, copy the API key using the copy icon **and store the third-party API key securely in your system. 7. Select **Save changes**. 8. Under **Permissions** > **Roles** select the role **Thirdparty interaction with in-store terminals**, and make sure no other roles are selected. 9. Under **Permissions** > **Accounts** select the accounts that the third-party credential needs to have access to.\ Make sure that these are the accounts that you set up webhooks for. 10. Select **Save changes**. 11. Securely send the API key to the third party. ## Let the third party send requests If the third party wants to send Terminal API requests to your terminals, inform them that they need to: 1. Listen to the Terminal API [display notifications](/point-of-sale/design-your-integration/notifications/display-notifications#display-notification-types) sent to their webhooks server. These include: * A `MessageHeader` with a `POIID` field that identifies the terminal. * A `ReferenceID` field with an `event` that indicates when the terminal is ready to receive a request. 2. In the [`MessageHeader` ](/point-of-sale/design-your-integration/terminal-api#request-message-header)of their input or display request, include a `POIID` field with the same value received in the display notification. 3. Format the rest of the request as described in our documentation. * For an example input request, see [Ask for a rating](/point-of-sale/shopper-engagement/shopper-input/rating/rating-single-press). That shows a screen that on various display sizes could look as follows: ![](/user/pages/docs/03.point-of-sale/41.shopper-engagement/06.third-party-interactions/screen-EN_rating-1-click-draft.png) * For both input and display request, the third party should set a time-out using `MinimumDisplayTime`. Otherwise the request will time out after three seconds. 4. Authenticate their request by specifying their third-party API key in the `x-API-key` header of the HTTP request. ## Canceling an in-progress interaction To block an incoming third-party interaction request, you can cancel the request: * [From your POS app](#cancel-interaction-from-pos) by sending a `DisplayRequest` that forces the terminal to show the standby screen. * [On the terminal](#cancel-interaction-from-terminal). ### Cancel from your POS app In general, requests are cancelled by sending an `AbortRequest` containing the `ServiceID` of the request you want to cancel. However, because the third party is sending the request, your POS app doesn't know the `ServiceID`. The solution is to send a `DisplayRequest` that instructs the terminal to show the standby screen. To cancel an in-progress third-party request from the POS app: 1. Make a [Terminal API](/point-of-sale/design-your-integration/terminal-api) display request, specifying: * The standard [`SaleToPOIRequest.MessageHeader` ](/point-of-sale/design-your-integration/terminal-api#request-message-header)object, with `MessageClass` set to **Device** and `MessageCategory` set to **Display**. | Parameter | Required | Description | | ----------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ProtocolVersion` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | **3.0** | | `MessageClass` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | **Device** | | `MessageCategory` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | **Display** | | `MessageType` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | **Request** | | `ServiceID` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | 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-") | Your unique ID for the POS system component to send this request from. | | `POIID` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The unique ID of the terminal to send this request to. Format: *\[device model]-\[serial number]*. | - The [DisplayRequest.DisplayOutput](https://docs.adyen.com/api-explorer/terminal-api/latest/post/display#request-DisplayOutput) array containing a single array item with: | Parameter | Value | | --------------------------------------------- | ------------------- | | `Device` | **CustomerDisplay** | | `InfoQualify` | **Display** | | `OutputContent.OutputFormat` | **MessageRef** | | `OutputContent.PredefinedContent.ReferenceID` | **Idle** | **Request to switch to the standby screen** ```json { "SaleToPOIRequest":{ "DisplayRequest":{ "DisplayOutput":[ { "Device":"CustomerDisplay", "InfoQualify":"Display", "OutputContent":{ "OutputFormat":"MessageRef", "PredefinedContent":{ "ReferenceID":"Idle" } } } ] }, "MessageHeader":{ "ProtocolVersion":"3.0", "MessageClass":"Device", "MessageCategory":"Display", "MessageType":"Request", "ServiceID":"043001", "SaleID":"POSSystemID12345", "POIID":"V400m-324688179" } } } ``` 2. In the display response, check the [OutputResult](https://docs.adyen.com/api-explorer/terminal-api/latest/post/display#responses-200-OutputResult).\ If the request is successful, this includes `Response.Result`: **Success**. **Response** ```json { "SaleToPOIResponse": { "DisplayResponse": { "OutputResult": [ { "Device": "CustomerDisplay", "InfoQualify": "Display", "Response": { "Result": "Success" } } ] }, "MessageHeader": { "MessageCategory": "Display", "MessageClass": "Device", "MessageType": "Response", "POIID": "V400m-324688179", "ProtocolVersion": "3.0", "SaleID": "POSSystemID12345", "ServiceID": "545" } } } ``` The terminal switches to the standby screen. 3. The third party receives a response containing: * `ErrorCondition`: **Cancel** * `Result`: **Failure** * `AdditionalResponse`: the message *A higher priority request has been received*. The next example shows the response to an input request after canceling from the POS app: **Third-party input request cancelled from POS app** ```json { "SaleToPOIResponse": { "InputResponse": { "InputResult": { "Device": "CustomerDisplay", "InfoQualify": "Display", "Response": { "AdditionalResponse": "message=A%20higher%20priority%20request%20has%20been%20received", "ErrorCondition": "Busy", "Result": "Failure" } } }, "MessageHeader": { "MessageCategory": "Input", "MessageClass": "Device", "MessageType": "Response", "POIID": "V400m-324688179", "ProtocolVersion": "3.0", "SaleID": "POSSystemID12345", "ServiceID": "603" } } } ``` ### Cancel from the terminal To cancel an in-progress third-party interaction on a terminal: * On the terminal keypad, select the *Cancel* key **![](/images/4/9/3/9/d/4939d94adbc3ebc98222ede1bcbb0ef0328893e2-cancel2x.png)**\ In case of a terminal without a keypad, on the display select the *Cancel* icon ![](/user/pages/reuse/image-library/buttons/cancel-icon/nav-cancel.svg?decoding=auto\&fetchpriority=auto) if the screen includes that. If this is successful: * The terminal shows the standby screen. * The third party receives a response containing: * `ErrorCondition`: **Cancel** * `Result`: **Failure** The next example shows the response to an input request after canceling from the terminal: **Third-party input request cancelled from terminal** ```json { "SaleToPOIResponse": { "InputResponse": { "InputResult": { "Device": "CustomerInput", "InfoQualify": "Input", "Input": { "DigitInput": "", "InputCommand": "DigitString" }, "Response": { "ErrorCondition": "Cancel", "Result": "Failure" } }, "OutputResult": { "Device": "CustomerDisplay", "InfoQualify": "Display", "Response": { "Result": "Success" } } }, "MessageHeader": { "MessageCategory": "Input", "MessageClass": "Device", "MessageType": "Response", "POIID": "e280-347069832", "ProtocolVersion": "3.0", "SaleID": "V400m-324688179", "ServiceID": "425" } } } ``` ## Testing After setting up all aspects of the third-party interaction, you need to check that the interaction behaves as expected. Contact the third party to discuss the scenarios to test for your specific use case. Here is an example of tests to run for a use case where the third party sends an input request: 1. Make a test transaction that is expected to trigger the third-party interaction. * Check that the expected question appears on the terminal. * React by giving an answer on the terminal. 2. Repeat, but this time do not react when the question appears, and check that the interaction times out as expected. 3. Repeat, but this time decline giving an answer, or cancel the interaction on the terminal. 4. Repeat, but this time cancel the interaction from the POS app. 5. Repeat all the above tests with other test transactions that are expected to trigger the third-party interaction. For example, test different payment instruments like credit cards, debit cards, and digital wallets. Or test different entry methods like tapping, inserting, and swiping. ## See also * [Display notifications](/point-of-sale/design-your-integration/notifications/display-notifications) * [Webhooks](/development-resources/webhooks) * [Input requests](/point-of-sale/shopper-engagement/shopper-input) * [Display requests](/point-of-sale/shopper-engagement/display-data)