# Get started with PayPal REST APIs Source: https://docs.paypal.ai/developer/how-to/api/get-started Current PayPal APIs use REST, authenticate with OAuth 2.0 access tokens, and return HTTP response codes and JSON responses. You can test US integrations with a PayPal Developer account. To try these REST APIs without a PayPal Developer account, you can use Postman. Learn more about this in our Postman guide. To explore PayPal's REST API descriptions, generate code for your API clients, and import OpenAPI documents into compatible third-party tools, see the PayPal REST API specifications on GitHub.
> **Important:** You need a PayPal Business account to:
> > * Go live with integrations.
> * Test integrations outside of the US.
## 1. Get your client ID and client secret PayPal integrations use a client ID and client secret to authenticate API calls: * A client ID identifies an app. You need a client ID to get a PayPal payment button and standard credit and debit card fields. * A client secret authenticates a client ID. To call PayPal APIs, you exchange your client ID and client secret for an access token. Keep your client secret safe. Here's how to get your client ID and client secret: 1. Select Log in to Dashboard and log in to your account or sign up for a new account. 2. Select **Apps & Credentials**. 3. New accounts come with a default application in the **REST API apps** section. To create a new project, select **Create App**. 4. Copy the client ID and client secret for your app.
## 2. Get an access token You exchange your client ID and client secret for an access token, which you use for authentication when calling PayPal REST APIs. You can call the PayPal OAuth API in any language. The following examples show you how to get your access token using cURL or Postman. ```bash theme={null} curl -v -X POST "https://api-m.sandbox.paypal.com/v1/oauth2/token" \ -u "CLIENT_ID:CLIENT_SECRET" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" ``` In the Postman app: 1. Set the verb to **POST**. 2. Enter [https://api-m.sandbox.paypal.com/v1/oauth2/token](https://api-m.sandbox.paypal.com/v1/oauth2/token) as the request URL. 3. On the **Authorization** tab, set up authorization: 1. For **TYPE**, select **Basic Auth**. 2. In **Username**, enter your client ID. 3. In **Password**, enter your client secret. 4. On the **Body** tab, complete these settings: 1. Select the **x-www-form-urlencoded** option. 2. In the **KEY** field, enter grant\_type. 3. In the **VALUE** field, enter. **client\_credentials**. 5. Select **Send**. ### Sample response PayPal returns an access token and the number of seconds for which the access token is valid, as shown in the following example. ```bash theme={null} { "scope": "https://uri.paypal.com/services/invoicing https://uri.paypal.com/services/disputes/read-buyer https://uri.paypal.com/services/payments/realtimepayment https://uri.paypal.com/services/disputes/update-seller https://uri.paypal.com/services/payments/payment/authcapture openid https://uri.paypal.com/services/disputes/read-seller https://uri.paypal.com/services/payments/refund https://api-m.paypal.com/v1/vault/credit-card https://api-m.paypal.com/v1/payments/.* https://uri.paypal.com/payments/payouts https://api-m.paypal.com/v1/vault/credit-card/.* https://uri.paypal.com/services/subscriptions https://uri.paypal.com/services/applications/webhooks", "access_token": "A21AAFEpH4PsADK7qSS7pSRsgzfENtu-Q1ysgEDVDESseMHBYXVJYE8ovjj68elIDy8nF26AwPhfXTIeWAZHSLIsQkSYz9ifg", "token_type": "Bearer", "app_id": "APP-80W284485P519543T", "expires_in": 31668, "nonce": "2020-04-03T15:35:36ZaYZlGvEkV4yVSz8g6bAKFoGSEzuy3CQcz3ljhibkOHg" } ``` ### Make API calls When you make API calls, replace `ACCESS-TOKEN` with your access token in the authorization header: `-H Authorization: Bearer ACCESS-TOKEN`. When your access token expires, call `/v1/oauth2/token` again to request a new access token. ## 3. Get sandbox account credentials The PayPal sandbox is a test environment that mirrors real-world transactions. By default, PayPal developer accounts have 2 sandbox accounts: a personal account for buying and a business account for selling. You'll get the login information for both accounts. Watch sandbox money move between accounts to test API calls. Take the following steps to get sandbox login information for business and personal accounts: 1. Log into the Developer Dashboard. 2. Select **Testing Tools** > **Sandbox Accounts**. To create more sandbox accounts, you can select **Create account**. 3. Locate the account for which you want to get credentials, and select `⋮`. 4. To see mock information, such as the account email address and a system-generated password, select **View/Edit Account**. 5. Go to `sandbox.paypal.com/signin/`, and sign in with the personal sandbox credentials. In a separate browser, sign in with the business sandbox credentials. 6. Make API calls with your app's access token to see sandbox money move between the personal and business accounts. ## See also * Sandbox testing guide * Multiparty payment solutions * Webhooks # Handling API responses when integrating with PayPal APIs Source: https://docs.paypal.ai/developer/how-to/api/handling-api-responses Correctly processing API responses ensures that your application can gracefully manage successful payments, declines, errors, and edge cases. This improves user experience, reduces failed transactions, and helps maintain compliance with PCI DSS, the security standards for handling credit card data. This guide provides software developers with best practices, tools, and integration details for handling PayPal API responses. It includes tips for both back-end and front-end environments. When integrating with PayPal, keep these principles in mind: * Always check and handle API responses and errors to ensure a secure and reliable integration. * Use PayPal's official SDKs and follow documented response handling patterns for server-side and client-side environments. * Implement strong error handling, logging, and user feedback for all payment flows. Use PayPal's sandbox tools to test error scenarios. ## Requirements and guidelines * Check the HTTP status code and response body for every API call. * Handle all possible error codes and messages. * Log errors and unexpected responses for troubleshooting. * Avoid exposing sensitive error details to users. * Use PayPal's sandbox tools to simulate errors. * Provide clear feedback to users for payment declines or failures. * Follow PayPal's [API Response Guidelines](https://developer.paypal.com/api/rest/responses/). ## Response handling flow This image shows the basic flow for handling API responses: ```mermaid theme={null} flowchart TD A[API Request] -->|Check HTTP Status Code| B{Success: 200-299?} B -->|Yes| C[Process Data] --> E B -->|No| D[Handle Error] --> E E[Provide User Feedback] ``` ## Understanding response types PayPal API responses generally fall into two categories: ### Successful responses A successful response has a status code between 200 and 299 and includes the requested data: ```json theme={null} { "id": "PAY-1234567890ABCDEF", "status": "COMPLETED", "amount": { "currency": "USD", "value": "15.00" } } ``` ### Error responses Error responses have status codes outside the 200-299 range and include error details: ```json theme={null} { "name": "VALIDATION_ERROR", "message": "Invalid request - see details", "debug_id": "9adb23571c146", "details": [ { "field": "amount", "issue": "cannot be negative" } ] } ``` ## HTTP status codes and error handling The following table shows common HTTP status codes from PayPal APIs and what they mean: | HTTP status code | Error name | What it means | What to do | | --------------------------- | ------------------------ | ---------------------------------- | -------------------------- | | `400 Bad Request` | `INVALID_REQUEST` | Formatting errors in your request. | Check your JSON structure. | | `401 Unauthorized` | `AUTHENTICATION_FAILURE` | Missing or expired access token. | Get a new access token. | | `403 Forbidden` | `NOT_AUTHORIZED` | No permission for this action. | Check account permissions. | | `404 Not Found` | `RESOURCE_NOT_FOUND` | Resource doesn't exist. | Verify the ID or URL. | | `422 Unprocessable Entity` | `UNPROCESSABLE_ENTITY` | Business rule errors. | Check error details. | | `500 Internal Server Error` | `INTERNAL_SERVER_ERROR` | PayPal server issue. | Try again later. | For more details, see the [Common errors](/developer/how-to/api/troubleshooting/common-errors) page. ## Tools, integrations, and features | Name | Purpose | Integration location | | ----------------------------------------- | ---------------------------------------------- | -------------------------------- | | Rest API response handling | Get formatted answers for payments and orders. | Back-end and front-end | | Error handling and codes | Find and fix errors and warnings. | Back-end and front-end | | Negative testing tools | Create test errors and declined payments. | Sandbox (back-end and front-end) | | Card decline and funding failure handling | Help users when cards are declined. | Back-end and front-end | ### How REST API responses work PayPal APIs send back structured JSON answers when you make requests about payments, orders, and accounts. These answers include status codes, results, and error details. Always check the status code and read the full response to handle both successes and errors well. Learn more in the [REST API responses guide](https://developer.paypal.com/api/rest/responses/). ### Error handling PayPal gives you specific error codes and messages to help you fix issues. By checking these codes and showing helpful messages to users, your app can guide people through problems and make payments easier. ## Common PayPal API error codes Here are the most common error codes you'll see and how to fix them: | Error | What it means | What to do | | ------------------------ | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | | `VALIDATION_ERROR` | Required fields are missing or have incorrect values. | Check the [validation error page](/developer/how-to/api/troubleshooting/common-errors/validation-error) for field requirements. | | `DUPLICATE_INVOICE_ID` | You used the same invoice ID more than once. | Use a unique invoice ID for each transaction. | | `CARD_EXPIRED` | Customer's card is expired. | Ask them to use a different card. | | `ORDER_ALREADY_CAPTURED` | The payment was already processed. | Check your records for the original payment. | | `PAYER_ACTION_REQUIRED` | The customer needs to do something. | Redirect the customer to the `rel:'payer-action` HATEOAS link in the response. | These guides have more details about handling errors: * [Common errors](/developer/how-to/api/troubleshooting/common-errors) * [Rest API errors](https://developer.paypal.com/api/rest/responses/) * [Payflow transaction responses](https://developer.paypal.com/api/nvp-soap/payflow/integration-guide/transaction-responses/) ### Testing your error handling PayPal offers tools to test how your app handles errors. These tools let you create test errors and declined payments without real problems. Use special headers and settings to test your error handling. You can create specific test errors by adding a header to your test API requests: ```bash theme={null} PayPal-Mock-Response: {"mock_application_codes":"INSTRUMENT_DECLINED"} ``` This lets you test error handling without causing real errors. Learn more about testing from these guides: * [Negative testing with request headers](https://developer.paypal.com/tools/sandbox/negative-testing/request-headers/) * [Sandbox error conditions](https://developer.paypal.com/tools/sandbox/error-conditions/) ### Handling card declines When a card is declined or payment fails, your app needs to handle it smoothly. Your system should spot these issues and give users clear feedback and options to try again. This helps them understand what went wrong and how to fix it. Learn more about handling payment problems: * [Card decline errors](https://developer.paypal.com/docs/checkout/advanced/card-decline-errors/) * [Handle funding failures](https://developer.paypal.com/docs/checkout/standard/customize/handle-funding-failures/) ## Integration This section explains how to handle PayPal API responses and errors in both back-end and front-end environments. ### Back-end The back end handles secure tasks like creating payments, checking transactions, and storing API keys. It talks directly to PayPal's APIs, processes responses, handles errors, and keeps sensitive data safe. Code examples in various programming languages show how to get access tokens and handle API responses securely. These examples show the right patterns to follow in your back-end code. ```bash theme={null} curl -X POST https://api-m.sandbox.paypal.com/v1/payments/payment \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ACCESS_TOKEN" \ -d '{...}' ``` ```java theme={null} import java.net.*; import java.io.*; public class PayPalApiExample { public static void main(String[] args) throws Exception { URL url = new URL("https://api-m.sandbox.paypal.com/v1/payments/payment"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Authorization", "Bearer ACCESS_TOKEN"); conn.setDoOutput(true); String jsonInputString = "{...}"; try(OutputStream os = conn.getOutputStream()) { byte[] input = jsonInputString.getBytes("utf-8"); os.write(input, 0, input.length); } int code = conn.getResponseCode(); BufferedReader br = new BufferedReader(new InputStreamReader( code == 201 ? conn.getInputStream() : conn.getErrorStream(), "utf-8")); StringBuilder response = new StringBuilder(); String responseLine; while ((responseLine = br.readLine()) != null) { response.append(responseLine.trim()); } System.out.println("Status: " + code + ", Response: " + response.toString()); } } ``` ```javascript theme={null} const fetch = require('node-fetch'); fetch('https://api-m.sandbox.paypal.com/v1/payments/payment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ACCESS_TOKEN' }, body: JSON.stringify({...}) }) .then(res => res.json().then(data => ({ status: res.status, body: data }))) .then(({ status, body }) => { if (status === 201) { console.log('Payment created:', body); } else { console.error('Error:', status, body); } }); ``` ```dotnet theme={null} using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main() { var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer ACCESS_TOKEN"); var content = new StringContent("{...}", Encoding.UTF8, "application/json"); var response = await client.PostAsync("https://api-m.sandbox.paypal.com/v1/payments/payment", content); var result = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { Console.WriteLine("Payment created: " + result); } else { Console.WriteLine("Error: " + response.StatusCode + " " + result); } } } ``` ```php theme={null} ``` ```python theme={null} import requests url = "https://api-m.sandbox.paypal.com/v1/payments/payment" headers = { "Content-Type": "application/json", "Authorization": "Bearer ACCESS_TOKEN" } data = {...} response = requests.post(url, json=data, headers=headers) if response.status_code == 201: print("Payment created:", response.json()) else: print("Error:", response.status_code, response.json()) ``` ```ruby theme={null} require 'net/http' require 'uri' require 'json' uri = URI('https://api-m.sandbox.paypal.com/v1/payments/payment') http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri.path, { 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ACCESS_TOKEN' }) request.body = {...}.to_json response = http.request(request) if response.code == "201" puts "Payment created: #{response.body}" else puts "Error: #{response.code} #{response.body}" end ``` ```typescript theme={null} import fetch from 'node-fetch'; async function createPayment() { const response = await fetch('https://api-m.sandbox.paypal.com/v1/payments/payment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ACCESS_TOKEN' }, body: JSON.stringify({...}) }); const data = await response.json(); if (response.status === 201) { console.log('Payment created:', data); } else { console.error('Error:', response.status, data); } } ``` ### Front-end The front end interacts with users, starts payments, and shows feedback based on API responses. Good response handling ensures users know the payment status, can retry if needed, and get clear guidance when something goes wrong. > **Important:** Never send your API keys or tokens from front-end code. The front-end should talk to your secure back end, which then talks to PayPal. Code examples show how to handle responses and errors in various front-end frameworks. These examples help you create user-friendly payment flows. ```javascript theme={null} // paypal.js export async function createPayment() { const response = await fetch('https://api-m.sandbox.paypal.com/v1/payments/payment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ACCESS_TOKEN' }, body: JSON.stringify({...}) }); const data = await response.json(); if (response.status === 201) { alert('Payment created!'); } else { alert('Error: ' + response.status); } } // index.html ``` ```javascript theme={null} import React from 'react'; function createPayment() { fetch('https://api-m.sandbox.paypal.com/v1/payments/payment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ACCESS_TOKEN' }, body: JSON.stringify({...}) }) .then(res => res.json().then(data => ({ status: res.status, body: data }))) .then(({ status, body }) => { if (status === 201) { alert('Payment created!'); } else { alert('Error: ' + status); } }); } export default function PayPalButton() { return ; } ``` ```javascript theme={null} ``` ```typescript theme={null} import React from 'react'; const createPayment = async () => { const response = await fetch('https://api-m.sandbox.paypal.com/v1/payments/payment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ACCESS_TOKEN' }, body: JSON.stringify({...}) }); const data = await response.json(); if (response.status === 201) { alert('Payment created!'); } else { alert('Error: ' + response.status); } }; const PayPalButton: React.FC = () => ( ); export default PayPalButton; ``` ## Security testing tips Testing your security setup is vital to protect against threats. Consider these key tests: ### Auth testing * Test with expired tokens to make sure your refresh system works. * Try operations with limited permissions to test your access controls. * Check that webhook security properly rejects unsigned events. ### Data protection testing * Make sure sensitive data isn't saved in your logs. * Check that error messages don't show sensitive details to users. * Test that front-end code never sees or handles secure data. ### Integration security testing * Use [PayPal's testing tools](https://developer.paypal.com/tools/sandbox/negative-testing/request-headers/) to create security-related errors. * Test with poor network conditions, like timeouts and drops. * Check that your security settings meet PayPal's requirements. For complete testing info, see the [Testing your response handling guide](/developer/how-to/api/handling-api-responses#testing-your-response-handling). ## Testing your response handling Follow these steps to test how your app handles PayPal responses: 1. Set up test accounts: * Create test merchant and buyer accounts. * Save the test login details. 2. Test successful payments: * Complete a test payment. * Check that your code handles success correctly. 3. Test error scenarios: * Use PayPal's tools to create test errors. * Add special headers to trigger specific errors. * Example: `PayPal-Mock-Response: {"mock_application_codes":"INSTRUMENT_DECLINED"}`. 4. Test recovery flows: * Make sure users can recover from errors. * Check that error messages are clear. * Test that retry options work correctly. ## Common problems and solutions You might face these common issues: | Problem | Solution | | ------------------------------ | ------------------------------------------------------------- | | Getting `401` errors regularly | Set up token refresh before tokens expire. | | Webhooks not working | Make sure your webhook URL is public and events are verified. | | Can't process refunds | Use the correct transaction ID from the original payment. | | Test payments always fail | Check if your test buyer account has enough funds. | ## Mobile app tips When building mobile apps with PayPal: * Use native SDKs when possible for better user experience. * Add extra error handling for spotty mobile connections. * Plan for offline scenarios when the app loses connection. * Add clear visual feedback during payment processing. ## References * [Rest API responses](https://developer.paypal.com/api/rest/responses/) * [Rest API overview](https://developer.paypal.com/api/rest/) * [Rest API requests](https://developer.paypal.com/api/rest/requests/) * [Payflow transaction responses](https://developer.paypal.com/api/nvp-soap/payflow/integration-guide/transaction-responses/) * [Negative testing with request headers](https://developer.paypal.com/tools/sandbox/negative-testing/request-headers/) * [Sandbox error conditions](https://developer.paypal.com/tools/sandbox/error-conditions/) * [Card decline errors](https://developer.paypal.com/docs/checkout/advanced/card-decline-errors/) * [Handle funding failures](https://developer.paypal.com/docs/checkout/standard/customize/handle-funding-failures/) # Making PayPal REST API requests Source: https://docs.paypal.ai/developer/how-to/api/make-api-requests Build proper API requests with the correct headers and parameters to ensure successful communication with PayPal's REST APIs. PayPal REST APIs authenticate with OAuth 2.0 access tokens, and return HTTP response codes with JSON-encoded responses. > **Important:** Before making REST API calls, you'll need to [get credentials](developer/how-to/apps-scopes-credentials). ## Base URLs All PayPal REST API requests target one of two base URLs: * Sandbox for testing: `https://api-m.sandbox.paypal.com` * Live for production: `https://api-m.paypal.com` ## 1st-party and 3rd-party calls When you make REST API calls to PayPal, you can make first-party or third-party calls. * **First-party calls:** API calls made to PayPal on behalf of your business. This method is also called a direct merchant integration. * **Third-party calls:** API calls made to PayPal on behalf of another merchant. This is common when building marketplaces, platforms, or large enterprise solutions. This method is also called a multiparty or partner integration. Third-party calls require additional HTTP headers: * [`PayPal-Auth-Assertion`](#paypal-auth-assertion): Identifies the merchant you're making a call for. * [`PayPal-Partner-Attribution-Id`](#paypal-partner-attribution-id): Identifies your platform to PayPal. ## Important HTTP headers The following is a list of all PayPal-specific HTTP request headers. ### PayPal-Auth-Assertion > **Optional:** For platforms and marketplaces only. This header is for platforms, marketplaces, large companies, and service providers that handle payments for more than one merchant. Examples include Square, eBay, Shopify, and other payment processors. #### Purpose Generating and storing separate access tokens for each merchant can be complex and costly. You can use the `PayPal-Auth-Assertion` header as one set of platform credentials for all merchants. The `PayPal-Auth-Assertion` header is a JSON Web Token (JWT) that identifies which merchant each API call is for. This header requires explicit consent from each merchant you represent. #### Build the JWT PayPal recommends using an unsigned JWT, because the information passed with the JWT is not sensitive. Build the JWT with 3 parts: * **Header:** For an unsigned JWT, set algorithm to `"alg": "none"`. * **Payload:** Include the following fields: * `iss`: The platform's `client_id` (issuer). * `payer_id`: The specific merchant's PayPal payer ID. * **Signature:** Use an empty string `""` for unsigned JWTs. If you prefer a signed JWT for security reasons, you can sign it with your secret from your API credentials. Base64 encode each part separately, then concatenate with periods: ``` [encoded_header].[encoded_payload].[encoded_signature] ``` Example HTTP header: ```http theme={null} PayPal-Auth-Assertion: eyJhbGciOiJub25lIn0.eyJpc3MiOiJZT1VSX1BMQVRGT1JNX0NMSUVOVF9JRCIsInBheWVyX2lkIjoiTUVSQ0hBTlRfUEFZRVJfSUQifQ. ``` Include the resulting JWT string in the `PayPal-Auth-Assertion` header when making API calls on behalf of that merchant. ```json theme={null} { "iss": "your_platform_client_id", "payer_id": "merchant_payer_id_here" } ``` ### PayPal-Partner-Attribution-Id > **Required:** For platforms and marketplaces only. This header does two things: * Identifies your platform to PayPal. * Tracks all transactions associated with your platform. The header value is your unique Build Notation (BN) code. Take the following steps to find your BN code: 1. From your developer dashboard, select **Apps & Credentials**. 2. Select the app you're using. 3. Under **App Settings**, scroll to **Reports**. 4. Your BN code appears on the last line of the Reports section. ### PayPal-Mock-Response > **Optional.** Use this header to simulate errors by passing an error code through the `mock_application_codes` parameter. For example, `"mock_application_codes": "DUPLICATE_INVOICE_ID"` to simulate two invoices sent with the same ID: ```bash theme={null} curl -X POST \ https://api-m.sandbox.paypal.com/v2/checkout/orders/YOUR-ORDER-ID/capture \ -H 'Authorization: Bearer YOUR-ACCESS-TOKEN' \ -H 'Content-Type: application/json' \ -H 'PayPal-Mock-Response: {"mock_application_codes": "DUPLICATE_INVOICE_ID"}' ``` For more information, see: * [Payment API error messages](https://developer.paypal.com/docs/api/payments/v2/#errors) * [Orders API error messages](https://developer.paypal.com/api/rest/reference/orders/v2/errors/) * [Simulate negative responses with request headers](https://developer.paypal.com/tools/sandbox/negative-testing/request-headers/#test-api-error-handling-routines) ### PayPal-Request-Id > **Important:** Recommended for all `POST` and `PUT` calls. The `PayPal-Request-Id` contains a unique user-generated ID that prevents duplicate transactions. PayPal recommends including this header in any API call that creates or modifies data. PayPal uses the `PayPal-Request-Id` to enforce **idempotency**. Idempotency means you can retry an API call multiple times without duplicating actions. For example, if a user presses a buy button multiple times, they aren't charged for each button press. With this header, you can retry calls knowing that PayPal won't process the same action for as long as the server stores the ID. PayPal stores the ID for up to 45 days. If you retry a call with the same `PayPal-Request-Id`, PayPal recognizes it as a duplicate and returns the result of the original call. ```bash theme={null} curl -v -X POST https://api-m.sandbox.paypal.com/v2/payments/authorizations/YOUR-ORDER-ID/capture \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR-ACCESS-TOKEN" \ -H "PayPal-Request-Id: 123e4567-e89b-12d3-a456-426655440010" \ -d '{ "amount": { "value": "10.99", "currency_code": "USD" }, "invoice_id": "INVOICE-123", "final_capture": true }' ``` ## Common authentication errors When using PayPal HTTP headers, you might encounter these issues: * **401 Unauthorized**: Check that your platform credentials are valid and that you have permission to act on behalf of the merchant. * **400 Bad Request**: Verify the JWT format is correct and all required fields are present. * **403 Forbidden**: Ensure the merchant has granted your platform appropriate permissions. For detailed error troubleshooting, check the response body. Find an error code, message, and debug ID to reference when contacting PayPal support. You can also refer to our [common errors](/developer/how-to/api/troubleshooting/common-errors/). ## Query PayPal REST APIs When making a REST API request to PayPal, append query parameters to the endpoint URL using the following format: ```http theme={null} https://api-m.sandbox.paypal.com/{resource}?parameter1=value1¶meter2=value2 ``` * Separate each query parameter with an ampersand `&`. * Introduce the first query parameter with a question mark `?`. * URL-encode parameter names and values if they contain special characters. ### Example: list invoices This example returns details for four invoices, starting from the third invoice, and includes the total invoice count. ```bash theme={null} curl -v -X GET https://api-m.sandbox.paypal.com/v1/invoicing/invoices?page=3&page_size=4&total_count_required=true\ -H "Content-Type: application/json" \ -H "Authorization: Bearer ACCESS-TOKEN" ``` * `page=3` requests the third page of results. * `page_size=4` limits the response to 4 items per page. * `total_count_required=true` asks PayPal to include the total count of items in the response. ### Query parameters > **Note:** Not all pagination parameters are available for all APIs. | Parameter | Type | Description | | ---------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `count` | integer | The number of items to list in the response. | | `end_time` | integer | The end date and time for the range to show in the response, in Internet date and time format. For example, `end_time=2025-03-07T11:00:00Z`. | | `page` | integer | The page number indicating which set of items will be returned in the response. For example, the combination of `page=1` and `page_size=20` returns the first 20 items. The combination of `page=2` and `page_size=20` returns items 21 through 40. | | `page_size` | integer | The number of items to return in the response. | | `total_count_required` | boolean | Indicates whether to show the total count in the response. | | `sort_by` | string | Sorts the payments in the response by a specified value, such as the create time or update time. | | `sort_order` | string | Sorts the items in the response in ascending or descending order. | | `start_id` | string | The ID of the starting resource in the response. When results are paged, you can use the `next_id` value as the `start_id` to continue with the next set of results. | | `start_index` | integer | The `start_index` parameter lets you specify the position in the list where results should begin. For example, setting `start_index=2` skips the first item and shows results from the second item onward. | | `start_time` | string | The start date and time for the range to show in the response, in Internet date and time format. For example, `start_time=2025-03-06T11:00:00Z`. | ## Example request: create invoice PayPal's REST APIs support standard HTTP methods - `GET`, `POST`, `PUT`, `PATCH`, `DELETE`. > **Important**: Include a `PayPal-Request-Id` header in all `POST` and `PUT` requests to prevent duplicate actions. The following request creates an invoice as a direct merchant: * From sender David Larusso, including address, email address, and phone number. * To recipient Stephanie Meyers, including address, email address, and phone number. * For one \$50 yoga mat including sales tax. * For one \$10 t-shirt including sales tax. * With \$20 minimum partial payments enabled. * With an optional tip. * With $10 packing charges and $10 shipping charges, including sales tax. * With a 5% invoice discount. ```bash theme={null} curl -v -X POST 'https://api-m.sandbox.paypal.com/v2/invoicing/invoices' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer YOUR-ACCESS-TOKEN' \ -H 'PayPal-Request-Id: YOUR-REQUEST-ID' \ -d '{ "detail": { "invoice_number": "123", "reference": "deal-ref", "invoice_date": "2028-11-22", "currency_code": "USD", "note": "Thank you for your business.", "term": "No refunds after 30 days.", "memo": "This is a long contract", "payment_term": { "term_type": "NET_10", "due_date": "2028-11-22" } }, "invoicer": { "name": { "given_name": "David", "surname": "Larusso" }, "address": { "address_line_1": "1234 First Street", "address_line_2": "337673 Hillside Court", "admin_area_2": "Anytown", "admin_area_1": "CA", "postal_code": "98765", "country_code": "US" }, "email_address": "merchant@example.com", "phones": [ { "country_code": "001", "national_number": "4085551234", "phone_type": "MOBILE" } ], "website": "www.test.com", "tax_id": "ABcNkWSfb5ICTt73nD3QON1fnnpgNKBy-Jb5SeuGj185MNNw6g", "logo_url": "https://example.com/logo.PNG", "additional_notes": "2-4" }, "primary_recipients": [ { "billing_info": { "name": { "given_name": "Stephanie", "surname": "Meyers" }, "address": { "address_line_1": "1234 Main Street", "admin_area_2": "Anytown", "admin_area_1": "CA", "postal_code": "98765", "country_code": "US" }, "email_address": "buyer@example.com", "phones": [ { "country_code": "001", "national_number": "4884551234", "phone_type": "HOME" } ] }, "shipping_info": { "name": { "given_name": "Earl", "surname": "Gray" }, "address": { "address_line_1": "1234 Main Street", "admin_area_2": "Anytown", "admin_area_1": "CA", "postal_code": "98765", "country_code": "US" } } } ], "items": [ { "name": "Yoga mat", "description": "Elastic mat to practice yoga.", "quantity": "1", "unit_amount": { "currency_code": "USD", "value": "50.00" }, "tax": { "name": "Sales Tax", "percent": "7.25" }, "discount": { "percent": "5" }, "unit_of_measure": "QUANTITY" }, { "name": "Yoga t-shirt", "quantity": "1", "unit_amount": { "currency_code": "USD", "value": "10.00" }, "tax": { "name": "Sales Tax", "percent": "7.25" }, "unit_of_measure": "QUANTITY" } ] }' ``` # Rate limiting with PayPal REST APIs Source: https://docs.paypal.ai/developer/how-to/api/rate-limiting Rate limiting restricts the number of API requests you can make in a specific time frame. When you exceed this limit, PayPal's servers may deny further requests until your usage drops below the limit. This protects the system from overload. If you or your customers receive a `429` status code, too many requests were sent, which might indicate anomalous traffic. PayPal uses rate limits to ensure stability. Understanding rate limiting can help you avoid disruptions when building or scaling your app. PayPal may enforce rate limits for several reasons: * **Excessive polling:** Making too many requests instead of using webhooks. * **Traffic spikes:** A sudden increase in requests due to user activity or system events. * **Token misuse:** Failing to reuse OAuth 2.0 tokens and repeatedly fetching new ones. * **Suspicious patterns:** Behavior flagged as atypical or potentially harmful. > **Note:** PayPal doesn't publish exact rate limits because they vary depending on the API, environment, and circumstances. By keeping these limits flexible, PayPal can scale services to match demand while preventing abuse. ## How to prepare for rate limiting Here's what you can do to reduce the chances of hitting a rate limit: * **Use webhooks instead of polling:** [Webhooks](https://developer.paypal.com/api/rest/webhooks/) let PayPal send updates directly to your system, so you don't need to keep requesting information. * **Cache OAuth 2.0 tokens:** Instead of creating new tokens for every request, securely store and reuse tokens until they expire. * **Optimize your requests:** Minimize unnecessary calls, and don't request data more often than needed. Combine requests whenever possible. * **Plan for scale:** If you expect high traffic, test your system to ensure it works efficiently under heavy load. ## What to do if you hit a rate limit If your API requests start failing due to rate limiting, follow these steps: * **Diagnose the issue:** Check your API logs to understand why the limit was triggered. Look for patterns in request frequency or behavior. * **Reduce request frequency:** Slow down request rates or spread them out over time to stay within limits. * **Retry with exponential backoff:** Increase the delay between requests each time a request fails. * **Use webhooks instead of polling:** If you're polling for updates, switch to PayPal's webhooks to receive alerts automatically. * **Implement error handling**: Implement error handling as in the following example code. In a production environment, you'd want to: * Use a more robust storage mechanism. * Implement proper secure token management. * Use a production-grade logging system. * Consider more sophisticated retry strategies with maximum retry limits. * Add additional error handling for different types of API responses. ```javascript theme={null} // Example error handling for rate limits function apiRequest(endpoint, data) { return fetch(endpoint, { method: 'POST', body: JSON.stringify(data), headers: { 'Content-Type': 'application/json' } }) .then(response => { if (response.status === 429) { // Extract retry-after header if available const retryAfter = response.headers.get('Retry-After') || 30; // Log the rate limiting event console.log(`Rate limited. Retrying in ${retryAfter} seconds`); // Implement exponential backoff return new Promise(resolve => { setTimeout(() => resolve(apiRequest(endpoint, data)), retryAfter * 1000); }); } return response.json(); }) .catch(error => { // Log the error for debugging console.error('API request failed:', error); // Determine if retry is appropriate if (isRetryableError(error)) { return retryWithBackoff(apiRequest, [endpoint, data]); } throw error; }); } ``` If you need further assistance, reach out to [Merchant Technical Support](https://www.paypal.com/mts?_ga=2.12095284.1829917444.1751296466-935108042.1736183519&_gac=1.90987240.1749058302.CjwKCAjw3f_BBhAPEiwAaA3K5GZi7UMt1wQxD_c8GrhAiGQRTsNsuH7lglTyr9KlGTH_zQ73HWpLtBoCtrsQAvD_BwE). # Agreement already canceled Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/agreement-already-cancelled Returns from the Orders V2 API. `AGREEMENT_ALREADY_CANCELLED` indicates that an operation is trying to execute on an already-canceled billing agreement. | Cause | Impact | Resolution | | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Manually canceled: The merchant or payer manually canceled the agreement.
- Automatically canceled: Certain conditions automatically canceled the agreement, such as payment failures or account issues.
- Logic error: The application implemented faulty logic that tried to modify an agreement without checking its status. | - Transaction failure: Transactions for the canceled agreement cannot proceed, potentially leading to failed payments and disrupted user subscriptions or services.
- Integration failures: Recurring logic based on this agreement might break, causing administrators or payers to make multiple calls attempting to resolve actions on a non-existent agreement.
- Customer dissatisfaction: Users affected by the cancellation might experience service interruption, thereby reducing trust and satisfaction. | - Check the agreement status: Ensure that you check the status of a billing agreement before beginning operations, such as by retrieving agreement details and verifying the cancellation status.
- Implement error handling: Manage errors by informing the payer or system about the current status of the billing agreement and providing appropriate options or messages.
- Update business logic: Ensure that your application logic correctly tracks the status of an agreement and attempts only valid operations. | # Cannot pay self Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/cannot-pay-self Returns from the Payments V1 API. `CANNOT_PAY_SELF` indicates that the payment request is attempting to send money to the same account initiating the transaction. | Cause | Impact | Resolution | | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Duplicate reference: The transaction or billing agreement attempts to reference the sender and receiver of payment as the same entity, which is invalid. | - Disrupted transactions: PayPal prevents the transaction from being processed to avoid misuse or fraud stemming from potential self-payment. | - Confirm separation: Ensure that the sender and receiver are different entities.
- Review API request: Ensure you use distinct PayPal account IDs or email addresses for the sender and receiver.
- Implement validation checks: Ensure that your application checks to prevent users from setting up billing agreements with duplicate entities.
- Debug application code: Review and debug the code to correct issues leading to payer and payee using the same account. | # Currency mismatch Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/currency-mismatch Returns from the Payments V2 API. `CURRENCY_MISMATCH` indicates a discrepancy between the currencies specified within different components in the transaction request. Typically, that means the currency used in the payment request does not match the currency expected or configured in the transaction. | Cause | Impact | Resolution | | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Mismatch in account: The currency specified in the transaction request does not match the currency configured for the merchant account or the payment method.
- Mismatch in transaction: The currency used in the transaction does not match the currency settings of the payer or payee accounts.
- Mismatch in request: The currency specified in one field of the API request does not match another field in the API request, such as between the payment amount and the transaction currency. | - Failed payment attempt: The transaction cannot be processed, leading to a failed payment attempt.
- Payer dissatisfaction: Failed payment attempts can cause delays and inconvenience for the payer and the merchant as PayPal does not complete the payment until you resolve the currency issue. | - Verify fields: Check the API request to ensure that all relevant fields consistently use the same currency.
- Verify configuration: Ensure that you configure the merchant account to accept payments in the specified currency and adjust settings as necessary.
- Match between accounts: Ensure that the currency settings align between payer and payee accounts.
- Verify payment method support: Confirm that the payment method [supports the specified currency](https://developer.paypal.com/docs/reports/reference/paypal-supported-currencies/).
- Verify transaction match: Ensure that the currency used in the transaction matches the currency expected by the payment method. | # Currency not allowed Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/currency-not-allowed Returns from the Payments V1 API. `CURRENCY_NOT_ALLOWED` indicates that PayPal does not support the currency specified in the transaction request. | Cause | Impact | Resolution | | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Unsupported currency: PayPal does not support the specified currency for the transaction.
- Unconfigured account: The merchant's PayPal account is not configured to accept payments in the specified currency.
- Region restrictions: The region or transaction type may have restrictions on certain currencies.
- Disabled currency: PayPal may support the currency but the account or payment method disabled it. | - Failed payment attempt: PayPal cannot process the transaction with the specified currency.
- Inconvenience: Failed payment attempts using an unsupported currency can cause inconvenience for the merchant and the payer, especially if the payer prefers to pay in a specific currency. | - Verify supported currencies: Change the currency code in your API request to a [supported currency](https://developer.paypal.com/docs/reports/reference/paypal-supported-currencies/) for your location or account.
- Configure account: Ensure that you have configured or enabled your PayPal account to accept payments in the desired currencies. | # Duplicate transactions Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/duplicate-transaction Returns from the Payments V2 API. `DUPLICATE_TRANSACTION` indicates that a transaction with identical details has already been processed, and has been flagged to prevent duplicate charges. | Cause | Impact | Resolution | | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | - Network latency or delays: Issues in network or server communication could result in a resending of the transaction request.
- Payer actions: A payer might inadvertently submit the payment information multiple times, such as by clicking the payment button more than once.
- Server error: The client-side application did not receive a response and retried the transaction. | - Customer dissatisfaction: Needing to perform additional steps to confirm the transaction status, or being unsure whether the transaction succeeded, can lead to customer confusion or frustration. | - Check transaction status: Verify whether the original transaction succeeded by checking the transaction history in your PayPal account or through the API.
- Implement idempotency: Use unique identifiers, such as an idempotency key, for each transaction request to ensure that retries do not result in duplicate transactions.
- Improve user feedback: Provide clear feedback to payers about their transaction status to prevent them from resubmitting the payment.
- Implement error handling: Implement error handling and network retry logic to manage connectivity issues without resubmitting identical requests. | # Merchant not enabled for reference transaction Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/merchant-not-enabled-for-reference-transaction Returns from the Payments V1 API. `MERCHANT_NOT_ENABLED_FOR_REFERENCE_TRANSACTION` indicates that the merchant account is not configured to perform reference transactions. | Cause | Impact | Resolution | | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | - Unconfigured account: The merchant account is not configured or approved to handle reference transactions. Reference transactions require specific permissions and account settings that PayPal does not enable by default on all accounts.
- Failed attempt: The merchant attempts a reference transaction without enabling the necessary permissions or account settings. | - Failed payment attempt: The merchant cannot process reference transactions for recurring billing, subscriptions, or other post-payment transactions.
- Business disruptions: Services that depend on automated billing fail to operate. | - [Contact customer support](https://www.paypal.com/us/cshelp/contact-us): Send a request to customer support to enable reference transactions for your account. Enabling reference transactions may require you to provide additional information about your account.
- Review account settings: Configure your account settings to support reference transactions.
- For more information, see [Initiate future transactions](https://developer.paypal.com/docs/checkout/advanced/customize/reference-transactions/). | # Not authorized Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/not-authorized The Orders v2 API returns a `403 Not Authorized` error when the API caller or the payee does not have permission. Review the common causes and how to fix them. If an issue persists or you have further questions, contact [PayPal Support](https://www.paypal.com/us/cshelp/technical). PAYEE\_ACCOUNT\_NOT\_VERIFIED | Cause | Impact | Resolution | | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - The payee did not verify their PayPal account.
- The payee ignored account restrictions or limits.
- The payee did not verify their email address. | PayPal stops the payment and blocks the transaction. This slows the purchase. |
- Tell the payee to check their email, link and confirm a bank account or card, and send required documents.
- Help them remove account restrictions or limits. Have them resolve any issues or contact PayPal support.
- Tell the payee to follow the steps in the PayPal email. | PAYEE\_NOT\_CONSENTED | Cause | Impact | Resolution | | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - The payee did not give permission to the API caller.
- Another account used its info to make the request for the payee.
- The payee did not agree to let the API caller finish the payment. |
- The payee blocks the helper account from processing payments.
- Customers cannot finish PayPal payments on the website. | - Enter the payee account in the `payee` field in the `purchase_units` object of the Orders API request. Enter correct info and give the API caller permission.
- For PayPal Complete Payments, give the API caller consent to collect partner fees for the payee. Add `PARTNER_FEE` during sign-up.
- If you already added permission or this issue persists, contact PayPal support. | PERMISSION\_DENIED | Cause | Impact | Resolution | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - The API caller skipped required permissions.
- The PayPal account doesn't have the permission you need.
- The API caller used expired or invalid OAuth access tokens.
- The account tries things it is not allowed to do, like a personal account using business tools.
- The API caller uses the wrong sandbox login info in a live environment or the other way around. | The payment stops, and the customer cannot finish the order. This can cause lost sales. | - Make sure the resource ID belongs to the PayPal account making the API call. If not, give the right permission.
- Use login info for the correct sandbox or live environment and get it from the PayPal Developer Dashboard.
- Ask for the right access when making tokens.
- Renew access tokens often and handle token expiration in the PayPal Developer Dashboard.
- Use the correct API endpoints for your environment. For sandbox, use `https://api.sandbox.paypal.com`. For live, use `https://api.paypal.com`.
- Make sure the PayPal account supports the requested API operations. Some features only work for business accounts or special integrations, like payouts. | # Common errors overview Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/overview Troubleshooting is an important part of integrating with the PayPal Orders API. The following provides explanations and solutions to help you quickly find and fix issues in your integration. | Issue | Action | | :---------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `AMOUNT_MISMATCH` | Ensure the total amount equals the sum of line items, taxes, and discounts. The API returns this error if the sale amounts are not reflected in the request. | | `CARD_EXPIRED` | Show the error to the payer and ask them to use a different card. | | `CANNOT_BE_NEGATIVE` | Enter a positive amount with no more than two decimal places. | | `CANNOT_BE_ZERO_OR_NEGATIVE` | Enter a positive, non-zero amount with no more than two decimal places. | | `CURRENCY_NOT_SUPPORTED` | Use a PayPal-supported currency. Make sure the receiving PayPal account accepts the currency. For a list of supported currencies, see [Currency codes](https://developer.paypal.com/docs/api/rest/reference/currency-codes/currency-codes/). | | `DECIMAL_PRECISION` | Round the amount to 2 decimal places and try again. If the issue persists, contact [PayPal support](https://www.paypal.com/us/cshelp/technical) and provide the `debug_id` from the API response. | | `DECIMALS_NOT_SUPPORTED` | Adjust the amount to match the number of decimal places the currency supports. | | `DUPLICATE_INVOICE_ID` | Use a different `invoice_id`. If you must reuse the same `invoice_id` and the issue persists, contact [PayPal support](https://www.paypal.com/us/cshelp/technical). | | `INCOMPATIBLE_PARAMETER_VALUE` | Make sure the parameters in the API request match the expected data types. For more information, see [Authentication](https://developer.paypal.com/api/rest/authentication/). | | `INVALID_PARAMETER_SYNTAX` | Make sure the API request JSON is correct and follows the PayPal API request format. If the issue persists, contact [PayPal support](https://www.paypal.com/us/cshelp/technical) and provide the `debug_id` from the API response. | | `INVALID_PARAMETER_VALUE` | Enter a valid parameter value. | | `INVALID_RESOURCE_ID` | Check the resource ID and try again. If the resource ID belongs to a different PayPal account, check the scopes and permissions for the receiving account. | | `INVALID_STRING_LENGTH` | Make sure text fields are not too long and include all required data. For string length requirements, see the [Orders API](https://developer.paypal.com/docs/api/orders/v2/#orders_create). | | `ITEM_TOTAL_MISMATCH` | Make sure the item totals match the quantity total. | | `MAX_NUMBER_OF_PAYMENT_ATTEMPTS_EXCEEDED` | Ask the payer to use a different payment method. | | `MISSING_REQUIRED_PARAMETER` | Make sure the JSON follows the PayPal API request format and includes all [required parameters](https://developer.paypal.com/docs/api/orders/v2/#orders_create). If the issue persists, contact [PayPal support](https://www.paypal.com/us/cshelp/technical) and provide the `debug_id` from the API response. | | `ORDER_ALREADY_AUTHORIZED` | To proceed, [call capture](https://developer.paypal.com/docs/api/orders/v2/#orders_capture) because the funds are authorized. If the authorization is more than 3 days old, reauthorize the funds before capturing. | | `ORDER_ALREADY_CAPTURED` | No action needed. Use a `GET` call on the order ID to get the capture ID or PayPal transaction ID. For multi-capture or split shipments, use `intent=AUTHORIZE`. See [Capture authorized payment](https://developer.paypal.com/docs/api/payments/v2/#authorizations_capture) for more information. | | `ORDER_NOT_APPROVED` | Ask the payer to complete PayPal checkout again to approve the order. Redirect them to the `'rel':'approve'` URL in the HATEOAS links from the create order call or provide a valid `payment_source` in the request. | | `PAYEE_ACCOUNT_RESTRICTED` | Contact PayPal customer support to lift restrictions on the receiving account. If you are a marketplace, ask the seller to resolve restrictions with PayPal. | | `PAYEE_NOT_CONSENTED` | Make sure the API caller has consent to collect partner fees for the payee. Add `PARTNER_FEE` to the capabilities during [signup](https://developer.paypal.com/docs/multiparty/seller-onboarding/before-payment/#generate-a-signup-link). If `PARTNER_FEE` is already added or the issue persists, contact [PayPal support](https://www.paypal.com/us/cshelp/technical). | | `PAYEE_NOT_ENABLED_FOR_CARD_PROCESSING` | Contact [PayPal support](https://www.paypal.com/us/cshelp/technical) to check the merchant or payee account configuration. | | `PAYER_ACTION_REQUIRED` | Redirect the payer to the `'rel':'payer-action'` HATEOAS link before authorizing or capturing the order. Some payment methods require a webhook subscription to notify you of background payer actions before capture succeeds. | | `PERMISSION_DENIED` | Make sure you have the correct permissions and scopes for the resource. If the resource ID belongs to another account, grant the necessary permissions. | | `POSTAL_CODE_REQUIRED` | Add a postal code to the request and try again. | | `REDIRECT_PAYER_FOR_ALTERNATE_FUNDING` | Redirect the payer to choose a different payment method. In PayPal, the payer can add a new payment method to their wallet or use a different card. | | `REFERENCED_CARD_EXPIRED` | Ask the payer to update their card information. Otherwise, future attempts will fail. | | `SHIPPING_ADDRESS_INVALID` | Fix the shipping address and try again. If using saved payment details, ask the payer for the correct shipping address. | | `TOKEN_ID_NOT_FOUND` | Validate the payment token. If your PayPal account is making API calls for another account, make sure the recipient account grants the necessary permissions. | | `UNPROCESSABLE_ENTITY` | Contact [PayPal support](https://www.paypal.com/us/cshelp/technical) with the `debug_id` or `correlation_id` from the response header. For legacy integrations, check the body or response parameters. | | `VALIDATION_ERROR` | Tell the payer the card number is incorrect and ask them to enter the correct number. | ## HTTP status codes and error messages The following table lists the most common HTTP status codes and error messages returned by the [Orders v2 API](https://developer.paypal.com/docs/api/orders/v2/#errors). | HTTP status code | Error message | Error code | | :-------------------------- | :--------------------------------------------------------------------------------------------------- | :----------------------- | | `400 Bad Request` | The request has the wrong format. | `INVALID_REQUEST` | | `401 Unauthorized` | Authentication failed because the authorization header is missing, or the credentials are not valid. | `AUTHENTICATION_FAILURE` | | `403 Forbidden` | Authorization failed because of lack of permissions. | `NOT_AUTHORIZED` | | `404 Not Found` | The specified resource does not exist. | `RESOURCE_NOT_FOUND` | | `422 Unprocessable Entity` | The requested action could not be performed, won't work, or failed business rules. | `UNPROCESSABLE_ENTITY` | | `500 Internal Server Error` | An internal server error occurred. | `INTERNAL_SERVER_ERROR` | | `503 Service Unavailable` | The service is unavailable. | `SERVICE_UNAVAILABLE` | ## Error samples The following examples show common error scenarios for the Orders v2 API. Each sample includes a request and the corresponding error response. ### Internal server error (500) The Orders v2 API returns a `500` status code when the server encounters an unexpected condition. The following sample shows a response when the server has an underlying issue or does not handle an internal exception. #### Create order request ```bash theme={null} curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/ \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ -d '{ "intent": "CAPTURE", "purchase_units": [ { "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f7b", "amount": { "currency_code": "USD", "value": "10.00" } } ], "payment_source": { "paypal": { "address": { "address_line_1": "2211 N First Street", "address_line_2": "17.3.160", "admin_area_1": "CA", "admin_area_2": "San Jose", "postal_code": "95131", "country_code": "US" }, "email_address": "johndoe@paypal.com", "payment_method_preference": "IMMEDIATE_PAYMENT_REQUIRED", "experience_context": { "return_url": "https://example.com/returnUrl", "cancel_url": "https://example.com/cancelUrl" } } } }' ``` #### Error response ```json theme={null} { "name": "INTERNAL_SERVER_ERROR", "message": "An internal server error has occurred.", "debug_id": "90957fca61718", "links": [ { "href": "https://developer.paypal.com/api/orders/v2/#error-INTERNAL_SERVER_ERROR", "rel": "information_link", "method": "GET" } ] } ``` ### Unprocessable entity error (422) The Orders v2 API returns a `422` status code when an order fails business validation. For example, this can happen if the payer uses an expired payment card. The following sample shows a create order request with an expired card and the resulting error response. #### Create order request ```bash theme={null} curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/ \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ -d '{ "intent": "AUTHORIZE", "purchase_units": [ { "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b", "amount": { "currency_code": "USD", "value": "100.00" } } ], "payment_source": { "card": { "number": "4111111111111111", "expiry": "2010-02", "name": "John Doe", "billing_address": { "address_line_1": "2211 N First Street", "address_line_2": "17.3.160", "admin_area_1": "CA", "admin_area_2": "San Jose", "postal_code": "95131", "country_code": "US" }, "stored_credential": { "payment_initiator": "MERCHANT", "payment_type": "ONE_TIME", "usage": "SUBSEQUENT" } } } }' ``` #### Error response ```json theme={null} { "name": "UNPROCESSABLE_ENTITY", "details": [ { "field": "/payment_source/card/expiry", "location": "body", "issue": "CARD_EXPIRED", "description": "The card is expired." } ], "message": "The requested action could not be performed, semantically incorrect, or failed business validation.", "debug_id": "866780170332c", "links": [ { "href": "https://developer.paypal.com/docs/api/orders/v2/#error-CARD_EXPIRED", "rel": "information_link", "method": "GET" } ] } ``` ### Bad request (400) The Orders v2 API returns a `400` status code when a request includes an incorrect or unsupported value. The following sample shows a create order request with an invalid `usage_pattern` and the resulting error response. #### Create order request ```bash theme={null} curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/ \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ -d '{ "intent": "CAPTURE", "purchase_units": [ { "reference_id": "PUHF", "amount": { "currency_code": "USD", "value": "10.00" } } ], "payment_source": { "paypal": { "attributes": { "customer": { "id": "jd120252fg4dm" }, "vault": { "confirm_payment_token": "ON_ORDER_COMPLETION", "usage_type": "MERCHANT", "usage_pattern": "IMM3DI4T3" } } } } }' ``` #### Error response ```json theme={null} { "name": "INVALID_REQUEST", "message": "Request is not well-formed, syntactically incorrect, or violates schema.", "debug_id": "10398537340c8", "details": [ { "field": "/payment_source/paypal/attributes/vault/usage_pattern", "value": "IMM3DI4T3", "location": "body", "issue": "INVALID_PARAMETER_VALUE", "description": "A parameter value is not valid." } ], "links": [ { "href": "https://developer.paypal.com/docs/api/orders/v2/#error-INVALID_PARAMETER_VALUE", "rel": "information_link" } ] } ``` ### Forbidden (403) The Orders v2 API returns a `403` status code when the API caller or payee does not have the required permissions for the request. The following sample shows a create order request that sets `items.category` to `DONATION` without the necessary permissions. #### Create order request ```bash theme={null} curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/ \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ -d '{ "intent": "CAPTURE", "purchase_units": [ { "amount": { "currency_code": "USD", "value": "5.00", "breakdown": { "item_total": { "currency_code": "USD", "value": "5.00" } } }, "items": [ { "name": "Donation to WWF", "unit_amount": { "currency_code": "USD", "value": "5.00" }, "quantity": "1", "category": "DONATION" } ] } ] }' ``` #### Error response ```json theme={null} { "name": "NOT_AUTHORIZED", "details": [ { "issue": "PERMISSION_DENIED_FOR_DONATION_ITEMS", "description": "The API Caller or Payee have not been granted appropriate permissions to send 'items.category' as 'DONATION'. Please speak to your account manager if you want to process these type of items." } ], "message": "Authorization failed due to insufficient permissions.", "debug_id": "90957fca61718", "links": [ { "href": "https://developer.paypal.com/api/orders/v2/#error-PERMISSION_DENIED_FOR_DONATION_ITEMS", "rel": "information_link", "method": "GET" } ] } ``` # Resource not found Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/resource-not-found A `RESOURCE_NOT_FOUND` error occurs when the specified resource does not exist. The following issues can cause this error. If an issue persists or you have further questions, contact [PayPal Support](https://www.paypal.com/us/cshelp/technical). INVALID\_RESOURCE\_ID Returns from the Payments v1 or Orders v2 APIs. | Cause | Impact | Resolution | | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - You entered an incorrect or malformed resource ID, so the system cannot find the resource.
- You used a resource ID in the API request that does not exist in the system.
- The API caller does not have permission to access the resource. | PayPal stops the payment and does not process the order. This slows down the purchase. | - Check that the resource ID in the API request is correct and exists in the system. Fix any typos or mistakes.
- Make sure the API caller has permission to access the resource. Update permissions if needed. | # Unprocessable entity Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/unprocessable-entity PayPal cannot process your request because it is incorrect or fails business rules. The issues below can cause an `UNPROCESSABLE_ENTITY` error. If an issue persists or you have further questions, contact [PayPal support](https://www.paypal.com/us/cshelp/technical). AGREEMENT\_ALREADY\_CANCELLED Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Previously canceled: The payer performed an API call to modify, execute, or otherwise interact with a previously canceled billing agreement.
- Oversight: The payer misunderstood the current agreement status.
- Business logic error: The system that is integrated with the API improperly checked the agreement status before attempting operations. | - Operations failure: The payer potentially cannot perform operations, such as processing payments, on the canceled agreement.
- Service disruption: Unintended or improperly communicated canceled billing agreements can disrupt service or billing processes.
- Payer dissatisfaction: Repeated transaction failures can lead to frustration and confusion among payers. | - Verify agreement status: Confirm the canceled status of the billing agreement.
- Review business logic: Ensure that the integrated system properly checks the status before attempting operations.
- Communicate with payers: Inform the payer about the unintended canceled billing agreement to resolve issues.
- Create a new billing agreement. | BILLING\_AGREEMENT\_NOT\_FOUND Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Incorrect billing agreement ID: The ID in the API request is incorrect.
- Improper billing agreement: The API request uses a missing billing agreement.
- Permission issue: The requesting account lacks permissions to manage the billing agreement.
| - Disrupted workflows: Workflows that use the billing agreement ID can be disrupted, which can lead to failures in other business operations.
| - Verify billing agreement ID: Ensure the accuracy of the billing agreement ID in the API request.
- Check agreement status: Confirm that the billing agreement ID belongs to an active billing agreement.
- Elevate permission: Ensure that the requesting account holds appropriate permissions to manage the billing agreement. | CANNOT\_PAY\_SELF Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Duplicate reference: The transaction or billing agreement attempts to reference the sender and receiver of payment as the same entity, which is invalid. | - Disrupted workflows: Intended payments or subscription setup fail, leading to unprocessable billing agreements and transactions.
- Disrupted revenue: Failed processes can lead to disruption of automated systems that use billing agreements and ongoing subscriptions. | - Confirm separation: Ensure that the sender and receiver are different entities.
- Review API request: Ensure you use distinct PayPal account IDs or email addresses for the sender and receiver.
- Implement validation checks: Ensure that your application checks to prevent users from setting up billing agreements with duplicate entities.
- Verify account details: Ensure that your application uses the correct account details for transactions and billing agreements.
- Implement retry mechanism: Develop business logic that waits a short period before attempting the request again, gradually increasing the wait time with each attempt. | CARD\_EXPIRED Returns from the PayPal Orders v2 or Payments v1 APIs. | Cause | Impact | Resolution | | :------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - You tried to pay with an expired card.
- An expired card cannot be used for payments.
- The payer must use a different card or payment method. | PayPal stops the payment. The payer cannot finish the purchase. This can cause lost sales. | - Show an error message that the card is expired.
- Ask the payer to use a different card or payment method.
- Help the payer switch payment methods and finish the payment. | CURRENCY\_NOT\_SUPPORTED Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Unsupported code: PayPal does not support the currency code in the API request.
- Region limitations: The region from which the API was initiated may not support the currency code.
- Account restrictions: The merchant account may have restrictions or limitations on supported currencies. | - Process failure: The billing agreement fails due to the use of unsupported currencies.
- Revenue loss: Subscriptions or recurring payments do not proceed due to this error, causing delays or issues for the payer. | - Verify currency support: Confirm that PayPal supports the currency code.
- Verify currency settings: Confirm that your PayPal business account can use the necessary [currencies](https://developer.paypal.com/docs/reports/reference/paypal-supported-currencies/).
- Cross-check regional restrictions: Ensure that your region does not restrict the currency used in your transaction or billing agreement.
- Change currency codes: Change the currency code used in your API request to a supported currency for your location or account. | DUPLICATE\_INVOICE\_ID Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Duplicate invoice ID: The API request uses a duplicate invoice ID. All transactions and billing agreements require a unique `invoice_id`.
- Reused invoice ID: The transaction or billing agreement uses a processed invoice ID typically due to a logic error or failure to manually update the ID. | - Rejected requests: The system prevents the completion of billing operations, potentially affecting liquidity and payer satisfaction. | - [Contact customer support](https://www.paypal.com/us/cshelp/contact-us): If your workflow requires duplicate invoice IDs, contact customer support.
- Confirm invoice usage: Confirm the use of unique invoice IDs in your billing agreements and transactions.
- Implement invoice ID mechanisms: Develop logic that generates a unique invoice ID for each transaction and billing agreement.
- Incorporate logs: Track and verify invoice IDs in the application to prevent reuse and assist with future debugging. | INSTRUMENT\_DECLINED Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Billing address issues: PayPal could not confirm the billing address for the payment method.
- Expired card: The payer used an expired or canceled payment instrument, such as a credit card.
- Declined transaction: The bank or card issuer declined the transaction due to reasons such as suspected fraud or account restrictions.
- Potential risk: The payer account may have insufficient funds, may pose a risk, or may have encountered a compliance issue.
- Incorrect billing information: The user entered incorrect information, such as CVV, expiration date, or account number. | - Payment failure: The payer cannot complete the payment, potentially affecting their access to services or products.
- Payer dissatisfaction: Repeated transaction failures can lead to frustration among payers.
- Revenue loss: The merchant may experience a loss of revenue due to unsuccessful transactions.​ | - Verify payment method: Ensure that the payer uses a valid, active, and sufficiently funded payment method.
- Fund availability: Confirm with the payer that their account holds sufficient funds or is within their credit limit.
- Contact financial institution: Encourage payers to contact their bank or card issuer to resolve any temporary holds or restrictions.
- Update billing instrument: If the payer used an expired or invalid instrument, ask the payer to update their payment information. | MERCHANT\_NOT\_ENABLED\_FOR\_REFERENCE\_TRANSACTION Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Improper configuration: The merchant account did not enable or properly configure reference transactions.
- Permission issue: The requesting account lacks permissions to manage reference transactions.
| - Disrupted workflows: The merchant cannot process future payments from the payer without manually acquiring authorization again.
- Disrupted revenue: Additional authorization requests can impact post-purchase revenue streams. | - Contact customer support: Send a request to customer support to enable reference transactions for your account. Enabling reference transactions may require you to provide additional information about your account. For more information, see [Initiate future transactions](https://developer.paypal.com/docs/checkout/advanced/customize/reference-transactions/).
- Verify configurations: Ensure that you configured your account settings to support reference transactions. PayPal may request additional information regarding your account to enable this feature. For more information, see [Initiate future transactions](https://developer.paypal.com/docs/checkout/advanced/customize/reference-transactions/). | NOT\_ENABLED\_FOR\_CHANNEL\_INITIATED\_BILLING Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - No approval: The merchant did not request or was not approved for channel-initiated billing.
- Improper configuration: The merchant account settings do not include necessary features, configurations, or permissions.
- Account restrictions or limitations: The merchant account may have restrictions or limitations based on their account type or region. | - Process failure: The merchant cannot create or manage their billing agreement.
- Revenue loss: Subscriptions, recurring payments, or other functionality reliant on channel-initiated billing do not proceed due to this error. | - Contact customer support: Work with customer support or your account manager to inquire about enabling channel-initiated billing support.
- Review account settings: Ensure that your account settings support the desired billing features. | ORDER\_ALREADY\_AUTHORIZED Returns from the Payments v2 or Orders v2 APIs. | Cause | Impact | Resolution | | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - You already authorized this PayPal order.
- You can only authorize an order once with `intent="AUTHORIZE"`.
- Duplicate requests may happen if you missed the first response.
- Network issues or delays may cause missed responses. | PayPal declines the second authorization. You cannot split the authorization into parts. | - Authorize the full order amount in one request, then make multiple captures if needed.
- Set `final_capture="false"` in capture requests for split shipments.
- Use PayPal webhooks to track order status.
- If your API call times out, contact PayPal support. | ORDER\_ALREADY\_CAPTURED Returns from the Orders v2 API. | Cause | Impact | Resolution | | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - You already captured this order. Payment is complete.
- You can only capture an order once with `intent="SALE"`.
- Duplicate requests may happen if you missed the first capture response. | If you only captured part of the amount, you cannot capture the rest unless you create a new order.
- If you meant to capture once, there is no payer impact. | - Use `intent="AUTHORIZE"` if you need to capture more than once.
- For single captures, make sure you record the API response to avoid duplicates.
- Use PayPal webhooks to track payment status. | ORDER\_NOT\_APPROVED Returns from the Payments v1 or Orders v2 APIs. | Cause | Impact | Resolution | | :------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | | - The payer did not approve the payment.
- The request may not include a valid `payment_source`. | PayPal declines the payment. The payment does not go through. This can delay the purchase. | - Send the payer to the approval URL (`rel:approve`) from the Create Order call.
- Make sure the request includes a valid `payment_source`. | PAYER\_ACCOUNT\_LOCKED\_OR\_CLOSED Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Account lock: Violation of [PayPal’s Acceptable Use Policy](https://www.paypal.com/us/legalhub/paypal/acceptableuse-full) due to suspicious activities can lead to an account lock or security concerns.
- Account closure: The payer or PayPal closed the account due to policy violations or other administrative reasons. | - Billing agreement failure: This error prevents payers from creating or processing billing agreements and their associated transactions.
- Service operations: Merchants and payers can experience service loss, which can cause revenue loss. | - [Contact customer support](https://www.paypal.com/us/cshelp/contact-us): Work with customer support to resolve the issue.
- Settle account: Resolve debts or disputes that led to the account lock or closure, then retry the billing agreement. | PAYER\_CANNOT\_PAY Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Insufficient funds: The payer does not have enough available funds or credit.
- Account limitations: The payer's account may have limitations or restrictions.
- Unverified account: The payer uses an unverified account or did not perform required updates, which prevents payments.
- Payment method issue: The payer used an expired or canceled payment instrument, such as a credit card.
- Account restrictions: The payer account encounters a compliance issue or external issue that restricts payment processing. | - Payment failure: The payer cannot complete the payment, potentially affecting their access to services or products.
- Payer dissatisfaction: Repeated transaction failures can lead to frustration among payers.
- Revenue loss: The merchant may experience a loss of revenue due to unsuccessful transactions. | - Check account status: Verify that both the payer's and merchant's PayPal accounts are in good standing without any limitations or restrictions.
- Verify payment method: Ensure that the payer uses a valid, active, and sufficiently funded payment method.
- Configure alternative payment options: Suggest that the payer use a different payment method.
Update account info: Ensure that the payer includes up-to-date account information, such as billing address and linked payment methods. | PAYEE\_NOT\_ENABLED\_FOR\_CARD\_PROCESSING Returns from the Orders v2 API. | Cause | Impact | Resolution | | :-------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | - The payee's account is not set up to take card payments.
- The payee has not finished onboarding for PayPal Complete Payments. | PayPal stops the payment. The payer cannot finish the purchase. This can cause lost sales.
- All payers trying to pay this payee will see this error. | - Make sure the payee finished onboarding and enabled card payments.
- If the payee manages onboarding, ask them to contact PayPal to turn on card payments. | PREVIOUS\_REQUEST\_IN\_PROGRESS Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Request conflict: Multiple requests conflict for the same resource, such as a billing agreement. PayPal requires the initial request to complete before processing another request. | - Operation hold: Multiple requests cause a halt on new operations on the affected resource until the resource processes the original request.
- Processing delay: Multiple requests can delay planned modifications or renewals of a resource. | - Verify request status: Check the status of the previous request to ensure its completion before initiating a new request.
- Queue requests: Process requests sequentially in a queue, allowing each request to complete before initiating the next request.
- Implement error handling: Develop business logic to handle this error and respond appropriately, such as notifying users of the delay or logging the error for further analysis. | REDIRECT\_PAYER\_FOR\_ALTERNATE\_FUNDING Returns from the Payments v1, and Orders v2 APIs. | Cause | Impact | Resolution | | :-------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - The payment failed because of a problem with the payer's chosen payment method. | PayPal stops the payment. The payer cannot finish the purchase. This can cause lost sales. | - Show an error message that the payment did not go through.
- Send the payer to PayPal checkout to pick another payment method.
- If the problem continues, ask the payer to use a different payment method or contact PayPal. | REDIRECT\_PAYER\_FOR\_ALTERNATE\_FUNDING Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Insufficient funds: The payer's account may not have enough funds or credit to cover the transaction amount.
- Payment method issue: The payment instrument, such as a credit card, is expired or canceled.
- Account limitations: The payer's PayPal account might have limitations or restrictions.
- Unsupported method: The transaction does not support the selected payment method. | - Incomplete transactions: The payer cannot complete the transaction with the selected payment method.
- User experience impact: Reselecting a payment method can add additional steps for the user and delay transaction processing. | - Change payment method: Inform the user to change their payment method, then retry the transaction.
- Implement alternative payment mechanism: If supported, develop business logic that redirects users to alternative payment methods, then retry the transaction. | REFERENCED\_CARD\_EXPIRED Returns from the Orders v2 or Vault v3 APIs. | Cause | Impact | Resolution | | :------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - The transaction uses a saved payment token, but the card is expired.
- The payer must use a different card or payment method. | PayPal stops the payment. The payer cannot finish the purchase. This can cause lost sales. | - Turn on Real-Time Account Updater (RTAU) to keep card expiration dates up to date.
- Show an error message if the saved card is expired.
- Update the saved payment token after you get a new one.
- Give the payer clear steps to finish the payment. | SHIPPING\_ADDRESS\_INVALID Returns from the Payments v1 or Orders v2 APIs. | Cause | Impact | Resolution | | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Some address fields are missing or incomplete.
- The address format is wrong.
- System issues prevent the address from being sent correctly. | PayPal declines the payment. The payment does not go through. This can delay the purchase. | - Check that all required address fields are filled in.
- Use address validation tools to fix the format.
- Make sure your system sends all address fields in the API request. | SHIPPING\_ADDRESS\_INVALID Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | - Incorrect formatting: The API request's shipping address fields (such as street, city, state, postal code, and country) contain formatting errors or invalid characters.
- Missing fields: The API request does not contain required shipping address fields.
- Validation failure: The address does not match the standards or validation rules set by PayPal or the postal service of the specified country.
- Mismatch: The country code and the country name provided may mismatch, causing the error. | - Process failure: The billing agreement, transaction, or subscription setup will not proceed.
- Workflow disruption: Delays in processing payments or setting up recurring billing agreements can impact payer satisfaction and business operations. | - Verify fields: Verify that all required fields in the shipping address use correct formatting.
- Match address: Ensure that the address fields, such as street, city, state, postal code, and country, match the expected format for the specified country.
- Verify country code: Ensure that the country code matches the country name, using address validation tools or services to confirm its accuracy.
- Revise address: Contact the payer to correct or confirm the address details. | TOKEN\_ID\_NOT\_FOUND Returns from the Payments v1 or Orders v2 APIs. | Cause | Impact | Resolution | | :--------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - PayPal does not recognize the token ID.
- The token may be wrong, mistyped, or the caller does not have permission. | PayPal stops the payment. The payer cannot finish the purchase. This can cause lost sales. | - Make sure the receiving account gave the needed permissions.
- Check that the token ID is correct.
- If the token is wrong or expired, create a new token. | TRANSACTION\_REFUSED Returns from the Billing Agreements API. | Cause | Impact | Resolution | | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Payment method issues: The payment method linked to the billing agreement might be invalid, expired, or otherwise unable to process the payment.​
- Insufficient funds: The payer's account may not have enough funds or credit to cover the transaction amount.
- Account limitations: The payer's PayPal account might have limitations or restrictions.
- Risk factors: If PayPal detects any potential risks based on merchant history or if there's high risk associated with the transaction, PayPal will refuse the transaction. | - Payment failure: The payer's failure to complete the payment can potentially affect their access to services or products.
- Payer dissatisfaction: Repeated transaction failures can lead to payer frustration.
- Revenue loss: The merchant may experience a loss of revenue due to unsuccessful transactions.​ | - Verify payment method: Ensure that the payer uses a valid, active, and sufficiently funded payment method.
- Check account status: Verify that both the payer's and merchant's PayPal accounts operate in good standing without any limitations or restrictions.
- Correct API request: Double-check the API request parameters to ensure they are correct and complete. | UNSUPPORTED\_PAYEE\_CURRENCY Returns from the Billing Agreements API. | Cause | Impact | Resolution | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Account restrictions: The payee account restrictions permit only transactions in certain currencies.
- Disabled currency: The payee did not enable the specified currency in their account settings.
- Region limitations: Certain regions do not make available specific currencies for the merchant account, resulting in a currency mismatch during a transaction. | - Process failure: The merchant cannot create or manage their billing agreement.
- Impacted business operations: PayPal does not record failed transactions, which prevents tracking of fund transfer issues and could impact subscription services or billing agreements. | - Confirm that PayPal supports the currency code.
- Configure account: Ensure that you have enabled the specified currency in your account settings to accept payment from the payee account.
- Currency conversion: Consider using a supported currency or handle currency conversion with PayPal currency conversion services. | # Unsupported payee currency Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/unsupported-payee-currency Returns from the Payments V1 API. `UNSUPPORTED_PAYEE_CURRENCY` indicates that the payee's PayPal account does not support the currency specified in the transaction, and the payee cannot accept payments. | Cause | Impact | Resolution | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Account restrictions: The payee account restrictions permit only transactions in certain currencies.
- Disabled currency: The payee did not enable the specified currency in their account settings.
- Region limitations: Certain regions do not make available specific currencies for the merchant account, resulting in a currency mismatch during a transaction. | - Failed payment attempt: The transaction cannot be completed using the specified currency.
- Customer dissatisfaction: Unprocessable payments can cause inconvenience for both the payer and payee. | - Verify supported currencies: Change the currency code in your API request to a [supported currency](https://developer.paypal.com/docs/reports/reference/paypal-supported-currencies/) for the payee account.
- Contact payee: Communicate with the payee to confirm their account settings and the currencies they enabled. | # Validation error Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/common-errors/validation-error You get a validation error when the API request contains invalid, missing, or incorrectly formatted data. This error can return from the [Orders v2](https://developer.paypal.com/docs/api/orders/v2/) or [Payments v1](https://developer.paypal.com/docs/api/payments/v1/) APIs. If an issue persists or you have further questions, contact [PayPal support](https://www.paypal.com/us/cshelp/technical). | Cause | Impact | Resolution | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | - Required fields are missing or contain incorrect values.
- Field values do not match expected data types.
- Currency codes are invalid or the amount formatting is incorrect.
- The request body is not properly formatted as JSON.
- The transaction is blocked based on the account's status or configuration.
- An incorrect or outdated API version is used. Some validation rules may change between versions. | The payment process stops, and the payer cannot complete the purchase. This can result in lost sales if not fixed quickly. | - Check the error details in the API response to find the exact field and issue.
- Ensure all required fields are there and contain valid data in the correct format and type.
- Update the request with correct data and resend it to allow the payment to process. | # Handling payment failures with PayPal Source: https://docs.paypal.ai/developer/how-to/api/troubleshooting/handling-payment-failures-with-paypal Detect and respond to payment failures using PayPal's Orders v2 API and Subscriptions API. This guide explains common failure reasons, how to surface errors to buyers, best practices for retrying or recovering failed payments, and how to leverage PayPal's intelligent retry mechanism. ## Key concepts * Payment failures can happen for many reasons, such as declined cards, expired payment methods, insufficient funds, risk restrictions, or business validation errors. * PayPal's APIs (Orders v2 and Subscriptions) return clear error codes and messages in their responses. * Proper handling improves user experience, reduces lost sales, and ensures smooth subscription renewals. * Some payment failures are asynchronous, meaning they might not be immediately apparent during the initial transaction. ## Common payment failure scenarios Here are some of the most frequent failure reasons and how to handle them: | Error Code / Issue | What It Means | What To Do | | :----------------------------------------- | :-------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | `INSTRUMENT_DECLINED` | Payment method was declined. | Prompt the buyer to select a different payment method. Restart the payment flow using `actions.restart()`. | | `CARD_EXPIRED` | Card is expired. | Inform the buyer and ask for a new card. | | `AMOUNT_MISMATCH`, `ITEM_TOTAL_MISMATCH` | Totals do not add up. | Fix item or amount totals in your API request and retry. | | `CURRENCY_NOT_SUPPORTED` | Unsupported currency. | Use a supported currency or update your PayPal account settings. | | `ORDER_NOT_APPROVED` | Buyer did not approve the order. | Redirect the buyer to approve the order again. | | `MAX_NUMBER_OF_PAYMENT_ATTEMPTS_EXCEEDED` | Too many failed attempts. | Ask the buyer to use a different payment method or contact PayPal support. | | `REDIRECT_PAYER_FOR_ALTERNATE_FUNDING` | Funding source failed, alternate source needed. | Prompt the buyer to choose a different payment method. | | `VALIDATION_ERROR`, `UNPROCESSABLE_ENTITY` | Invalid or missing data. | Show a clear error, ask the buyer to correct the information, and retry. | | `PAYMENT_DENIED` | The payment was denied by PayPal. | Investigate the reason for denial and contact PayPal support if needed. Prompt the buyer to use a different payment method. | | `PAYER_CANNOT_PAY` | The payer is unable to pay using the selected payment method. | Prompt the buyer to select a different payment method or contact PayPal support. | | `CANNOT_BILL_PAST_DUE_BALANCE` | The subscription is suspended because the past due balance exceeds the maximum allowed. | Contact PayPal support to resolve the suspension or prompt the buyer to pay the outstanding balance. | | `REJECTED_DUE_TO_RISK_REVERSAL` | The payment was rejected due to a risk reversal, such as a chargeback or dispute. | Investigate the reason for the reversal and contact PayPal support if needed. | | `TRANSACTION_REFUSED` | The transaction was refused by the processor. | Prompt the buyer to use a different payment method or contact their bank. | | `INVALID_ACCOUNT_STATUS` | The payer's account is in an invalid state, such as locked or inactive. | Prompt the buyer to contact PayPal support to resolve their account issue. | | `INVALID_REQUEST` | The request was malformed or missing required parameters. | Review the request parameters and ensure they are valid. | | `AUTHENTICATION_FAILURE` | Authentication failed due to invalid credentials. | Verify your API credentials and ensure they are correct. | | `NOT_AUTHORIZED` | You are not authorized to perform this action. | Check your account permissions and ensure you have the necessary privileges. | | `RESOURCE_NOT_FOUND` | The requested resource was not found. | Verify the resource ID and ensure it exists. | | `UNPROCESSABLE_ENTITY` | The request was well-formed but could not be processed due to semantic errors. | Review the request data and ensure it is valid and consistent. | See the [Orders v2 API Troubleshooting Guide](https://developer.paypal.com/api/rest/integration/orders-api/troubleshooting/) and the [Subscriptions API documentation](https://developer.paypal.com/docs/subscriptions/) for a more comprehensive list of error codes. ## Detect and handle payment failures ### 1. Check API responses * Always inspect responses from the Orders API (create, authorize, or capture endpoints) or the Subscriptions API (create, update, or activate subscription endpoints). * If the response contains an error code, use it to determine the next step. **Example: Handling a Declined Payment in JavaScript (Orders API)** ```javascript theme={null} paypal.Buttons({ onApprove: (data, actions) => { return actions.order.capture().then(details => { // Payment successful }).catch(err => { // Handle payment failure if (err.name === "INSTRUMENT_DECLINED") { // Restart the payment flow to let buyer choose another method return actions.restart(); } else { // Show a generic error message alert("Payment could not be completed. Please try again."); } }); } }).render('#paypal-button-container'); ``` ```javascript theme={null} import React, { useEffect } from 'react'; function PayPalButton() { useEffect(() => { paypal.Buttons({ onApprove: (data, actions) => { return actions.order.capture().then(details => { // Payment successful }).catch(err => { // Handle payment failure if (err.name === "INSTRUMENT_DECLINED") { // Restart the payment flow to let buyer choose another method return actions.restart(); } else { // Show a generic error message alert("Payment could not be completed. Please try again."); } }); } }).render('#paypal-button-container'); }, []); return
; } export default PayPalButton; ```
```typescript theme={null} import React, { useEffect } from 'react'; function PayPalButton() { useEffect(() => { (window as any).paypal.Buttons({ onApprove: (data: any, actions: any) => { return actions.order.capture().then((details: any) => { // Payment successful }).catch((err: any) => { // Handle payment failure if (err.name === "INSTRUMENT_DECLINED") { // Restart the payment flow to let buyer choose another method return actions.restart(); } else { // Show a generic error message alert("Payment could not be completed. Please try again."); } }); } }).render('#paypal-button-container'); }, []); return
; } export default PayPalButton; ```
```javascript theme={null} paypal.Buttons({ onApprove: (data, actions) => { return actions.order.capture().then(details => { // Payment successful }).catch(err => { // Handle payment failure if (err.name === "INSTRUMENT_DECLINED") { // Restart the payment flow to let buyer choose another method return actions.restart(); } else { // Show a generic error message alert("Payment could not be completed. Please try again."); } }); } }).render('#paypal-button-container'); ```
* `actions.restart()` restarts the payment flow so the buyer can select a different funding source. ### 2. Surface errors to buyers * Show clear, actionable error messages, such as “Your card was declined. Please try another payment method.” * For validation or data errors, prompt the buyer to correct the issue and retry. ### 3. Retry or recover * For funding failures, prompt the buyer to choose another payment method. * For expired cards or exceeded attempts, ask the buyer to update their information or use a new card. * For business validation errors, correct the data and resend the request. ## Intelligent retries for subscriptions PayPal's **intelligent retry** mechanism automatically attempts to recover failed subscription payments. * When a subscription payment fails, PayPal uses a proprietary algorithm to determine the best time to retry the payment. * This algorithm considers factors such as the buyer's payment history, risk signals, and bank availability. * Merchants can configure retry schedules and monitor retry attempts in the PayPal dashboard. * Intelligent retries can significantly increase subscription renewal rates without requiring any action from the merchant. ## Asynchronous payment processing and webhooks * Some payment failures are **asynchronous** and might not be immediately reflected in the API response. * For example, a buyer's bank might initially authorize a payment but later decline it due to fraud concerns. * To track these asynchronous failures reliably, it's highly recommended to use PayPal Webhooks. ### Relevant webhook events * **Orders API** * `PAYMENT.CAPTURE.COMPLETED`: Indicates a successful payment capture. * `PAYMENT.CAPTURE.DENIED`: Indicates a failed payment capture. * **Subscriptions API** * `BILLING.SUBSCRIPTION.PAYMENT.FAILED`: Indicates a failed subscription payment. * `BILLING.SUBSCRIPTION.PAYMENT.SUCCEEDED`: Indicates a successful subscription payment. * Configure your webhook listener to receive these events and take appropriate action (e.g., notify the buyer, update your database). ## Manual retries for subscriptions In addition to intelligent retries, you can also manually retry failed subscription payments. * **PayPal Dashboard:** You can retry payments directly from the [PayPal dashboard](https://www.paypal.com/businessmanage/subscriptions). * **Subscriptions API:** You can use the Subscriptions API to trigger a manual retry. ## Monitor and log failures * Log all failed payment attempts with error codes and messages for troubleshooting. * Use PayPal Webhooks to track asynchronous failures and notify your team or the buyer when needed. ## Best practices * Promptly inform buyers of the failure reason and guide them to resolve it. * Restart the payment flow for funding source errors using `actions.restart()` in the Smart Buttons integration (for Orders API). * Validate all order data before sending requests to avoid preventable errors. * Monitor webhook events for real-time updates on payment status for both Orders and Subscriptions. * Leverage intelligent retries for Subscriptions to automatically recover failed payments. * Consider manual retries for Subscriptions if intelligent retries are unsuccessful. * Test payment failure scenarios during integration to ensure your system handles them correctly. ## Troubleshooting * **Check the PayPal status page:** Verify that PayPal services are operating normally. * **Review your API logs:** Look for any errors or warnings in your API requests and responses. * **Use the PayPal Developer Dashboard:** Monitor your webhook events and API usage. * **Contact PayPal support:** If you're unable to resolve the issue, contact PayPal support for assistance. With these steps, you can handle payment failures smoothly, helping buyers complete their purchase, ensuring smooth subscription renewals, and reducing lost sales. ## See also * [Orders v2 API Reference](/reference/api/rest/orders/create-order) * [Orders v2 integration documentation](https://developer.paypal.com/api/rest/integration/orders-api/) * [Common errors for the Orders v2 API](https://developer.paypal.com/api/rest/integration/orders-api/errors/) * [Troubleshooting errors for the Orders v2 API](https://developer.paypal.com/api/rest/integration/orders-api/troubleshooting/) * [Handle funding failures for direct merchants](https://developer.paypal.com/docs/checkout/standard/customize/handle-funding-failures/) * [Handle funding failures for partners](https://developer.paypal.com/docs/multiparty/checkout/standard/customize/handle-funding-failures/) * [Subscriptions API Reference](https://developer.paypal.com/docs/api/subscriptions/v1/) * [Subscriptions integration documentation](https://developer.paypal.com/docs/subscriptions/) * [Subscription payment failures and recovering balances](https://developer.paypal.com/docs/subscriptions/customize/payment-failure-retry/) # Apps, scopes, and credentials Source: https://docs.paypal.ai/developer/how-to/apps-scopes-credentials PayPal Apps are registered apps within the PayPal Developer ecosystem that verify and authorize your software to interact with PayPal's services. Each app receives unique credentials (client ID and client secret) that establish a secure connection between your app and PayPal's payment processing network. Register your application with PayPal to get the credentials needed for API access and understand which permissions your app requires. PayPal Apps operate on a modern REST API architecture and follow a structured development process: * App Registration * Sandbox Testing * API Integration PayPal's sandbox environment provides developers with testing accounts to simulate real payment scenarios without processing actual transactions. PayPal sandbox provides testing environments with two main account types: ## Understanding scopes Scopes define your app's permissions and access levels to PayPal services. The scope field in the authentication response shows all available permissions for your app. ### Common PayPal API scopes #### Payment processing * `https://uri.paypal.com/services/payments/payment/authcapture` - Process payments and captures * `https://uri.paypal.com/services/payments/payment` - Real-time payment processing * `https://uri.paypal.com/services/payments/refund` - Process refunds * `https://uri.paypal.com/services/payments` - General payments API access #### Vault services * `https://uri.paypal.com/services/vault/payment-tokens/creditcard` - Store credit card info * `https://uri.paypal.com/services/vault/payment-tokens/read` - Manage stored credit cards #### Business services * `https://uri.paypal.com/services/invoicing` - Create and manage invoices * `https://uri.paypal.com/services/subscriptions` - Subscription management * `https://uri.paypal.com/services/payments/payouts` - Send payouts #### Dispute management * `https://uri.paypal.com/services/disputes/read-buyer` - Read buyer dispute info * `https://uri.paypal.com/services/disputes/read-seller` - Read seller dispute info * `https://uri.paypal.com/services/disputes/update-seller` - Update seller dispute status #### System integration * `https://uri.paypal.com/services/webhooks` - Webhook management * `openid` - OpenID Connect authentication ### PayPal API credentials PayPal REST APIs use two types of credentials for authentication: **Client ID**: A public identifier for your PayPal app. Safe to use in client-side code and sufficient for basic payment buttons and card fields. **Client Secret**: A private key that verifies your app for API calls. Must be kept secure and used only server-side. ### Getting credentials Obtain credentials through the PayPal Developer Dashboard: * New accounts get a "Default Application" with ready-to-use credentials * Create additional apps through "Create App" in Apps & Credentials * Copy the client ID and client secret for your setup For detailed implementation guides, refer to each service area's specific PayPal API docs. # Advanced configuration Source: https://docs.paypal.ai/developer/how-to/sdk/js/v6/advanced Advanced configuration options for the JavaScript SDK v6 help you customize the payment experience. ## Prerequisites Before you integrate: * Get a [client ID and secret](/developer/how-to/api/get-started#1-get-your-client-id-and-client-secret). * [Set up the v6 SDK](/developer/how-to/sdk/js/v6/configuration). ## Configure presentation modes and fallback For advanced use cases, you can choose a [specific presentation mode](/reference/sdk/js/v6/reference#parameters-6). Then, implement your own fallback logic with the `isRecoverable` error property. ```javascript expandable lines theme={null} // Alternatively, set up a standard PayPal button with a custom order of presentation modes async function configurePayPalButton(sdkInstance) { const paypalPaymentSession = sdkInstance.createPayPalOneTimePaymentSession( paymentSessionOptions, ); const paypalButton = document.querySelector("paypal-button"); paypalButton.removeAttribute("hidden"); paypalButton.addEventListener("click", async () => { const createOrderPromiseReference = createOrder(); const presentationModesToTry = ["payment-handler", "popup", "modal"]; for (const presentationMode of presentationModesToTry) { try { await paypalPaymentSession.start( { presentationMode }, createOrderPromiseReference, ); // Exit early when start() successfully resolves break; } catch (error) { // Try another presentationMode for a recoverable error if (error.isRecoverable) { continue; } throw error; } } }); } ``` # Button color updates Source: https://docs.paypal.ai/developer/how-to/sdk/js/v6/button-color-updates PayPal button color updates require no JavaScript SDK integration changes. When PayPal updates its brand guidelines, the PayPal JavaScript SDK v5 and v6 automatically update the appearance of buttons rendered on your site. No code changes are required.
Current color Current button New button New color
Gold Current gold PayPal button New blue PayPal button Blue
Blue Current blue PayPal button New blue PayPal button Blue
Silver Current silver PayPal button New white PayPal button White
White Current white PayPal button New white PayPal button White
Black Current black PayPal button New black PayPal button Black
## Set your button color You can set the button color for accessibility or branding reasons. To choose a specific color, apply one of the [supported color classes](/reference/sdk/js/v6/reference#web-components) to your `` element. ```html theme={null} ``` ### Ensure accessibility To comply with [WCAG 2.1 AA standards](https://www.w3.org/TR/WCAG21/): * On light backgrounds, use the blue or black button. * On dark backgrounds, use the white button. # Set up JavaScript SDK v6 Source: https://docs.paypal.ai/developer/how-to/sdk/js/v6/configuration The PayPal JavaScript SDK v6 enables you to accept the following payment methods on your website: * PayPal and Pay Later * Venmo (US only) * Google Pay * Apple Pay * Fastlane guest checkout * Credit and debit cards The v6 SDK is faster and more secure than previous versions. It also supports standalone button integrations and iframe-based integrations for stricter security. [Check out a sample integration in GitHub](https://github.com/paypal-examples/v6-web-sdk-sample-integration). ## Prerequisites Before you start, make sure to [get your PayPal client ID and secret](/developer/how-to/api/get-started#1-get-your-client-id-and-client-secret). If you're a **partner integrating on behalf of other merchants**, follow these additional steps to set up your integration: * [Onboard as a partner with PayPal](https://developer.paypal.com/docs/multiparty/get-started/) * [Configure your accounts](https://developer.paypal.com/docs/multiparty/create-account/) * [Onboard sellers](https://developer.paypal.com/docs/multiparty/seller-onboarding/) * [Integrate backend with the Orders v2 API](https://developer.paypal.com/docs/multiparty/checkout/advanced/integrate/#integrate-back-end) ## Include the SDK script Include the v6 SDK script on each page of your site that needs to accept payments. ```html theme={null} ``` For sandbox and testing environments: ```html theme={null} ``` ## Authenticate the SDK Authenticate with a client ID or a client token. Most integrations should authenticate with a client ID. ### Option A: client ID (recommended) For most integrations, use your PayPal client ID to authenticate the SDK. You can think of the client ID as your application's user name. This static client ID value is safe to include in your front-end code. When to use client ID: * Standard checkout integrations (PayPal, cards, Venmo, digital wallets) * One-time payments * Card vaulting (save card payment methods) * Most payment integrations (this is the default) Select the tab that matches your integration type: * **Direct merchants** process payments into their own PayPal account. * **Partners** process payments on behalf of other merchants. Replace `"YOUR_CLIENT_ID"` with your client ID. ```javascript lines theme={null} const sdkInstance = await window.paypal.createInstance({ clientId: "YOUR_CLIENT_ID", components: ["paypal-payments"], }); ``` * Replace `"YOUR_PARTNER_CLIENT_ID"` with your client ID. * Replace `"SELLER_MERCHANT_ID"` with the merchant ID of the seller you're creating the payment session for. ```javascript lines theme={null} const sdkInstance = await window.paypal.createInstance({ clientId: "YOUR_PARTNER_CLIENT_ID", merchantId: "SELLER_MERCHANT_ID", components: ["paypal-payments"], }); ``` ### Option B: client token Client token authentication is required for Fastlane integrations. For all other use cases, use **Option A: client ID**. A client token is a secure, browser-safe access token generated server-side from your PayPal client ID and secret. This call returns an `access_token` which you use as the client token when you initialize the v6 SDK. Use `expires_in` for caching management on the server side. Partner calls must include [`PayPal-Auth-Assertion`](/developer/how-to/api/make-api-requests#paypal-auth-assertion) and [`PayPal-Partner-Attribution-Id`](/developer/how-to/api/make-api-requests#paypal-partner-attribution-id) headers. **Endpoint:** `/v1/oauth2/token/` ```bash lines theme={null} curl -X POST 'https://api-m.sandbox.paypal.com/v1/oauth2/token' \ -u 'PAYPAL_CLIENT_ID:PAYPAL_CLIENT_SECRET' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'grant_type=client_credentials' \ -d 'domains[]=YOUR_URL1_FOR_THE_SESSION,YOUR_URL2_FOR_THE_SESSION' \ -d 'response_type=client_token' ``` ```json lines theme={null} { "access_token" : "A21AAJrhF-LjFoXzGPJlszGfKg4omnKy5e_eeRXPYzHLb3OdbjtCB3w89nm_6wCCbqn7qSdzjW77VGE7NAJAbXw53ZVpiX5tQ", "app_id" : "APP-80W284485P519543T", "expires_in" : 32400, "nonce" : "2025-10-22T14:32:24ZNpKbSPKuOEA75fCkaNqAcQC_7GbyY1wYSpE1qTeMDaQ", "scope" : "https://uri.paypal.com/services/invoicing https://uri.paypal.com/services/payments/futurepayments https://uri.paypal.com/services/vault/payment-tokens/read https://uri.paypal.com/services/disputes/read-buyer https://uri.paypal.com/services/payments/realtimepayment https://uri.paypal.com/services/payments/client-payments-eligibility https://uri.paypal.com/services/identity/activities https://api.paypal.com/v1/vault/credit-card https://api.paypal.com/v1/payments/.* https://uri.paypal.com/services/reporting/search/read https://uri.paypal.com/services/vault/payment-tokens/readwrite https://api.paypal.com/v1/payments/refund https://uri.paypal.com/services/applications/webhooks https://uri.paypal.com/services/credit/client-offer-presentment/read https://uri.paypal.com/services/paypalhere https://uri.paypal.com/services/disputes/update-seller openid https://uri.paypal.com/services/payments/payment/authcapture Braintree:Vault https://uri.paypal.com/services/disputes/read-seller https://uri.paypal.com/services/payments/orders/client_sdk_orders_api https://uri.paypal.com/services/payments/refund https://uri.paypal.com/payments/payouts https://api.paypal.com/v1/vault/credit-card/.* https://uri.paypal.com/services/shipping/trackers/readwrite https://uri.paypal.com/services/subscriptions https://api.paypal.com/v1/payments/sale/.*/refund", "token_type" : "Bearer" } ``` The following server-side endpoint returns the client token to your client application. Call this endpoint from your frontend: ```javascript lines theme={null} async function getBrowserSafeClientToken() { const response = await fetch("/paypal-api/auth/browser-safe-client-token", { method: "GET", headers: { "Content-Type": "application/json", }, }); const { accessToken } = await response.json(); return accessToken; } ``` ## Initialize the v6 SDK Use `window.paypal.createInstance()` to initialize the SDK with your client ID or a client token for authentication. Also, use it to define the components you want to load and to manage other configurations like `locale` and `pageType`. The method returns an SDK instance that provides access to payment eligibility checking and session creation methods. ### `window.paypal.createInstance(options)` Use `window.paypal.createInstance` to initialize the PayPal SDK. This method configures the SDK for your specific integration needs and returns an SDK instance that you'll use to create payment sessions. #### Parameters
Parameter Required Description
clientId conditional

string. Your PayPal client ID. Use this for most integrations. Mutually exclusive with clientToken.

clientToken conditional

string. A secure, browser-safe token that your server generates using your PayPal client ID and secret. Required for PayPal payment vaulting and Fastlane integrations. This token expires after 15 minutes and is bound to your domain for security. You must generate a new token when needed. Mutually exclusive with clientId.

components no

string\[]. An array of SDK components to load for your integration. Each component enables specific payment functionality.

Available components:

  • paypal-payments — PayPal and Pay Later checkout
  • venmo-payments — Venmo payments (US only)
  • paypal-guest-payments — Standalone credit or debit card button
  • paypal-messages — Promotional messaging
  • card-fields — Inline credit and debit card fields
  • fastlane — Accelerated guest checkout
  • googlepay-payments — Google Pay integration
  • applepay-payments — Apple Pay integration

Default: \["paypal-payments"]

pageType no

string. The type of page where the SDK is being initialized. This helps PayPal optimize the payment experience and provide better analytics.

Accepted values:

  • checkout — Checkout or payment page
  • product-details — Individual product page
  • cart — Shopping cart page
  • mini-cart — Mini cart or side cart
  • home — Homepage
locale no

string. The locale for the UI components, specified as a BCP-47 language tag, for example, `"en-US"`, `"fr-FR"`, `"de-DE"`. If not specified, the SDK automatically detects the buyer's locale from their browser settings.

clientMetadataId no

string. A unique identifier for tracking and debugging. You can generate this using crypto.randomUUID() or your own ID generation system. This ID helps correlate SDK sessions with your server-side logs.

merchantId yes for partners

string. A unique identifier for the seller you're processing payments for.

partnerAttributionId no

string. PayPal issues this BN\_CODE to you during partner onboarding.

#### Returns Returns a promise that resolves to an SDK instance object. This instance provides methods for checking payment eligibility and creating payment sessions. * `findEligibleMethods()` - Check payment method availability * `createPayPalOneTimePaymentSession()` - Create a payment session * `createFastlane()` - Initialize accelerated guest checkout (Fastlane) ### Example Partners must include the `merchantId` parameter when initializing the SDK instance. Direct merchants can omit this parameter. ```javascript lines expandable theme={null} // Basic initialization with client ID (recommended for most integrations) const sdkInstance = await window.paypal.createInstance({ clientId: "YOUR_CLIENT_ID", }); // With client token (required for PayPal vaulting and fastlane) const sdkInstance = await window.paypal.createInstance({ clientToken: "YOUR_CLIENT_TOKEN", }); // Full configuration with client ID const sdkInstance = await window.paypal.createInstance({ clientId: "YOUR_CLIENT_ID", components: ["paypal-payments", "venmo-payments"], pageType: "checkout", locale: "en-US", clientMetadataId: crypto.randomUUID(), }); // With error handling try { const sdkInstance = await window.paypal.createInstance({ clientId: "YOUR_CLIENT_ID", }); console.log("PayPal SDK initialized successfully"); } catch (error) { console.error("Failed to initialize PayPal SDK:", error); } ``` ## Recommended frontend setup This is the recommended approach for most implementations. It includes all payment methods with eligibility logic and automatic fallback handling. The following are key components of the integration: ### PayPal SDK instance * **Purpose**: Main entry point for PayPal functionality * **Components**: Includes `paypal-payments` component * **Authentication**: Requires client token from server ### Eligibility check * **Purpose**: Determines payment methods available to the buyer * **Factors**: User location, currency, account status, device type * **Implementation**: Always check before showing payment buttons ### Payment sessions * **PayPal**: Standard PayPal payments * **Pay Later**: Financing options with specific product codes * **PayPal Credit**: Credit-based payments with country-specific configuration ### Web components * ``: Standard PayPal payment button * ``: Pay Later financing button * ``: PayPal Credit button ### Example The following is an example of what an `app.js` file might look like when implementing the recommended setup. Partners must include the `merchantId` parameter when initializing the SDK instance. Direct merchants can omit this parameter. ```javascript expandable lines theme={null} async function onPayPalWebSdkLoaded() { try { // Create PayPal SDK instance const sdkInstance = await window.paypal.createInstance({ clientId: "YOUR_CLIENT_ID", components: ["paypal-payments"], pageType: "checkout", }); // Check eligibility for all payment methods const paymentMethods = await sdkInstance.findEligibleMethods({ currencyCode: "USD", }); // Set up PayPal button if eligible if (paymentMethods.isEligible("paypal")) { configurePayPalButton(sdkInstance); } // Set up Pay Later button if eligible if (paymentMethods.isEligible("paylater")) { const payLaterPaymentMethodDetails = paymentMethods.getDetails("paylater"); setupPayLaterButton(sdkInstance, payLaterPaymentMethodDetails); } // Set up PayPal Credit button if eligible if (paymentMethods.isEligible("credit")) { const paypalCreditPaymentMethodDetails = paymentMethods.getDetails("credit"); setupPayPalCreditButton(sdkInstance, paypalCreditPaymentMethodDetails); } } catch (error) { console.error("SDK initialization error:", error); } } // Shared payment session options for all payment methods const paymentSessionOptions = { // Called when user approves a payment async onApprove(data) { console.log("Payment approved:", data); try { const orderData = await captureOrder({ orderId: data.orderId, }); console.log("Payment captured successfully:", orderData); } catch (error) { console.error("Payment capture failed:", error); } }, // Called when user cancels a payment onCancel(data) { console.log("Payment cancelled:", data); }, // Called when an error occurs during payment onError(error) { console.error("Payment error:", error); }, }; // Set up standard PayPal button async function configurePayPalButton(sdkInstance) { const paypalPaymentSession = sdkInstance.createPayPalOneTimePaymentSession( paymentSessionOptions, ); const paypalButton = document.querySelector("paypal-button"); paypalButton.removeAttribute("hidden"); paypalButton.addEventListener("click", async () => { try { await paypalPaymentSession.start( { presentationMode: "auto" }, // Auto-detects best presentation mode createOrder(), ); } catch (error) { console.error("PayPal payment start error:", error); } }); } // Set up Pay Later button async function setupPayLaterButton(sdkInstance, payLaterPaymentMethodDetails) { const payLaterPaymentSession = sdkInstance.createPayLaterOneTimePaymentSession( paymentSessionOptions ); const { productCode, countryCode } = payLaterPaymentMethodDetails; const payLaterButton = document.querySelector("paypal-pay-later-button"); // Configure button with Pay Later specific details payLaterButton.productCode = productCode; payLaterButton.countryCode = countryCode; payLaterButton.removeAttribute("hidden"); payLaterButton.addEventListener("click", async () => { try { await payLaterPaymentSession.start( { presentationMode: "auto" }, createOrder(), ); } catch (error) { console.error("Pay Later payment start error:", error); } }); } // Set up PayPal Credit button async function setupPayPalCreditButton(sdkInstance, paypalCreditPaymentMethodDetails) { const paypalCreditPaymentSession = sdkInstance.createPayPalCreditOneTimePaymentSession( paymentSessionOptions ); const { countryCode } = paypalCreditPaymentMethodDetails; const paypalCreditButton = document.querySelector("paypal-credit-button"); // Configure button with PayPal Credit specific details paypalCreditButton.countryCode = countryCode; paypalCreditButton.removeAttribute("hidden"); paypalCreditButton.addEventListener("click", async () => { try { await paypalCreditPaymentSession.start( { presentationMode: "auto" }, createOrder(), ); } catch (error) { console.error("PayPal Credit payment start error:", error); } }); } ``` ## Return order ID to SDK The `createOrder()` function must return a promise that resolves to `{ orderId: "YOUR_ORDER_ID" }`. This is a key difference between v6 and previous versions of the SDK. ```javascript lines theme={null} // In v6, this must return an object with the shape: { orderId: "YOUR_ORDER_ID" } return fetch("/paypal-api/checkout/orders/create", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(orderPayload), }) .then(response => response.json()) .then(data => ({ orderId: data.id })); // <-- Required return value } // End createOrder ``` ## Best practices The following are best practices for integrating the v6 SDK. Keep sensitive operations server-side and validate all payment data. Provide clear feedback to users throughout the payment flow. ### Security * Obtain client tokens from your secure server * Never expose PayPal client secrets in frontend code * All payment processing happens through PayPal's secure servers * Never pass up item total from browser - this can be manipulated * Validate order details on your server before capture ### User experience * Always check eligibility before showing payment buttons * Provide clear loading states during payment processing * Handle popup blockers gracefully with `{ presentationMode:auto }` * Show appropriate error messages for different failure scenarios ### Performance * Initialize the SDK early, but avoid blocking page load * Cache client tokens appropriately * Use presentation mode fallback strategies ## See also * [JavaScript SDK v6 reference](/reference/sdk/js/v6/reference) * [React SDK v6 reference](/reference/sdk/react) # Sandboxed ``` ## Merchant page JavaScript implementation This example implements page-state management, secure postMessage listeners with origin validation, and handlers for different presentation modes (`popup`, `modal`, `payment-handler`). ```javascript lines expandable theme={null} class PageState { state = { presentationMode: null, lastPostMessage: null, merchantDomain: null, }; constructor() { this.merchantDomain = window.location.origin; } set presentationMode(value) { this.state.presentationMode = value; const element = document.getElementById("presentationMode"); element.innerHTML = value; } set lastPostMessage(event) { const statusContainer = document.getElementById("postMessageStatus"); statusContainer.innerHTML = JSON.stringify(event.data); this.state.lastPostMessage = event; } } const pageState = new PageState(); // Set up secure postMessage listener with origin validation function setupPostMessageListener() { window.addEventListener("message", (event) => { // 🔒 CRITICAL: Always validate origin to prevent XSS attacks! if (event.origin !== "http://localhost:3000") { return; } pageState.lastPostMessage = event; const { eventName, data } = event.data; const { presentationMode } = pageState; if (eventName === "presentationMode-changed") { const { presentationMode } = data; pageState.presentationMode = presentationMode; } else if (presentationMode === "popup") { popupPresentationModePostMessageHandler(event); } else if (presentationMode === "modal") { modalPresentationModePostMessageHandler(event); } }); } ``` ## PayPal ` ``` ## PostMessage origin validation This example implements critical security measures, such as validating message origins to prevent XSS attacks and ensuring that only trusted domains can communicate with your application. ```javascript lines expandable theme={null} // ✅ ALWAYS validate message origin window.addEventListener("message", (event) => { if (event.origin !== expectedOrigin) { return; // Ignore messages from unknown origins } // Process trusted message }); // ❌ NEVER accept messages without validation window.addEventListener("message", (event) => { // Vulnerable to XSS attacks! processMessage(event.data); }); ``` ## Content security policy header configuration Content Security Policy (CSP) headers control resource loading and prevent unauthorized script execution while allowing necessary PayPal SDK and `