Test and go live with Subscriptions

DocsCurrentLast updated: September 29th 2023, @ 7:38:40 am


You can run negative tests on your integration to manage the responses you give to your customers.

Know before you code

  • Before you trigger a simulation, you'll need to you need to get an access token.
  • Use Postman to explore and test PayPal APIs.

Test flow

Test a transaction to see the subscription created in the merchant account.

Test the transaction as a buyer

  1. Select the PayPal button on the page.

  2. Use the sandbox personal login information from the Developer Dashboard to log in and simulate the buyer making a purchase.

  3. In the Checkout window, notice the purchase amount in the upper right corner. USD is the default currency. You can customize the PayPal JavaScript SDK with different currency codes.

    Availability: The JavaScript SDK onShippingChange, onShippingAddressChange, and onShippingOptionsChange functions are not compatible with Subscriptions.

  4. Select the pull-down arrow next to the purchase amount. The subscription details are available for the buyer to review. It should appear similar to the following image: Subscription details in checkout

  5. Complete the flow.

Confirm funds move from the buyer account

  1. Use the sandbox personal account you used to complete the purchase to log in to https://www.sandbox.paypal.com/myaccount/autopay/connect/. This URL takes you to the automatic payments page in the sandbox personal account.
  2. Confirm the subscription appears in the active automatic payment list. Select the active automatic payment to see the details of the subscription.
  3. Log out of the account.

Confirm funds move to the merchant account

  1. Use the sandbox business account information from the Developer Dashboard to log in to https://www.sandbox.paypal.com/billing/subscriptions. This URL takes you to the subscriptions management page in the sandbox business account.
  2. Confirm the subscription made by the test buyer appears on the Subscriptions tab. Select the subscription to see the details of the subscription.
  3. Log out of the account.

Simulation methods

To trigger a simulation for the Subscriptions API, you can use either a JSON pointer in the request payload or a path parameter in the request URI.

Use a JSON pointer in the request payload

TriggerTest valueSimulated error response
plan_idERRSUB033NOT_AUTHORIZED

Request

curl -X POST \
  https://api-m.sandbox.paypal.com/v1/billing/subscriptions \
  -H 'Authorization: Bearer  <Access Token>'
  -d '{
        "plan_id": "ERRSUB033",
            "start_time": "2020-02-06T15:00:00Z",
            "quantity": "1",
            "shipping_amount": {
                "currency_code": "USD",
                "value": "12.00"
            },
            "subscriber": {
                "name": {
                    "given_name": "John",
                    "surname": "Doe"
                },
                "email_address": "customer@example.com",
                "shipping_address": {
                    "name": {
                        "full_name": "John Doe"
                    },
                    "address": {
                        "address_line_1": "2211 N First Street",
                        "address_line_2": "Building 17",
                        "admin_area_2": "San Jose",
                        "admin_area_1": "CA",
                        "postal_code": "95131",
                        "country_code": "US"
                    }
                }
            },
            "application_context": {
                "brand_name": "Walmart Inc",
                "locale": "en-US",
                "shipping_preference": "SET_PROVIDED_ADDRESS",
                "user_action": "SUBSCRIBE_NOW",
                "payment_method": {
                    "payer_selected": "PAYPAL_CREDIT",
                    "payee_preferred": "IMMEDIATE_PAYMENT_REQUIRED"
                },
                "return_url": "http://zoho.com/returnUrl",
                "cancel_url": "http://zoho.com/cancelUrl"
            }
        }'

Response

{
  "name": "NOT_AUTHORIZED",
  "debugId": "b1d1f06c7246c",
  "message": "Authorization failed due to insufficient permissions.",
  "details": [
      {
          "issue": "PERMISSION_DENIED",
          "description": "You do not have permission to access or perform operations on this resource."
      }
  ],
  "links": [
      {
          "href": "https://developer.paypal.com/docs/api/v1/billing/subscriptions#PERMISSION_DENIED",
          "rel": "information_link",
          "method": "GET"
      }
  ]
}

Use a path parameter in the request URI

Trigger or test valueSimulated error response
v1/billing/subscriptions/ERRSUB068/activateRESOURCE_NOT_FOUND

Request

curl -X GET \
  https://api-m.sandbox.paypal.com/v1/billing/subscriptions/ERRSUB068/activate \
  -H 'Authorization: Bearer <Access Token>' \
  -H 'Content-Type: application/json' \
  -d '{
     "reason": "Reactivating the subscription"
  }
}'

Response

{
    "name": "RESOURCE_NOT_FOUND",
    "message": "The specified resource does not exist.",
    "debug_id": "c2d1f06c7246c",
     "details": [
        {
            "issue": "INVALID_RESOURCE_ID",  
            "description": "Requested resource ID was not found",
            "value": "I-TT452GLLEP1G"
        }
    ],
    "links": [
        {
            "href": "https://developer.paypal.com/docs/api/v1/billing/subscriptions#RESOURCE_NOT_FOUND,
            "rel": "information_link"
        }
    ]
}

Test values

Use the following test values to trigger positive and negative responses for these subscriptions actions:

Product

Plan

Subscription

Product

Note: Test values are case sensitive.

Create product

Negative response test values

Use the JSON pointer in the request payload to simulate the following error responses at POST /v1/catalogs/products.

TriggerTest valueSimulated error response
nameERRCAT001INTERNAL_SERVER_ERROR
nameERRCAT002NOT_AUTHORIZED
nameERRCAT003INVALID_REQUEST
nameERRCAT004INVALID_REQUEST
nameERRCAT005UNPROCESSABLE_ENTITY

Get product

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at GET /v1/catalogs/products/{test_value}.

Trigger or test valueSimulated error response
/v1/catalogs/products/ERRCAT008INTERNAL_SERVER_ERROR
/v1/catalogs/products/ERRCAT009NOT_AUTHORIZED
/v1/catalogs/products/ERRCAT010RESOURCE_NOT_FOUND

List products

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at GET /v1/billing/plans/?&total_required={test_value}.

Trigger or test valueSimulated error response
/v1/catalogs/products?total_required=ERRCAT006INTERNAL_SERVER_ERROR
/v1/catalogs/products?total_required=ERRCAT007NOT_AUTHORIZED

Update product

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at PATCH /v1/catalog/products/{test_value}.

Trigger or test valueSimulated error response
/v1/catalogs/products/ERRCAT011INTERNAL_SERVER_ERROR
/v1/catalogs/products/ERRCAT012NOT_AUTHORIZED
/v1/catalogs/products/ERRCAT013INVALID_REQUEST
/v1/catalogs/products/ERRCAT014UNPROCESSABLE_ENTITY

Plan

Note: Test values are case sensitive.

Create plan

Negative response test values

Use the JSON pointer in the request payload to simulate the following error responses at POST /v1/billing/plans/.

TriggerTest valueSimulated error response
nameERRSUB001INTERNAL_SERVER_ERROR
nameERRSUB002NOT_AUTHORIZED
nameERRSUB003INVALID_REQUEST
nameERRSUB004UNPROCESSABLE_ENTITY

Activate plan

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at POST/v1/billing/plans/{test_value}/activate.

Trigger or test valueSimulated error response
/v1/billing/plans/ERRSUB015/activateINTERNAL_SERVER_ERROR
/v1/billing/plans/ERRSUB016/activateNOT_AUTHORIZED
/v1/billing/plans/ERRSUB017/activateRESOURCE_NOT_FOUND
/v1/billing/plans/ERRSUB018/activateUNPROCESSABLE_ENTITY

Deactivate plan

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at POST /v1/billing/plans/{test_value}/deactivate.

Trigger or test valueSimulated error response
/v1/billing/plans/ERRSUB019/deactivateINTERNAL_SERVER_ERROR
/v1/billing/plans/ERRSUB020/deactivateNOT_AUTHORIZED
/v1/billing/plans/ERRSUB021/deactivateRESOURCE_NOT_FOUND
/v1/billing/plans/ERRSUB022/deactivateUNPROCESSABLE_ENTITY

Get plan

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at GET /v1/billing/plans/{test_value}.

Trigger or test valueSimulated error response
/v1/billing/plans/ERRSUB008INTERNAL_SERVER_ERROR
/v1/billing/plans/ERRSUB009NOT_AUTHORIZED
/v1/billing/plans/ERRSUB009RESOURCE_NOT_FOUND

List plans

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at GET /v1/billing/plans/?page_size=3&page=1&total_required={test_value}.

Trigger or test valueSimulated error response
/v1/billing/plans?page_size=3&page=1&total_required=ERRSUB005INTERNAL_SERVER_ERROR
/v1/billing/plans?page_size=3&page=1&total_required=ERRSUB006NOT_AUTHORIZED
/v1/billing/plans?page_size=3&page=1&total_required=ERRSUB007INVALID_REQUEST

Update plan

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at PATCH /v1/billing/plans/{test_value}.

Trigger or test valueSimulated error response
/v1/billing/plans/ERRSUB011INTERNAL_SERVER_ERROR
/v1/billing/plans/ERRSUB012NOT_AUTHORIZED
/v1/billing/plans/ERRSUB013RESOURCE_NOT_FOUND
/v1/billing/plans/ERRSUB014INVALID_REQUEST

Change plan pricing

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at POST /v1/billing/plans/{test_value}/update-pricing-schemes.

Trigger or test valueSimulated error response
/v1/billing/plans/ERRSUB023/update-pricing-schemesINTERNAL_SERVER_ERROR
/v1/billing/plans/ERRSUB024/update-pricing-schemesNOT_AUTHORIZED
/v1/billing/plans/ERRSUB025/update-pricing-schemesINVALID_REQUEST
/v1/billing/plans/ERRSUB026/update-pricing-schemesRESOURCE_NOT_FOUND
/v1/billing/plans/ERRSUB027/update-pricing-schemesUNPROCESSABLE_ENTITY
/v1/billing/plans/ERRSUB028/update-pricing-schemesUNPROCESSABLE_ENTITY
/v1/billing/plans/ERRSUB029/update-pricing-schemesUNPROCESSABLE_ENTITY
/v1/billing/plans/ERRSUB030/update-pricing-schemesUNPROCESSABLE_ENTITY
/v1/billing/plans/ERRSUB031/update-pricing-schemesUNPROCESSABLE_ENTITY

Subscription

Note: Test values are case sensitive.

Create subscription

Negative response test values

Use the JSON pointer in the request payload to simulate the following error responses at POST /v1/billing/subscriptions.

TriggerTest valueSimulated error response
plan_idERRSUB032INTERNAL_SERVER_ERROR
plan_idERRSUB033NOT_AUTHORIZED
plan_idERRSUB034INVALID_REQUEST
plan_idERRSUB035INVALID_REQUEST
plan_idERRSUB036INVALID_REQUEST
plan_idERRSUB037INVALID_REQUEST
plan_idERRSUB038INVALID_REQUEST
plan_idERRSUB039UNPROCESSABLE_ENTITY
plan_idERRSUB040UNPROCESSABLE_ENTITY

Activate subscriptions

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at POST /v1/billing/subscriptions/{test_value}/activate.

Trigger or test valueSimulated error response
/v1/billing/subscriptions/ERRSUB066/activateINTERNAL_SERVER_ERROR
/v1/billing/subscriptions/ERRSUB067/activateNOT_AUTHORIZED
/v1/billing/subscriptions/ERRSUB068/activateRESOURCE_NOT_FOUND
/v1/billing/subscriptions/ERRSUB069/activateUNPROCESSABLE_ENTITY
/v1/billing/subscriptions/ERRSUB070/activateUNPROCESSABLE_ENTITY

Get subscription

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at GET /v1/billing/subscriptions/{test_value}.

Trigger or test valueSimulated error response
/v1/billing/subscriptions/ERRSUB044INTERNAL_SERVER_ERROR
/v1/billing/subscriptions/ERRSUB045NOT_AUTHORIZED
/v1/billing/subscriptions/ERRSUB046RESOURCE_NOT_FOUND

Update subscription

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at PATCH /v1/billing/subscriptions/{test_value}.

Trigger or test valueSimulated error response
/v1/billing/subscriptions/ERRSUB047INTERNAL_SERVER_ERROR
/v1/billing/subscriptions/ERRSUB048NOT_AUTHORIZED
/v1/billing/subscriptions/ERRSUB049RESOURCE_NOT_FOUND
/v1/billing/subscriptions/ERRSUB050INVALID_REQUEST
/v1/billing/subscriptions/ERRSUB051UNPROCESSABLE_ENTITY
/v1/billing/subscriptions/ERRSUB052UNPROCESSABLE_ENTITY

Revise subscription

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at POST /v1/billing/subscriptions/{test_value}/revise.

Trigger or test valueSimulated error response
/v1/billing/subscriptions/ERRSUB053/reviseINTERNAL_SERVER_ERROR
/v1/billing/subscriptions/ERRSUB054/reviseNOT_AUTHORIZED
/v1/billing/subscriptions/ERRSUB055/reviseINVALID_REQUEST
/v1/billing/subscriptions/ERRSUB056/reviseUNPROCESSABLE_ENTITY

Suspend subscription

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at POST /v1/billing/subscriptions/{test_value}/suspend.

Trigger or test valueSimulated error response
/v1/billing/subscriptions/ERRSUB059/suspendINTERNAL_SERVER_ERROR
/v1/billing/subscriptions/ERRSUB060/suspendNOT_AUTHORIZED
/v1/billing/subscriptions/ERRSUB061/suspendINVALID_REQUEST
/v1/billing/subscriptions/ERRSUB062/suspendUNPROCESSABLE_ENTITY

Capture subscription

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at POST /v1/billing/subscriptions/{test_value}/capture.

Trigger or test valueSimulated error response
/v1/billing/subscriptions/ERRSUB071/captureINTERNAL_SERVER_ERROR
/v1/billing/subscriptions/ERRSUB072/captureNOT_AUTHORIZED
/v1/billing/subscriptions/ERRSUB073/captureRESOURCE_NOT_FOUND
/v1/billing/subscriptions/ERRSUB074/captureINVALID_REQUEST
/v1/billing/subscriptions/ERRSUB075/captureINVALID_REQUEST

Get subscription transaction

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at GET /v1/billing/subscriptions/{test_value}/transactions.

Trigger or test valueSimulated error response
/v1/billing/subscriptions/ERRSUB076/transactionsINTERNAL_SERVER_ERROR
/v1/billing/subscriptions/ERRSUB076/transactionsNOT_AUTHORIZED
/v1/billing/subscriptions/ERRSUB076/transactionsRESOURCE_NOT_FOUND
/v1/billing/subscriptions/ERRSUB076/transactionsINVALID_REQUEST

Cancel subscription

Negative response test values

Use the path parameter in the request URI method to simulate the following error responses at POST /v1/billing/subscriptions/{test_value}/cancel.

Trigger or test valueSimulated error response
/v1/billing/subscriptions/ERRSUB063/cancelINTERNAL_SERVER_ERROR
/v1/billing/subscriptions/ERRSUB064/cancelNOT_AUTHORIZED
/v1/billing/subscriptions/ERRSUB065/cancelRESOURCE_NOT_FOUND

Error handling

An error includes:

  • The error name and description.
  • A link to error-related documentation.
  • A debug ID.
  • Error details.

API errors

HTTP status codeError nameMessageDetails
400INVALID_REQUESTRequest is not well-formed, syntactically incorrect, or violates schema.A required field is missing.
401AUTHENTICATION_FAILUREAuthorization error occurred.Authorization error occurred. Check your credentials.
403NOT_AUTHORIZEDAuthorization failed due to insufficient permissions.You do not have permission to access or perform operations on this resource.
404RESOURCE_NOT_FOUNDThe specified resource does not exist.Requested resource ID was not found.
422UNPROCESSABLE_ENTITYThe requested action could not be performed, semantically incorrect, or failed business validation.Invalid plan status for activate action; plan status should be either inactive or created.
500INTERNAL_SERVER_ERRORAn internal server error has occurred.Resend the request at another time. If this error continues, contact PayPal Merchant Technical Support.

Sample error response

{
  "name": "INVALID_REQUEST",
  "message": "Request is not well-formed, syntactically incorrect, or violates schema",
  "debug_id": "6u3y6fca61718",
  "details": [{
    "field": "/plan_id",
    "issue": "MISSING_REQUIRED_PARAMETER",
    "description": "A required field is missing.",
    "location": "body"
  }],
  "links": [{
    "href": "https://developer.paypal.com/docs/api/v2/payments/#INVALID_REQUEST",
    "rel": "information_link",
    "method": "GET"
  }]
}

Go live

  1. Change the base URL for all your REST API calls from https://api-m.sandbox.paypal.com to https://api-m.paypal.com.
  2. Change the references to your sandbox API credentials to the live credentials. To get live API credentials, create a live REST API.