{"title":"Building a local integration","category":"default","creationDate":1560352500,"content":"<p>Before you start building a point-of-sale integration with Adyen-provided payment terminals, you need to <a href=\"\/point-of-sale\/design-your-integration\/choose-your-architecture\">choose between local or cloud communications<\/a>. This determines how your POS system &mdash;also referred to as cash register&mdash; connects to the Adyen payment terminals and the Adyen payments platform.<\/p>\n<p>This section of the documentation explains what to do if you have decided to use local communications.<\/p>\n<h2>Requirements<\/h2>\n<p>Before you begin, take into account the following information.<\/p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: left;\">Requirement<\/th>\n<th style=\"text-align: left;\">Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: left;\"><strong>Integration type<\/strong><\/td>\n<td style=\"text-align: left;\">The information on this page is relevant for building a point-of-sale integration with the Adyen Terminal API and Adyen payment terminals using local communications.<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><strong><a href=\"\/development-resources\/api-credentials\/\">API credentials<\/a><\/strong><\/td>\n<td style=\"text-align: left;\">To set up a shared key using API calls, your API credential must have the following role: <ul><li markdown=\"1\">Management API\u2014Terminal Advanced settings read and write<\/li><\/ul><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\"><strong><a href=\"\/account\/user-roles\">Customer Area roles<\/a><\/strong><\/td>\n<td style=\"text-align: left;\">To set up a shared key using the Customer Area you must have the following user role: <ul><li>Merchant POS Terminal Management Admin role\/li&gt;<\/ul><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>How it works<\/h2>\n<p>With local communications, your POS system sends an API request over the local network to the IP address of the payment terminal. When the shopper completes the transaction on the terminal, the terminal routes the request to the Adyen payments platform for processing. Optionally you can set up display notifications to inform your staff on the progress of the transaction and the result. You receive the API response  synchronously.<\/p>\n<p><img alt=\"\" src=\"\/user\/pages\/docs\/03.point-of-sale\/04.design-your-integration\/06.choose-your-architecture\/01.local\/local_flow.png\" \/><\/p>\n<p>To build a local integration, you need to:<\/p>\n<ol>\n<li><a href=\"#configure-network\">Configure your network<\/a>. To allow outgoing HTTPS traffic, you need to add Adyen domains to your firewall's allowlist, and you need to open certain network ports.<\/li>\n<li><a href=\"#install-library\">Optionally install an API library<\/a>. This step can save you development time.<\/li>\n<li><a href=\"#protect-communications\">Protect local communications<\/a>. This step involves validating the terminal certificate against the Adyen root certificate, and adding code to encrypt API requests and decrypt API responses.<\/li>\n<li><a href=\"#build-payment-flow\">Build the payment flow<\/a>. For example, ensure your POS app can send Terminal API payment requests and other requests, and receive the synchronous response.<\/li>\n<li>Learn how to <a href=\"#handle-network-issues\">handle network issues<\/a>.<\/li>\n<\/ol>\n<h2 id=\"configure-network\">1. Configure your network<\/h2>\n<p>To enable your POS app to connect directly to the terminal:<\/p>\n<ol>\n<li>\n<p>Add Adyen's domains to your firewall's allowlist.<br \/>\nConfigure your firewall to allow outgoing HTTPS traffic from the IP addresses of your POS apps and terminals to:<\/p>\n<ul>\n<li><code>*.adyen.com<\/code><\/li>\n<li><code>*.adyenpayments.com<\/code><\/li>\n<\/ul>\n<p>Allowlisting should be based on the DNS name of these URLs. Your firewall should dynamically check for IP address updates, at least every 60 seconds.<\/p>\n<div class=\"notices red\">\n<p>Do not hard-code Adyen's IP addresses, because these can change over time. We do not share a list of our IP addresses publicly.<\/p>\n<\/div>\n<\/li>\n<li>\n<p>Open the ports:<\/p>\n<ul>\n<li><strong>tcp\/443<\/strong> to the internet.<\/li>\n<li><strong>tcp\/8443<\/strong> on your LAN.<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Use the correct <a href=\"\/point-of-sale\/design-your-integration\/network-and-connectivity\/network-configuration#communications-security\">Transport Layer Security (TLS) version and ciphers<\/a>.<\/p>\n<\/li>\n<li>\n<p>To <a href=\"\/point-of-sale\/design-your-integration\/network-and-connectivity\/network-configuration#configuring-the-terminal-IP-address\">assign IP addresses to your terminals<\/a>, use DHC reservation (recommended), or manually configure static IP addresses. Optionally you can get notified about changes in terminal IP addresses.<\/p>\n<\/li>\n<\/ol>\n<p>For more information and recommendations, see <a href=\"\/point-of-sale\/design-your-integration\/network-and-connectivity\">Network and connectivity<\/a>.<\/p>\n<h2 id=\"install-library\">2. (Optional) Install an API library<\/h2>\n<p>On our <a href=\"https:\/\/github.com\/adyen\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">GitHub<\/a>, we provide server-side API libraries in several languages. Installing a GitHub library is not required, but can save you development time. The libraries include all Terminal API models so you can use these to create requests. Most libraries also send requests to Adyen using a built-in HTTP client, construct the correct test and live endpoints, and help to <a href=\"#protect-communications\">protect local communications<\/a>.<\/p>\n<p>The following Adyen GitHub libraries are available for a local Terminal API integration:<\/p>\n<ul>\n<li>.NET - <a href=\"https:\/\/github.com\/Adyen\/adyen-dotnet-api-library\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">adyen-dotnet-api-library<\/a><\/li>\n<li>iOS - <a href=\"https:\/\/github.com\/Adyen\/adyen-terminal-api-ios\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">adyen-terminal-api-ios<\/a><\/li>\n<li>Java - <a href=\"https:\/\/github.com\/Adyen\/adyen-java-api-library\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">adyen-java-api-library<\/a><\/li>\n<li>Node - <a href=\"https:\/\/github.com\/Adyen\/adyen-node-api-library\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">adyen-node-api-library<\/a><\/li>\n<\/ul>\n<div class=\"sc-notice warning\"><div>\n<p>These GitHub libraries work with Terminal API and are completely separate from the <a href=\"\/point-of-sale\/classic-library-deprecation\">classic libraries, which have been deprecated<\/a>.<\/p>\n<\/div><\/div>\n<h2 id=\"protect-communications\">3. Protect local communications<\/h2>\n<div class=\"notices yellow\">\n<p>While you are building a <strong>test<\/strong> integration, we do not enforce this step. This allows you to develop the functional and security aspects in parallel. However, you will <strong>not be able to process live transactions<\/strong> until you have secured the requests between your POS app and your terminal.<\/p>\n<\/div>\n<p>If your integration uses local communications, you need to protect your integration against <a href=\"https:\/\/en.wikipedia.org\/wiki\/Man-in-the-middle_attack\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">man-in-the-middle attacks<\/a>, eavesdropping, and tampering. The steps you need to take are:<\/p>\n<ol>\n<li><a href=\"#install-root-cert\">Install Adyen's root certificate<\/a>.<\/li>\n<li><a href=\"#set-up-shared-key\">Set up a shared key<\/a>.<\/li>\n<li><a href=\"#add-code\">Add code<\/a> to validate the terminal certificate against the root certificate and encrypt communications using the shared key.<\/li>\n<\/ol>\n<h3 id=\"install-root-cert\">Install Adyen's root certificate<\/h3>\n<p>The root certificate contains information about Adyen's public key, which is used to sign other certificates such as the certificate on the terminal. To verify the certificate on the terminal against the public key, you have to add Adyen's root certificate to a trust store that is available to your POS app.<\/p>\n<p>The instructions differ depending on the operating system. Select one of the tabs below.<\/p>\n\n<div id=\"tabIyOmp\">\n    <div data-component-wrapper=\"tabs\">\n        <tabs\n                        :items=\"[{&quot;title&quot;:&quot;General instructions&quot;,&quot;content&quot;:&quot;\\n&lt;ol&gt;\\n&lt;li&gt;\\n&lt;p&gt;Download the Adyen public root certificates:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;&lt;a href=\\&quot;\\\/point-of-sale\\\/design-your-integration\\\/choose-your-architecture\\\/local\\\/adyen-terminalfleet-test.pem\\&quot;&gt;\\n  &lt;code&gt;adyen-terminalfleet-test.pem&lt;\\\/code&gt;\\n&lt;\\\/a&gt;. This is the test root certificate for validating the certificate on &lt;strong&gt;test&lt;\\\/strong&gt; terminals.&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;&lt;a href=\\&quot;\\\/point-of-sale\\\/design-your-integration\\\/choose-your-architecture\\\/local\\\/adyen-terminalfleet-live.pem\\&quot;&gt;\\n  &lt;code&gt;adyen-terminalfleet-live.pem&lt;\\\/code&gt;\\n&lt;\\\/a&gt;. This is the live root certificate for validating the certificate on &lt;strong&gt;live&lt;\\\/strong&gt; terminals.&lt;\\\/p&gt;\\n&lt;!-- list separator --&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;p&gt;If your system requires another format, such as &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;.crt&lt;\\\/strong&gt;&lt;\\\/span&gt; or &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;.cer&lt;\\\/strong&gt;&lt;\\\/span&gt;, you can use OpenSSL commands to convert the certificates. For example:&lt;\\\/p&gt;\\n&lt;pre&gt;&lt;code class=\\&quot;language-bash\\&quot;&gt;openssl x509 -outform der -in adyen-terminalfleet-test.pem -out adyen-terminalfleet-test.crt&lt;\\\/code&gt;&lt;\\\/pre&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Verify that the &lt;strong&gt;SHA-256 fingerprint&lt;\\\/strong&gt; (also called thumbprint) of the root certificates matches the following:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;&lt;strong&gt;Test&lt;\\\/strong&gt; root certificate: &lt;code&gt;3A 33 C3 34 C3 0F 69 46 E9 75 4B 6B B1 67 2B 54 6F BA A9 66 FB 6A 4B 58 AA 4E 3A BE 80 A7 EC BE&lt;\\\/code&gt;&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;&lt;strong&gt;Live&lt;\\\/strong&gt; root certificate: &lt;code&gt;06 D4 86 41 95 4B 95 7D 7A F5 F5 E4 5A 58 D8 61 DB 0D E3 CC ED BB 98 36 60 BB 01 6C E6 14 2D A1&lt;\\\/code&gt;&lt;\\\/p&gt;\\n&lt;!-- list separator --&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;p&gt;To get the SHA-256 fingerprint, you can use the following OpenSSL command:&lt;\\\/p&gt;\\n&lt;div data-component-wrapper=\\&quot;code-sample\\&quot;&gt;\\n&lt;code-sample :title=\\&quot;&#039;.pem files&#039;\\&quot; :id=\\&quot;&#039;&#039;\\&quot; :code-data=&#039;[{\\&quot;language\\&quot;:\\&quot;bash\\&quot;,\\&quot;tabTitle\\&quot;:\\&quot;\\&quot;,\\&quot;content\\&quot;:\\&quot;openssl x509 -in adyen-terminalfleet-test.pem -noout -sha256 -fingerprint\\&quot;}]&#039; :enable-copy-link-to-code-block=\\&quot;true\\&quot; :code-sample-card-size=\\&quot;&#039;fullsize&#039;\\&quot;&gt;&lt;\\\/code-sample&gt;\\n&lt;\\\/div&gt;\\n&lt;p&gt;&lt;\\\/p&gt;\\n&lt;div data-component-wrapper=\\&quot;code-sample\\&quot;&gt;\\n&lt;code-sample :title=\\&quot;&#039;.crt or .cer files&#039;\\&quot; :id=\\&quot;&#039;&#039;\\&quot; :code-data=&#039;[{\\&quot;language\\&quot;:\\&quot;bash\\&quot;,\\&quot;tabTitle\\&quot;:\\&quot;\\&quot;,\\&quot;content\\&quot;:\\&quot;openssl x509 -inform der -in adyen-terminalfleet-test.crt -noout -sha256 -fingerprint\\&quot;}]&#039; :enable-copy-link-to-code-block=\\&quot;true\\&quot; :code-sample-card-size=\\&quot;&#039;fullsize&#039;\\&quot;&gt;&lt;\\\/code-sample&gt;\\n&lt;\\\/div&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Install the Adyen root certificates in the trust store of your POS app, following your vendor&#039;s instructions.&lt;\\\/p&gt;\\n&lt;p&gt;You can add root certificates to the user or system trust store. At the user level, it is easier to import a certificate.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ol&gt;\\n&quot;,&quot;altTitle&quot;:null,&quot;oldTabId&quot;:1,&quot;relation&quot;:&quot;&quot;},{&quot;title&quot;:&quot;Windows&quot;,&quot;content&quot;:&quot;\\n&lt;ol&gt;\\n&lt;li&gt;\\n&lt;p&gt;Click the following links to download the Adyen public root certificates:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;&lt;a href=\\&quot;\\\/point-of-sale\\\/design-your-integration\\\/choose-your-architecture\\\/local\\\/adyen-terminalfleet-test.pem\\&quot;&gt;\\n  &lt;code&gt;adyen-terminalfleet-test.pem&lt;\\\/code&gt;\\n&lt;\\\/a&gt;. This is the test root certificate for validating the certificate on &lt;strong&gt;test&lt;\\\/strong&gt; terminals.&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;&lt;a href=\\&quot;\\\/point-of-sale\\\/design-your-integration\\\/choose-your-architecture\\\/local\\\/adyen-terminalfleet-live.pem\\&quot;&gt;\\n  &lt;code&gt;adyen-terminalfleet-live.pem&lt;\\\/code&gt;\\n&lt;\\\/a&gt;. This is the live root certificate for validating the certificate on &lt;strong&gt;live&lt;\\\/strong&gt; terminals.&lt;\\\/p&gt;\\n&lt;!-- list separator --&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;In the Microsoft Management Console (MMC), add the Certificates snap-in:&lt;\\\/p&gt;\\n&lt;ol&gt;\\n&lt;li&gt;In the &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Run&lt;\\\/strong&gt;&lt;\\\/span&gt; window, enter &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;mmc&lt;\\\/strong&gt;&lt;\\\/span&gt;.&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Select &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;File&lt;\\\/strong&gt;&lt;\\\/span&gt; &amp;gt; &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Add\\\/Remove Snap-in&lt;\\\/strong&gt;&lt;\\\/span&gt; and add the &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Certificates&lt;\\\/strong&gt;&lt;\\\/span&gt; snap-in to your user or computer trust store (referred to as &lt;em&gt;account&lt;\\\/em&gt;).&lt;\\\/p&gt;\\n&lt;!-- list separator --&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ol&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Go to &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Certificates&lt;\\\/strong&gt;&lt;\\\/span&gt; &amp;gt; &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Trusted Root Certification Authorities&lt;\\\/strong&gt;&lt;\\\/span&gt; &amp;gt; &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Certificates&lt;\\\/strong&gt;&lt;\\\/span&gt;.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Import the Adyen root certificate into the &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Trusted Root Certification Authorities&lt;\\\/strong&gt;&lt;\\\/span&gt; trust store:&lt;br \\\/&gt;\\nSelect &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Action&lt;\\\/strong&gt;&lt;\\\/span&gt; &amp;gt; &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;All tasks&lt;\\\/strong&gt;&lt;\\\/span&gt; &amp;gt; &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Import&lt;\\\/strong&gt;&lt;\\\/span&gt;, select the Adyen root certificate, and complete the wizard steps.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Double-click the imported root certificate and on the &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Details&lt;\\\/strong&gt;&lt;\\\/span&gt; tab verify that the &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Thumbprint&lt;\\\/strong&gt;&lt;\\\/span&gt; matches the following &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;SHA-1&lt;\\\/strong&gt;&lt;\\\/span&gt; fingerprint:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;&lt;strong&gt;Test&lt;\\\/strong&gt; root certificate: &lt;code&gt;D5 02 7F A8 B3 93 96 DB 2A 4F B1 86 EF 61 E4 A4 40 A7 30 51&lt;\\\/code&gt;&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;&lt;strong&gt;Live&lt;\\\/strong&gt; root certificate: &lt;code&gt;62 61 0D 88 27 8E 95 B7 F8 57 9A 9B 5E 07 85 D7 72 87 66 42&lt;\\\/code&gt;&lt;\\\/p&gt;\\n&lt;!-- list separator --&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;To verify that the root certificate is installed, in the &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Run&lt;\\\/strong&gt;&lt;\\\/span&gt; window open &lt;code&gt;certmgr.msc&lt;\\\/code&gt; for a user trust store or &lt;code&gt;certlm.msc&lt;\\\/code&gt; for a system trust store and check that the Adyen root certificate is listed under &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Trusted Root Certification Authorities&lt;\\\/strong&gt;&lt;\\\/span&gt; -&amp;gt; &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;Certificates&lt;\\\/strong&gt;&lt;\\\/span&gt;.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ol&gt;\\n&lt;p&gt;Apart from using the &lt;a href=\\&quot;https:\\\/\\\/docs.microsoft.com\\\/en-us\\\/dotnet\\\/framework\\\/wcf\\\/feature-details\\\/how-to-view-certificates-with-the-mmc-snap-in\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot; class=\\&quot;external-link no-image\\&quot;&gt;MMC Certificates snap-in&lt;\\\/a&gt; as described above, you could also use &lt;a href=\\&quot;https:\\\/\\\/docs.microsoft.com\\\/en-us\\\/powershell\\\/module\\\/pki\\\/import-certificate?view=windowsserver2019-ps\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot; class=\\&quot;external-link no-image\\&quot;&gt;PowerShell&lt;\\\/a&gt; to import the root certificates.&lt;\\\/p&gt;\\n&quot;,&quot;altTitle&quot;:null,&quot;oldTabId&quot;:1,&quot;relation&quot;:&quot;&quot;},{&quot;title&quot;:&quot;iOS&quot;,&quot;content&quot;:&quot;\\n&lt;ol&gt;\\n&lt;li&gt;\\n&lt;p&gt;Use the following links to download the Adyen public root certificates from our documentation website:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;&lt;a href=\\&quot;\\\/point-of-sale\\\/design-your-integration\\\/choose-your-architecture\\\/local\\\/adyen-terminalfleet-test.pem\\&quot;&gt;\\n  &lt;code&gt;adyen-terminalfleet-test.pem&lt;\\\/code&gt;\\n&lt;\\\/a&gt;. This is the test root certificate for validating the certificate on &lt;strong&gt;test&lt;\\\/strong&gt; terminals.&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;&lt;a href=\\&quot;\\\/point-of-sale\\\/design-your-integration\\\/choose-your-architecture\\\/local\\\/adyen-terminalfleet-live.pem\\&quot;&gt;\\n  &lt;code&gt;adyen-terminalfleet-live.pem&lt;\\\/code&gt;\\n&lt;\\\/a&gt;. This is the live root certificate for validating the certificate on &lt;strong&gt;live&lt;\\\/strong&gt; terminals.&lt;\\\/p&gt;\\n&lt;!-- list separator --&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Use the following OpenSSL command to convert the certificates to &lt;span translate=\\&quot;no\\&quot;&gt;&lt;strong&gt;.crt&lt;\\\/strong&gt;&lt;\\\/span&gt; format:&lt;\\\/p&gt;\\n&lt;pre&gt;&lt;code class=\\&quot;language-bash\\&quot;&gt;openssl x509 -outform der -in adyen-terminalfleet-test.pem -out adyen-terminalfleet-test.crt&lt;\\\/code&gt;&lt;\\\/pre&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Add the Adyen public root certificate to the app bundle.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Add the following to your implementation of &lt;code&gt;URLSessionDelegate&lt;\\\/code&gt; that handles the communication with the payment terminals.&lt;\\\/p&gt;\\n&lt;pre&gt;&lt;code class=\\&quot;language-swift\\&quot;&gt;class MyURLSessionDelegate: NSObject, URLSessionDelegate {\\n    func urlSession(\\n        _ session: URLSession,\\n        didReceive challenge: URLAuthenticationChallenge,\\n        completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -&amp;gt; Void\\n    ) {\\n        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {\\n            if let certFile = Bundle.main.path(forResource: \\&quot;adyen-terminalfleet-test\\&quot;, ofType: \\&quot;crt\\&quot;),\\n               let data = try? Data(contentsOf: URL(fileURLWithPath: certFile)),\\n               let cert = SecCertificateCreateWithData(nil, data as CFData),\\n               let trust = challenge.protectionSpace.serverTrust {\\n                SecTrustSetAnchorCertificates(trust, [cert] as CFArray)\\n                SecTrustSetAnchorCertificatesOnly(trust, true)\\n                var error: CFError?\\n                if SecTrustEvaluateWithError(trust, &amp;amp;error) {\\n                    completionHandler(.useCredential, URLCredential(trust: trust))\\n                } else {\\n                    completionHandler(.cancelAuthenticationChallenge, nil)\\n                }\\n            } else {\\n                completionHandler(.cancelAuthenticationChallenge, nil)\\n            }\\n        } else {\\n            completionHandler(.performDefaultHandling, nil)\\n        }\\n    }\\n}&lt;\\\/code&gt;&lt;\\\/pre&gt;\\n&quot;,&quot;altTitle&quot;:null,&quot;oldTabId&quot;:1,&quot;relation&quot;:&quot;&quot;}]\"\n            :should-update-when-url-changes='false'>\n        <\/tabs>\n    <\/div>\n<\/div>\n\n<\/li>\n<\/ol>\n<h3 id=\"set-up-shared-key\">Set up a shared key<\/h3>\n<p>To prevent others from being able to read messages sent between your POS app and the payment terminal, you need to encrypt the communications. For that, you first need to create a key passphrase and share it with Adyen. Both your code (or the Adyen GitHub library you are using) and the terminal will apply a key derivation function to the passphrase, and use the resulting key material to encrypt communications.<\/p>\n<p>You can create a shared key manually in your Customer Area or with an API call. For both options, you can set up the shared key at the company, merchant, store, or terminal level. If your use case does not require a specific level, we recommend setting up a shared key at the highest possible level. For more information, see <a href=\"\/point-of-sale\/design-your-integration\/determine-account-structure\/configure-features#settings-at-different-levels\">Settings at different levels<\/a> and <a href=\"\/point-of-sale\/automating-terminal-management\/configure-terminals-api#inheritance\">Inheritance of settings<\/a>.<\/p>\n\n<div id=\"tabHLElT\">\n    <div data-component-wrapper=\"tabs\">\n        <tabs\n                        :items=\"[{&quot;title&quot;:&quot;Create a shared key in the Customer Area&quot;,&quot;content&quot;:&quot;\\n&lt;ol&gt;\\n&lt;li&gt;\\n&lt;p&gt;Log in to your &lt;a href=\\&quot;https:\\\/\\\/ca-test.adyen.com\\\/\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot; class=\\&quot;external-link no-image\\&quot;&gt;Customer Area&lt;\\\/a&gt;.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Go to the account level that you want to set up a shared key for.&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;For a company or merchant account, select the account and go to &lt;strong&gt;In-person payments&lt;\\\/strong&gt; &amp;gt; &lt;strong&gt;Terminal settings&lt;\\\/strong&gt;.&lt;\\\/li&gt;\\n&lt;li&gt;For a store, go to &lt;strong&gt;In-person payments&lt;\\\/strong&gt; &amp;gt; &lt;strong&gt;Stores&lt;\\\/strong&gt; and select the store.&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;For a terminal,  go to &lt;strong&gt;In-person payments&lt;\\\/strong&gt; &amp;gt; &lt;strong&gt;Payment devices&lt;\\\/strong&gt;, select the &lt;strong&gt;Terminals&lt;\\\/strong&gt; tab, and then select your terminal.&lt;\\\/p&gt;\\n&lt;!-- list separator --&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;On the &lt;strong&gt;Settings&lt;\\\/strong&gt; page, select &lt;strong&gt;Integrations&lt;\\\/strong&gt;.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Under &lt;strong&gt;Encryption key&lt;\\\/strong&gt;, select &lt;strong&gt;Decrypted&lt;\\\/strong&gt; and then complete the fields:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;&lt;strong&gt;Key identifier&lt;\\\/strong&gt;: a description to recognize the key by.&lt;\\\/li&gt;\\n&lt;li&gt;&lt;strong&gt;Key passphrase&lt;\\\/strong&gt;: a string of random characters that must consist of:\\n&lt;ul&gt;\\n&lt;li&gt;At least 12 characters.&lt;\\\/li&gt;\\n&lt;li&gt;At least 1 uppercase letter: &lt;code&gt;[A-Z]&lt;\\\/code&gt;.&lt;\\\/li&gt;\\n&lt;li&gt;At least 1 lowercase letter: &lt;code&gt;[a-z]&lt;\\\/code&gt;.&lt;\\\/li&gt;\\n&lt;li&gt;At least 1 digit: &lt;code&gt;[0-9]&lt;\\\/code&gt;.&lt;\\\/li&gt;\\n&lt;li&gt;At least 1 special character. Limited to the following: &lt;code&gt;~&lt;\\\/code&gt;, &lt;code&gt;!&lt;\\\/code&gt;, &lt;code&gt;@&lt;\\\/code&gt;, &lt;code&gt;#&lt;\\\/code&gt;, &lt;code&gt;$&lt;\\\/code&gt;, &lt;code&gt;%&lt;\\\/code&gt;, &lt;code&gt;^&lt;\\\/code&gt;, &lt;code&gt;&amp;amp;&lt;\\\/code&gt;, &lt;code&gt;*&lt;\\\/code&gt;, &lt;code&gt;(&lt;\\\/code&gt;, &lt;code&gt;)&lt;\\\/code&gt;, &lt;code&gt;_&lt;\\\/code&gt;, &lt;code&gt;+&lt;\\\/code&gt;, &lt;code&gt;=&lt;\\\/code&gt;, &lt;code&gt;}&lt;\\\/code&gt;, &lt;code&gt;{&lt;\\\/code&gt;, &lt;code&gt;]&lt;\\\/code&gt;, &lt;code&gt;[&lt;\\\/code&gt;, &lt;code&gt;;&lt;\\\/code&gt;, &lt;code&gt;:&lt;\\\/code&gt;, &lt;code&gt;?&lt;\\\/code&gt;, &lt;code&gt;.&lt;\\\/code&gt;, &lt;code&gt;,&lt;\\\/code&gt;, &lt;code&gt;&amp;gt;&lt;\\\/code&gt;, &lt;code&gt;&amp;lt;&lt;\\\/code&gt;.&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;&lt;\\\/li&gt;\\n&lt;li&gt;&lt;strong&gt;Key version&lt;\\\/strong&gt;: the version number of the key. For example, &lt;strong&gt;1&lt;\\\/strong&gt;.&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;div class=\\&quot;sc-notice info\\&quot;&gt;&lt;div&gt;\\n&lt;p&gt;If this section is not visible or if you cannot edit the fields, ask our &lt;a href=\\&quot;https:\\\/\\\/ca-test.adyen.com\\\/ca\\\/ca\\\/contactUs\\\/support.shtml?form=other\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot; class=\\&quot;external-link no-image\\&quot;&gt;Support Team&lt;\\\/a&gt; to set the required permission for your user.&lt;\\\/p&gt;\\n&lt;\\\/div&gt;&lt;\\\/div&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Select &lt;strong&gt;Save&lt;\\\/strong&gt;.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;Securely store the key identifier, passphrase, and version in your system.&lt;\\\/p&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ol&gt;\\n&lt;h4&gt;Look up your shared key&lt;\\\/h4&gt;\\n&lt;p&gt;You can later look up the details of the shared key that was created:&lt;\\\/p&gt;\\n&lt;ol&gt;\\n&lt;li&gt;In your &lt;a href=\\&quot;https:\\\/\\\/ca-test.adyen.com\\\/\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot; class=\\&quot;external-link no-image\\&quot;&gt;Customer Area&lt;\\\/a&gt;, under &lt;strong&gt;In-person payments&lt;\\\/strong&gt;, go to the &lt;strong&gt;Terminal settings&lt;\\\/strong&gt; for your company, merchant account, or store.&lt;\\\/li&gt;\\n&lt;li&gt;Select &lt;strong&gt;Integrations&lt;\\\/strong&gt; and under &lt;strong&gt;Terminal API&lt;\\\/strong&gt; go to &lt;strong&gt;Encryption key&lt;\\\/strong&gt;.&lt;\\\/li&gt;\\n&lt;li&gt;To see the key identifier, passphrase, and version values, select &lt;strong&gt;Decrypted&lt;\\\/strong&gt;.&lt;\\\/li&gt;\\n&lt;\\\/ol&gt;\\n&quot;,&quot;altTitle&quot;:null,&quot;oldTabId&quot;:1,&quot;relation&quot;:&quot;&quot;},{&quot;title&quot;:&quot;Create a shared key with an API call&quot;,&quot;content&quot;:&quot;\\n&lt;p&gt;To create a shared key:&lt;\\\/p&gt;\\n&lt;ol&gt;\\n&lt;li&gt;\\n&lt;p&gt;Use one of the following endpoints:&lt;\\\/p&gt;\\n&lt;ul&gt;\\n&lt;li&gt;PATCH  &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/patch\\\/companies\\\/(companyId)\\\/terminalSettings\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;\\\/companies\\\/{companyId}\\\/terminalSettings&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;li&gt;PATCH  &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/patch\\\/merchants\\\/(merchantId)\\\/terminalSettings\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;\\\/merchants\\\/{merchantId}\\\/terminalSettings&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;li&gt;PATCH  &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/patch\\\/stores\\\/(storeId)\\\/terminalSettings\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;\\\/stores\\\/{storeId}\\\/terminalSettings&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;li&gt;PATCH  &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/patch\\\/terminals\\\/(terminalId)\\\/terminalSettings\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;\\\/terminals\\\/{terminalId}\\\/terminalSettings&lt;\\\/a&gt;&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;\\n&lt;p&gt;Specify a  &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/patch\\\/companies\\\/(companyId)\\\/terminalSettings#request-nexo\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;nexo&lt;\\\/a&gt; object with the following properties:&lt;\\\/p&gt;\\n&lt;table&gt;\\n&lt;thead&gt;\\n&lt;tr&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Parameter&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Required&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Type&lt;\\\/th&gt;\\n&lt;th style=\\&quot;text-align: left;\\&quot;&gt;Description&lt;\\\/th&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/thead&gt;\\n&lt;tbody&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt; &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/patch\\\/companies\\\/(companyId)\\\/terminalSettings#request-nexo-encryptionKey-identifier\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;identifier&lt;\\\/a&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;string&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The unique identifier of the shared key.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt; &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/patch\\\/companies\\\/(companyId)\\\/terminalSettings#request-nexo-encryptionKey-passphrase\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;passphrase&lt;\\\/a&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;string&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The secure passphrase to protect the shared key. Must consist of: &lt;ul&gt;&lt;li markdown=\\&quot;1\\&quot;&gt;At least 12 characters.&lt;\\\/li&gt;&lt;li markdown=\\&quot;1\\&quot;&gt;At least 1 uppercase letter: &lt;code&gt;[A-Z]&lt;\\\/code&gt;.&lt;\\\/li&gt;&lt;li markdown=\\&quot;1\\&quot;&gt;At least 1 lowercase letter: &lt;code&gt;[a-z]&lt;\\\/code&gt;.&lt;\\\/li&gt;&lt;li markdown=\\&quot;1\\&quot;&gt;At least 1 digit: &lt;code&gt;[0-9]&lt;\\\/code&gt;.&lt;\\\/li&gt;&lt;li markdown=\\&quot;1\\&quot;&gt;At least 1 special character. Limited to the following: &lt;code&gt;~&lt;\\\/code&gt;, &lt;code&gt;!&lt;\\\/code&gt;, &lt;code&gt;@&lt;\\\/code&gt;, &lt;code&gt;#&lt;\\\/code&gt;, &lt;code&gt;$&lt;\\\/code&gt;, &lt;code&gt;%&lt;\\\/code&gt;, &lt;code&gt;^&lt;\\\/code&gt;, &lt;code&gt;&amp;amp;&lt;\\\/code&gt;, &lt;code&gt;*&lt;\\\/code&gt;, &lt;code&gt;(&lt;\\\/code&gt;, &lt;code&gt;)&lt;\\\/code&gt;, &lt;code&gt;_&lt;\\\/code&gt;, &lt;code&gt;+&lt;\\\/code&gt;, &lt;code&gt;=&lt;\\\/code&gt;, &lt;code&gt;}&lt;\\\/code&gt;, &lt;code&gt;{&lt;\\\/code&gt;, &lt;code&gt;]&lt;\\\/code&gt;, &lt;code&gt;[&lt;\\\/code&gt;, &lt;code&gt;;&lt;\\\/code&gt;, &lt;code&gt;:&lt;\\\/code&gt;, &lt;code&gt;?&lt;\\\/code&gt;, &lt;code&gt;.&lt;\\\/code&gt;, &lt;code&gt;,&lt;\\\/code&gt;, &lt;code&gt;&amp;gt;&lt;\\\/code&gt;, &lt;code&gt;&amp;lt;&lt;\\\/code&gt;.&lt;\\\/li&gt;&lt;\\\/ul&gt;&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;tr&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt; &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/patch\\\/companies\\\/(companyId)\\\/terminalSettings#request-nexo-encryptionKey-version\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;version&lt;\\\/a&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;&lt;img title=\\&quot;-white_check_mark-\\&quot; alt=\\&quot;-white_check_mark-\\&quot; class=\\&quot;smileys\\&quot; src=\\&quot;\\\/user\\\/data\\\/smileys\\\/emoji\\\/white_check_mark.png\\&quot; \\\/&gt;&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;integer&lt;\\\/td&gt;\\n&lt;td style=\\&quot;text-align: left;\\&quot;&gt;The version number of the shared key. For example, &lt;strong&gt;1&lt;\\\/strong&gt;.&lt;\\\/td&gt;\\n&lt;\\\/tr&gt;\\n&lt;\\\/tbody&gt;\\n&lt;\\\/table&gt;\\n&lt;div data-component-wrapper=\\&quot;code-sample\\&quot;&gt;\\n&lt;code-sample :title=\\&quot;&#039;\\\/terminalSettings\\\/encryptionKey request&#039;\\&quot; :id=\\&quot;&#039;terminalsettings-encryptionkey-request-2253072399&#039;\\&quot; :code-data=\\&quot;[{&amp;quot;language&amp;quot;:&amp;quot;bash&amp;quot;,&amp;quot;tabTitle&amp;quot;:&amp;quot;curl&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;curl https:\\\\\\\/\\\\\\\/management-test.adyen.com\\\\\\\/v3\\\\\\\/companies\\\\\\\/{companyId}\\\\\\\/terminalSettings \\\\\\\\\\\\n    -H &#039;x-API-key: ADYEN_API_KEY&#039; \\\\\\\\\\\\n    -X PATCH \\\\\\\\\\\\n    -d &#039;{\\\\n         \\\\&amp;quot;nexo\\\\&amp;quot;: {\\\\n             \\\\&amp;quot;encryptionKey\\\\&amp;quot; : {\\\\n                 \\\\&amp;quot;identifier\\\\&amp;quot;: \\\\&amp;quot;KEY_IDENTIFIER\\\\&amp;quot;,\\\\n                 \\\\&amp;quot;passphrase\\\\&amp;quot;: \\\\&amp;quot;KEY_PASSPHRASE\\\\&amp;quot;,\\\\n                 \\\\&amp;quot;version\\\\&amp;quot;: 1\\\\n             }\\\\n         }\\\\n       }&#039;&amp;quot;},{&amp;quot;language&amp;quot;:&amp;quot;java&amp;quot;,&amp;quot;tabTitle&amp;quot;:&amp;quot;Java&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;\\\\\\\/\\\\\\\/ Adyen Java API Library v25.0.0\\\\nimport com.adyen.Client;\\\\nimport com.adyen.enums.Environment;\\\\nimport com.adyen.model.management.*;\\\\nimport java.time.OffsetDateTime;\\\\nimport java.util.*;\\\\nimport com.adyen.service.management.*;\\\\n\\\\nClient client = new Client(\\\\&amp;quot;ADYEN_API_KEY\\\\&amp;quot;, Environment.TEST);\\\\n\\\\n\\\\\\\/\\\\\\\/ Request objects\\\\nKey key = new Key()\\\\n\\\\t.identifier(\\\\&amp;quot;KEY_IDENTIFIER\\\\&amp;quot;)\\\\n\\\\t.passphrase(\\\\&amp;quot;KEY_PASSPHRASE\\\\&amp;quot;)\\\\n\\\\t.version(1);\\\\n\\\\nNexo nexo = new Nexo()\\\\n\\\\t.encryptionKey(key);\\\\n\\\\nTerminalSettings terminalSettings = new TerminalSettings()\\\\n\\\\t.nexo(nexo);\\\\n\\\\n\\\\\\\/\\\\\\\/ Make the request\\\\nTerminalSettingsCompanyLevelApi service = new TerminalSettingsCompanyLevelApi(client);\\\\nTerminalSettings response = service.updateTerminalSettings(\\\\&amp;quot;companyId\\\\&amp;quot;, terminalSettings, null);&amp;quot;},{&amp;quot;language&amp;quot;:&amp;quot;php&amp;quot;,&amp;quot;tabTitle&amp;quot;:&amp;quot;PHP&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;\\\\\\\/\\\\\\\/ Adyen PHP API Library v17.4.0\\\\nuse Adyen\\\\\\\\Client;\\\\nuse Adyen\\\\\\\\Environment;\\\\nuse Adyen\\\\\\\\Model\\\\\\\\Management\\\\\\\\Key;\\\\nuse Adyen\\\\\\\\Model\\\\\\\\Management\\\\\\\\Nexo;\\\\nuse Adyen\\\\\\\\Model\\\\\\\\Management\\\\\\\\TerminalSettings;\\\\nuse Adyen\\\\\\\\Service\\\\\\\\Management\\\\\\\\TerminalSettingsCompanyLevelApi;\\\\n\\\\n$client = new Client();\\\\n$client-&amp;gt;setXApiKey(\\\\&amp;quot;ADYEN_API_KEY\\\\&amp;quot;);\\\\n$client-&amp;gt;setEnvironment(Environment::TEST);\\\\n\\\\n\\\\n\\\\\\\/\\\\\\\/ Request objects\\\\n$key = new Key();\\\\n$key\\\\n\\\\t-&amp;gt;setIdentifier(\\\\&amp;quot;KEY_IDENTIFIER\\\\&amp;quot;)\\\\n\\\\t-&amp;gt;setPassphrase(\\\\&amp;quot;KEY_PASSPHRASE\\\\&amp;quot;)\\\\n\\\\t-&amp;gt;setVersion(1);\\\\n\\\\n$nexo = new Nexo();\\\\n$nexo\\\\n\\\\t-&amp;gt;setEncryptionKey($key);\\\\n\\\\n$terminalSettings = new TerminalSettings();\\\\n$terminalSettings\\\\n\\\\t-&amp;gt;setNexo($nexo);\\\\n\\\\n\\\\\\\/\\\\\\\/ Make the request\\\\n$service = new TerminalSettingsCompanyLevelApi($client);\\\\n$response = $service-&amp;gt;updateTerminalSettings(&#039;companyId&#039;, $terminalSettings);&amp;quot;},{&amp;quot;language&amp;quot;:&amp;quot;cs&amp;quot;,&amp;quot;tabTitle&amp;quot;:&amp;quot;C#&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;\\\\\\\/\\\\\\\/ Adyen .net API Library v14.3.0\\\\nusing Adyen;\\\\nusing Environment = Adyen.Model.Environment;\\\\nusing Adyen.Model;\\\\nusing Adyen.Model.Management;\\\\nusing Adyen.Service.Management;\\\\n\\\\nvar config = new Config()\\\\n{\\\\n    XApiKey = \\\\&amp;quot;ADYEN_API_KEY\\\\&amp;quot;,\\\\n    Environment = Environment.Test\\\\n};\\\\nvar client = new Client(config);\\\\n\\\\n\\\\\\\/\\\\\\\/ Fill in your request objects\\\\nKey key = new Key\\\\n{\\\\n\\\\tIdentifier = \\\\&amp;quot;KEY_IDENTIFIER\\\\&amp;quot;,\\\\n\\\\tPassphrase = \\\\&amp;quot;KEY_PASSPHRASE\\\\&amp;quot;,\\\\n\\\\tVersion = 1\\\\n};\\\\n\\\\nNexo nexo = new Nexo\\\\n{\\\\n\\\\tEncryptionKey = key\\\\n};\\\\n\\\\nTerminalSettings terminalSettings = new TerminalSettings\\\\n{\\\\n\\\\tNexo = nexo\\\\n};\\\\n\\\\n\\\\\\\/\\\\\\\/ Make the request\\\\nvar service = new TerminalSettingsCompanyLevelService(client);\\\\nvar response = service.UpdateTerminalSettings(\\\\&amp;quot;companyId\\\\&amp;quot;, terminalSettings);&amp;quot;},{&amp;quot;language&amp;quot;:&amp;quot;js&amp;quot;,&amp;quot;tabTitle&amp;quot;:&amp;quot;NodeJS (JavaScript)&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;\\\\\\\/\\\\\\\/ Adyen Node API Library v16.2.0\\\\n\\\\\\\/\\\\\\\/ Require the parts of the module you want to use\\\\nconst { Client, ManagementAPI } = require(&#039;@adyen\\\\\\\/api-library&#039;);\\\\n\\\\n\\\\\\\/\\\\\\\/ Initialize the client object\\\\nconst client = new Client({apiKey: \\\\&amp;quot;ADYEN_API_KEY\\\\&amp;quot;, environment: \\\\&amp;quot;TEST\\\\&amp;quot;});\\\\n\\\\n\\\\\\\/\\\\\\\/ Create the request object\\\\nconst terminalSettings = {\\\\n  nexo: {\\\\n    encryptionKey: {\\\\n      identifier: \\\\&amp;quot;KEY_IDENTIFIER\\\\&amp;quot;,\\\\n      passphrase: \\\\&amp;quot;KEY_PASSPHRASE\\\\&amp;quot;,\\\\n      version: 1\\\\n    }\\\\n  }\\\\n}\\\\n\\\\n\\\\\\\/\\\\\\\/ Make the request\\\\nconst managementAPI = new ManagementAPI(client);\\\\nconst response = managementAPI.TerminalSettingsCompanyLevelApi.updateTerminalSettings(\\\\&amp;quot;companyId\\\\&amp;quot;, terminalSettings);&amp;quot;},{&amp;quot;language&amp;quot;:&amp;quot;go&amp;quot;,&amp;quot;tabTitle&amp;quot;:&amp;quot;Go&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;\\\\\\\/\\\\\\\/ Adyen Go API Library v9.2.0\\\\nimport (\\\\n\\\\t\\\\&amp;quot;context\\\\&amp;quot;\\\\n\\\\t\\\\&amp;quot;github.com\\\\\\\/adyen\\\\\\\/adyen-go-api-library\\\\\\\/v9\\\\\\\/src\\\\\\\/common\\\\&amp;quot;\\\\n\\\\t\\\\&amp;quot;github.com\\\\\\\/adyen\\\\\\\/adyen-go-api-library\\\\\\\/v9\\\\\\\/src\\\\\\\/adyen\\\\&amp;quot;\\\\n\\\\t\\\\&amp;quot;github.com\\\\\\\/adyen\\\\\\\/adyen-go-api-library\\\\\\\/v9\\\\\\\/src\\\\\\\/management\\\\&amp;quot;\\\\n)\\\\n\\\\nclient := adyen.NewClient(&amp;amp;common.Config{\\\\n    ApiKey:      \\\\&amp;quot;ADYEN_API_KEY\\\\&amp;quot;,\\\\n    Environment: common.TestEnv,\\\\n})\\\\n\\\\n\\\\\\\/\\\\\\\/ Fill in your request objects\\\\nkey := management.Key{\\\\n\\\\tIdentifier: common.PtrString(\\\\&amp;quot;KEY_IDENTIFIER\\\\&amp;quot;),\\\\n\\\\tPassphrase: common.PtrString(\\\\&amp;quot;KEY_PASSPHRASE\\\\&amp;quot;),\\\\n\\\\tVersion: common.PtrInt32(1),\\\\n}\\\\n\\\\nnexo := management.Nexo{\\\\n\\\\tEncryptionKey: &amp;amp;key,\\\\n}\\\\n\\\\nterminalSettings := management.TerminalSettings{\\\\n\\\\tNexo: &amp;amp;nexo,\\\\n}\\\\n\\\\n\\\\\\\/\\\\\\\/ Make the request\\\\nservice := client.Management()\\\\nreq := service.TerminalSettingsCompanyLevelApi.UpdateTerminalSettingsInput(\\\\&amp;quot;companyId\\\\&amp;quot;).TerminalSettings(terminalSettings)\\\\nres, httpRes, err := service.TerminalSettingsCompanyLevelApi.UpdateTerminalSettings(context.Background(), req)&amp;quot;},{&amp;quot;language&amp;quot;:&amp;quot;py&amp;quot;,&amp;quot;tabTitle&amp;quot;:&amp;quot;Python&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;# Adyen Python API Library v12.2.0\\\\nimport Adyen\\\\n\\\\nadyen = Adyen.Adyen()\\\\nadyen.client.xapikey = \\\\&amp;quot;ADYEN_API_KEY\\\\&amp;quot;\\\\nadyen.client.platform = \\\\&amp;quot;test\\\\&amp;quot; # The environment to use library in.\\\\n\\\\njson_request = {\\\\n  \\\\&amp;quot;nexo\\\\&amp;quot;: {\\\\n    \\\\&amp;quot;encryptionKey\\\\&amp;quot;: {\\\\n      \\\\&amp;quot;identifier\\\\&amp;quot;: \\\\&amp;quot;KEY_IDENTIFIER\\\\&amp;quot;,\\\\n      \\\\&amp;quot;passphrase\\\\&amp;quot;: \\\\&amp;quot;KEY_PASSPHRASE\\\\&amp;quot;,\\\\n      \\\\&amp;quot;version\\\\&amp;quot;: 1\\\\n    }\\\\n  }\\\\n}\\\\n\\\\nresult = adyen.management.terminal_settings_company_level_api.update_terminal_settings(request=json_request, companyId=\\\\&amp;quot;companyId\\\\&amp;quot;)&amp;quot;},{&amp;quot;language&amp;quot;:&amp;quot;rb&amp;quot;,&amp;quot;tabTitle&amp;quot;:&amp;quot;Ruby&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;# Adyen Ruby API Library v9.2.0\\\\nrequire \\\\&amp;quot;adyen-ruby-api-library\\\\&amp;quot;\\\\n\\\\nadyen = Adyen::Client.new\\\\nadyen.api_key = &#039;ADYEN_API_KEY&#039;\\\\nadyen.env = :test # Set to \\\\&amp;quot;live\\\\&amp;quot; for live environment\\\\n\\\\nrequest_body = {\\\\n  :nexo =&amp;gt; {\\\\n    :encryptionKey =&amp;gt; {\\\\n      :identifier =&amp;gt; &#039;KEY_IDENTIFIER&#039;,\\\\n      :passphrase =&amp;gt; &#039;KEY_PASSPHRASE&#039;,\\\\n      :version =&amp;gt; 1\\\\n    }\\\\n  }\\\\n}\\\\n\\\\nresult = adyen.management.terminal_settings_company_level_api.update_terminal_settings(request_body, &#039;companyId&#039;)&amp;quot;},{&amp;quot;language&amp;quot;:&amp;quot;ts&amp;quot;,&amp;quot;tabTitle&amp;quot;:&amp;quot;NodeJS (TypeScript)&amp;quot;,&amp;quot;content&amp;quot;:&amp;quot;\\\\\\\/\\\\\\\/ Adyen Node API Library v16.2.0\\\\n\\\\\\\/\\\\\\\/ Require the parts of the module you want to use\\\\nimport { Client, ManagementAPI, Types } from \\\\&amp;quot;@adyen\\\\\\\/api-library\\\\&amp;quot;;\\\\n\\\\n\\\\\\\/\\\\\\\/ Initialize the client object\\\\nconst client = new Client({apiKey: \\\\&amp;quot;ADYEN_API_KEY\\\\&amp;quot;, environment: \\\\&amp;quot;TEST\\\\&amp;quot;});\\\\n\\\\n\\\\\\\/\\\\\\\/ Create the request objects\\\\nconst key: Types.management.Key = {\\\\n\\\\tidentifier: \\\\&amp;quot;KEY_IDENTIFIER\\\\&amp;quot;,\\\\n\\\\tpassphrase: \\\\&amp;quot;KEY_PASSPHRASE\\\\&amp;quot;,\\\\n\\\\tversion: 1\\\\n};\\\\n\\\\nconst nexo: Types.management.Nexo = {\\\\n\\\\tencryptionKey: key\\\\n};\\\\n\\\\nconst terminalSettings: Types.management.TerminalSettings = {\\\\n\\\\tnexo: nexo\\\\n};\\\\n\\\\n\\\\\\\/\\\\\\\/ Make the request\\\\nconst managementAPI = new ManagementAPI(client);\\\\nconst response = managementAPI.TerminalSettingsCompanyLevelApi.updateTerminalSettings(\\\\&amp;quot;companyId\\\\&amp;quot;, terminalSettings);&amp;quot;}]\\&quot; :enable-copy-link-to-code-block=\\&quot;true\\&quot; :code-sample-card-size=\\&quot;&#039;fullsize&#039;\\&quot;&gt;&lt;\\\/code-sample&gt;\\n&lt;\\\/div&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n&lt;p&gt;The response returns all settings that your API credential has access to, including the shared key that you defined in the request:&lt;\\\/p&gt;\\n&lt;div data-component-wrapper=\\&quot;code-sample\\&quot;&gt;\\n&lt;code-sample :title=\\&quot;&#039;\\\/terminalSettings\\\/encryptionKey response&#039;\\&quot; :id=\\&quot;&#039;&#039;\\&quot; :code-data=&#039;[{\\&quot;language\\&quot;:\\&quot;json\\&quot;,\\&quot;tabTitle\\&quot;:\\&quot;\\&quot;,\\&quot;content\\&quot;:\\&quot;{\\\\n    \\\\\\&quot;cardholderReceipt\\\\\\&quot;: {\\\\n        \\\\\\&quot;headerForAuthorizedReceipt\\\\\\&quot;: \\\\\\&quot;header1,header2,filler\\\\\\&quot;\\\\n    },\\\\n    \\\\\\&quot;gratuities\\\\\\&quot;: [\\\\n        {\\\\n            \\\\\\&quot;currency\\\\\\&quot;: \\\\\\&quot;EUR\\\\\\&quot;,\\\\n            \\\\\\&quot;usePredefinedTipEntries\\\\\\&quot;: true,\\\\n            \\\\\\&quot;predefinedTipEntries\\\\\\&quot;: [\\\\n                \\\\\\&quot;1000\\\\\\&quot;,\\\\n                \\\\\\&quot;20%\\\\\\&quot;\\\\n            ],\\\\n            \\\\\\&quot;allowCustomAmount\\\\\\&quot;: true\\\\n        }\\\\n    ],\\\\n    \\\\\\&quot;nexo\\\\\\&quot;: {\\\\n        \\\\\\&quot;encryptionKey\\\\\\&quot;: {\\\\n            \\\\\\&quot;identifier\\\\\\&quot;: \\\\\\&quot;KEY_IDENTIFIER\\\\\\&quot;,\\\\n            \\\\\\&quot;passphrase\\\\\\&quot;: \\\\\\&quot;KEY_PASSPHRASE\\\\\\&quot;,\\\\n            \\\\\\&quot;version\\\\\\&quot;: 1\\\\n        },\\\\n        \\\\\\&quot;eventUrls\\\\\\&quot;: {\\\\n            \\\\\\&quot;eventPublicUrls\\\\\\&quot;: [\\\\n                {\\\\n                    \\\\\\&quot;password\\\\\\&quot;: \\\\\\&quot;notification\\\\\\&quot;,\\\\n                    \\\\\\&quot;url\\\\\\&quot;: \\\\\\&quot;...\\\\\\&quot;,\\\\n                    \\\\\\&quot;username\\\\\\&quot;: \\\\\\&quot;adyen\\\\\\&quot;\\\\n                }\\\\n            ]\\\\n        },\\\\n        \\\\\\&quot;nexoEventUrls\\\\\\&quot;: [\\\\n            \\\\\\&quot;...\\\\\\&quot;\\\\n        ]\\\\n    },\\\\n    \\\\\\&quot;opi\\\\\\&quot;: {\\\\n        \\\\\\&quot;enablePayAtTable\\\\\\&quot;: false\\\\n    },\\\\n    \\\\\\&quot;receiptPrinting\\\\\\&quot;: {\\\\n        \\\\\\&quot;merchantApproved\\\\\\&quot;: true,\\\\n        \\\\\\&quot;merchantRefused\\\\\\&quot;: true,\\\\n        \\\\\\&quot;merchantCancelled\\\\\\&quot;: true,\\\\n        \\\\\\&quot;merchantRefundApproved\\\\\\&quot;: true,\\\\n        \\\\\\&quot;merchantRefundRefused\\\\\\&quot;: true,\\\\n        \\\\\\&quot;merchantVoid\\\\\\&quot;: true,\\\\n        \\\\\\&quot;shopperApproved\\\\\\&quot;: true,\\\\n        \\\\\\&quot;shopperRefused\\\\\\&quot;: true,\\\\n        \\\\\\&quot;shopperCancelled\\\\\\&quot;: true,\\\\n        \\\\\\&quot;shopperRefundApproved\\\\\\&quot;: true,\\\\n        \\\\\\&quot;shopperRefundRefused\\\\\\&quot;: true,\\\\n        \\\\\\&quot;shopperVoid\\\\\\&quot;: true\\\\n    },\\\\n    \\\\\\&quot;signature\\\\\\&quot;: {\\\\n        \\\\\\&quot;askSignatureOnScreen\\\\\\&quot;: true,\\\\n        \\\\\\&quot;skipSignature\\\\\\&quot;: false\\\\n    },\\\\n    \\\\\\&quot;timeouts\\\\\\&quot;: {\\\\n        \\\\\\&quot;fromActiveToSleep\\\\\\&quot;: 30\\\\n    },\\\\n    \\\\\\&quot;offlineProcessing\\\\\\&quot;: {\\\\n        \\\\\\&quot;chipFloorLimit\\\\\\&quot;: 0\\\\n    },\\\\n    \\\\\\&quot;passcodes\\\\\\&quot;: {\\\\n        \\\\\\&quot;adminMenuPin\\\\\\&quot;: \\\\\\&quot;1111\\\\\\&quot;,\\\\n        \\\\\\&quot;txMenuPin\\\\\\&quot;: \\\\\\&quot;1111\\\\\\&quot;,\\\\n        \\\\\\&quot;screenLockPin\\\\\\&quot;: \\\\\\&quot;1111\\\\\\&quot;\\\\n    },\\\\n    \\\\\\&quot;standalone\\\\\\&quot;: {\\\\n        \\\\\\&quot;enableStandalone\\\\\\&quot;: false,\\\\n        \\\\\\&quot;currencyCode\\\\\\&quot;: \\\\\\&quot;EUR\\\\\\&quot;\\\\n    }\\\\n}\\&quot;}]&#039; :enable-copy-link-to-code-block=\\&quot;true\\&quot; :code-sample-card-size=\\&quot;&#039;fullsize&#039;\\&quot;&gt;&lt;\\\/code-sample&gt;\\n&lt;\\\/div&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ol&gt;\\n&lt;h4&gt;Look up your shared key&lt;\\\/h4&gt;\\n&lt;p&gt;You can later look up the details of the shared key that was created:&lt;\\\/p&gt;\\n&lt;ol&gt;\\n&lt;li&gt;Make a GET call to one of the following endpoints:\\n&lt;ul&gt;\\n&lt;li&gt;\\n &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/get\\\/companies\\\/(companyId)\\\/terminalSettings\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;\\\/companies\\\/{companyId}\\\/terminalSettings&lt;\\\/a&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/get\\\/merchants\\\/(merchantId)\\\/terminalSettings\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;\\\/merchants\\\/{merchantId}\\\/terminalSettings&lt;\\\/a&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/get\\\/stores\\\/(storeId)\\\/terminalSettings\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;\\\/stores\\\/{storeId}\\\/terminalSettings&lt;\\\/a&gt;\\n&lt;\\\/li&gt;\\n&lt;li&gt;\\n &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/get\\\/terminals\\\/(terminalId)\\\/terminalSettings\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;\\\/terminals\\\/{terminalId}\\\/terminalSettings&lt;\\\/a&gt;\\n&lt;\\\/li&gt;\\n&lt;\\\/ul&gt;&lt;\\\/li&gt;\\n&lt;li&gt;In the response, see the  &lt;a href=\\&quot;https:\\\/\\\/docs.adyen.com\\\/api-explorer\\\/Management\\\/latest\\\/get\\\/companies\\\/(companyId)\\\/terminalSettings#responses-200-nexo-encryptionKey\\&quot; class=\\&quot;codeLabel  external-link no-image\\&quot; target=\\&quot;_blank\\&quot; rel=\\&quot;nofollow noopener noreferrer\\&quot;&gt;nexo.encryptionKey&lt;\\\/a&gt; object for the key identifier, passphrase, and version of your shared key.&lt;\\\/li&gt;\\n&lt;\\\/ol&gt;\\n&quot;,&quot;altTitle&quot;:null,&quot;oldTabId&quot;:1,&quot;relation&quot;:&quot;&quot;}]\"\n            :should-update-when-url-changes='false'>\n        <\/tabs>\n    <\/div>\n<\/div>\n\n<h3 id=\"add-code\">Add code to protect local communications<\/h3>\n<p>Your integration must:<\/p>\n<ul>\n<li><strong>Validate the terminal certificate<\/strong>: this confirms that your POS app is communicating directly with an Adyen-supplied payment terminal, and not an impostor.<\/li>\n<li><strong>Encrypt communications<\/strong>: this prevents intruders from reading the messages transmitted between your POS app and the terminal.<\/li>\n<\/ul>\n<p>There are two ways to get this done: use one of our <a href=\"#install-library\">GitHub libraries<\/a>, or write your own code. For instructions, select one of the options below.<\/p>\n<div class=\"next-steps\" id=\"next-steps\" >\n<a href=\"\/point-of-sale\/design-your-integration\/choose-your-architecture\/local\/protect-with-library\" class=\"next-steps__step\" style=\"width:45%;\" target=\"_self\"><p class=\"next-steps__body\"><div style=\"text-align: center;\"><img src=\"\/user\/themes\/adyen\/images\/illustrations\/library.svg\"><h6 class=\"next-steps__title\">Use a GitHub library<\/h6><p>Handle the protection of local communications through a library.<\/p><\/div><\/p><\/a><a href=\"\/point-of-sale\/design-your-integration\/choose-your-architecture\/local\/protect\" class=\"next-steps__step\" style=\"width:45%;\" target=\"_self\"><p class=\"next-steps__body\"><div style=\"text-align: center;\"><img src=\"\/user\/themes\/adyen\/images\/illustrations\/digital-signature.svg\"><h6 class=\"next-steps__title\">Do it yourself<\/h6><p>Write your own code to handle the protection of local communications.<\/p><\/div><\/p><\/a><\/div>\n\n<h2 id=\"build-payment-flow\">4. Build your payment flow<\/h2>\n<p>The payment features that you minimally need to integrate, are the same regardless if you use local or cloud communications. These features, described under <a href=\"\/point-of-sale\/basic-tapi-integration\">Implement the payment flow<\/a>, are:<\/p>\n<ul>\n<li>Make a payment.<\/li>\n<li>Issue a refund.<\/li>\n<li>Cancel an in-progress payment.<\/li>\n<li>Generate receipts.<\/li>\n<li>Add details about your application to your requests.<\/li>\n<li>Verify the status of a transaction (also see <a href=\"#handle-network-issues\">5. Handle network issues<\/a>).<\/li>\n<\/ul>\n<p>With local communications you additionally need to consider the following points:<\/p>\n<ul>\n<li>\n<p>Sending requests and handling the synchronous response:<br \/>\nAdyen-supplied payment terminals listen for Terminal API POST requests to <code>\/nexo<\/code> on port <strong>8443<\/strong>. For example, if your terminal has the IP address <strong>198.51.100.1<\/strong> you make API requests to <code>https:\/\/198.51.100.1:8443\/nexo<\/code>.<\/p>\n<p>When you make a payment, the result is provided through a synchronous API response. To receive the synchronous response, your POS app needs to make HTTPS requests to the terminal using a time-out of more than 120 seconds. During this time the connection is kept alive and a synchronous response will follow.<\/p>\n<\/li>\n<li>\n<p>Whether you want your POS app to show messages, called display notifications, that keep your staff up to date with the progress of the transaction.<\/p>\n<\/li>\n<\/ul>\n<h3>Showing display notifications in your POS app<\/h3>\n<p>During a transaction or <em><a href=\"\/get-started-with-adyen\/adyen-glossary\/#tender\">tender<\/a><\/em>, the payment terminal generates display notifications. You can show these in your POS app to keep your staff up-to-date on the progress of the tender. For example, whether the customer has selected Dynamic Currency Conversion, or finished entering their PIN.<\/p>\n<p>To set this up, see <a href=\"\/point-of-sale\/design-your-integration\/notifications\/display-notifications\">Display notifications<\/a>.<\/p>\n<h2 id=\"handle-network-issues\">5. Handle network issues<\/h2>\n<p>To make your integration more resilient in case of connection issues, your integration should automatically <a href=\"\/point-of-sale\/basic-tapi-integration\/verify-transaction-status\">make a transaction status request<\/a> when it does not receive a synchronous payment response from Adyen.<\/p>\n<p>Payment requests time out after 120 seconds. If you do not receive a payment response (or you receive a response indicating a time-out) after 150 seconds, your integration should automatically make a transaction status request.<\/p>\n<p>Showing the result of the transaction status request in your POS app reduces the risk that your store staff will unnecessarily try to cancel or refund the transaction, or make a duplicate transaction.<\/p>\n<div class=\"notices blue\">\n<p>You can optionally request the status of a transaction before 120 seconds. For example, you may also want to let store staff manually request the status of a payment at any time from the POS app.<\/p>\n<\/div>\n<h2>See also<\/h2>\n<div class=\"see-also-links output-inline\" id=\"see-also\">\n<ul><li><a href=\"\/point-of-sale\"\n                        target=\"_self\"\n                        >\n                    Terminal API integration\n                <\/a><\/li><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/framework\/wcf\/feature-details\/how-to-view-certificates-with-the-mmc-snap-in\"\n                        target=\"_blank\"\n                         class=\"external\">\n                    How to: View certificates with the MMC snap-in\n                <\/a><\/li><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/powershell\/module\/pki\/import-certificate?view=windowsserver2019-ps\"\n                        target=\"_blank\"\n                         class=\"external\">\n                    Importing certificates with the PowerShell\n                <\/a><\/li><li><a href=\"\/point-of-sale\/design-your-integration\/choose-your-architecture\/local\/protect-with-library\"\n                        target=\"_self\"\n                        >\n                    Set up protection of local communications using an Adyen GitHub library\n                <\/a><\/li><li><a href=\"\/point-of-sale\/design-your-integration\/choose-your-architecture\/local\/protect\"\n                        target=\"_self\"\n                        >\n                    Set up protection of local communications yourself\n                <\/a><\/li><\/ul><\/div>\n","url":"https:\/\/docs.adyen.com\/point-of-sale\/design-your-integration\/choose-your-architecture\/local","articleFields":{"description":"Learn how to build a Terminal API integration with local communications.","feedback_component":true,"last_edit_on":"12-11-2025 10:08","filters_component":false,"decision_tree":"[]","page_id":"bf0c2c64-5742-4a32-8f31-253841c63209"},"algolia":{"url":"https:\/\/docs.adyen.com\/point-of-sale\/design-your-integration\/choose-your-architecture\/local","title":"Building a local integration","content":"Before you start building a point-of-sale integration with Adyen-provided payment terminals, you need to choose between local or cloud communications. This determines how your POS system &mdash;also referred to as cash register&mdash; connects to the Adyen payment terminals and the Adyen payments platform.\nThis section of the documentation explains what to do if you have decided to use local communications.\nRequirements\nBefore you begin, take into account the following information.\n\n\n\nRequirement\nDescription\n\n\n\n\nIntegration type\nThe information on this page is relevant for building a point-of-sale integration with the Adyen Terminal API and Adyen payment terminals using local communications.\n\n\nAPI credentials\nTo set up a shared key using API calls, your API credential must have the following role: Management API\u2014Terminal Advanced settings read and write\n\n\nCustomer Area roles\nTo set up a shared key using the Customer Area you must have the following user role: Merchant POS Terminal Management Admin role\/li&gt;\n\n\n\nHow it works\nWith local communications, your POS system sends an API request over the local network to the IP address of the payment terminal. When the shopper completes the transaction on the terminal, the terminal routes the request to the Adyen payments platform for processing. Optionally you can set up display notifications to inform your staff on the progress of the transaction and the result. You receive the API response  synchronously.\n\nTo build a local integration, you need to:\n\nConfigure your network. To allow outgoing HTTPS traffic, you need to add Adyen domains to your firewall's allowlist, and you need to open certain network ports.\nOptionally install an API library. This step can save you development time.\nProtect local communications. This step involves validating the terminal certificate against the Adyen root certificate, and adding code to encrypt API requests and decrypt API responses.\nBuild the payment flow. For example, ensure your POS app can send Terminal API payment requests and other requests, and receive the synchronous response.\nLearn how to handle network issues.\n\n1. Configure your network\nTo enable your POS app to connect directly to the terminal:\n\n\nAdd Adyen's domains to your firewall's allowlist.\nConfigure your firewall to allow outgoing HTTPS traffic from the IP addresses of your POS apps and terminals to:\n\n*.adyen.com\n*.adyenpayments.com\n\nAllowlisting should be based on the DNS name of these URLs. Your firewall should dynamically check for IP address updates, at least every 60 seconds.\n\nDo not hard-code Adyen's IP addresses, because these can change over time. We do not share a list of our IP addresses publicly.\n\n\n\nOpen the ports:\n\ntcp\/443 to the internet.\ntcp\/8443 on your LAN.\n\n\n\nUse the correct Transport Layer Security (TLS) version and ciphers.\n\n\nTo assign IP addresses to your terminals, use DHC reservation (recommended), or manually configure static IP addresses. Optionally you can get notified about changes in terminal IP addresses.\n\n\nFor more information and recommendations, see Network and connectivity.\n2. (Optional) Install an API library\nOn our GitHub, we provide server-side API libraries in several languages. Installing a GitHub library is not required, but can save you development time. The libraries include all Terminal API models so you can use these to create requests. Most libraries also send requests to Adyen using a built-in HTTP client, construct the correct test and live endpoints, and help to protect local communications.\nThe following Adyen GitHub libraries are available for a local Terminal API integration:\n\n.NET - adyen-dotnet-api-library\niOS - adyen-terminal-api-ios\nJava - adyen-java-api-library\nNode - adyen-node-api-library\n\n\nThese GitHub libraries work with Terminal API and are completely separate from the classic libraries, which have been deprecated.\n\n3. Protect local communications\n\nWhile you are building a test integration, we do not enforce this step. This allows you to develop the functional and security aspects in parallel. However, you will not be able to process live transactions until you have secured the requests between your POS app and your terminal.\n\nIf your integration uses local communications, you need to protect your integration against man-in-the-middle attacks, eavesdropping, and tampering. The steps you need to take are:\n\nInstall Adyen's root certificate.\nSet up a shared key.\nAdd code to validate the terminal certificate against the root certificate and encrypt communications using the shared key.\n\nInstall Adyen's root certificate\nThe root certificate contains information about Adyen's public key, which is used to sign other certificates such as the certificate on the terminal. To verify the certificate on the terminal against the public key, you have to add Adyen's root certificate to a trust store that is available to your POS app.\nThe instructions differ depending on the operating system. Select one of the tabs below.\n\n\n    \n        \n        \n    \n\n\n\n\nSet up a shared key\nTo prevent others from being able to read messages sent between your POS app and the payment terminal, you need to encrypt the communications. For that, you first need to create a key passphrase and share it with Adyen. Both your code (or the Adyen GitHub library you are using) and the terminal will apply a key derivation function to the passphrase, and use the resulting key material to encrypt communications.\nYou can create a shared key manually in your Customer Area or with an API call. For both options, you can set up the shared key at the company, merchant, store, or terminal level. If your use case does not require a specific level, we recommend setting up a shared key at the highest possible level. For more information, see Settings at different levels and Inheritance of settings.\n\n\n    \n        \n        \n    \n\n\nAdd code to protect local communications\nYour integration must:\n\nValidate the terminal certificate: this confirms that your POS app is communicating directly with an Adyen-supplied payment terminal, and not an impostor.\nEncrypt communications: this prevents intruders from reading the messages transmitted between your POS app and the terminal.\n\nThere are two ways to get this done: use one of our GitHub libraries, or write your own code. For instructions, select one of the options below.\n\nUse a GitHub libraryHandle the protection of local communications through a library.Do it yourselfWrite your own code to handle the protection of local communications.\n\n4. Build your payment flow\nThe payment features that you minimally need to integrate, are the same regardless if you use local or cloud communications. These features, described under Implement the payment flow, are:\n\nMake a payment.\nIssue a refund.\nCancel an in-progress payment.\nGenerate receipts.\nAdd details about your application to your requests.\nVerify the status of a transaction (also see 5. Handle network issues).\n\nWith local communications you additionally need to consider the following points:\n\n\nSending requests and handling the synchronous response:\nAdyen-supplied payment terminals listen for Terminal API POST requests to \/nexo on port 8443. For example, if your terminal has the IP address 198.51.100.1 you make API requests to https:\/\/198.51.100.1:8443\/nexo.\nWhen you make a payment, the result is provided through a synchronous API response. To receive the synchronous response, your POS app needs to make HTTPS requests to the terminal using a time-out of more than 120 seconds. During this time the connection is kept alive and a synchronous response will follow.\n\n\nWhether you want your POS app to show messages, called display notifications, that keep your staff up to date with the progress of the transaction.\n\n\nShowing display notifications in your POS app\nDuring a transaction or tender, the payment terminal generates display notifications. You can show these in your POS app to keep your staff up-to-date on the progress of the tender. For example, whether the customer has selected Dynamic Currency Conversion, or finished entering their PIN.\nTo set this up, see Display notifications.\n5. Handle network issues\nTo make your integration more resilient in case of connection issues, your integration should automatically make a transaction status request when it does not receive a synchronous payment response from Adyen.\nPayment requests time out after 120 seconds. If you do not receive a payment response (or you receive a response indicating a time-out) after 150 seconds, your integration should automatically make a transaction status request.\nShowing the result of the transaction status request in your POS app reduces the risk that your store staff will unnecessarily try to cancel or refund the transaction, or make a duplicate transaction.\n\nYou can optionally request the status of a transaction before 120 seconds. For example, you may also want to let store staff manually request the status of a payment at any time from the POS app.\n\nSee also\n\n\n                    Terminal API integration\n                \n                    How to: View certificates with the MMC snap-in\n                \n                    Importing certificates with the PowerShell\n                \n                    Set up protection of local communications using an Adyen GitHub library\n                \n                    Set up protection of local communications yourself\n                \n","type":"page","locale":"en","boost":16,"hierarchy":{"lvl0":"Home","lvl1":"In-person payments","lvl2":"Design your integration","lvl3":"Choose an integration architecture","lvl4":"Building a local integration"},"hierarchy_url":{"lvl0":"https:\/\/docs.adyen.com\/","lvl1":"https:\/\/docs.adyen.com\/point-of-sale","lvl2":"https:\/\/docs.adyen.com\/point-of-sale\/design-your-integration","lvl3":"https:\/\/docs.adyen.com\/point-of-sale\/design-your-integration\/choose-your-architecture","lvl4":"\/point-of-sale\/design-your-integration\/choose-your-architecture\/local"},"levels":5,"category":"In-person payments","category_color":"green","tags":["Building","local","integration"]},"articleFiles":{"local_flow.png":"<img alt=\"\" src=\"https:\/\/docs.adyen.com\/user\/pages\/docs\/03.point-of-sale\/04.design-your-integration\/06.choose-your-architecture\/01.local\/local_flow.png\" \/>","adyen-terminalfleet-live.pem":"<p alt=\"\">adyen-terminalfleet-live.pem<\/p>","adyen-terminalfleet-test.pem":"<p alt=\"\">adyen-terminalfleet-test.pem<\/p>","terminalsettings-encryptionkey-request-2253072399.js":"<p alt=\"\">terminalsettings-encryptionkey-request-2253072399.js<\/p>"}}
