# PayPal for Unified Payments API
> **Note**
>
> We no longer support new PayPal integrations on the Payments API. For new PayPal integrations, use the [Payment Setup API](https://www.checkout.com/docs/payments/accept-payments/accept-a-payment-using-the-payment-setup-api.md).
Build your own UI and integrate with our API to process PayPal payments.
The payment flow varies depending on the payment experience you want to offer and how you capture the payment. As a general guide, you should:
1. [Configure the front-end PayPal JS SDK](#Configure_the_front-end_PayPal_JS_SDK).
2. [Request a Checkout.com payment context](#Request_a_Checkout.com_payment_context).
3. [Open the PayPal pop-up](#Open_the_PayPal_pop-up).
If you offer a _Continue_ payment experience, you must [get the latest customer data from PayPal](#Retrieve_customer_data_from_PayPal) to create an _order review_ page.
4. [Request a payment](#Request_a_payment).
If you are using a manual capture payment, you must also [capture the payment](#Manually_capture_the_payment).
### Configure the front-end PayPal JS SDK
You can use the JavaScript SDK to render the buttons and payment method icons in any page of your store.
1. Initialize the PayPal JS SDK by adding it in a ``
The PayPal JS SDK accepts the following query parameters:
| Query parameter | Description |
| --- | --- |
| `client-id` | The client ID for the Checkout.com environment you are configuring the SDK for.
If you are configuring your:
- Sandbox environment – Use the value: `ASLqLf4pnWuBshW8Qh8z_DRUbIv2Cgs3Ft8aauLm9Z-MO9FZx1INSo38nW109o_Xvu88P3tly88XbJMR`.
- Production environment – Use the value: `ATbi1ysGm-jp4RmmAFz1EWH4dFpPd-VdXIWWzR4QZK5LAvDu_5atDY9dsUEJcLS5mTpR8Wb1l_m6Ameq`. |
| `merchant-id` | Your PayPal merchant ID.
Checkout.com will provide you with your ID during your integration. |
| `disable-funding` | Specifies which funding sources to disable for the transaction.
Checkout.com only supports PayPal Direct Payment. You must set this query parameter to `&disable-funding=credit,card,sepa, bancontact,blik,eps,giropay,ideal,mercadopago,mybank,p24,sofort`. |
| `enable-funding` | Specifies which funding sources to enable for the transaction.
To enable the PayPal Pay Later option, this value must be set to `paylater`.
- `paylater`
- See [Pay Later](#PayPal_Pay_Later) for more details. |
| `commit` | Specifies which checkout experience button to display in the PayPal pop-up:
- To display a _Pay Now_ button, set the query parameter to `true`.
- To display a _Continue_ button, set the query parameter to `false`. |
Additionally, you must configure the following script parameter as follows:
| Script parameters | Value |
| --- | --- |
| `data-partner-attribution-id` | `CheckoutLtd_PSP` |
| `buyer-country` | The country the customer is located in, which is used to determine the funding sources they are eligible for.
If you do not provide a value, this defaults to their IP geolocation. |
| `currency` | The currency for the transaction.
If you do not provide a value, this defaults to USD. |
2. Place a `
` wrapper on the page you want to render the PayPal button:
```html
```
3. Add a `
```
The [PayPal JavaScript configuration](https://developer.paypal.com/sdk/js/configuration/) documentation provides additional information.
### Request a Checkout.com payment context
A Checkout.com payment context request will return an `order_id`, which is required when you configure subsequent requests.
To make it easier to reconcile the payment at a later date, include the following fields in your request:
- `reference`
- `processing.invoice_id`
> **Information**
>
> The Payment Contexts API supports [idempotency](https://www.checkout.com/docs/developer-resources/api/idempotency.md). You can safely retry API requests without the risk of duplicate requests.
> **Information**
>
> Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md).
**Production**
`POST` `https://{prefix}.api.checkout.com/payment-contexts`
**Sandbox**
`POST` `https://{prefix}.api.sandbox.checkout.com/payment-contexts`
#### Request example
```json
{
"source": {
"type": "paypal"
},
"currency": "USD",
"amount": 2000,
"capture": false,
"items": [
{
"name": "laptop",
"unit_price": 2000,
"quantity": 1
}
],
"processing": {
"invoice_id": "12345",
"user_action": "pay_now"
},
"processing_channel_id": "{{PayPal-processingChannel-personal}}",
"success_url": "http://www.example.com/success.html",
"failure_url": "http://www.example.com/failure.html"
}
```
You can find the full list, as well as complete request and response examples, in our [API reference](https://api-reference.checkout.com/).
#### Response example
If you receive a `201 Created` success status response code, your request was successful.
In the response, you'll receive an order ID in the` partner_metadata` field. You can pass this order ID to the PayPal SDK's `createOrder()` method.
```json
{
"id": "pct_ckjrpk7vux4ejhghe6ssgkoy2y",
"partner_metadata": {
"order_id": "7YP86878G2990415D"
},
"_links": {
"self": {
"href": "https://{prefix}.api.checkout.com/payment-contexts/pct_ckjrpk7vux4ejhghe6ssgkoy2y"
}
}
}
```
#### Pay Now experience
Use the _Pay Now_ checkout experience if you know the final payment amount when you initiate the payment flow:
1. Set the `user_action` field to `pay_now` in the request.
2. Include `commit=true` in the JS script URL to display a _Complete purchase_ button in the flow.
When the customer selects _Complete purchase_, the payment is completed without requiring any further action from them.
#### Continue experience
Use the _Continue_ checkout experience if you want to present PayPal as an option upfront for a faster checkout experience and higher conversion rates.
1. Set the `user_action` field to `continue` in the request.
2. Include `commit=false` in the JS script URL to display a _Continue to Review Order_ button in the flow.
> **Information**
>
> If you do not specify the `user_action` field in your request, the _Continue_ payment flow is used by default.
When the customer selects _Continue to Review Order_, they will be redirected to the PayPal payment page. There, customers can edit their shipping address or adjust their shipping option before submitting the order.
While the customer is on the PayPal page, you can update their shopping cart to include additional shipping costs. PayPal provides shipping configuration in the `shipping_preference` field using the following values:
- `no_shipping` – Shipping does not have to be defined, usually for digital goods and services where physical delivery is not required.
- `set_provided_address` – The customer uses the merchant-provided address; the customer can only update the address if you do not provide one.
- `get_from_file` – Collects the shipping details from the PayPal widget. This is the default value.
> **Information**
>
> If you set `"shipping_preference": "set_provided_address"`, the following fields are required:
>
> - `address_line1`
> - `country`, as a two-character [country code](https://www.checkout.com/docs/developer-resources/codes/country-codes.md)
### Open the PayPal pop-up
1. Manage the order via the PayPal JS SDK:
- In the `createOrder()` handler of your script, use the `order_id` returned from the payment context request.
- Use the `onApprove()` handler to continue to the next step in your payment flow after your customer transaction is approved.
#### Retrieve customer data from PayPal
If you implement a _Continue_ checkout experience, you must:
1. [Retrieve the latest customer data](https://api-reference.checkout.com/tag/Payment-Context/#operation/getPaymentContext) after the customer confirms payment in PayPal pop-up.
2. Display this information on the _Review Order_ page.
You can use the updated information from the payment context when you request a payment later.
In the front end, once the customer confirms the payment in the PayPal pop-up, you can use the `onApprove()` callback function to get information from the user’s session on PayPal’s side. The response will contain all fields required to create the payment.
> **Information**
>
> Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md).
**Production**
`GET` `https://{prefix}.api.checkout.com/payment-contexts/{id}`
**Sandbox**
`GET` `https://{prefix}.api.sandbox.checkout.com/payment-contexts/{id}`
#### Response example
```json
{
"payment_request": {
"source": {
"type": "paypal"
},
"amount": 2000,
"currency": "USD",
"payment_type": "Regular",
"authorization_type": "Final",
"capture": false,
"customer": {
"name": "Toby Smith",
"email": "apm-payer@personal.example.com"
},
"shipping": {
"first_name": "Toby",
"last_name": "Smith",
"address": {
"address_line1": "1 Main St",
"city": "San Jose",
"state": "CA",
"zip": "95131",
"country": "US"
}
},
"items": [
{
"name": "laptop",
"quantity": 1,
"unit_price": 2000
}
],
"success_url": "http://www.example.com/success.html",
"failure_url": "http://www.example.com/failure.html",
"processing_channel_id": "pc_zmcw5ppbvr3ullkdlza6u4teoi"
},
"partner_metadata": {
"customer_id": "WDB9U9PV7Y2KY",
"order_id": "7YP86878G2990415D"
}
}
```
### Request a payment
> **Information**
>
> Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md).
**Production**
`POST` `https://{prefix}.api.checkout.com/payments`
**Sandbox**
`POST` `https://{prefix}.api.sandbox.checkout.com/payments`
#### Request example
On the final order review page, the customer has the option to update the following details, which may affect the total payment amount:
- Shipping address
- Shipping method
If the customer does not make any changes, you can use the following request example:
```json
{
"payment_context_id":"pct_ckjrpk7vux4ejhghe6ssgkoy2y",
"processing_channel_id": "{{NAS-processingChannel-personal}}"
}
```
If the customer updates either of the shipping details, you must provide updated values in your payment request. Your request should only include the fields impacted by the customer's update to the shipping details. For example:
- The new `shipping.address`
- The new `amount`, to reflect the change in shipping method or address
```json
{
"payment_context_id":"pct_ckjrpk7vux4ejhghe6ssgkoy2y",
"shipping": {
"first_name": "Toby",
"last_name": "Arden",
"address": {
"address_line1": "1 Main St",
"city": "San Jose",
"state": "CA",
"zip": "95131",
"country": "US"
},
"processing_channel_id": "{{NAS-processingChannel-personal}}"
}
}
```
#### Response example
Your request was successful if you receive a `202 Success` response code which contains the `status` field set to `Pending`.
```json
{
"id": "pay_z7wmqrxtmkouzlhhvyxuc3ecxq",
"status": "Pending",
"customer": {
"id": "cus_qypaijolqf5enei2y5b5men32m",
"email": "sb-278ci3399829@business.example.com",
"name": "John Doe"
},
"processing": {
"partner_order_id": "7YP86878G2990415D"
},
"_links": {
"self": {
"href": "https://{prefix}.api.checkout.com/payments/pay_z7wmqrxtmkouzlhhvyxuc3ecxq"
}
}
}
```
You can choose to automatically capture the payment, or capture it manually at a later time. By default, PayPal is configured to auto capture the payment.
- To automatically capture the payment, set `"capture": true` in the payment context request.
- To manually capture the payment, set `"capture": false` in the payment context request and set `&intent=authorize` query parameter in the JS SDK call:
`
```
2. Replace the `createOrder()` function in the SDK code with `createBillingAgreement()`.
### Request a recurring payment
> **Information**
>
> Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md).
**Production**
`POST` `https://{prefix}.api.checkout.com/payments/`
**Sandbox**
`POST` `https://{prefix}.api.sandbox.checkout.com/payments/`
### Request example
Use this request only if the customer did not make any changes in the final review page.
```json
{
"payment_context_id":"pct_ckjrpk7vux4ejhghe6ssgkoy2y",
"processing_channel_id": "{{NAS-processingChannel-personal}}"
}
```
### Response example
Your request was successful if you receive a `202 Success` status response code which contains a `status` field set to `Pending`, and an `id` field.
You must store the `source.id` from this response to use it in subsequent requests.
```json
{
"id": "pay_myvk2vuj3dgeffho6iuretryfm",
"status": "Pending",
"source": {
"id": "src_fkhtu6spgqfelnndfqcjpsnaae",
"type": "paypal"
},
"processing": {
"partner_order_id": "7GU48395JD5519252"
},
"_links": {
"self": {
"href": "https://{prefix}.api.checkout.com/payments/pay_myvk2vuj3dgeffho6iuretryfm"
}
}
}
```
---
## Set up subsequent requests
To set up subsequent payment requests:
1. Your customer must accept the billing agreement in the PayPal pop-up widget.
2. The initial payment status must be `Captured`.
3. You must use the `source.id` from the initial payment response to initiate subsequent payment requests.
### Subsequent request example
> **Information**
>
> Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md).
**Production**
`POST` `https://{prefix}.api.checkout.com/payments/`
**Sandbox**
`POST` `https://{prefix}.api.sandbox.checkout.com/payments/`
```json
{
"source": {
"type": "id",
"id": "src_fkhtu6spgqfelnndfqcjpsnaae"
},
"merchant_initiated": true,
"currency": "USD",
"amount": 2000,
"items": [
{
"name": "laptop",
"unit_price": 2000,
"quantity": 1
}
],
"processing_channel_id": "{{NAS-processingChannel-personal}}",
"success_url": "http://www.example.com/success.html",
"failure_url": "http://www.example.com/failure.html",
"payment_type": "recurring"
}
```
### Subsequent response example
Your request was successful if you receive a `202 Success` response with the `status` field set to `Pending`.
```json
{
"id": "pay_ok7yhvutuylevnatk3x3dxviq4",
"status": "Captured",
"source": {
"id": "src_fkhtu6spgqfelnndfqcjpsnaae",
"type": "paypal"
},
"processing": {
"partner_order_id": "83U53060E16713839"
},
"_links": {
"self": {
"href": "https://{prefix}.api.checkout.com/payments/pay_ok7yhvutuylevnatk3x3dxviq4"
}
}
}
```
---
## Add Pay Later button
To display the Pay Later button, you must configure the following query parameters in your JS SDK call:
- `enable-funding` set to `paylater`
- `buyer-country` set to one of the supported countries
- `currency` set to the local currency for the selected country
For example, to configure Pay Later in the United States, your ``
---
## Get payment details
After you requested the payment. you can use the `payment_id` found in the payment response to retrieve details about the payment.
For more details, see our [API reference](https://api-reference.checkout.com/tag/Payments/#operation/getPaymentsList).
---
---
## Refund a payment
PayPal supports both partial and full refunds. PayPal refunds are based on the capture and not on the payment. You must specify the `capture_action_id` in your refund request if you perform multiple captures.
You can refund payment through the [Dashboard](https://dashboard.checkout.com) or using the [Refund API](https://www.checkout.com/docs/payments/manage-payments/refund-a-payment).
> **Information**
>
> If you refund or void a transaction directly via PayPal instead of using our API or Dashboard, the payment status will not sync back with Checkout.com.
> **Information**
>
> Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md).
**Production**
`POST` `https://{prefix}.api.checkout.com/payments/{id}/refunds`
**Sandbox**
`POST` `https://{prefix}.api.sandbox.checkout.com/payments/{id}/refunds`
#### Request example
```json
{
"amount": 100
}
```
#### Response example
```json
{
"actionId": "act_cxpffngdvouvabegyy3asiuou",
"_links": {
"payment": {
"href": "https://{prefix}.api.checkout.com/payments/pay_ok7yhvutuylevnatk3x3dxviq4"
}
}
}
```
### Refund a payment for manual capture flow
If you perform multiple partial captures, you must make a partial or full refund on the specific capture based on the capture ID assigned to it. You do this by specifying the `capture_action_id` and `amount` fields in your refund request.
> **Information**
>
> If you perform multiple partial captures, the refund amount cannot exceed the amount of that specific capture. You can see the capture amount and the capture action id using our [GET action endpoint](https://api-reference.checkout.com/tag/Payments/#operation/getPaymentActions).
> **Information**
>
> Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md).
**Production**
`POST` `https://{prefix}.api.checkout.com/payments/{id}/refunds`
**Sandbox**
`POST` `https://{prefix}.api.sandbox.checkout.com/payments/{id}/refunds`
#### Request example for multiple partial captures
```json
{
"amount": 1000,
"capture_action_id" : "act_d2on4akgfwfexg3ye65la3udtq"
}
```
#### Response example
```json
{
"actionId": "act_d2on4akgfwfexg3ye65la3udtq",
"reference": "ORD-5023-4E89",
"_links": {
"payment": {
"href": "https://{prefix}.api.checkout.com/payments/pay_jwvjl5tin54ubn7x2stvmunske"
}
}
}
```
---
## Cancel or void a payment
### Cancel a payment with auto capture
When you create a payment using the auto capture payment flow, you cannot void it.
If you wish to reverse a payment in progress, wait for the `payment_captured` webhook and then process a refund. See the [webhooks](#Webhooks) section for more information about the webhooks you may receive.
### Void payment for manual captured payment flow
A payment can be fully voided if it has been authorized but not yet captured. PayPal does not support partial voids.
> **Information**
>
> Your base URL's `{prefix}` value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see [API endpoints](https://www.checkout.com/docs/developer-resources/api/api-endpoints.md).
**Production**
`POST` `https://{prefix}.api.checkout.com/payments/{id}/voids`
**Sandbox**
`POST` `https://{prefix}.api.sandbox.checkout.com/payments/{id}/voids`
#### Response example
```json
{
"action_id": "act_y3oqhf46pyzuxjbcn2giaqnb44",
"reference": "ORD-5023-4E89",
"_links": {
"payment": {
"href": "https://{prefix}.api.sandbox.checkout.com/payments/pay_y3oqhf46pyzuxjbcn2giaqnb44"
}
}
}
```
---
## Test your integration
To test your integration, you'll need a PayPal developer account.
With your developer account, you can create:
- A PayPal sandbox environment
- A PayPal Business sandbox account
- A PayPal Personal sandbox account to test payments
1. [Create a PayPal developer account](https://developer.paypal.com/api/rest), if you do not already have one.
2. Using your developer account, [create PayPal Business and Personal sandbox accounts](https://developer.paypal.com/tools/sandbox/accounts#link-createandmanagesandboxaccounts).
> **Information**
>
> To see your test payments, you must create your sandbox accounts using your [PayPal developer account](https://developer.paypal.com/api/rest).
For more details, see the [PayPal sandbox testing guide](https://developer.paypal.com/api/rest/sandbox).
The following table provides an overview of the PayPal accounts required for your test integration:
| Account type | Description | Purpose |
| --- | --- | --- |
| Developer | PayPal developer account. | Access the PayPal developer dashboard, create and manage Business and Personal sandbox accounts. |
| Business | PayPal sandbox Business account. For example, with an email address ending in `@business.example.com`. | Add PayPal as a payment method in your test Customer Area. Provide the Merchant ID and email address of this account. |
| Personal | PayPal sandbox Personal account. For example, with an email address ending in `@personal.example.com` | Test payments from a customer's side. |
After you created a PayPal developer and sandbox accounts, you're ready to start testing:
1. Contact your account manager or [request support](https://dashboard.checkout.com/support/new?topic=case_account_management_and_access&issue=issue_account_changes) to activate PayPal payments in the sandbox environment.
2. Create a PayPal transaction, by following the [PayPal Payment flow](#PayPal_payment_flow) and using either an [Auto-capture](#Request_a_payment), [Manual-capture](#Manually_capture_the_payment), or [Recurring payment flow](#Recurring_payments).
3. Log in to the test customer's PayPal account.
You will then be redirected to your predefined success URL.
---
## Move your integration to the production environment
> **Information**
>
> We strongly recommend that you use a generic company email address for your live PayPal Business account instead of a personal email address. This is to prevent having to configure a new account for your business if the personal email address is no longer in use in the future.
1. Log in to [PayPal](https://www.paypal.com/signin) with your live Business account.
2. Follow [PayPal's Merchant Account Admin Guide](https://developer.paypal.com/archive/paypal-payments-standard/admin/third-party) on granting third-party permissions. Under _Permissions_, select the following items:
- _Use Express Checkout to process payments_
- _Issue a refund for a specific transaction_
- _Process your shopper's credit or debit card payments_
- _Authorize and capture your PayPal transactions_
- _Obtain information about a single transaction_
- _Obtain authorization for pre-approved payments and initiate pre-approved transactions_
- _Generate consolidated reports for all accounts_ - if available in your region
- _Use Express Checkout to process mobile payments_ - if you plan on supporting mobile payments
3. If you're using PayPal for recurring payments, also select the following boxes:
- _Charge an existing customer based on a prior transaction_
- _Create and manage Recurring Payments_
---
## Additional information required for airlines
Using the `processing.airline_data` field, airlines must provide additional information about the ticket, passenger, and flight in their payment context request:
```json
{
"processing": {
"airline_data": [
{
"ticket": {
"number": "045-21351455613",
"issue_date": "2023-05-20",
"issuing_carrier_code": "AI",
"travel_agency_name": "World Tours",
"travel_agency_code": "01"
}
},
{
"passenger": [
{
"first_name": "Toby",
"last_name": "Smith",
"date_of_birth": "1990-05-26",
"address": {
"country": "US"
}
}
]
},
{
"flight_leg_details": [
{
"flight_number": "101",
"carrier_code": "BA",
"class_of_travelling": "J",
"departure_airport": "LHR",
"departure_date": "2023-06-19",
"departure_time": "15:30",
"arrival_airport": "LAX",
"stop_over_code": "X",
"fare_basis_code": "SPRSVR"
},
{
"flight_number": "103",
"carrier_code": "BA",
"class_of_travelling": "J",
"departure_airport": "LAX",
"departure_date": "2023-06-23",
"departure_time": "15:30",
"arrival_airport": "LHR",
"stop_over_code": "X",
"fare_basis_code": "SPRSVR"
}
]
}
]
}
}
```