--- title: "Make a payment" description: "Make an in-person card payment." url: "https://docs.adyen.com/point-of-sale/basic-tapi-integration/make-a-payment" source_url: "https://docs.adyen.com/point-of-sale/basic-tapi-integration/make-a-payment.md" canonical: "https://docs.adyen.com/point-of-sale/basic-tapi-integration/make-a-payment" last_modified: "2020-05-13T13:42:00+02:00" language: "en" --- # Make a payment Make an in-person card payment. [View source](/point-of-sale/basic-tapi-integration/make-a-payment.md) This page describes how to make a basic Terminal API payment request. As mentioned in the requirements, there are various integration design aspects that you must have decided on and implemented first. These aspects are described on other pages. Also note that you need to have a boarded test payment terminal or a mobile device for testing. ## Requirements Before you begin, take into account the following requirements and preparations. | Requirement | Description | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Integration type** | Use this information to build a [Terminal API integration](/point-of-sale/design-your-integration/terminal-api) with payment terminals or with a [Mobile solution](/point-of-sale/ipp-mobile). | | **Hardware** | Make sure you have:- A [POS test card](/point-of-sale/testing-pos-payments#testing-card-payments). - A test payment terminal that has been boarded. Or if you are building a Mobile solution, you need to have an Android or iOS mobile device that you can use for testing. | | **Setup steps** | Before you begin, make sure you have scoped and designed your integration and followed the applicable integration checklist up to the point where you are ready to integrate making a test payment. See the information for your integration type.- Payment terminals: [Terminal API integration checklist](/point-of-sale/get-started/tapi-checklist); [Design your integration](/point-of-sale/design-your-integration). - Android Mobile solution: [Get-started checklist](/point-of-sale/mobile-android/checklists#get-started-checklist); [Build your solution](/point-of-sale/mobile-android/build). - iOS Mobile solution: [Get-started checklist](/point-of-sale/mobile-ios/checklists#get-started-checklist); [Build your solution](/point-of-sale/mobile-ios/build). | ## How it works 1. From your POS app, you send an [API request to make a payment](#make-a-payment). 2. The request is routed to the payment terminal or mobile device. 1. A screen appears that prompts the customer to present their means of payment. The customer can tap, insert, or swipe a credit or debit card, or use an NFC digital wallet like Apple Pay. If needed, the customer enters their PIN or signature. 2. A waiting screen is shown while we try to get the payment authorized. 3. After the authorization attempt, a screen appears that shows if the payment was approved or declined. The following example screens show the payment flow.\ Note that the position of screen elements can differ by payment terminal model (or other hardware as used in a Mobile solution). This applies, for example, to the icon that indicates the location of the contactless reader. | Payment screen | Authorizing screen | Approved screen | | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | ![Payment screen](/user/pages/docs/03.point-of-sale/05.basic-tapi-integration/01.make-a-payment/screen-EN_payment.svg?decoding=auto\&fetchpriority=auto) | ![Authorizing screen](/user/pages/docs/03.point-of-sale/05.basic-tapi-integration/01.make-a-payment/screen-EN_authorizing.svg?decoding=auto\&fetchpriority=auto) | ![Approved screen](/user/pages/docs/03.point-of-sale/05.basic-tapi-integration/01.make-a-payment/screen-EN_approved.svg?decoding=auto\&fetchpriority=auto) | 3. You [check the API response](#payment-response). Note that if you use asynchronous cloud communications with payment terminals, you receive the API response in an [event notification](/point-of-sale/design-your-integration/notifications/event-notifications#async-response).\ If you did not receive a response or if the payment failed, you take [troubleshooting](#troubleshooting) steps. ## Make a payment request To initiate the payment: 1. Make a [Terminal API](/point-of-sale/design-your-integration/terminal-api) payment request, specifying: * The standard [`SaleToPOIRequest.MessageHeader` ](/point-of-sale/design-your-integration/terminal-api#request-message-header)object, with `MessageClass` set to **Service** and `MessageCategory` set to **Payment**. | 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-") | **Service** | | `MessageCategory` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | **Payment** | | `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 [PaymentRequest](https://docs.adyen.com/api-explorer/terminal-api/latest/post/payment) object with: | Parameter | Required | Description | | ------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `SaleData.SaleTransactionID` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | An object with:- `TransactionID`: A string with your reference to identify a payment. We recommend using a unique value per payment. In your Customer Area and Adyen reports, this will show as the **merchant reference** for the transaction. - `TimeStamp`: A string with the date and time of the request in [UTC format](https://en.wikipedia.org/wiki/ISO_8601#Coordinated_Universal_Time_\(UTC\)). | | `PaymentTransaction.AmountsReq` | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | An object with:- `Currency`: A string with the three-letter [currency code](/development-resources/currency-codes) for the transaction. - `RequestedAmount`: The final transaction amount in number format, with a decimal point. For example, **10.99**. | **Payment request of USD 10.99** #### JSON ```json { "SaleToPOIRequest":{ "MessageHeader":{ "ProtocolVersion":"3.0", "MessageClass":"Service", "MessageCategory":"Payment", "MessageType":"Request", "SaleID":"POSSystemID12345", "ServiceID":"0207111104", "POIID":"V400m-324688179" }, "PaymentRequest":{ "SaleData":{ "SaleTransactionID":{ "TransactionID":"27908", "TimeStamp":"2019-03-07T10:11:04+00:00" } }, "PaymentTransaction":{ "AmountsReq":{ "Currency":"USD", "RequestedAmount":10.99 } } } } } ``` #### Java ```java String saleID = "YOUR_CASH_REGISTER_ID"; String serviceID = "YOUR_UNIQUE_ATTEMPT_ID"; String POIID = "YOUR_TERMINAL_ID"; String transactionID = "YOUR_UNIQUE_TRANSACTION_ID"; SaleToPOIRequest saleToPOIRequest = new SaleToPOIRequest(); MessageHeader messageHeader = new MessageHeader(); messageHeader.setProtocolVersion("3.0"); messageHeader.setMessageClass( MessageClassType.SERVICE ); messageHeader.setMessageCategory( MessageCategoryType.PAYMENT ); messageHeader.setMessageType( MessageType.REQUEST ); messageHeader.setSaleID(saleID); messageHeader.setServiceID(serviceID); messageHeader.setPOIID(POIID); saleToPOIRequest.setMessageHeader(messageHeader); PaymentRequest paymentRequest = new PaymentRequest(); SaleData saleData = new SaleData(); TransactionIdentification saleTransactionID = new TransactionIdentification(); saleTransactionID.setTransactionID(transactionID); saleTransactionID.setTimeStamp(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar())); saleData.setSaleTransactionID(saleTransactionID); paymentRequest.setSaleData(saleData); PaymentTransaction paymentTransaction = new PaymentTransaction(); AmountsReq amountsReq = new AmountsReq(); amountsReq.setCurrency("USD"); amountsReq.setRequestedAmount( BigDecimal.valueOf(10.99) ); paymentTransaction.setAmountsReq(amountsReq); paymentRequest.setPaymentTransaction(paymentTransaction); saleToPOIRequest.setPaymentRequest(paymentRequest); terminalAPIRequest.setSaleToPOIRequest(saleToPOIRequest); ``` 2. In the [PaymentResponse](https://docs.adyen.com/api-explorer/terminal-api/latest/post/payment#responses-200), note the following:\ []() | Parameter | Description | | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `POIData.POITransactionID.TransactionID` | The unique [transaction identifier](/point-of-sale/design-your-integration/terminal-api#transaction-identifier) for the payment. Save this ID in your system. You may need this ID later, for example, to look up the payment in your Customer Area, for reconciliation purposes, or to make other requests such as a refund or manual capture. | | `Response.Result` | The result is **Success** for an approved payment, or **Failure** for a declined payment. In case of a [partial authorization](/point-of-sale/partial-authorizations) the result can also be **Partial**. | | `Response.ErrorCondition` | If the `Result` was **Failure**, this parameter indicates why the payment failed. | | `Response.AdditionalResponse` | A string with additional transaction data. The string can consist of form-encoded key-value pairs, or a Base64-encoded JSON object. You can ask our [Support Team](https://ca-test.adyen.com/ca/ca/contactUs/support.shtml?form=other) to ensure you always receive the `AdditionalResponse` in one of these formats. | | `PaymentReceipt` | An object with data you can use to [generate a customer receipt and a cashier receipt](/point-of-sale/basic-tapi-integration/generate-receipts). | ### Tab: Payment approved The following example indicates that the payment was successful. The transaction identifier for this payment is **BV0q001769085761003.ZGQVNH6ZT8DJFRV5**: **Successful payment response** ```json { "SaleToPOIResponse": { "MessageHeader": {...}, "PaymentResponse": { "POIData": { "POIReconciliationID": "1000", "POITransactionID": { "TimeStamp": "2026-01-22T12:42:42.537Z", "TransactionID": "BV0q001769085761003.ZGQVNH6ZT8DJFRV5" } }, "PaymentReceipt": [...], "PaymentResult": { "AmountsResp": { "AuthorizedAmount": 10.99, "Currency": "USD" }, ..., "PaymentAcquirerData": { "AcquirerPOIID": "V400m-324688179", "AcquirerTransactionID": { "TimeStamp": "2026-01-22T12:42:42.537Z", "TransactionID": "ZGQVNH6ZT8DJFRV5" }, "ApprovalCode": "123456", "MerchantID": "YOUR_MERCHANT_ACCOUNT" }, "PaymentInstrumentData": { "CardData": { "CardCountryCode": "840", "EntryMode": [ "ICC" ], "MaskedPan": "600007 **** 7003", "PaymentBrand": "mc", "SensitiveCardData": {...} }, "PaymentInstrumentType": "Card" } }, "Response": { "AdditionalResponse": "...&acquirerResponseCode=APPROVED...&merchantReference=379&...&posAuthAmountCurrency=USD&posAuthAmountValue=1099&posEntryMode=ICC...&pspReference=ZGQVNH6ZT8DJFRV5...&refusalReasonRaw=APPROVED&shopperCountry=US...&store=YOUR_STORE...&transactionReferenceNumber=ZGQVNH6ZT8DJFRV5&transactionType=GOODS_SERVICES&txdate=22-01-2026&txtime=13%3a42%3a42", "Result": "Success" }, "SaleData": { "SaleTransactionID": { "TimeStamp": "2026-01-22T12:42:40.722Z", "TransactionID": "379" } } } } } ``` ### Tab: Payment declined The following example shows that the payment failed because the transaction was cancelled on the payment screen. **Failed payment response** ```json { "SaleToPOIResponse": { "MessageHeader": {...}, "PaymentResponse": { "POIData": { "POIReconciliationID": "1000", "POITransactionID": { "TimeStamp": "2026-01-22T12:40:03.215Z", "TransactionID": "BV0q001769085602001" } }, "PaymentResult": { "PaymentAcquirerData": { "AcquirerPOIID": "V400m-324688179", "MerchantID": "YOUR_MERCHANT_ACCOUNT" }, "PaymentInstrumentData": { "CardData": {}, "PaymentInstrumentType": "Card" } }, "Response": { "AdditionalResponse": "...&message=108%20Shopper%20cancelled%20tx...&posAuthAmountCurrency=USD&posAuthAmountValue=1099...&refusalReason=108%20Shopper%20cancelled%20tx&store=YOUR_STORE&tid=47069832&transactionType=GOODS_SERVICES&txdate=22-01-2026&txtime=13%3a40%3a03", "ErrorCondition": "Cancel", "Result": "Failure" }, "SaleData": { "SaleTransactionID": { "TimeStamp": "2026-01-22T12:40:02.015Z", "TransactionID": "742" } } } } } ``` You can also view the details of a payment in your [Customer Area](https://ca-test.adyen.com/), under **Transactions** > **Payments**. ## Troubleshooting There are two types of issues with payment requests that your integration must be able to handle: * You made a payment request but did not receive a response (either a direct Terminal API response, or a Terminal API response received as an event notification). * The payment response indicates a failure. ### No response It is possible that you do not receive a payment response due to a technical or connection issue. It is also possible that the payment remains in progress for a long time, for example when the customer does not react to a prompt on the payment terminal. To cope with these scenarios, we strongly recommend that your integration is able to automatically [verify the transaction status](/point-of-sale/basic-tapi-integration/verify-transaction-status). This can help reduce the risk that your store staff unnecessarily refunds the payment, or makes a duplicate payment. ### Failure If a payment fails, the [PaymentResponse](https://docs.adyen.com/api-explorer/terminal-api/latest/post/payment#responses-200) includes: * `Response.Result`: **Failure**. * `Response.ErrorCondition`: The type of failure. For example, **Refusal** when the card issuer refused the transaction. * `Response.AdditionalResponse`: Contains a `message` with additional information about why the payment failed. In the case of a declined payment, the additional response also includes the `refusalReason`, for example, **Expired card**. To learn what to do, see: * [Handle responses](/point-of-sale/error-scenarios): The various scenarios that can lead to a failed payment request. * [Refusal reasons](/point-of-sale/error-scenarios/refusal-reasons-pos): The most common refusal reasons grouped by `ErrorCondition`, with information about whether you can retry the transaction. ## Testing To make test payments, you need to have a [POS test card](/point-of-sale/testing-pos-payments#testing-card-payments) and either a test payment terminal that has been boarded, or an Android or iOS mobile device that you can use for testing if you are building a Mobile solution. While building a test integration, you can simulate payment failure scenarios. For example, if you specify a `RequestedAmount` with 123 as the last three digits, such as 101.23 or 41.23, the payment will be declined. For information about the payment scenarios you can test, see [Simulating declined payments](/point-of-sale/testing-pos-payments/test-card-v2#testing-declines). ## See also * [Check the status of a transaction](/point-of-sale/basic-tapi-integration/verify-transaction-status) * [Handle responses](/point-of-sale/error-scenarios) * [Testing POS payments](/point-of-sale/testing-pos-payments)