This is the abridged developer documentation for SumUp Developer # Getting started > Start integrating SumUp quickly by creating a sandbox account, choosing your integration path, and processing your first payment. Welcome to the SumUp Developer Portal. Here you'll find everything you need to integrate SumUp's payment solutions into your product. The documentation is divided into several sections: - **[Quick start](/getting-started/)** – set up a sandbox merchant account and run through a first payment in minutes. - **[Online Payments](/online-payments/)** – accept card payments on the web or in mobile apps. - **[Terminal Payments](/terminal-payments/)** – use SumUp card readers to take in-person payments. - **[Developer Resources](/tools/authorization/)** – explore authentication, webhooks, LLM tooling, and other utilities. Create a [sandbox merchant account](https://me.sumup.com) to experiment safely and then dive into the section that best fits your use case. # Online Payments > Get started with accepting online payments. This guide walks you through creating a sandbox merchant account and processing your first transaction in minutes. import { Aside, Steps } from '@astrojs/starlight/components'; import Image from '@components/content/Image.astro'; Online payments form an integral part of the SumUp product portfolio. SumUp supports online payments through multiple approaches to address every merchant use case. Use one of the out-of-the-box integrations or build a complete custom payments flow with the APIs. Your app communicates with SumUp via HTTP requests defined in the [API Reference](/api).​ ![Image showing integrations in SumUp](/img/guides/integrations.png) To get started, review the options SumUp offers for managing online payments. ## Getting a Sandbox Merchant Account To test SumUp APIs and tools without involving real money, use a sandbox merchant account. Create one from your Dashboard account as follows. 1. Log in to your SumUp account. 2. Open the drop-down menu between **Support** and your user panel. 3. Select **Sandbox Merchant Account**. Your merchant account is now in sandbox mode. A screenshot of the account selection dropdown in the SumUp dashboard with the sandbox merchant account highlighted with red circle With your sandbox merchant account, begin making API calls with real data. Sandbox merchant accounts **do not** process transactions with real funds. The sandbox merchant account has a different ID and displays a clear warning. Requests with a value of 11 (in any currency) always fail by design, to test failed transaction scenarios. A screenshot of the dashboard with sandbox merchant account selected When finished experimenting with the sandbox merchant account, switch back to a regular account for business purposes. ## Authorization All online payment products use SumUp APIs, which require authorization via an API key or access token. See the [Authorization Guide](/tools/authorization/) for details on available options.​ ## Checkout Products SumUp provides a range of checkout products for seamless integration with your website. ### SumUp Card Widget For a quick and seamless integration, we've developed a sleek payment widget. Incorporating the [SumUp Card Widget](/online-payments/checkouts/card-widget/) only requires adding a single script to your payment page! #### Alternative Payment Methods The Card Widget supports [Alternative Payment Methods](/online-payments/apm) (APMs) to accept payments beyond traditional card schemes (Visa or Mastercard). Access APMs through the [SumUp Card Widget](/online-payments/checkouts/card-widget/) by contacting us via the [contact form](/contact). Available APMs include: - Apple Pay - Bancontact - Blik - Boleto - EPS - Google Pay - iDeal - MyBank - PIX - Przelewy24 - Satispay ### SumUp Swift Checkout SDK The Swift Checkout SDK provides a complete and fast checkout experience to your end users, collecting payment, address, and contact information with a click of a button. See the [Swift Checkout Documentation](/online-payments/checkouts/swift-checkout/) for details. ## Plugins For Prestashop, Wix, or WooCommerce, use SumUp plugins for seamless payments. See the [Plugins section](/online-payments/plugins/) for details on each.​ ## Custom Integrations ### SumUp APIs SumUp provides REST APIs for services such as creating and executing payments, storing cards, and issuing refunds. SumUp APIs use API keys or [OAuth 2.0](http://tools.ietf.org/html/rfc6749) for authentication. They also support Cross-Origin Resource Sharing (CORS) for secure browser access from different domains. The API handles requests and responses primarily in JSON format, except when requests contain form-encoded data. Typically, requests consist of name/value pairs sent to SumUp API URI: `api.sumup.com`. ### Receiving Payments To receive payments, [create a checkout](/online-payments/guides/single-payment/#1-create-a-checkout). Use merchant-direct payments or initiate on a merchant's behalf based on your [authorization type](/tools/authorization/). Checkouts are created via server-to-server communication to keep access tokens and credentials secret and prevent changes to sensitive details like transaction amount or recipient. [Completing checkouts](/online-payments/guides/single-payment/#2-complete-a-checkout) via web browser or mobile app to avoid handling sensitive data like card details on your servers, eliminating PCI DSS compliance needs. SumUp offers the following checkout completion options: - You could build a [custom card form](/online-payments/guides/single-payment/#2-complete-a-checkout) that you must submit to the SumUp servers for processing - You could use the [SumUp Card Widget](/online-payments/checkouts/card-widget/) - You could process payments with [Alternative Payment Methods](/online-payments/apm), like Boleto, Bancontact & iDeal - You could process [recurring payments](/online-payments/guides/tokenization-with-payment-sdk) Successful checkout completion processes payment to the merchant's SumUp account.​ ## Contact SumUp # 3-D Secure flow > Learn about 3DS flow, SCA requirements, and how to handle 3DS when processing payments. import { Aside } from '@astrojs/starlight/components'; SumUp supports 3-D Secure payments for added security in online transactions. EMVCo developed 3D Secure 2, a payment card authentication protocol that meets Strong Customer Authentication (SCA) requirements. It reduces fraud through additional layers such as biometrics. [SCA (Strong Customer Authentication)](https://en.wikipedia.org/wiki/Strong_customer_authentication#cite_note-2) is an obligatory security measure, requiring two-factor authentication to verify consumer identity in payment transactions, using at least two independent, consumer-based factors: - Something the customer knows (e.g. Password, PIN) - Something the customer has (e.g. Phone, Token generator) - Something the customer is (e.g. Fingerprint, Face ID) Each of these elements must be independent, to ensure the security of others is not compromised in the event of a security breach. ## How It Works Both the merchant account and card issuer must support 3-D Secure. The flow adds a checkout step, dependent on the card scheme and issuing bank.​ ![Challenge screen](/img/guides/challenge_screen.png) ## Integration for Single Payments 1. Add the `redirect_url` parameter to your [checkout creation request](/api/checkouts/create). This URL receives the user after payment completion. 2. [Process the checkout](/api/checkouts/process) to get a `next_step` object with details for the required next action, allowing you to redirect the user to a required challenge screen. 3. Use the `next_step` content to redirect an end user to a challenge screen. The `next_step` object contains: | Parameter | Value | | -------------- | ----------------------------------------------------------------------------- | | `method` | `POST` | | `url` | `https://issuing-bank.com/acs?reqid=B69D8F090C031E959A3BB2C4D7DFE7F8F7C09B28` | | `redirect_url` | `https://mysite.com/completed_purchase` | | `mechanism` | `iframe` or `browser` | | `payload` | `object` | Example `payload`: ```js { "arbitrary_param_name_1": "arbitrary_param_value_1", "arbitrary_param_name_2": "arbitrary_param_value_2", "arbitrary_param_name_3": "arbitrary_param_value_3", "arbitrary_param_name_4": "arbitrary_param_value_4" } ``` Example redirect via auto-submitting form: ```html
``` The user reaches the issuer's authentication screen for additional verification (e.g. a challenge token, SMS, or other data). After submitting, SumUp completes the payment and the user is redirected to the `redirect_url` appointed at the checkout creation, through a `GET` request with the corresponding `checkout_id` query parameter. To confirm a checkout's status, make a `GET` request to the [retrieve a checkout](/api/checkouts/get) endpoint. # Alternative Payment Methods > Learn about supported alternative payment methods, activation steps, and integration options. import { Aside } from '@astrojs/starlight/components'; Alternative Payment Methods (APMs) provide alternatives to standard card payment schemes. They offer familiar and frictionless payment experiences to your customers, while making you stand out from your competitors offering only traditional payment experiences. APMs have completely transformed how we pay online. For example, in the Netherlands more than half of the consumers use iDeal to pay online merchandise. Some types of APMs are prepaid cards, mobile payments, e-wallets, and "buy now, pay later" installment-based schemes. ## Supported Alternative Payment Methods The APMs you can offer depend on the country your business is registered and operating in. Here's a list of the currently available APMs at SumUp: | APM | Country | | | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | | Apple Pay | Austria, Belgium, Brazil, Bulgaria, Chile, Croatia, Cyprus, Czech Republic, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Ireland, Italy, Latvia, Lithuania, Luxembourg, Malta, Netherlands, Norway, Poland, Portugal, Romania, Slovenia, Slovakia, Spain, Sweden, Switzerland, United Kingdom | | | Bancontact | Belgium | | | Blik | Poland | | | Boleto | Brazil | | | EPS | Austria | | | Google Pay | Austria, Belgium, Brazil, Bulgaria, Chile, Croatia, Cyprus, Czechia, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Ireland, Italy, Latvia, Lithuania, Luxembourg, Malta, Netherlands, Norway, Poland, Portugal, Romania, Slovenia, Slovakia, Spain, Sweden, Switzerland, United Kingdom | | | iDeal | Netherlands | | | MyBank | Greece, Italy, Spain | | | PIX | Brazil | | | Przelewy24 | Poland | | | Satispay | Italy | | ## Enabling Alternative Payment Methods As a **sole trader**, APMs are automatically enabled for your merchant account after completing the regular registration steps and performing a test transaction with one of our remote payment products, such as [Payment Links](https://sumup.co.uk/payment-links/), [Invoices](https://sumup.co.uk/invoices), and [Online Store](https://sumup.co.uk/online-store/). As with any other legal type, you must request activation from our support team or via our [contact form here](/contact), providing your merchant ID (MXXXXX). Our team will onboard your merchant account and grant access to the APMs applicable to your business location. Once your request is processed, APMs become available within [Payment Links](https://sumup.co.uk/payment-links/), [Invoices](https://sumup.co.uk/invoices), and [Online Store](https://sumup.co.uk/online-store/). ## Integration You can offer APMs through a number of approaches: - Through the [SumUp Payment Widget](/online-payments/checkouts/card-widget). To make APM payments successful, you must always set a `redirect_url` upon [checkout creation](/api/checkouts/create). Beyond that step, the SumUp Payment Widget will handle the rest. - [API Integrations](/online-payments/apm/integration-guide/) - Through the [Swift Checkout SDK](/online-payments/checkouts/swift-checkout/) - Direct Integration: - [Apple Pay](/online-payments/apm/apple-pay) - [Google Pay](/online-payments/apm/google-pay) # Apple Pay > Learn how to integrate Apple Pay, including prerequisites, domain validation, and API calls. import { Aside } from "@astrojs/starlight/components"; import Image from "@components/content/Image.astro"; In this guide, you will learn how to directly integrate Apple Pay with SumUp, so that you can retain your own UI/UX flow. Please note that you can also offer Apple Pay through our Payment Widget (see [Payment Widget documentation](/online-payments/checkouts/card-widget#alternative-payment-methods)). ## Prerequisites - You have a SumUp merchant account and have already filled in your [account details](https://me.sumup.com/account). - Get familiar with [Apple Pay on the Web guide](https://developer.apple.com/documentation/apple_pay_on_the_web). - Offering Apple Pay requires registering with Apple on all web domains that will expose an Apple Pay button (includes TLD and subdomains). This is a requirement for production AND test environments. - If you want to test payments without involving real funds, [create a sandbox merchant account](/online-payments/#getting-a-sandbox-merchant-account). - Complete the domain onboarding setup steps described in your Dashboard under **Settings** > **For developers** > **Payment wallets**. Screenshot of the dashboard Developer Settings, showing Payment wallets section that includes Apple Pay and Google Pay ## Accepting Apple Pay Payments with SumUp To begin your implementation, follow these steps: 1. [Create a checkout](https://developer.sumup.com/api/checkouts/create#create-a-checkout) 2. Create an [Apple Payment request](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaypaymentrequest) ```js const applePaymentRequest = { currencyCode: "EUR", countryCode: "DE", merchantCapabilities: ["supports3DS"], supportedNetworks: ["masterCard", "visa"], total: { label: "Demo", amount: "0.00", type: "final", }, }; ``` 3. Initiate an [Apple Pay session](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession/2320659-applepaysession) and call the [begin method](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession/1778001-begin) 4. Listen for the `onvalidatemerchant` callback and collect the `validateUrl` property. Create the following payload ```json { "target": "https://apple-pay-gateway-cert.apple.com/paymentservices/startSession", "context": "your_domain_name" } ``` and initiate a merchant session by calling ```http PUT https://api.sumup.com/v0.1/checkouts/${checkoutId}/apple-pay-session ``` 5. The response from the previous step is needed to complete the merchant validation with the [`completeMerchantValidation`](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession/1778015-completemerchantvalidation/) method 6. Submitting the payment dialogue triggers the `onpaymentauthorized` callback, this is when you need to [process the checkout](https://developer.sumup.com/api/checkouts/process#process-a-checkout). The process checkout request body needs to include a `payment_type` of `apple_pay` and an `apple_pay` object, containing the response from step 7 ```json { "payment_type": "apple_pay", "id": "9be2da07-a7bd-4877-bc0a-e16cd909a876", "amount": 12, "currency": "EUR", "apple_pay": { "token": { "paymentData": { "data": "si2xuT2ArQo689SfE-long-token", "signature": "MIAGCSqGSIb3DQEHA-long-signature", "header": { "publicKeyHash": "PWfjDi3TSwgZ20TY/A7f3V6J/1rhHyRDCspbeljM0io=", "ephemeralPublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaBtz7UN2MNV0qInJVEEhXy10PU0KfO6KxFjXm93oKWL6lCsxZZGDl/EKioUHVSlKgpsKGin0xvgldfxeJVgy0g==", "transactionId": "62e0568bc9258e9d0e059d745650fc8211d05ef7a7a1589a6411bf9b12cdfd04" }, "version": "EC_v1" }, "paymentMethod": { "displayName": "MasterCard 8837", "network": "MasterCard", "type": "debit" }, "transactionIdentifier": "62E0568BC9258E9D0E059D745650FC8211D05EF7A7A1589A6411BF9B12CDFD04" } } } ``` # Google Pay > Learn how to integrate Google Pay, including domain registration, payment requests, and processing. import { Aside } from '@astrojs/starlight/components'; import Image from '@components/content/Image.astro'; In this guide, you will learn how to directly integrate Google Pay with SumUp. Please note that you can also offer Google Pay through our Payment Widget (see [Payment Widget documentation](/online-payments/checkouts/card-widget#alternative-payment-methods)). ## Prerequisites - You have a SumUp merchant account and have already filled in your [account details](https://me.sumup.com/account). - If you want to test payments without involving real funds, [create a sandbox merchant account](/online-payments/#getting-a-sandbox-merchant-account). - Review [Google Pay API terms of service](https://payments.developers.google.com/terms/sellertos). - Complete the domain onboarding setup steps described in your Dashboard under **Settings** > **For developers** > **Payment wallets**. You can read Google's tutorial [Google Pay for Payments](https://developers.google.com/pay/api/web/guides/tutorial), which covers the requirements you're expected to follow in order to successfully offer this payment method. Screenshot of the dashboard Developer Settings, showing Payment wallets section that includes Apple Pay and Google Pay ## Accepting Google Pay Payments with SumUp Considering you've adhered to the prerequisites, the following steps will enable you to begin accepting Google Pay payments through SumUp: 1. Create a base payment request object, containing: - `tokenizationSpecification` object with the following parameters: - `gateway`- always equal to "sumup" - `gatewayMerchantId`- your SumUp merchant code - [`merchantInfo` object](https://developers.google.com/pay/api/web/reference/request-objects#MerchantInfo) with the following keys: - `merchantId`- unique identifier provided to you by Google once you register your domain with them - `merchantName`- your merchant name ```js const baseRequest = { apiVersion: 2, apiVersionMinor: 0, merchantInfo: { merchantId: '123456789123456789' merchantName: 'Example Merchant', }, allowedPaymentMethods: [ { type: 'CARD', parameters: { allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'], allowedCardNetworks: ['MASTERCARD', 'VISA'], }, tokenizationSpecification: { type: 'PAYMENT_GATEWAY', parameters: { gateway: 'sumup', gatewayMerchantId: 'exampleGatewayMerchantId', }, }, }, ], }; ``` 2. Load the [Google Pay API JavaScript library](https://developers.google.com/pay/api/web/guides/tutorial#js-load) on the web page you will offer this payment method 3. Initialize a `PaymentsClient` object for the environment you are implementing. Two values are possible here: `TEST` for testing the integration and `PRODUCTION` for live payments. ```js const paymentsClient = new google.payments.api.PaymentsClient({ environment: 'PRODUCTION', }); ``` 4. [Check readiness to pay](https://developers.google.com/pay/api/web/guides/tutorial#isreadytopay) with Google Pay API 5. [Launch the Google Pay button](https://developers.google.com/pay/api/web/guides/tutorial#add-button) 6. [Create a PaymentDataRequest](https://developers.google.com/pay/api/web/guides/tutorial#paymentdatarequest) using the `baseRequest` object and append the `transactionInfo` and `merchantInfo` objects. Your `PaymentDataRequest` should look like this: ```js const paymentDataRequest = { apiVersion: 2, apiVersionMinor: 0, merchantInfo: { merchantName: 'Example Merchant', }, allowedPaymentMethods: [ { type: 'CARD', parameters: { allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'], allowedCardNetworks: ['MASTERCARD', 'VISA'], }, tokenizationSpecification: { type: 'PAYMENT_GATEWAY', parameters: { gateway: 'sumup', gatewayMerchantId: 'exampleGatewayMerchantId', }, }, merchantInfo: { merchantId: 'your_merchant_id', merchantName: 'your_merchant_name', }, transactionInfo: { totalPriceStatus: 'FINAL', totalPriceLabel: 'Total', totalPrice: `${checkoutInfo.amount}`, currencyCode: checkoutInfo.currency || 'EUR', countryCode: 'DE', }, }, ], }; ``` 7. [Create a checkout](/api/checkouts/create) with SumUp 8. [Call the `loadPaymentData`](https://developers.google.com/pay/api/web/reference/client#loadPaymentData) method and pass it the `PaymentDataRequest` as an argument. This method will respond in a Promise, where if resolved you will receive a `PaymentData` object 9. [Process the checkout](/api/checkouts/process). The process checkout request body needs to include a `payment_type` of `google_pay` and a `google_pay` object, containing the response from the previous step ```json { "payment_type": "google_pay", "id": "6te2da07-a7bd-4877-bc0a-e16cd909a876", "amount": 12, "currency": "EUR", "google_pay": { "apiVersionMinor": 0, "apiVersion": 2, "paymentMethodData": { "description": "Visa •••• 1111", "tokenizationData": { "type": "PAYMENT_GATEWAY", "token": "token-data" }, "type": "CARD", "info": { "cardNetwork": "VISA", "cardDetails": "1111" } } } } ``` ## Troubleshooting ### Screenshots for Google Google demands screenshots for the onboarding process, but you don't have the integration ready yet? Simply add `#sumup-widget:google-pay-demo-mode` to your URL to render the Google Pay button for onboarding purposes. ### Testing Google Pay Integration Locally This is not possible at the moment. You need to use a staging environment and validate the test domain in Google API console. ### Error Decrypting Google Pay Token Internal Server Error with a message pointing to Google Pay token decryption error is most likely caused by the wrong `environment` value in the `paymentsClient` object. Make sure it's set to `PRODUCTION` as below. ```js const paymentsClient = new google.payments.api.PaymentsClient({ environment: 'PRODUCTION', }); ``` # Integration Guide > Learn about the request parameters and flows required to process alternative payment methods. ## Overview Alternative Payment Methods (further referred to as APMs) are similar to normal checkouts. One key difference is that the customer needs to take an additional action in order to finalize the payment with most APMs. Before proceeding, read the [online payments guide](/online-payments/). ## Check Available APMs Check which payment methods are available to your merchant account. 1. [Create a checkout](/api/checkouts/create) and use the checkout `id` to fetch the list of available payment methods from the following endpoint `https://api.sumup.com/v0.1/checkouts/{checkout_id}/payment-methods`. Example response: ```json { "items": [ { "id": "card", "name": "Credit Card" }, { "id": "blik", "name": "Blik" }, { "id": "apple_pay", "name": "Apple Pay" } ] } ``` Note that this object might change between checkouts as APMs are not offered for all currencies and amounts, and we are continuously introducing new APMs for you to offer. We recommend handling the returned payment methods as an allowlist for this checkout, and then picking all the payment methods you want to offer. Do **not** simply display all methods returned if your integration doesn't support them. The customer chooses one of the payment methods from the returned values, sent as part of the process checkout request under `payment_type`. The currently available payment method ids are: `card`, `ideal`, `bancontact`, `boleto`, `eps`, `mybank`, `satispay`, `blik`, `p24`, `pix`, `qr_code_pix`, `apple_pay`, `paypal`, `google_pay`. _name_ is just for display purposes. APMs differ from the behavior of cards. There are two possible flows, which we call `artifacts` or `redirect instructions`, explained in more detail below. APMs also require different input parameters obtained from the customer, as listed below: | Payment method name | Parameters | Flow | | ------------------- | --------------------------------------------------- | -------- | | bancontact | First name, Last name, Country | Redirect | | blik | First name, Last name, Country, Email | Redirect | | boleto | First name, Last name, Country, Email, Address, CPF | Artifact | | eps | First name, Last name, Country, Email | Redirect | | ideal | First name, Last name, Country, Email | Redirect | | myBank | First name, Last name, Country, Email | Redirect | | p24 | First name, Last name, Country, Email | Redirect | | satispay | First name, Last name, Country, Email | Redirect | | pix | | Artifact | | qr_code_pix | | Artifact | Example payload: ```json { "payment_type": "#Payment method name", "personal_details": { "email": "#Email", "first_name:": "#First Name", "last_name": "#Last Name", "tax_id": "#CPF", "address": { "country": "#Country", "city": "#Address", "line1": "#Address", "postal_code": "#Address", "state": "#Address" } } } ``` ### Process Checkout Using Redirect Flow In the Redirect Flow, when the checkout is processed, you receive the `"status": "pending"` parameter and the `next_step` parameter, which means an additional action is required to process the payment.Example response: ```json { ... "status": "pending", "next_step": { "url": "https://apm-redirect-link", "method": "POST", "payload": { "....": "..." } }, ... } ``` Most of the time, this is a simple redirect to a 3rd party page, like Blik, where the customer can pay. But, as shown above, POST requests are also possible. For all calls, ensure that the payload is included, and the appropriate method is used. Once the customer completes the necessary actions on the page, they are redirected to the `redirect_url` specified under the [create checkout request](/api/checkouts/create). Now you can retrieve the final status via a [GET checkout request](/api/checkouts/get/). ### Process Checkout Using Payment Method Artifacts Flow Payment method artifacts are images, PDFs etc. which the customer gets in order to pay. Currently, we have 3 payment methods which have artifacts: `boleto`, `pix` and `qr_code_pix`. Example requests for each: **boleto:** ```json { "boleto": { "barcode": "23790001246004987209031123456704579990000010000", "url": "https://api.sumup.com/v0.1/checkouts/19c11c6c-be1d-4dd6-b718-2798878117cb/boletos/1044833949", "valid_until": "2022-02-01T17:57:10.442+00:00", "artefacts": [ { "name": "invoice", "content_type": "application/pdf", "location": "https://homolog.meiosdepagamentobradesco.com.br/apiboleto/Bradesco?token=bWJvYXpkc1hXRzdhRVkyUUFGZUV4T25NYjBVVEZrNG93Y3RKLzM4cTh5dWdDWEh5dDQyTXN6ZHl5NFdjaHBkZg..", "created_at": "2022-01-21T17:57:10.443+00:00" }, { "name": "code", "content_type": "text/plain", "location": "https://api.sumup.com/v0.1/artefacts/5266b29e-625b-43c0-a74a-8985ea3acd8a/content", "content": "23790001246004987209031123456704579990000010000", "created_at": "2022-01-21T17:57:10.445+00:00" } ] } } ``` **pix:** ```json { "pix": { "artefacts": [ { "name": "barcode", "content_type": "image/jpeg", "location": "https://api.sumup.com/v0.1/artefacts/ee69508f-1b16-4ead-8416-8d2085933e6f/content", "created_at": "2021-10-12T22:06:46.327+00:00" }, { "name": "code", "content_type": "text/plain", "location": "https://api.sumup.com/v0.1/artefacts/1e1e5130-17d1-495a-8e36-2a50d40dacde/content", "content": "00020126580014br.gov.bcb.pix0136a4fac492-d03b-45a8-bd43-c3f23d4bac68520400005303986540520.005802BR5916Priscila Manhaes6009Sao Paulo62290525SUMUP202110122206453822986304A61E", "created_at": "2021-10-12T22:06:46.326+00:00" } ] } } ``` **qr_code_pix:** ```json { "qr_code_pix": { "artefacts": [ { "name": "barcode", "content_type": "image/jpeg", "location": "https://api.sam-app.ro/v0.1/artefacts/ee69508f-1b16-4ead-8416-8d2085933e6f/content", "created_at": "2021-10-12T22:06:46.327+00:00" }, { "name": "code", "content_type": "text/plain", "location": "https://localhost:3000/v0.1/artefacts/1e1e5130-17d1-495a-8e36-2a50d40dacde/content", "content": "00020126580014br.gov.bcb.pix0136a4fac492-d03b-45a8-bd43-c3f23d4bac68520400005303986540520.005802BR5916Priscila Manhaes6009Sao Paulo62290525SUMUP202110122206453822986304A61E", "created_at": "2021-10-12T22:06:46.326+00:00" } ] } } ``` The major difference between `qr_code_pix` and `pix` is that `pix` is paid directly into the merchant's SumUp bank account if they have one. `qr_code_pix` is paid out with the normal payout process and incurs a fee. For all artifact payments, you need to provide the customer with the artifact and wait for the checkout to eventually complete. Once the user has paid, you can retrieve the final status via the [GET checkout request](/api/checkouts/get/). # Online Payments SDKs > Overview of the available SumUp SDKs for online payments. SumUp provides the following Online Payment SDKs: - [Server-side SDKs](/online-payments/sdks/) - Node.js, Go, Python, Java, PHP, .NET, and Rust clients for the SumUp API - [React Native SDK](/online-payments/sdks/react-native/) - provides a payment sheet that is displayed on top of your app - [Swift Checkout SDK](/online-payments/checkouts/swift-checkout) - fast online checkout experience for Apple Pay and Google Pay # Payment Widget > Explore the SumUp Payment Widget, including mounting and configuration for your site. import { Aside, Steps } from "@astrojs/starlight/components"; import CardWidget from "@components/content/CardWidget.astro"; The Payment Widget, available to all SumUp merchants, simplifies website checkouts, handling PCI and PSD2 compliance with customization options. It collects card and alternative payment method details. For card payments, it dynamically recognizes the brand and shows the respective brand icon. Using the widget is really easy! A secure HTTPS connection is used to submit the payment information. For production usage we only support HTTPS for the payment page. (note: [during development browsers will treat `localhost` as secure](https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Secure_Contexts#potentially_trustworthy_origins)). ## Prerequisites Payment Widget requires only the ability to create online checkouts via [SumUp checkout API](/api/checkouts/create), authorized by API key or access token (see the [Authorization Guide](/tools/authorization/) for details).​ ## Compliance ### Payment Card Industry The Payment Widget ensures PCI compliance for your business. You do not need to worry about storing or sending sensitive information, such as card details, to SumUp servers. ### Payment Services Directive 2 Strong Customer Authentication (SCA) under Payment Services Directive 2 (PSD2) requires two-factor authentication for European online payments. The widget supports 3D Secure, with bank fallback to 3D Secure 1 in case the customer's bank doesn't support 3DS 2, adding security layers like bank redirects, SMS codes, or app confirmation. Regardless of the 3DS version used, the customer is provided with a seamless checkout experience. ## Integration 1. In order to integrate the Payment Widget on your website, include the `sdk.js` script on your payment page. ```js ``` 2. Once the script is loaded, you have access to a global variable `SumUpCard`, with a `mount` method which renders the available payment methods. 3. [Create a checkout](/api/checkouts/create) and copy the returned `id`. 4. Pass the returned `id` from the checkout response to the widget component. ```html
``` The Payment Widget makes a request to execute the checkout and after the request is completed, you get a response based on the callback function configured. As a result of successful integration, you can see the following component:
## Configurations The Payment Widget allows you to customize certain properties on the card display, as listed below. If you wish to override the default settings, add your own configuration property-value pairs to the `SumUpCard.mount` method. ```js SumUpCard.mount({ checkoutId: "...", // 'config-name': 'config-value' }); ``` | Property Name | Description | Value | Default Value | Required | | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ | -------- | | `checkoutId` | The unique ID you receive once you [create a checkout](/online-payments/guides/single-payment/#1-create-a-checkout). | `string` | _no default value_ | yes | | `onResponse` | The callback function that will be called when you receive a response from the payment form. The first parameter is one of the following: | `function` | `null` | no | | `onLoad` | The callback function that will be called when the card widget is loaded. | `function` | `null` | no | | `onPaymentMethodsLoad` | The callback is called when the payment methods are loaded for the given `checkoutId`. Usually used for when the host page needs to change depending on the payment methods available.

Payment methods can be filtered in order to limit those shown by the widget. `return` the list of payment methods for the widget to render as an _Array of Strings_. E.g. to show only Boleto, when available: `() => ['boleto']`; | `function` | `null` | no | | `onChangeInstallments`\* | The callback function that will be called when the user changes the dropdown for installments. The first and only parameter will be the number of selected installments. (`showInstallments` must be enabled). | `function` | `null` | no | | `showSubmitButton` | Displays or hides the form's submit button. | `boolean` | `true` | no | | `showFooter` | Displays or hides "Powered by SumUp" label. | `boolean` | `true` | no | | `showInstallments`\* | Displays or hides a dropdown for choosing installments. Once enabled this overrides any value of the configuration `installments` and will not display `amount` on the submit button. | `boolean` | `false` | no | | `showZipCode`\*\* | Displays or hides ZIP code input field. It is mandatory for merchant users from USA. | `boolean` | `false` | no | | `showEmail` | Displays or hides email input field. At some time in the future it'll be a mandatory field for every integrator because of the SCA. | `boolean` | `false` | no | | `email` | Alternative way (to `showEmail`) to pass user's email if for example you know it from a previous step in your application. This configuration doesn't display additional input fields. If for some reason both `showEmail` and `email` are passed the `email` will have no effect over the displayed input field. | `string` | `null` | no | | `installments`\* | The number of installments with which the transaction should be processed. | `number`
[1 .. 12] | `null` | no | | `maxInstallments`\* | The maximum amount of installments in the selector displayed by the widget. | `number`
[1 .. 12] | `12` | no | | `id` | `id` of the element that you wish to render the card widget in. _Example:_ `
` | `string` | `"sumup-card"` | no | | `donateSubmitButton` | Changes the text of the submit button to "Donate". | `boolean` | `false` | no | | `amount` | The `amount` you want to be displayed on the submit button. _Requires_ `currency` _and_ `locale` _to take effect._ | `string` | `null` | no | | `currency` | The `currency` for the `amount` you want to be displayed on the submit button. | One of: `"EUR"`, `"BGN"`, `"BRL"`, `"CHF"`, `"CZK"`, `"DKK"`, `"GBP"`, `"HUF"`, `"NOK"`, `"PLN"`, `"SEK"`, `"USD"` | `null` | no | | `locale` | Translates all texts into the given locale. Also specifies the formatting of the `amount` and `currency`. | One of:
`"bg-BG"`, `"cs-CZ"`, `"da-DK"`, `"de-AT"`, `"de-CH"`, `"de-DE"`, `"de-LU"`, `"el-CY"`, `"el-GR"`, `"en-GB"`, `"en-IE"`, `"en-MT"`, `"en-US"`, `"es-CL"`, `"es-ES"`, `"et-EE"`, `"fi-FI"`, `"fr-BE"`, `"fr-CH"`, `"fr-FR"`, `"fr-LU"`, `"hu-HU"`, `"it-CH"`, `"it-IT"`, `"lt-LT"`, `"lv-LV"`, `"nb-NO"`, `"nl-BE"`, `"nl-NL"`, `"pt-BR"`, `"pt-PT"`, `"pl-PL"`, `"sk-SK"`, `"sl-SI"`, `"sv-SE"` | `"en-GB"` | no | | `country` | Sets the country where the user account is from. | One of: `"AT"`, `"BE"`, `"BG"`, `"BR"`, `"CH"`, `"CL"`, `"CO"`, `"CY"`, `"CZ"`, `"DE"`, `"DK"`, `"EE"`, `"ES"`, `"FI"`, `"FR"`, `"GB"`, `"GR"`, `"HR"`, `"HU"`, `"IE"`, `"IT"`, `"LT"`, `"LU"`, `"LV"`, `"MT"`, `"NL"`, `"NO"`, `"PL"`, `"PT"`, `"RO"`, `"SE"`, `"SI"`, `"SK"`, `"US"` | `null` | no | | `googlePay` | Required for accepting payments with the widget via Google Pay:
For more details check [Google Pay **`merchantInfo`** documentation](https://developers.google.com/pay/api/web/reference/request-objects#MerchantInfo). | `{merchantId: string, merchantName: string}` | `null` | no | _\* Installments are available only to merchant users in Brazil._
_\*\* ZIP code is required only for merchant users in the USA._ ## Methods | Name | Description | Parameters | Return Type | | ------- | ----------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `mount` | Initializes and renders the payment form. | JSON object with a [configuration](#configurations). | Returns object that contains three methods: `submit`, `unmount` and `update`. | ## Alternative Payment Methods Depending on the country a merchant is registered in, [Alternative Payment Methods (APMs)](/online-payments/apm) are available for accepting payments from your customers. Please note, the `show*` configuration properties from the [widget configurations](#configurations) do not apply to APMs. The APMs will only render fields applicable to the respective payment method. You can begin offering APMs to your customers, once you are onboarded as a merchant. Request assistance with getting onboarded for APMs through our [contact form](/contact). ## Custom Styling Custom styling to most of the SumUp Payment Widget elements is enabled by the `data-sumup-id` attribute. To get all elements, query the DOM with `document.querySelectorAll('[data-sumup-id]')`. Here's an example of updating styles for one of the elements: ```css [data-sumup-id="widget__container"] { color: red; line-height: 18px; } ``` You can also style child elements to those with the `data-sumup-id`, by chaining their tag or other uniquely identifiable attribute. Elements like Payment Selector have some additional items you can query to extend your customizations. To style a specific Payment Selector, you need to appoint the `data-sumup-item=${payment.id}`. ```css [data-sumup-id="payment_option"][data-sumup-item="blik"] { display: none; } ``` ## Using Your Own Submit Button If you need to use your own submit button, you can achieve this by following the example below: ```html ``` ## Handling Strict Content Security Policies Pages with strict [Content Security Policies](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) (CSP) may experience issues with styles or images when rendering the SumUp Payment Widget. This section contains the necessary adjustments to render the Payment Widget properly. To confirm your issue is related to CSP, check your browser's console for a similar error message: ```text Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' \*\*\* Either the 'unsafe-inline' keyword, a hash ('sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='), or a nonce ('nonce-...') is required to enable inline execution. ``` ### Required Configurations In order to properly render the card widget with CSP in place, you must whitelist the following URLs for your application: | Content Type | URL | | ------------ | ----------------------------------- | | SDK & API | 'https://\*.sumup.com' | | Images | 'data:', 'https://static.sumup.com' | Additionally, `nonce` is required to make inline styles work on your host page. For more information view [the CSP docs](https://content-security-policy.com/nonce/). Example implementation with `nonce`: ```js const express = require("express"); const app = express(); const http = require("http"); const server = http.createServer(app); const port = process.env.PORT || 4000; const crypto = require("crypto"); // Resources const apisToConnect = ["https://gateway.sumup.com", "https://api.sumup.com"]; const imagesResources = [ "data:", // inline icons "https://static.sumup.com", // For generated barcodes "https://api.sumup.com", ]; const scriptsResources = [ "https://gateway.sumup.com", // PLUS nonce-$HASH ]; const stylesResources = [ // nonce-$HASH ]; const framesResources = ["https://gateway.sumup.com"]; app.get("/", (req, res) => { const nonce = crypto.randomBytes(16).toString("base64"); res.setHeader( "Content-Security-Policy", `default-src 'self';` + ` connect-src 'self' ${apisToConnect.join(" ")};` + ` img-src 'self' ${imagesResources.join(" ")};` + ` script-src 'self' ${scriptsResources.join(" ")} 'nonce-${nonce}';` + ` style-src 'self' 'nonce-${nonce}';` + ` frame-src 'self' ${framesResources.join(" ")};`, ); // res.send(`

Test CSP

Test using generated nonce: ${nonce}
See without nonce
Footer
`); }); server.listen(port, () => { console.log("listening on:", port); }); ``` If you continue to experience issues with rendering the Payment Widget, reach out to our support through this [contact form](/contact). # Hosted Checkout > Use the Swift Checkout SDK to add card payment, Apple Pay, and Google Pay to your website with minimal setup. import { Aside } from '@astrojs/starlight/components'; import Image from '@components/content/Image.astro'; ## About Hosted Checkout Hosted Checkout offers a complete checkout flow for payment collection. It's called "Hosted Checkout", because SumUp renders and hosts the entire checkout UI, which your customers can access via URL returned by our checkout API. The hosted checkout page aims at ease of integration, requiring little to no code, offering a summary of the checkout details, and providing a complete flow for handling payment collection. It covers the payment flows all the way to the success page. Hosted Checkouts is available to all SumUp merchants and getting started with it is really easy! A screenshot of the Hosted Checkout form showing available payment options, including Google Pay, Apple Pay, and card payment ## Prerequisites Hosted Checkout requires only the ability to create online checkouts via [SumUp checkout API](/api/checkouts/create), authorized by API key or access token (see the [Authorization Guide](/tools/authorization/) for details).​ ## Accessing Hosted Checkout You can opt-in for Hosted Checkout by providing an extra parameter to your POST request payload. The parameter name should be `hosted_checkout` and the value should be an object with the following structure: `{ "enabled": true }`. The response includes the Hosted Checkout properties: - `hosted_checkout` is returned as provided in the request - `hosted_checkout_url` provides the URL of the page handling the payment flow 1. Send a request with the `"hosted_checkout": { "enabled": true }` in the body. ```bash curl -X POST https://api.sumup.com/v0.1/checkouts \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $SUMUP_API_KEY" \ -d '{ "amount": 12.00, "checkout_reference": "b50pr914-6k0e-3091-a592-890010285b3d", "currency": "EUR", "description": "A sample checkout", "merchant_code": "MCXXXXXX", "hosted_checkout": { "enabled": true } }' ``` The response body contains the `hosted_checkout` and `hosted_checkout_url` parameters: ```json { "amount": 12, "checkout_reference": "b50pr914-6k0e-3091-a592-890010285b3d", "checkout_type": "checkout", "currency": "EUR", "date":"2000-01-01T12:49:24.899+00:00", "description": "A sample checkout", "id": "64553e20-3f0e-49e4-8af3-fd0eca86ce91", "merchant_code": "MCXXXXXX", "merchant_country": "DE", "merchant_name": "Sample Shop", "purpose": "CHECKOUT", "status": "PENDING", "transactions": [], "hosted_checkout": { "enabled": true }, "hosted_checkout_url": "https://checkout.sumup.com/pay/8f9316a3-cda9-42a9-9771-54d534315676" } ``` 2. Use the payment page provided under `hosted_checkout_url` to complete the flow you're building. See [Configuring Hosted Checkout](#configuring-hosted-checkout) for more information. ## Configuring Hosted Checkout ### Redirecting Users After Successful Payment Hosted Checkout is meant to suit a broad range of use cases, from a simple self-contained payment solution, to a checkout step integrated within a longer flow. When creating a checkout, simply provide a `redirect_url` parameter to include a redirect link in the success page, under a "Redirect to merchant website" button. ## Hosted Checkout Status Pages With Hosted Checkout, your payment flow is covered from start to finish. All successful payments are presented with a success page, informing users of the completed payment. Hosted Checkout also accommodates other payment outcomes: - Successful payments. This page includes the "Back to merchant website" button only if the `redirect_url` was provided at checkout creation. A screenshot of the Hosted Checkout payment successful confirmation form - Failed payments include express checkout payment methods for a quick retry. A screenshot of the Hosted Checkout payment failed form - Expired session page is shown for all unpaid checkouts after session expiration or checkout expiration (currently 30 minutes). A screenshot of the Hosted Checkout session expiry form - Not found page is shown for all URLs that do not match any existing session in our system. A screenshot of the Hosted Checkout page not found form # Swift Checkout SDK > Learn about the Swift Checkout SDK to offer Apple Pay and Google Pay on your website with minimal setup. import { Aside } from '@astrojs/starlight/components'; The Swift Checkout SDK enables you to offer a complete and fast checkout experience to your end users, allowing you to collect payment, address, and contact information with a click of a button. Swift Checkout SDK allows for Google Pay and Apple Pay setup. ## Prerequisites - Add a payment method to your browser or wallet. For example, you can save a card in Chrome, add a card to your Apple Wallet for Safari and iOS - Serve your application over HTTPS. This is a requirement both in development and in production environments. One way to get up and running is to use a service like [ngrok](https://ngrok.com/) Currently available payment methods through Swift Checkout SDK: - [Apple Pay](#apple-pay-setup) - [Google Pay](#google-pay-setup) ## SumUp Swift Checkout SDK Setup Include the SDK.js in your page as shown below: ```html
``` Or with JavaScript: ```javascript function injectScript() { return new Promise((resolve) => { var script = document.createElement('script'); script.type = 'text/javascript'; script.onload = function () { resolve(window.SumUp); }; script.src = 'https://js.sumup.com/swift-checkout/v1/sdk.js'; document.body.appendChild(script); }); } ``` Once the script is loaded, a new SumUp object is injected into the window instance representing SumUp SDK namespace, which contains the SwiftCheckout client. ## Obtaining a Public API Key To obtain a public API key navigate to your [Developer Settings Portal](https://developer.sumup.com/auth/login) and select **API keys** from the top right corner menu. Your public merchant key will be automatically generated with a `Private` label and a value such as `sup_pk_0x98lsJhJAs...u5kvg`. ## SumUp Swift Checkout Client ```javascript const swiftCheckoutClient = new window.SumUp.SwiftCheckout('sup_pk_0x98lsJhJAs...u5kvg'); ``` The client contains a set of objects to render a payment element UI, request payment authorization and process a payment using SumUp’s API. ### Payment Request Object The payment request object requests payment authorizations made with various payment methods. It requires an argument that contains a set of details, information about the requested transaction to be processed, that will be presented to the user to authorize the payment later. Payment request object arguments consist of: - `countryCode`: Represents the country or region of the merchant’s principle place of business. - `total`: Represents what is about to be paid by the user, E.g. a summary of an order. It requires a `label` and an `amount`. The `amount` value must be provided as a string in major unit and should use a period (`.`) as a decimal separator.\ More specifically, the `amount` value should match the following regex: `^[0-9]+(\.[0-9][0-9])?$` Optional: - `locale`: Represents the locale the text "Pay with \{\{payment method\}\}" will be displayed with in the buttons. ```js const paymentRequest = swiftCheckoutClient.paymentRequest({ countryCode: 'DE', locale: 'de-DE', total: { label: 'My goods', amount: { currency: 'EUR', value: '65.00' }, }, }); ``` - `shippingOptions`: Represents a collection of shipping methods the end user can select from to receive their purchased goods. The initial `shippingOptions` list can be later modified according to the shipping address the user selects in the payment dialog. ```js const paymentRequest = swiftCheckoutClient.paymentRequest({ shippingOptions: [ { id: 'post', label: 'postal service', amount: { currency: 'EUR', value: '0.00' }, description: 'free post', }, ], }); ``` This object is an analogue to the [PaymentRequest - Web APIs](https://developer.mozilla.org/en-US/docs/Web/API/PaymentRequest/PaymentRequest). The payment request instance contains the logic related to **checking payment method availability and showing** the payment method dialogue once the user interacts with a **payment element**. ### Payment Request Interface All methods in the payment request object are asynchronous. Listed below are the payment request methods and their usage: #### `canMakePayment` Checks if the given merchant public key has access to at least one payment method and checks the payment method availability in the given environment (browser). Returns a promise that resolves in a `boolean`. #### `availablePaymentMethods` Returns the available payment methods for a merchant. Returns a promise that resolves in an `array` of objects representing each available payment method. #### `show` Shows the payment authorization dialogue for a given payment method. It requires an object containing a `paymentMethod`, which defines the selected payment method. This method is usually used along with the `PaymentElement`'s `onSubmit` event. The `show` method resolves with a `AuthorizedPayment`, which contains the `details` shared by the user once they authorize the payment request. The property `details` contains `paymentMethod`, `contactInformation`, `shippingAddress` and may contain `shippingOptions`. A `PaymentRequestCancelledError` will be thrown when the user rejects or cancels the transaction. ```js paymentRequest .show({ paymentMethod: 'apple_pay' }) .then(processCheckoutAttempt) .then(handleResponse) .catch((error) => { if ( error instanceof SumUp.SwiftCheckout.Errors.PaymentRequestCancelledError ) { console.log('Cancelled by the user'); } else { throw error; } }); ``` #### `abort` Terminates a payment request before it is processed. Once a payment request has been terminated using this method, the payment request will not be processed and the payment dialogue will be closed. ```js if (someCustomCheck()) { try { await paymentRequest.abort(); // will throw an error. console.log('Payment request aborted due to my custom reason.') } catch(e) { console.error( 'Unable to abort, because the user is currently in the process of paying.' ); } } ``` #### `onShippingAddressChange` Allows adding an event handler which will be triggered every time the user changes their shipping address. The handler can optionally provide a return value to change the following in the payment dialog: - `total` - `shippingOptions` ```js paymentRequest.onShippingAddressChange(async (newShippingAddress) => { const { total, shippingOptions } = await someAsyncOperation( newShippingAddress, ); return { total, shippingOptions, }; }); ``` #### `onShippingOptionsChange` Allows adding an event handler which will be triggered every time the user changes their shipping option choice. The handler can optionally provide a return value to change the following in the payment dialog: - `total` - `shippingAddress` - `shippingOptions` ```js paymentRequest.onShippingOptionsChange(async (selectedShippingOption) => { const { newTotal, newShippingAddress, newShippingOptions } = await someAsyncOperation( total shippingOption, ); return { total, shippingAddress, shippingOptions, }; }); ``` ### Payment Element Builder In order to request a payment, you need to create a UI element. The SDK provides a built-in PaymentElement UI builder, which allows you to create and configure the payment buttons. _Each payment button can be rendered individually as well._ The Swift Elements Builder allows you to attach an `onSubmit` handler, which will be called once the user clicks on one of the buttons rendered by it. The `mount` method accepts a `paymentMethods` array, enabling you to filter the payment methods you want to offer. The arguments passed during `mount`, will render one or more buttons: ```js const buttons = swiftCheckoutClient.elements(); buttons .onSubmit((paymentEvent) => console.log(paymentEvent)) .mount({ paymentMethods: [ { id: 'apple_pay' }, { id: 'google_pay' } // See `paymentRequest.availablePaymentMethods()` for all available payment methods ], container: document.querySelector('#express-checkout-container'), }); ``` #### Rendering Buttons for Available Payment Methods Once the UI and Payment Request are configured, you have to check the availability of Swift payment methods and `mount` them into the page. The SDK checks several factors to determine if a given payment method is available: - Is the payment method available for the given merchant? - Is the payment method available on the browser? - Is the wallet/card ready to accept payment requests? After checking if making payments is possible, render the payment element into a given placeholder as shown below: ```js paymentRequest.canMakePayment().then((isAvailable) => { if (isAvailable) { paymentRequest.availablePaymentMethods().then((paymentMethods) => { buttons.mount({ paymentMethods, container: document.querySelector('#express-checkout-container'), }); }); } else { console.error('No payment method available!'); } }); ``` ### Requesting Payment Authorization The authorization dialogue is where the user will review the payment requested, select a payment card and a shipping address. Finally, they can authorize the payment request to be **processed**. Using the payment element builder, configure it to `show` the payment authorization dialogue from the Payment Request instance upon the `onSubmit` event. Once the user authorizes the payment the `show` method will resolve a `PaymentResponse` containing details about the payment authorization. ```js buttons.onSubmit((paymentMethodEvent) => { paymentRequest .show(paymentMethodEvent) .then((paymentResponse) => console.log(paymentResponse)); }); ``` To understand more about the PaymentResponse objects see Mozilla's official [PaymentResponse - Web APIs](https://developer.mozilla.org/en-US/docs/Web/API/PaymentResponse) documentation. ### Processing an Authorized Payment Request To process a payment, the SumUp API requires you to create a checkout for a given amount. The checkout creation requires an authenticated request. Thus, we recommend implementing an endpoint on your backend that will authenticate with our API, create a checkout and return a `checkoutId`. Once you obtain a `checkoutId`, call the `processCheckout` method from the SwiftCheckout client with the `checkoutId` and the `PaymentResponse`, which was received in the previous step, to start the processing the checkout. ```js paymentRequest .show(paymentMethodEvent) .then((paymentResponse) => { console.log(paymentResponse.details); // contactInfo, shippingAddress, etc. // here you create your order and a sumup checkout const checkoutId = 'c463bf5e-d397-4bca-9d2e-a4e04f668b1c'; return swiftCheckoutClient.processCheckout(checkoutId, paymentResponse); }) .then(console.log) .catch(console.error); ``` ### The Complete Implementation ```js const swiftCheckoutClient = new window.SumUp.SwiftCheckout( 'fOcmczrYtYMJ7Li5GjMLLcUeC9dN', ); const paymentRequest = swiftCheckoutClient.paymentRequest({ total: { label: 'One Shoe', amount: { value: '100.0', }, }, shippingOptions: [ { id: 'post', label: 'postal service', amount: { currency: 'EUR', value: '0.00' }, description: 'free post', }, ], }); const buttons = swiftCheckoutClient.elements(); buttons.onSubmit((paymentMethodEvent) => { paymentRequest .show(paymentMethodEvent) .then((paymentResponse) => { console.log(paymentResponse.details); // Create your order and a checkout const checkoutId = 'c463bf5e-d397-4bca-9d2e-a4e04f668b1c'; return swiftCheckoutClient.processCheckout(checkoutId, paymentResponse); }) .then((result) => { if (result.status === 'PAID') { window.location.href = '/thankyou'; } else { console.error( 'It was not possible to process the checkout', result.message, ); } }) .catch((error) => { if ( error instanceof SumUp.SwiftCheckout.Errors.PaymentRequestCancelledError ) { console.error('Cancelled by the user'); } else { throw error; } }); }); paymentRequest.canMakePayment().then((isAvailable) => { if (isAvailable) { paymentRequest.availablePaymentMethods().then((paymentMethods) => { buttons.mount({ paymentMethods, container: document.querySelector('#express-checkout-container'), }); }); } else { console.error('No payment method is available.'); } }); ``` ## Error Handling The Swift Checkout SDK returns a series of Errors depending on the event that has taken place. You can use the errors to customise the user experience and communicate error causes as you see fit. - `PaymentRequestCancelledError` is thrown when the end user closes the open payment dialog or presses the button `esc`. - `PaymentRequestInvalidActionError` is thrown when the end user has submitted the payment dialog and then attempted to cancel the payment. Once the payment form is submitted the payment can no longer be cancelled. - `PaymentRequestInternalError` is thrown when attempting to handle the payment request in a forbidden manner. Reasons that you may receive include the following codes, available in the `code` field of the Error object: - `SHIPPING_CONTACT_SELECTION` - `SHIPPING_ADDRESS_SELECTION` - `SHIPPING_METHOD_SELECTION` - `INTERNAL_VALIDATION` - `COMPLETE_PAYMENT` - `UNKNOWN` ## Apple Pay Setup ### Prerequisites - [Verify your domain with Apple Pay](#verify-your-domain-with-apple-pay), both in development and production - For Apple Pay [additional configurations](#apple-pay-setup) are required, including macOS 10.12.1+ or iOS 10.1+ ### Verify your domain with Apple Pay To use Apple Pay, you need to register with Apple on all of your web domains which will show an Apple Pay button. Apple’s documentation for Apple Pay on the Web describes their process of “merchant validation”, which SumUp handles for you behind the scenes. You don’t need to create an Apple Merchant ID, CSR and so on, as described in their documentation. Instead, follow the steps in this section: 1. Request the domain association file through our [contact form](https://developer.sumup.com/contact/) and host it at `https://[YOUR_DOMAIN_NAME]/.well-known/apple-developer-merchantid-domain-association`. 2. Once hosted, request assistance from our integration specialists through the form, to register your domain with Apple. ## Google Pay Setup ### Prerequisites - [Request production access](https://pay.google.com/business/console/) to Google Pay for your domain name - Adhere to the [Google Pay requirements](https://developers.google.com/pay/api/web/guides/setup#get-started) - Review [Google Pay API terms of service](https://payments.developers.google.com/terms/sellertos) ### Google Pay Specific Parameters Google Pay’s base payment request object requires a few unique parameters: - [`merchantInfo` object](https://developers.google.com/pay/api/web/reference/request-objects#MerchantInfo) with the following keys: - `merchantId`- unique identifier provided to you by Google once you [register your domain](https://pay.google.com/business/console/) with them - `merchantName`- your merchant name Here’s an example of how the merchantInfo object is included in a Google Pay payment request: ```js const paymentRequest = sumUpClient.paymentRequest({ methodData: [ { supportedMethods: 'google_pay', data: { merchantInfo: { merchantId: '123456789123456789', merchantName: 'Example Merchant', }, }, }, ], }); ``` ### Validating Your Domain with Google Pay In order to use Google Pay you need to validate your domain with Google. This process requires rendering a nonfunctional Google Pay button on your website and providing them with screenshots of your checkout flow. To render a Google Pay button on your shop in demo mode, you need to add the `#sumup:google-pay-demo-mode` hash to the page's URL. Once the hash has been applied you can proceed with the domain validation steps: 1. Create an account in the [Google Pay console](https://pay.google.com/business/console) 2. Go to the **Google Pay API** tabitem in your Google Pay console 3. Navigate to the **Integrate with your website** and click on **+ Add website** 4. Fill out the form with the requested information (domain name, buyflow screenshots, etc.) 5. At the top of the page click on **Submit for approval** # Custom Integrations > Integration guides for building with SumUp SDKs and APIs. import { Steps } from '@astrojs/starlight/components'; import Image from '@components/content/Image.astro'; Guides in this section cover the basics of SumUp APIs, allowing you to develop a custom integration if SumUp products don't fully support your use case. ## Getting a Sandbox Merchant Account Create a sandbox merchant account to test APIs without real money: 1. Log in to your SumUp account. 2. Open the drop-down menu between **Support** and your user panel. 3. Select **Sandbox Merchant Account**. Your merchant account is now switched to sandbox mode. A screenshot of the account selection dropdown in the SumUp dashboard with the sandbox merchant account highlighted with red circle With your sandbox merchant account, begin making API calls with real data. Sandbox merchant accounts **do not** process transactions with real funds. The sandbox merchant account has a different ID and displays a clear warning. Requests with a value of 11 (in any currency) always fail by design, to test failed transaction scenarios. A screenshot of the dashboard with sandbox merchant account selected When finished experimenting with the sandbox merchant account, switch back to a regular account for business purposes. SumUp provides official SDKs for Node.js, Go, Python, Java, PHP, .NET, and Rust — visit the [SDKs overview page](/online-payments/sdks/) to choose the client that fits your stack. # Refunds > Walks through looking up transactions and issuing full or partial refunds. import { Aside, Tabs, TabItem } from '@astrojs/starlight/components'; import Multicode from '@components/content/Multicode.astro'; ## Overview In this guide, you will learn how to refund a transaction. You will go through the following steps: 1. [Look up a transaction ID (Optional)](#1-look-up-a-transaction-id) 2. [Refund a transaction](#2-refund-a-transaction) by using one of the available options: - [Option A: Make a full refund](#make-a-full-refund) - [Option B: Make a partial refund](#make-a-partial-refund) When you complete these steps, the payment you have previously processed through SumUp will be refunded either partially or in full. ## Before You Begin Here are the things that you need in order to complete the steps in this guide: - [SumUp merchant account](https://me.sumup.com/login) with completed [account details](https://me.sumup.com/account). - You can also use a [sandbox merchant account](/online-payments/#getting-a-sandbox-merchant-account). - [Registered client application](/tools/authorization/oauth/#register-an-oauth-application) with SumUp. - Valid access token obtained with the [Authorization code flow](/tools/authorization/oauth/#authorization-code-flow). - You have processed a checkout and you have the checkout ID. ## Steps ### 1. Look up a Transaction ID 1. Make a GET request to the `https://api.sumup.com/v0.1/checkouts/{id}` endpoint, where the value of the `{id}` path parameter is the identifier of the checkout resource. Example request: ```bash curl -X GET \ https://api.sumup.com/v0.1/checkouts/4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2 \ -H "Authorization: Bearer $SUMUP_API_KEY" ``` ```ts const checkout = await client.checkouts.get("4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2"); ``` ```csharp var checkout = await client.Checkouts.GetAsync("4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2"); ``` ```java var checkout = client.checkouts().getCheckout("4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2"); ``` ```go ctx := context.Background() client := sumup.NewClient() checkout, err := client.Checkouts.Get(ctx, "4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2") ``` ```py checkout = client.checkouts.get("4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2") ``` ```rust let checkout = client .checkouts() .get("4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2") .await?; ``` ```php $checkout = $sumup->checkouts->get('4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2'); $checkoutReference = $checkout->checkout_reference; $checkoutId = $checkout->id; ``` The response contains a JSON body with the full details of the processed checkout resource. You can find the transaction ID in the `id` attribute of the respective transaction resource (`664200af-2b62-4142-9c73-a2a505310d78` in the sample response below). ```json { "checkout_reference": "CO287866", ... "id": "4ebc2ed7-bb8c-4d4d-a110-08fd31301bf2", ... "transactions": [ { "id": "664200af-2b62-4142-9c73-a2a505310d78", ... } ] } ``` ### 2. Refund a Transaction - [Option A: Make a full refund](#make-a-full-refund) - [Option B: Make a partial refund](#make-a-partial-refund) #### Make a Full Refund 1. Make a POST request with an empty request body to the `https://api.sumup.com/v0.1/me/refund/{txn_id}` endpoint, where the value of the `{txn_id}` path parameter is the identifier of the transaction resource. Example request for the transaction with identifier `664200af-2b62-4142-9c73-a2a505310d78`: ```bash curl -X POST \ https://api.sumup.com/v0.1/me/refund/19aa3cca-89f6-42d2-b462-463b0b53e959 \ -H "Authorization: Bearer $SUMUP_API_KEY" ``` ```ts await client.transactions.refund("19aa3cca-89f6-42d2-b462-463b0b53e959"); ``` ```csharp await client.Transactions.RefundAsync("19aa3cca-89f6-42d2-b462-463b0b53e959"); ``` ```java client.transactions().refundTransaction( "19aa3cca-89f6-42d2-b462-463b0b53e959", RefundTransactionRequest.builder().build() ); ``` ```go ctx := context.Background() client := sumup.NewClient() err := client.Transactions.Refund(ctx, "19aa3cca-89f6-42d2-b462-463b0b53e959", sumup.TransactionsRefundParams{}) ``` ```py from sumup.transactions.resource import RefundTransactionBody client.transactions.refund( "19aa3cca-89f6-42d2-b462-463b0b53e959", RefundTransactionBody(), ) ``` ```rust client .transactions() .refund("19aa3cca-89f6-42d2-b462-463b0b53e959", None) .await?; ``` ```php $sumup->transactions->refund('19aa3cca-89f6-42d2-b462-463b0b53e959'); ``` The response returns a 204 HTTP status code and contains no body. #### Make a Partial Refund 1. Make a POST request to the `https://api.sumup.com/v0.1/me/refund/{txn_id}` endpoint, where the value of the `{txn_id}` path parameter is the identifier of the transaction resource. Unlike the option for a full refund, the request body for partial refunds should be a JSON object with the amount you want to refund for the transaction. Example request for a partial refund for the amount of 24.42 EUR: ```bash curl -X POST \ https://api.sumup.com/v0.1/me/refund/19aa3cca-89f6-42d2-b462-463b0b53e959 \ -H "Authorization: Bearer $SUMUP_API_KEY" \ -H 'Content-Type: application/json' \ -d '{"amount": 24.42}' ``` ```ts await client.transactions.refund("19aa3cca-89f6-42d2-b462-463b0b53e959", { amount: 24.42, }); ``` ```csharp await client.Transactions.RefundAsync( "19aa3cca-89f6-42d2-b462-463b0b53e959", new TransactionsRefundRequest { Amount = 24.42f, }); ``` ```java client.transactions().refundTransaction( "19aa3cca-89f6-42d2-b462-463b0b53e959", RefundTransactionRequest.builder().amount(24.42f).build() ); ``` ```go ctx := context.Background() client := sumup.NewClient() amount := float32(24.42) client.Transactions.Refund(ctx, "19aa3cca-89f6-42d2-b462-463b0b53e959", sumup.TransactionsRefundParams{ Amount: &amount, }) ``` ```py from sumup.transactions.resource import RefundTransactionBody client.transactions.refund( "19aa3cca-89f6-42d2-b462-463b0b53e959", RefundTransactionBody(amount=24.42), ) ``` ```rust use sumup::resources::transactions::RefundTransactionBody; client .transactions() .refund( "19aa3cca-89f6-42d2-b462-463b0b53e959", Some(RefundTransactionBody { amount: Some(24.42) }), ) .await?; ``` ```php $sumup->transactions->refund('19aa3cca-89f6-42d2-b462-463b0b53e959', [ 'amount' => 24.42, ]); ``` The response returns a 204 HTTP status code and contains no body. ## Result You have successfully refunded a transaction (either partially or in full) for a payment you previously processed. The refunded amount will be credited to the same payment method the customer had used to pay with in the original transaction. The processing fees associated with the original transaction are not returned. # Response Handling > Explains how to interpret SumUp API responses. ## Overview Once an API call is submitted to SumUp, you will receive a standard HTTP response informing you if your request has been successful or not. In most cases the HTTP codes are accompanied by a response body in [JSON](https://json.org/) format. Codes in the `2xx` range indicate success,`4xx` range indicates errors where the information provided results in a failure. Codes in the `5xx` range are rare and indicate server-side errors. ## Successful Requests Successfully processed requests return one of the following HTTP status codes: `200 OK`, `201 Created`, `202 Accepted`, `204 No Content`. Depending on the use case response bodies may not be present at all. A response body can look like this: ```json { "next_step": { "url": "https://dummy-3ds-gateway.com/cap?RID=1233&VAA=A", "method": "POST", "redirect_url": "https://mysite.com/completed_purchase", "mechanism": "iframe", "payload": { "PaReq": "eJxVUttu2zAM/RXDr4MjyY5dO6BVuE27FZuDZHGG9VGRmMSFb/..f16+jLt/gPhUvGGw==", "MD": "b1a536c0-29b9-11eb-adc1-0242ac120002" } } } ``` ## Client-Side Issues `4xx` are occasions where you can take action to correct your application requests. Typically, these codes are returned upon user error, such as invalid API calls, incorrect values, missing parameters, etc. The response you receive will provide an indication to the root cause that triggered it. Here's an example of a `4xx` response: ```json { "message": "Validation error", "error_code": "MISSING", "param": "merchant_code" } ``` ## Server-Side Issues `5xx` stand for server errors. Although rare, if you receive such code, we recommend retrying your request. Should the returned codes continue to be in the `5xx` range, [reach out to us](/contact). # Accept a Payment > Create and process a checkout for a single card payment. import { Aside, Tabs, TabItem } from '@astrojs/starlight/components'; ## Overview This guide covers single payments over SumUp API, using customer-entered card details without associating it with a specific customer saved for the merchant user's account. Ideal for quick checkout processing if you don't want to use our [Payment Widget](/online-payments/checkouts/card-widget). You will go through the following steps: 1. [Create a checkout](#1-create-a-checkout) 2. [Complete a checkout](#2-complete-a-checkout) When you complete these steps, you will have processed a payment with a payment card entered by a customer. ## Prerequisites - [SumUp merchant account](https://me.sumup.com/login) with completed [account details](https://me.sumup.com/account). - You can also use a [sandbox merchant account](/online-payments/#getting-a-sandbox-merchant-account). - [Registered client application](/tools/authorization/oauth/#register-an-oauth-application) with SumUp. - Valid access token obtained either with the [Authorization code flow](/tools/authorization/oauth/#authorization-code-flow) or [Client credentials flow](/tools/authorization/oauth/#client-credentials-flow). ## Steps ### 1. Create a Checkout To create a new checkout resource, make a POST request to the `https://api.sumup.com/v0.1/checkouts` endpoint. | Attribute name | Description | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | checkout_reference | A unique string identifying the payment in your system. It must be unique for your application. | | amount | The amount for which the payment is made. | | currency | The three-letter [ISO4217](https://en.wikipedia.org/wiki/ISO_4217) code of the payment currency. It must match the currency registered for the specified merchant (see `merchant_code`). | | merchant_code | The code of the registered SumUp merchant the payment is made. | Example request: ```bash curl -X POST \ https://api.sumup.com/v0.1/checkouts \ -H "Authorization: Bearer $SUMUP_API_KEY" \ -H 'Content-Type: application/json' \ -d '{ "merchant_code": "ME7RMQN3", "amount": 15.0, "currency": "EUR", "checkout_reference": "unique-checkout-ref-123" }' ``` ```ts const checkout = await client.checkouts.create({ merchant_code: merchantCode, amount: 15.0, currency: "EUR", checkout_reference: "unique-checkout-ref-123" }); ``` ```csharp var checkout = await client.Checkouts.CreateAsync(new CheckoutCreateRequest { MerchantCode = merchantCode, Amount = 15.0f, Currency = Currency.Eur, CheckoutReference = "unique-checkout-ref-123", }); ``` ```java var checkout = client.checkouts().createCheckout( CheckoutCreateRequest.builder() .merchantCode(merchantCode) .amount(15.0f) .currency(Currency.EUR) .checkoutReference("unique-checkout-ref-123") .build() ); ``` ```go checkout, err := client.Checkouts.Create(ctx, sumup.CheckoutsCreateParams{ MerchantCode: merchantCode, Amount: 15.0, Currency: sumup.CurrencyEUR, CheckoutReference: "unique-checkout-ref-123", }) ``` ```py checkout = client.checkouts.create( CreateCheckoutBody( merchant_code=merchant_code, amount=15.00, currency="EUR", checkout_reference="unique-checkout-ref-123", ) ) ``` ```rust let checkout = client.checkouts().create(Some(CheckoutCreateRequest { merchant_code, amount: 15., currency: Currency::EUR, checkout_reference: "unique-checkout-ref-123".into(), description: None, return_url: None, customer_id: None, purpose: None, id: None, status: None, date: None, valid_until: None, transactions: None, redirect_url: None, })).await?; ``` ```php $checkout = $sumup->checkouts->create([ 'merchant_code' => $merchantCode, 'amount' => 15.0, 'currency' => 'EUR', 'checkout_reference' => 'unique-checkout-ref-123', ]); ``` The response contains a JSON body with the details of the created checkout resource. Note the identifier of the resource - you will need it for all operations on the resource, such as processing the payment in the next step. The resource identifier is returned in the `id` attribute, or `f14425c6-8bc1-4d02-957c-47573f762828` in the sample response below. The `status` attribute shows that the payment for this resource is pending and will be processed when you complete the checkout with the payment instrument details. ```json { "checkout_reference": "CO746453", "amount": 10, "currency": "EUR", "merchant_code": "ME7RMQN3", "description": "Sample one-time payment", "id": "f14425c6-8bc1-4d02-957c-47573f762828", "status": "PENDING", "date": "2018-09-28T13:47:01.832Z", "transactions": [] } ``` ### 2. Complete a Checkout To process the checkout and trigger the payment, make a PUT request to the `https://api.sumup.com/v0.1/checkouts/{id}` endpoint, where the value of the `{id}` path parameter is the identifier of the checkout resource. The request body should be a JSON object with the payment type (`card`) and the payment card details. For more information about the request, see the [API Reference](/api/checkouts/process). Example request for [Step 1 checkout](#1-create-a-checkout): ```bash curl -X PUT \ https://api.sumup.com/v0.1/checkouts/f14425c6-8bc1-4d02-957c-47573f762828 \ -H "Authorization: Bearer $SUMUP_API_KEY" \ -H 'Content-Type: application/json' \ -d '{ "payment_type": "card", "card": { "name": "Boaty McBoatface", "number": "4200000000000042", "expiry_month": "12", "expiry_year": "23", "cvv": "123" } }' ``` ```ts const checkout = await client.checkouts.process("f14425c6-8bc1-4d02-957c-47573f762828", { payment_type: "card", card: { name: "Boaty McBoatface", number: "4200000000000042", expiry_month: "12", expiry_year: "23", cvv: "123", }, }); ``` ```csharp var checkout = await client.Checkouts.ProcessAsync( "f14425c6-8bc1-4d02-957c-47573f762828", new ProcessCheckout { PaymentType = "card", Card = new Card { Name = "Boaty McBoatface", Number = "4200000000000042", ExpiryMonth = "12", ExpiryYear = "23", Cvv = "123", Last4Digits = "0042", Type = CardType.Visa, }, }); ``` ```java var checkout = client.checkouts().processCheckout( "f14425c6-8bc1-4d02-957c-47573f762828", ProcessCheckout.builder() .paymentType(ProcessCheckoutPaymentType.CARD) .card( Card.builder() .name("Boaty McBoatface") .number("4200000000000042") .expiryMonth(CardExpiryMonth.fromValue("12")) .expiryYear("23") .cvv("123") .build() ) .build() ); ``` ```go checkoutSuccess, err := client.Checkouts.Process(ctx, "f14425c6-8bc1-4d02-957c-47573f762828", sumup.CheckoutsProcessParams{ Card: &sumup.Card{ Cvv: "123", ExpiryMonth: "12", ExpiryYear: "23", Name: "Boaty McBoatface", Number: "4200000000000042", }, PaymentType: sumup.ProcessCheckoutPaymentTypeCard, }) ``` ```py from sumup.checkouts.resource import Card, ProcessCheckoutBody checkout = client.checkouts.process( "f14425c6-8bc1-4d02-957c-47573f762828", ProcessCheckoutBody( payment_type="card", card=Card( name="Boaty McBoatface", number="4200000000000042", expiry_month="12", expiry_year="23", cvv="123", ), ), ) ``` ```rust let checkout = client .checkouts() .process( "f14425c6-8bc1-4d02-957c-47573f762828", sumup::resources::checkouts::ProcessCheckout { payment_type: "card".into(), installments: None, mandate: None, customer_id: None, token: None, personal_details: None, card: Some(sumup::resources::checkouts::Card { name: "Boaty McBoatface".into(), number: "4200000000000042".into(), expiry_month: "12".into(), expiry_year: "23".into(), cvv: "123".into(), zip_code: None, last_4_digits: "0042".into(), type_: "VISA".into(), }), }, ) .await?; ``` ```php $checkout = $sumup->checkouts->process( 'f14425c6-8bc1-4d02-957c-47573f762828', [ 'payment_type' => 'card', 'card' => [ 'name' => 'Boaty McBoatface', 'number' => '4200000000000042', 'expiry_month' => '12', 'expiry_year' => '23', 'cvv' => '123', ], ] ); ``` The response contains a JSON body with the details of the processed checkout resource in which the attributes related to the payment outcome are populated: ```json { "checkout_reference": "CO746453", "amount": 10.0, "currency": "EUR", "merchant_code": "ME7RMQN3", "description": "Sample one-time payment", "id": "f14425c6-8bc1-4d02-957c-47573f762828", "status": "PAID", "date": "2018-09-28T13:47:01.832Z", "transaction_code": "TFDCP3FLQ7", "transaction_id": "19aa3cca-89f6-42d2-b462-463b0b53e959", "transactions": [ { "id": "19aa3cca-89f6-42d2-b462-463b0b53e959", "transaction_code": "TFDCP3FLQ7", "merchant_code": "ME7RMQN3", "amount": 10.0, "vat_amount": 0.0, "tip_amount": 0.0, "currency": "EUR", "timestamp": "2018-09-28T13:48:28.768Z", "status": "SUCCESSFUL", "payment_type": "ECOM", "entry_mode": "CUSTOMER_ENTRY", "installments_count": 1, "auth_code": "585388", "internal_id": 24118507 } ] } ``` ## Result You have made a payment with a payment card entered by a customer without associating it with a specific customer saved for a merchant user's account. If the payment is successful, the funds will be transferred to the merchant user according to the configured account settings. # Save Customer Cards > Tokenize cards with the Payment Widget for future recurring payments. import { Aside, Tabs, TabItem } from '@astrojs/starlight/components'; import Image from '@components/content/Image.astro'; ## About Card Tokenization In this guide, you will learn how to use the Payment Widget to store card details for future use, and how to set up recurring payments, as SumUp handles the UI/UX and consent collection for you. Alternatively, you can process payments with your own UI, following the API guidelines also provided in this document. This feature is also known as **card on file** or **tokenization**. You will go through the following steps: 1. [Create a customer](#creating-customer). 2. [Create checkout intended for card tokenization](#creating-checkout-to-save-card), where we specify it's for tokenization purpose. This is where 3DS verification takes place. The transaction amount is instantly reimbursed. 3. [Process payment with the payment widget](#processing-request-with-payment-widget) or [process payment directly with SumUp API](#processing-request-directly). 4. [Retrieve the tokenized card](#retrieving-tokenized-card). 5. [Make subsequent payments with the tokenized card](#processing-recurring-payments). ## Prerequisites - You have a merchant account with [SumUp](https://me.sumup.com/login) and have already filled in your [account details](https://me.sumup.com/account). - You can also create a [sandbox merchant account](/online-payments/#getting-a-sandbox-merchant-account). Please note that setting up 3DS verification in a sandbox merchant account requires contact with our team at integrations@sumup.com. - You have an API Key. For more details see the [Authorization Guide](/tools/authorization/api-keys/). - You have control over the backend server to retrieve data securely. ## Creating Customer A customer resource is a representation of a person or business paying for a product or service. It contains personal information such as name, contact details, postal address, as well as a unique identifier relevant to your business logic (`customer_id`). 1. Create a new customer resource with a POST request to the `https://api.sumup.com/v0.1/customers` endpoint: ```bash curl -X POST \ https://api.sumup.com/v0.1/customers \ -H "Authorization: Bearer $SUMUP_API_KEY" \ -H 'Content-Type: application/json' \ -d '{ "customer_id": "MYCUSTOMERID-123", "personal_details": { "address": { "city": "Venice", "state": "California", "country": "US", "line1": "606 Venezia Ave", "line2": "Front", "postal_code": "90291" }, "birthdate": "1949-11-11", "email": "thedude@example.com", "first_name": "Jeffrey", "last_name": "Lebowski", "phone": "+1 310-555-1234" } }' ``` ```ts const customer = await client.customers.create({ customer_id: "MYCUSTOMERID-123", personal_details: { first_name: "Jeffrey", last_name: "Lebowski", email: "thedude@example.com", phone: "+1 310-555-1234", birth_date: "1949-11-11", address: { city: "Venice", state: "California", country: "US", line_1: "606 Venezia Ave", line_2: "Front", postal_code: "90291", }, }, }); ``` ```csharp var customer = await client.Customers.CreateAsync(new Customer { CustomerId = "MYCUSTOMERID-123", PersonalDetails = new PersonalDetails { FirstName = "Jeffrey", LastName = "Lebowski", Email = "thedude@example.com", Phone = "+1 310-555-1234", BirthDate = new System.DateTime(1949, 11, 11), Address = new AddressLegacy { City = "Venice", State = "California", Country = "US", Line1 = "606 Venezia Ave", Line2 = "Front", PostalCode = "90291", }, }, }); ``` ```java var customer = client.customers().createCustomer( Customer.builder() .customerId("MYCUSTOMERID-123") .personalDetails( PersonalDetails.builder() .firstName("Jeffrey") .lastName("Lebowski") .email("thedude@example.com") .phone("+1 310-555-1234") .birthDate(java.time.LocalDate.parse("1949-11-11")) .address( AddressLegacy.builder() .city("Venice") .state("California") .country("US") .line1("606 Venezia Ave") .line2("Front") .postalCode("90291") .build() ) .build() ) .build() ); ``` ```go str := func(v string) *string { return &v } customer, err := client.Customers.Create(ctx, sumup.CustomersCreateParams{ CustomerID: "MYCUSTOMERID-123", PersonalDetails: &sumup.PersonalDetails{ FirstName: str("Jeffrey"), LastName: str("Lebowski"), Email: str("thedude@example.com"), Phone: str("+1 310-555-1234"), Address: &sumup.AddressLegacy{ City: str("Venice"), State: str("California"), Country: str("US"), Line1: str("606 Venezia Ave"), Line2: str("Front"), PostalCode: str("90291"), }, }, }) ``` ```py from sumup.customers.resource import CreateCustomerBody from sumup.customers.types import AddressLegacy, PersonalDetails customer = client.customers.create( CreateCustomerBody( customer_id="MYCUSTOMERID-123", personal_details=PersonalDetails( first_name="Jeffrey", last_name="Lebowski", email="thedude@example.com", phone="+1 310-555-1234", birth_date="1949-11-11", address=AddressLegacy( city="Venice", state="California", country="US", line_1="606 Venezia Ave", line_2="Front", postal_code="90291", ), ), ) ) ``` ```rust let customer = client .customers() .create(sumup::resources::customers::Customer { customer_id: "MYCUSTOMERID-123".into(), personal_details: Some(sumup::resources::common::PersonalDetails { first_name: Some("Jeffrey".into()), last_name: Some("Lebowski".into()), email: Some("thedude@example.com".into()), phone: Some("+1 310-555-1234".into()), birth_date: None, tax_id: None, address: Some(sumup::resources::common::AddressLegacy { city: Some("Venice".into()), state: Some("California".into()), country: Some("US".into()), line_1: Some("606 Venezia Ave".into()), line_2: Some("Front".into()), postal_code: Some("90291".into()), }), }), }) .await?; ``` ```php $customer = $sumup->customers->create([ 'customer_id' => 'MYCUSTOMERID-123', 'personal_details' => [ 'first_name' => 'Jeffrey', 'last_name' => 'Lebowski', 'email' => 'thedude@example.com', 'phone' => '+1 310-555-1234', 'address' => [ 'city' => 'Venice', 'state' => 'California', 'country' => 'US', 'line_1' => '606 Venezia Ave', 'line_2' => 'Front', 'postal_code' => '90291', ], ], ]); ``` You should expect a standard `201 Created` response, with the customer details you passed. For full details, see the [endpoint documentation](/api/customers/create). Having created the customer, we can now proceed to making a payment ## Creating Checkout to Save Card Now, we need to tokenize the customer's card, and we will need a checkout for this. The checkout resource is a representation of a payment being made by the previously created customer. It contains information such as the amount, currency, and a unique `checkout_reference` identifier that is relevant to your business logic. The flow is initiated with the `create a checkout` endpoint. It is important to pass the `customer_id` parameter in this step, for future linking to a payment instrument. Critically, a `purpose` parameter is passed to indicate the payment type as **recurring payment** and process an authorization charge of the checkout amount indicated, **which is instantly reimbursed**. Note that this doesn't automatically imply further payments from this customer - at this point, we're just tokenizing the card. 1. To create a new checkout resource, make a POST request to the `https://api.sumup.com/v0.1/checkouts` endpoint. Example of such request: ```bash curl -X POST \ https://api.sumup.com/v0.1/checkouts \ -H "Authorization: Bearer $SUMUP_API_KEY" \ -H 'Content-Type: application/json' \ -d '{ "checkout_reference": "MYCHECKOUT", "amount": 1, "currency": "EUR", "merchant_code": "MDEERENR", "description": "My checkout", "customer_id": "MYCUSTOMERID-123", "purpose": "SETUP_RECURRING_PAYMENT" }' ``` ```ts const checkout = await client.checkouts.create({ checkout_reference: "MYCHECKOUT", amount: 1, currency: "EUR", merchant_code: "MDEERENR", description: "My checkout", customer_id: "MYCUSTOMERID-123", purpose: "SETUP_RECURRING_PAYMENT", }); ``` ```csharp var checkout = await client.Checkouts.CreateAsync(new CheckoutCreateRequest { CheckoutReference = "MYCHECKOUT", Amount = 1.0f, Currency = Currency.Eur, MerchantCode = "MDEERENR", Description = "My checkout", CustomerId = "MYCUSTOMERID-123", Purpose = "SETUP_RECURRING_PAYMENT", }); ``` ```java var checkout = client.checkouts().createCheckout( CheckoutCreateRequest.builder() .checkoutReference("MYCHECKOUT") .amount(1.0f) .currency(Currency.EUR) .merchantCode("MDEERENR") .description("My checkout") .customerId("MYCUSTOMERID-123") .purpose(CheckoutCreateRequestPurpose.SETUP_RECURRING_PAYMENT) .build() ); ``` ```go customerID := "MYCUSTOMERID-123" purpose := sumup.CheckoutCreateRequestPurposeSetupRecurringPayment description := "My checkout" checkout, err := client.Checkouts.Create(ctx, sumup.CheckoutsCreateParams{ CheckoutReference: "MYCHECKOUT", Amount: 1, Currency: sumup.CurrencyEUR, MerchantCode: "MDEERENR", Description: &description, CustomerID: &customerID, Purpose: &purpose, }) ``` ```py from sumup.checkouts.resource import CreateCheckoutBody checkout = client.checkouts.create( CreateCheckoutBody( checkout_reference="MYCHECKOUT", amount=1, currency="EUR", merchant_code="MDEERENR", description="My checkout", customer_id="MYCUSTOMERID-123", purpose="SETUP_RECURRING_PAYMENT", ) ) ``` ```rust let checkout = client .checkouts() .create(Some(sumup::resources::checkouts::CheckoutCreateRequest { checkout_reference: "MYCHECKOUT".into(), amount: 1.0, currency: sumup::resources::checkouts::Currency::EUR, merchant_code: "MDEERENR".into(), description: Some("My checkout".into()), customer_id: Some("MYCUSTOMERID-123".into()), purpose: Some("SETUP_RECURRING_PAYMENT".into()), id: None, status: None, date: None, valid_until: None, transactions: None, return_url: None, redirect_url: None, })) .await?; ``` ```php $checkout = $sumup->checkouts->create([ 'checkout_reference' => 'MYCHECKOUT', 'amount' => 1, 'currency' => 'EUR', 'merchant_code' => 'MDEERENR', 'description' => 'My checkout', 'customer_id' => 'MYCUSTOMERID-123', 'purpose' => 'SETUP_RECURRING_PAYMENT', ]); ``` You should expect a standard `201 Created` response, with the checkout reference and both merchant and customer information. ```json { "amount": 1, "checkout_reference": "MYCHECKOUT", "checkout_type": "checkout", "currency": "EUR", "customer_id": "MYCUSTOMERID-123", "date": "2025-10-29T15:09:11.550+00:00", "description": "My checkout", "id": "7164c99b-13cb-42a1-8ba1-3c2c46a29de7", "merchant_code": "MDEERENR", "merchant_country": "PL", "merchant_name": "Sandbox Merchant Account", "pay_to_email": "a8e019f9bb2f49159182e8bd61eb5ea6@developer.sumup.com", "purpose": "SETUP_RECURRING_PAYMENT", "status": "PENDING", "transactions": [] } ``` For more information, see the [create a checkout](/api/checkouts/create) endpoint. ## Processing Request with Payment Widget The [SumUp's Payment Widget](/online-payments/checkouts/card-widget/) is a JavaScript library that allows you to securely process checkouts and collect card details securely, handling consent collection and 3DS verification. These steps are mandatory due to legal requirements, which is why we recommend processing the checkout with our widget. Once you have a checkout reference from the step above, you can mount the payment widget into your website and collect the card details. Pass the `checkout_reference` from above as the `checkoutId` here. ```html
``` Upon mounting the Payment Widget with a recurring purpose checkout, you should see the following screen: Card on file with payment widget The user is prompted to enter their card details, give consent to store their card details and complete the checkout. The widget uses the [Process Checkout endpoint](/api/checkouts/process) to securely process the checkout. We strongly recommend using the widget over direct integration, as the widget correctly handles all legal requirements for payments. If the previous operation is successful, and the card is stored with the **Save for future payments option**, a `payment_instrument` object containing a `token` representing the card is created (AKA tokenized card) for this customer. ```json "payment_instrument": { "token": "6878cb7f-6515-47bf-bdd9-1408d270fdce" } ``` At any time, you can fetch the list of tokenized cards of a customer by requesting them via [the list payment instruments](/api/customers/list-payment-instruments) endpoint. ```bash curl -X GET \ "https://api.sumup.com/v0.1/customers/${CUSTOMER_ID}/payment-instruments" \ -H "Authorization: Bearer $SUMUP_API_KEY" \ -H "Content-Type: application/json;charset=UTF-8" ``` ```ts const instruments = await client.customers.listPaymentInstruments("MYCUSTOMERID-123"); ``` ```csharp var instruments = await client.Customers.ListPaymentInstrumentsAsync("MYCUSTOMERID-123"); ``` ```java var instruments = client.customers().listPaymentInstruments("MYCUSTOMERID-123"); ``` ```go instruments, err := client.Customers.ListPaymentInstruments(ctx, "MYCUSTOMERID-123") ``` ```py instruments = client.customers.list_payment_instruments("MYCUSTOMERID-123") ``` ```rust let instruments = client .customers() .list_payment_instruments("MYCUSTOMERID-123") .await?; ``` ```php $instruments = $sumup->customers->listPaymentInstruments('MYCUSTOMERID-123'); ``` ## Processing Request Directly If you want to provide a fully customized experience, you can process the request using [SumUp API directly](/api/checkouts/process). In this case, you need to make sure to handle all legal requirements yourself. Critically, SumUp API expects the `mandate` object in the request. By providing the `mandate` object, **you are stating that you have obtained the consent of the customer**. The `mandate` object establishes the authorization framework for storing and reusing card details. It defines what the card token will be used for (only recurring payments for the time being), while capturing the technical details of the tokenization request for security and compliance purposes. ```json { "payment_type": "card", "installments": 1, "card": { "name": "FIRSTNAME LASTNAME", "number": "4111111111111111", "expiry_year": "2023", "expiry_month": "01", "cvv": "123", "zip_code": "12345" }, "mandate": { "type": "recurrent", "user_agent": "Chrome: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36.", "user_ip": "2001:0db8:85a3:0000:0a00:8a2e:0370:7300" } } ``` Again, a `payment_instrument` object containing a `token` representing the card is created (AKA tokenized card) for this customer. ```json "payment_instrument": { "token": "6878cb7f-6515-47bf-bdd9-1408d270fdce" } ``` At any time, you can fetch the list of tokenized cards of a customer by requesting them via [the list payment instruments](/api/customers/list-payment-instruments) endpoint. ```bash curl -X GET \ "https://api.sumup.com/v0.1/customers/${CUSTOMER_ID}/payment-instruments" \ -H "Authorization: Bearer $SUMUP_API_KEY" \ -H "Content-Type: application/json;charset=UTF-8" ``` ## Retrieving Tokenized Card Having successfully processed the checkout, a token representing the payment instrument (card) is created. You can now [retrieve the checkout](/api/checkouts/get) to find this token within a `payment_instrument` object for later recurrent payment. Example response: ```json { "id": "cd36780e-f43d-4f22-1i9e-e32a1a1bafc8", "checkout_reference": "0BYNWLYC7KV", "amount": 3.51, "currency": "EUR", ... "payment_instrument": { "token": "2fa27578-e765-5dbh-aa97-d45d3d6cdfbb" } } ``` ## Processing Recurring Payments Having tokenized the customer's card, you can now process recurring payments by referencing the saved token and the associated customer. Both `token` and `customer_id` fields are required. 1. [Create a checkout](/api/checkouts/create) again. This time, it's for the actual payment. The previous checkout was for tokenizing the card only. 2. Process the checkout. Make sure to pass the following data (`installments` is only valid for the Brazilian market): ```json { "payment_type": "card", "installments": 1, "token": "{{CARD_TOKEN}}" "customer_id": "{{CUSTOMER_ID}}", } ``` ## What's Next? You may be interested in the following resources related to Online Payments: - [Handling Refunds](/online-payments/guides/refund) - [Response Handling](/online-payments/guides/response-handling) # Plugins > Overview of SumUp plugins for third-party platforms. import CardLink from '@components/CardLink.astro'; import CardStack from '@components/CardStack.astro'; These plugins enable quick SumUp payment integration on PrestaShop, Wix, and WooCommerce, requiring only your API key and merchant information to start. Select a plugin of interest for further, detailed instructions. # PrestaShop > Accept SumUp payments with the PrestaShop plugin. import { Aside } from '@astrojs/starlight/components'; import Button from '@components/content/Button.astro'; To use PrestaShop with SumUp, download the SumUp Payment module plugin, which requires configuration in your SumUp dashboard. ## Prerequisites You will need an active [SumUp account](https://me.sumup.com). As an authorized Payment Institution by the Central Bank of Ireland, SumUp must verify your identity and business ownership. Please make sure your [business model is supported by SumUp](https://help.sumup.com/en-GB/articles/3G8ZHjdgFZjmKWOmDWS52m). ## Installation 1. Follow [the register application guide](/tools/authorization/oauth/#register-an-oauth-application) to obtain the client credentials for your app. 2. Download the client credentials JSON as described in the [access client credentials section](/tools/authorization/oauth/#4-access-the-client-credentials). 3. Upload the JSON to the **Module Configuration** page in PrestaShop Backoffice. 4. After SumUp account verification, [contact us](/contact) to enable online payments scope for your PrestaShop online store. ![SumUp Payment Gateway for PrestaShop](/img/guides/prestashop_step_5.png) Once you receive a confirmation from SumUp, you’re fully set-up! Note that minimum transaction amount is 1 EUR (or equivalent). # WIX > Accept SumUp payments on your WIX online store. Connect your [WIX online store](https://wix.com) dashboard to SumUp for secure payment processing through our payment gateway, as explained in this guide. ## Prerequisites - Active [SumUp account](https://me.sumup.com). If you don't have one yet, sign up on [our website](https://me.sumup.com/signup). As an authorized Payment Institution by the Central Bank of Ireland, SumUp must verify your identity and business ownership. - Business model supported by SumUp, according to our [allowed businesses article](https://help.sumup.com/en-GB/articles/3G8ZHjdgFZjmKWOmDWS52m). - WIX online store. WIX integration supports the following Alternative Payment Methods (APMs): iDeal (Netherlands), Bancontact (Belgium), P24 (Poland), EPS (Austria). Apple Pay and Google Pay are currently unavailable. ## Installation 1. First, create your secret API Key. [See this article](/tools/authorization/api-keys/#create-an-api-key) for details. Copy your key before proceeding. 2. In WIX dashboard, go to **Settings** > **Accept payments**. 3. Select **SumUp**, paste your secret API Key in **Account Information**, and **Save**. That's it! You can now start accepting payments through SumUp on your WIX online store. If you have any questions or encounter any issues, contact our [customer service](https://me.sumup.com/en-gb/support) team. # WooCommerce > Accept SumUp payments with the WooCommerce plugin. import { Aside } from "@astrojs/starlight/components"; import Button from "@components/content/Button.astro"; The [SumUp Payment Gateway for WooCommerce](https://wordpress.org/plugins/sumup-payment-gateway-for-woocommerce/) enables payments on WordPress sites without coding, enabling your customizations and providing your customers the convenience of securely buying products from your website without being redirected to other pages. The plugin supports major cards (Visa, Mastercard, Amex, Diners, Discover, JCB) via embedded forms. Transactions are processed through the SumUp payment platform with [transaction history provided in the SumUp Dashboard](https://me.sumup.com/sales/transactions). ## Prerequisites - Active [SumUp account](https://me.sumup.com). If you don't have one yet, sign up on [our website](https://me.sumup.com/signup). As an authorized Payment Institution by the Central Bank of Ireland, SumUp must verify your identity and business ownership. - [Review allowed businesses](https://help.sumup.com/hc/en-gb/articles/115008338707-Restricted-businesses) before [signing up](https://me.sumup.com). ## Installing the Plugin ### Automatic Installation The automatic installation is the easiest option, as WordPress handles the file transfer and you don't need to leave your web browser. 1. Install the plugin via the **Plugins** section in the WordPress Dashboard. 2. Click on **Add new** and search for **SumUp Payment Gateway for WooCommerce**. 3. Click on the **Install Now** button. 4. Click **Activate** to active the plugin. ### Manual Installation 1. [Download our plugin](https://wordpress.org/plugins/sumup-payment-gateway-for-woocommerce/). 2. Upload it to your web server using FTP. See [WordPress codex](https://wordpress.org/support/article/managing-plugins/#manual-upload-via-wordpress-admin) for details on how to do this. Before setting up the plugin, create your client credentials. ## Integration Options For plugin versions `2.5` or later, both a [simple](#simple-integration) and [advanced](#advanced-integration) integration flows are available. If you are using a plugin version below `2.5`, follow the steps in our [advanced integration guide](#advanced-integration). ### Simple Integration Available for plugin versions above `2.5`. 1. Click **Connect account** to initiate the lightweight integration flow (redirects to SumUp Dashboard). 2. In your SumUp Dashboard, click on **Start setup** to generate your production API keys. Once the flow is initiated, we will take care of generating live API keys for your SumUp account. When the flow completes successfully, they will become available to your WordPress shop. At this point, you can start accepting payments through SumUp on your WordPress shop. ![SumUp Payment Gateway for WooCommerce plugin settings](/img/guides/woocommerce_plugin.png) ### Advanced Integration 1. Once the plugin is activated, click **Advanced version**. 2. [Create your API Key](/tools/authorization/api-keys/#create-an-api-key). 3. Enter SumUp credentials (API Key, email, and merchant code) and settings. ## Additional Configuration - Enable the SumUp Payment Gateway - Set customer-facing title/description - Apply an optional payment method description, visible by your customers - Match shop currency to SumUp account - Require ZIP code from your customers. **Mandatory for US merchants** - We recommend enabling the logging option for better troubleshooting should any issues occur (logs can be found in **WooCommerce** > **Status** > **Logs**) - Choose between popup or embedded payment form with the **Open Payment in modal?** option ### Update Your Website Before accepting payments through SumUp, your website should display the following information: - Business & product information - Delivery, cancellation & return/refund policy - Payment & billing process - All prices must have the respective currency prefix - Privacy policy - Security policy ## Configuration for Legacy Plugin (Version Older than 2.5) ### Create Your Client Credentials To create client credentials you must have an active [SumUp account](https://me.sumup.com) with completed [account details](https://me.sumup.com/account). Your account has successfully completed the onboarding process, and you have received the `payments` scope activation. If you don't have the `payments` scope activated yet, [contact us](/contact) for assistance. Once you ensure you've met the above requirements, you can proceed with our [Register application guide](/tools/authorization/oauth/#register-an-oauth-application) to set up your client credentials. ## Plugin Configuration Now that you have created your client credentials and installed the plugin, you can proceed with configuration. In WordPress Dashboard, go to **Plugins** `. **Settings** under the SumUp WooCommerce plugin. You will find the following customization options: - Enable the SumUp Payment Gateway - Apply custom title of the payment method, visible by your customers - Apply an optional payment method description, visible by your customers - Apply your shop currency corresponding to the one set in your SumUp account - **Client ID** and **Client Secret** of your application. Both are located in the JSON file you created in the [Create your client credentials step](#create-your-client-credentials), in the following key-value pair: ```json { "id": "CCCFAXYD", "name": "My Online Store Name", "client_id": "fOcmczrYtYMJ7Li5GjMLLcUeC9dN", "client_secret": "717bd571b54297494cd7a79b491e8f2c1da6189c4cc2d3481380e8366eef539c", "application_type": "web", "redirect_uris": ["https://mywebsite.com/callback"] } ``` - The email address of your SumUp merchant account - The merchant code associated with your SumUp account - Require ZIP code from your customers. **Mandatory for US merchants** - We recommend enabling logs for better troubleshooting, should any issues occur (Logs can be accessed in **WooCommerce** > **Status** > **Logs**) # SDKs > Build on SumUp's APIs with officially supported server-side SDKs. SumUp maintains open-source SDKs that wrap the public API and handle the heavy lifting of authentication, pagination, and resource helpers. Each package ships with examples and type definitions so you spend less time wiring HTTP requests and more time on your business logic. ## Choose Your SDK - **[Node.js](/online-payments/sdks/nodejs/)** – published on npm as `@sumup/sdk` with first-class TypeScript typings and ESM support. - **[Go](/online-payments/sdks/go/)** – idiomatic Go module `github.com/sumup/sumup-go` with context-aware clients and pkg.go.dev documentation. - **[Python](/online-payments/sdks/python/)** – `sumup-py` provides both synchronous and asynchronous clients built on top of `httpx`. - **[Java](/online-payments/sdks/java/)** – Java 17+ SDK published to Maven Central as `com.sumup:sumup-sdk`. - **[PHP](/online-payments/sdks/php/)** – Composer package `sumup/sumup-php` with first-party clients for SumUp APIs. - **[Rust](/online-payments/sdks/rust/)** – `sumup` crate published to crates.io with comprehensive docs at docs.rs. - **[.NET](/online-payments/sdks/dotnet/)** – NuGet package `SumUp` targeting supported .NET releases. All SDKs require valid [authorisation credentials](/tools/authorization/) and work against both sandbox and production environments. After picking an SDK, follow the quickstart guide for installation, environment variables, and example calls. :::tip[Client-side options] Looking for client-side or checkout experiences? See the [React Native SDK](/online-payments/sdks/react-native/) and [Swift Checkout SDK](/online-payments/checkouts/swift-checkout/). ::: # .NET SDK > Use the official .NET client to talk to every SumUp public API. The [`SumUp`](https://github.com/sumup/sumup-dotnet) package is the official .NET SDK for SumUp APIs. It targets all currently supported .NET releases and ships async-first clients. ## Installation ```bash dotnet add package SumUp --prerelease ``` ## Configure Authentication Set the `SUMUP_ACCESS_TOKEN` environment variable or pass the token into `SumUpClientOptions`. ```bash export SUMUP_ACCESS_TOKEN="sup_sk_MvxmLOl0..." ``` ## Examples ### Online Payment Checkout ```csharp using System; using SumUp; using var client = new SumUpClient(); var merchantResponse = await client.Merchant.GetAsync(); var merchantCode = merchantResponse.Data?.MerchantProfile?.MerchantCode ?? throw new InvalidOperationException("Merchant code not returned."); var checkoutReference = $"checkout-{Guid.NewGuid():N}"; var checkoutResponse = await client.Checkouts.CreateAsync(new CheckoutCreateRequest { Amount = 10.00f, Currency = Currency.Eur, CheckoutReference = checkoutReference, MerchantCode = merchantCode, Description = "Test payment", RedirectUrl = "https://example.com/success", ReturnUrl = "https://example.com/webhook", }); Console.WriteLine($"Checkout ID: {checkoutResponse.Data?.Id}"); ``` ### Cloud API Checkout ```csharp using SumUp; using var client = new SumUpClient(); var readerCheckout = await client.Readers.CreateCheckoutAsync( merchantCode: "your-merchant-code", readerId: "your-reader-id", body: new CreateReaderCheckoutRequest { Description = "Coffee purchase", ReturnUrl = "https://example.com/webhook", TotalAmount = new CreateReaderCheckoutRequestTotalAmount { Currency = "EUR", MinorUnit = 2, Value = 1000, }, }); Console.WriteLine($"Reader checkout created: {readerCheckout.Data?.Data?.ClientTransactionId}"); ``` # Go SDK > Call the SumUp APIs from idiomatic Go code. [`sumup-go`](https://github.com/sumup/sumup-go) is the official Go module. It exposes typed clients for every endpoint, handles authentication headers, and surfaces helpers for common request payloads. ## Installation Install the module with `go get github.com/sumup/sumup-go` (or `go install` for reproducible builds). ## Configure Authentication Create a secret API key or OAuth access token in the [developer dashboard](https://me.sumup.com/developers). The SDK reads `SUMUP_API_KEY` by default, so setting `SUMUP_API_KEY=sup_sk_MvxmLOl0...` before running your binary is enough. You can also pass the key explicitly: ```go client := sumup.NewClient(client.WithAPIKey("sup_sk_MvxmLOl0...")) ``` ## Examples ### Online Payment Checkout ```go package main import ( "context" "fmt" "log" "os" sumup "github.com/sumup/sumup-go" ) func main() { ctx := context.Background() client := sumup.NewClient() merchantCode := os.Getenv("SUMUP_MERCHANT_CODE") desc := "Online payment via card widget" checkout, err := client.Checkouts.Create(ctx, sumup.CheckoutsCreateParams{ Amount: 25.00, CheckoutReference: "ORDER-1001", Currency: sumup.CurrencyEUR, Description: &desc, MerchantCode: merchantCode, }) if err != nil { log.Fatalf("create checkout: %v", err) } fmt.Println(*checkout.ID) // Return checkout ID to your webpage so the SumUp card widget can complete the payment. } ``` ### Cloud API Checkout ```go package main import ( "context" "fmt" "log" "os" "strings" "time" sumup "github.com/sumup/sumup-go" ) func main() { ctx := context.Background() client := sumup.NewClient() merchantCode := os.Getenv("SUMUP_MERCHANT_CODE") affiliateKey := os.Getenv("SUMUP_AFFILIATE_KEY") appID := os.Getenv("SUMUP_APP_ID") readerList, err := client.Readers.List(ctx, merchantCode) if err != nil { log.Fatalf("list readers: %v", err) } var solo sumup.Reader for _, rdr := range readerList.Items { if strings.EqualFold(string(rdr.Device.Model), "solo") { solo = rdr break } } if solo.ID == "" { log.Fatal("Pair a Solo reader before using the Cloud API.") } checkout, err := client.Readers.CreateCheckout(ctx, merchantCode, string(solo.ID), sumup.CreateCheckoutRequest{ TotalAmount: sumup.CreateCheckoutRequestTotalAmount{ Currency: "EUR", MinorUnit: 2, Value: 1500, }, }) if err != nil { log.Fatalf("create checkout: %v", err) } fmt.Println(checkout.Data.ClientTransactionId) } ``` # Java SDK > Use the official Java client to talk to every SumUp public API. import JavaSdkInstallTabs from "@components/content/JavaSdkInstallTabs.astro"; The [`com.sumup:sumup-sdk`](https://github.com/sumup/sumup-java) package is the official Java SDK generated from the SumUp OpenAPI specification. It requires Java 17 or newer and ships both synchronous and asynchronous clients. ## Installation Add the dependency to your build file. ## Configure Authentication Set the `SUMUP_API_KEY` environment variable or pass the token directly. ```bash export SUMUP_API_KEY="sup_sk_MvxmLOl0..." ``` ```java import com.sumup.sdk.SumUpClient; SumUpClient client = new SumUpClient("sup_sk_MvxmLOl0..."); ``` ## Examples ### Online Payment Checkout ```java import com.sumup.sdk.SumUpClient; import com.sumup.sdk.models.CheckoutCreateRequest; import com.sumup.sdk.models.Currency; SumUpClient client = SumUpClient.builder().build(); CheckoutCreateRequest request = CheckoutCreateRequest.builder() .amount(25.00f) .currency(Currency.EUR) .checkoutReference("ORDER-1001") .merchantCode(System.getenv("SUMUP_MERCHANT_CODE")) .description("Online payment via card widget") .build(); var checkout = client.checkouts().createCheckout(request); System.out.println(checkout.id()); ``` ### Cloud API Checkout ```java import com.sumup.sdk.SumUpClient; import com.sumup.sdk.models.CreateReaderCheckoutRequest; import com.sumup.sdk.models.Money; SumUpClient client = SumUpClient.builder().build(); String merchantCode = System.getenv("SUMUP_MERCHANT_CODE"); String readerId = client.readers().listReaders(merchantCode).items().stream() .findFirst() .orElseThrow(() -> new IllegalStateException("No paired readers found.")) .id() .value(); CreateReaderCheckoutRequest request = CreateReaderCheckoutRequest.builder() .description("Reader checkout") .totalAmount( Money.builder() .currency("EUR") .minorUnit(2L) .value(1500L) .build()) .build(); client.readers().createReaderCheckout(merchantCode, readerId, request); ``` # Node.js SDK > Use the official TypeScript client to talk to every SumUp public API. The [`@sumup/sdk`](https://github.com/sumup/sumup-ts) package wraps SumUp API, ships TypeScript declarations, and works in modern Node.js runtimes (>=18) as well as Cloudflare Workers, Vercel, and other ESM-friendly environments. ## Installation Install with `npm install @sumup/sdk` (or `yarn add` / `pnpm add`). ## Configure Authentication The client reads the `SUMUP_API_KEY` environment variable automatically, so deploying with `SUMUP_API_KEY=sup_sk_MvxmLOl0...` is enough for most server workloads. You can also pass the secret explicitly: ```ts const client = new SumUp({ apiKey: "sup_sk_MvxmLOl0..." }); ``` If you use OAuth, exchange the authorization code for an access token and pass it as the `accessToken` option instead of `apiKey`. ## Examples ### Online Payment Checkout ```ts import SumUp from "@sumup/sdk"; const client = new SumUp({ apiKey: process.env.SUMUP_API_KEY ?? "" }); async function createOnlineCheckout() { const checkout = await client.checkouts.create({ amount: 2500, checkout_reference: "ORDER-1001", currency: "EUR", merchant_code: process.env.SUMUP_MERCHANT_CODE ?? "", pay_to_email: process.env.SUMUP_PAY_TO_EMAIL ?? "", description: "Online payment via card widget", }); console.log(checkout.id); // Return checkout.id to your webpage so the SumUp card widget can complete the payment. } createOnlineCheckout().catch((error) => { console.error(error); process.exit(1); }); ``` ### Cloud API Checkout ```ts import SumUp from "@sumup/sdk"; const client = new SumUp({ apiKey: process.env.SUMUP_API_KEY ?? "" }); async function createSoloCheckout() { const merchantCode = process.env.SUMUP_MERCHANT_CODE ?? ""; const affiliateKey = process.env.SUMUP_AFFILIATE_KEY ?? ""; const affiliateAppId = process.env.SUMUP_APP_ID ?? ""; if (!affiliateKey || !affiliateAppId) { throw new Error( "Set SUMUP_AFFILIATE_KEY and SUMUP_APP_ID to use the Cloud API.", ); } const { items: readers } = await client.readers.list(merchantCode); const solo = readers.find((reader) => reader.device.model === "solo"); if (!solo) { throw new Error("Pair a Solo reader before using the Cloud API."); } const checkout = await client.readers.createCheckout(merchantCode, solo.id, { total_amount: { currency: "EUR", minor_unit: 2, value: 1500, }, }); console.log(checkout.data.client_transaction_id); } createSoloCheckout().catch((error) => { console.error(error); process.exit(1); }); ``` # PHP SDK > Introduction to the SumUp PHP SDK and first steps to get you started. The [`sumup-php`](https://github.com/sumup/sumup-php) package is the official PHP SDK for SumUp APIs. It provides service clients for common resources, such as: - managing merchant accounts - managing checkouts - managing customers - managing payouts - querying transactions - managing readers ## Installation Install with `composer require sumup/sumup-php`. ## Configure Authentication Set the `SUMUP_API_KEY` environment variable or pass the API key directly to the `SumUp\SumUp` constructor. You can also provide an OAuth access token via `access_token`. ```bash export SUMUP_API_KEY='your-api-key-here' ``` ## Examples ### Online Payment Checkout ```php checkouts->create([ 'merchant_code' => getenv('SUMUP_MERCHANT_CODE'), 'amount' => 25.00, 'currency' => 'EUR', 'checkout_reference' => 'ORDER-1001', 'description' => 'Online payment via card widget', ]); echo $checkout->id . PHP_EOL; // Return $checkout->id to your webpage so the SumUp card widget can complete the payment. } catch (SDKException $exception) { echo 'SumUp SDK error: ' . $exception->getMessage(); } ``` ### Cloud API Checkout ```php readers->list($merchantCode)->items ?? []; $firstSolo = $readers[0] ?? null; if (!$firstSolo) { throw new RuntimeException('Pair a Solo reader before using the Cloud API.'); } $payload = [ 'total_amount' => [ 'currency' => 'EUR', 'minor_unit' => 2, 'value' => 1500, ], 'affiliate' => [ 'app_id' => getenv('SUMUP_APP_ID'), 'foreign_transaction_id' => 'solo-' . time(), 'key' => getenv('SUMUP_AFFILIATE_KEY'), ], 'description' => 'Cloud API checkout', ]; $checkoutResponse = $sumup->readers->createCheckout( $merchantCode, $firstSolo->id, $payload ); echo $checkoutResponse->data['client_transaction_id'] . PHP_EOL; } catch (SDKException | RuntimeException $exception) { echo 'Error: ' . $exception->getMessage(); } ``` ## SDK Documentation For more information read the **[documentation](https://github.com/sumup/sumup-php)**. # Python SDK > Build synchronous or async SumUp integrations with Python. [`sumup-py`](https://github.com/sumup/sumup-py) provides first-party Python bindings for every SumUp API. It ships both synchronous and asynchronous clients powered by `httpx`, includes Pydantic models for request bodies, and offers type hints for modern editors. ## Installation Install with `pip install sumup`. If you use [uv](https://docs.astral.sh/uv/), run `uv add sumup`. ## Configure Authentication Expose your secret API key or OAuth access token as an environment variable and pass it to either the synchronous `Sumup` or asynchronous `AsyncSumup` client. You can also pass the key manually: ```py client = Sumup(api_key="sup_sk_MvxmLOl0...") ``` ## Examples ### Online Payment Checkout ```py import os from sumup import Sumup from sumup.checkouts.resource import CreateCheckoutBody client = Sumup(api_key=os.environ["SUMUP_API_KEY"]) checkout = client.checkouts.create( CreateCheckoutBody( merchant_code=os.environ["SUMUP_MERCHANT_CODE"], amount=25.00, checkout_reference="ORDER-1001", currency="EUR", description="Online payment via card widget", ) ) print(checkout.id) # Return checkout.id to your webpage so the SumUp card widget can complete the payment. ``` ### Cloud API Checkout ```py import asyncio import os from time import time from sumup import AsyncSumup from sumup.readers.resource import ( CreateReaderCheckoutBody, CreateReaderCheckoutBodyAffiliate, CreateReaderCheckoutBodyTotalAmount, ) async def create_solo_checkout() -> None: client = AsyncSumup(api_key=os.environ["SUMUP_API_KEY"]) merchant_code = os.environ["SUMUP_MERCHANT_CODE"] readers = await client.readers.list(merchant_code) solo = next((reader for reader in readers.items if reader.device.model == "solo"), None) if solo is None: raise RuntimeError("Pair a Solo reader before using the Cloud API.") checkout = await client.readers.create_checkout( merchant_code, solo.id, CreateReaderCheckoutBody( total_amount=CreateReaderCheckoutBodyTotalAmount(currency="EUR", minor_unit=2, value=1500), ), ) print(checkout.data.client_transaction_id) asyncio.run(create_solo_checkout()) ``` # React Native Checkout SDK > Step-by-step guide for integrating the SumUp React Native Payment SDK, from prerequisites to checkout creation and mounting the payment sheet. import { Aside, Tabs, TabItem } from '@astrojs/starlight/components'; import Button from '@components/content/Button.astro'; import Image from '@components/content/Image.astro'; SumUp's React Native Payment SDK provides a payment sheet that is displayed on top of your app. It collects user payment details, confirms a payment, and saves a card for future usage. Moreover, it allows a user to use Apple Pay or Google Pay to process payments. Challenge screen ## Integration ### Before You Begin Here are the things that you need in order to complete the steps in this guide: - You have a merchant account with [SumUp](https://me.sumup.com/login) and have already filled in your [account details](https://me.sumup.com/account). - For a **sandbox merchant account** reach out to our support team through this [contact form](/contact). - You have [registered your client application](/tools/authorization/oauth/#register-an-oauth-application) with SumUp. - You have a valid access token obtained via the [Authorization code flow](/tools/authorization/oauth/#authorization-code-flow). - The restricted `payment_instruments` scope is enabled for your client application. If it isn't enabled, [contact us](/contact) and request it. - Review the [single payment guide](https://developer.sumup.com/online-payments/guides/single-payment/#before-you-begin). ### Create a Checkout Initializing the SDK works by passing it a `checkout_id`. To [create a checkout](/api/checkouts/create) on your backend make the following request: ```bash curl --request POST \ --url https://api.sumup.com/v0.1/checkouts \ --header "Authorization: Bearer $SUMUP_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "checkout_reference": "44ea5096-b83f-46e1-9323-fe82a8cb7eb5", "currency": "SEK", "amount": 9.99, "description": "Order #1234", "merchant_code": "MXXXXXXX", "return_url": "https://example.com", "redirect_url": "https://sumup.com" }' ``` ```ts const checkout = await client.checkouts.create({ checkout_reference: "44ea5096-b83f-46e1-9323-fe82a8cb7eb5", amount: 9.99, currency: "SEK", merchant_code: "MXXXXXXX", description: "Order #1234", return_url: "https://example.com", redirect_url: "https://sumup.com", }); ``` ```csharp var checkout = await client.Checkouts.CreateAsync(new CheckoutCreateRequest { CheckoutReference = "44ea5096-b83f-46e1-9323-fe82a8cb7eb5", Amount = 9.99f, Currency = Currency.Sek, MerchantCode = "MXXXXXXX", Description = "Order #1234", ReturnUrl = "https://example.com", RedirectUrl = "https://sumup.com", }); ``` ```java var checkout = client.checkouts().createCheckout( CheckoutCreateRequest.builder() .checkoutReference("44ea5096-b83f-46e1-9323-fe82a8cb7eb5") .amount(9.99f) .currency(Currency.SEK) .merchantCode("MXXXXXXX") .description("Order #1234") .returnUrl("https://example.com") .redirectUrl("https://sumup.com") .build() ); ``` ```go description := "Order #1234" returnURL := "https://example.com" redirectURL := "https://sumup.com" checkout, err := client.Checkouts.Create(ctx, sumup.CheckoutsCreateParams{ CheckoutReference: "44ea5096-b83f-46e1-9323-fe82a8cb7eb5", Amount: 9.99, Currency: sumup.CurrencySEK, MerchantCode: "MXXXXXXX", Description: &description, ReturnURL: &returnURL, RedirectURL: &redirectURL, }) ``` ```py from sumup.checkouts.resource import CreateCheckoutBody checkout = client.checkouts.create( CreateCheckoutBody( checkout_reference="44ea5096-b83f-46e1-9323-fe82a8cb7eb5", amount=9.99, currency="SEK", merchant_code="MXXXXXXX", description="Order #1234", return_url="https://example.com", redirect_url="https://sumup.com", ) ) ``` ```rust let checkout = client .checkouts() .create(Some(sumup::resources::checkouts::CheckoutCreateRequest { checkout_reference: "44ea5096-b83f-46e1-9323-fe82a8cb7eb5".into(), amount: 9.99, currency: sumup::resources::checkouts::Currency::SEK, merchant_code: "MXXXXXXX".into(), description: Some("Order #1234".into()), return_url: Some("https://example.com".into()), redirect_url: Some("https://sumup.com".into()), customer_id: None, purpose: None, id: None, status: None, date: None, valid_until: None, transactions: None, })) .await?; ``` ```php $checkout = $sumup->checkouts->create([ 'checkout_reference' => '44ea5096-b83f-46e1-9323-fe82a8cb7eb5', 'currency' => 'SEK', 'amount' => 9.99, 'description' => 'Order #1234', 'merchant_code' => 'MXXXXXXX', 'return_url' => 'https://example.com', 'redirect_url' => 'https://sumup.com', ]); ``` The SDK will process the checkout once a customer provides payment details. If payment details aren't passed an error will be received. ## Set up SDK Install the npm module by one of the following commands: ```bash npm i sumup-react-native-alpha npm i react-native-webview ``` ```bash yarn add sumup-react-native-alpha yarn add react-native-webview ``` You need to install `react-native-localization` to automatically detect the user system language. ```bash npm i react-native-localization ``` ```bash yarn add react-native-localization ``` If you don't need it, please provide the language field in the `initPaymentSheet` function. ```javascript await initPaymentSheet({ checkoutId, language: 'en', }); ``` Next, install the native modules. ```bash cd ios pod install ``` SDK should be initialized by wrapping your payment screen into SumUpProvider. This component requires an `apiKey` you can create in the [API Keys settings](/tools/authorization/api-keys/). ```javascript import { SumUpProvider } from 'sumup-react-native-alpha'; export default function App() { return ( ); } ``` ## Provide Payment Details Before showing the payment sheet, it needs to be initialized. Call `initPaymentSheet` with the parameters like in example below: ```js import React, { useEffect } from "react"; import { View, Alert } from "react-native"; import { useSumUp } from "sumup-react-native-alpha"; export default function MainScreen() { const { initPaymentSheet } = useSumUp(); const initSumUpPaymentSheet = async () => { const { error } = await initPaymentSheet({ checkoutId: "...", customerId: "...", language: "en", // en or sv are supported }); if (error) { Alert.alert( error.status, error.status === "failure" ? error.message : undefined ); } else { Alert.alert("Payment Sheet was configured"); } }; useEffect(() => { initSumUpPaymentSheet(); }, []); ... ``` **Required** fields for `initPaymentSheet`: - `checkoutId` - described in section [Create a checkout](/online-payments/sdks/react-native/#create-a-checkout). *Optional*: - `customerId` - used for saving cards for future usage. - `language` - English and Sweden are supported (if undefined, react-native-localization will be used to check user device language). ## Show Payment Sheet After initialization a payment sheet can be shown. When a user presses a button, you can show it by calling `presentPaymentSheet()`. After a user completes a payment, this function will return a callback. If any errors take place, the callback will contain an error field with the details. ```js ... const showPaymentSheet = async () => { const { error } = await presentPaymentSheet(); if (error) { Alert.alert( error.status, error.status === "failure" ? error.message : undefined ); } else { Alert.alert("Payment successfully was processed"); } }; return (