Subscriptions Integration
To integrate the Subscriptions API, first set up your development environment and then create a product, plan, and subscription.
Availability: Customers who integrated with Subscriptions before April 2019 can access reference and support material in the archived Subscriptions integration guide.
Note: This integration is not supported for merchants in the gambling category.
1. Set up your development environment
Before you can integrate Subscriptions, you must set up your development environment. After you get a token that lets you access protected REST API resources, you create sandbox accounts to test your web and mobile apps. For details, see Get Started.
Then, return to this page to integrate Subscriptions.
2. Create a product
A product captures goods or services offered for a subscription.
Note: This is a one time operation.
The <ID>
is either merchant-provided or system-generated and begins with PROD-xxxx
.
Create your product by calling /products
:
curl -v -X POST https://api.sandbox.paypal.com/v1/catalogs/products \
-H "Content-Type: application/json" \
-H "Authorization: Bearer Access-Token" \
-H "PayPal-Request-Id: merchant-generated-ID \ // Optional and if passed, helps identify idempotent requests
-d '{
"name": "Video Streaming Service",
"description": "Video streaming service",
"type": "SERVICE",
"category": "SOFTWARE",
"image_url": "https://example.com/streaming.jpg",
"home_url": "https://example.com/home"
}'
A successful request returns the HTTP 201 Created
status code with a JSON response body.
{
"id": "PROD-XYAB12ABSB7868434",
"name": "Video Streaming Service",
"description": "Video streaming service",
"type": "SERVICE",
"category": "SOFTWARE",
"image_url": "https://example.com/streaming.jpg",
"home_url": "https://example.com/home",
"create_time": "2019-01-10T21:20:49Z",
"update_time": "2019-01-10T21:20:49Z",
"links": [
{
"href": "https://api.paypal.com/v1/catalogs/products/72255d4849af8ed6e0df1173",
"rel": "self",
"method": "GET"
},
{
"href": "https://api.paypal.com/v1/catalogs/products/72255d4849af8ed6e0df1173",
"rel": "edit",
"method": "PATCH"
}
]
}
If creating a product succeeds, it triggers the CATALOG.PRODUCT.CREATED
webhook.
3. Create a plan
You can associate multiple plans to a product. For example, a video streaming service can have several plans: trial, basic, standard, and premium.
You can create either a finite plan or an infinite plan:
- Finite Plan - A plan with a fixed number of cycles. Once a buyer subscribes, a finite plan expires after the total number of cycles defined for are completed. For example, a buyer can subscribe to an online tutorial service for 3 cycles.
- Infinite Plan - A plan without a fixed number of cycles. Once a buyer subscribes, an infinite plan remains active until cancelation. For example, a buyer can subscribe to a video or music streaming service with no specified end date.
A trial period plan is useful to let your subscriber try your product at a free or discounted price before regular billing cycles start.
Note: Creating a plan is a one time operation.
Create a plan by calling /plans
. Plans are active by default.
This sample request creates a trial plan with a fixed pricing scheme. For quantity (user or seat) based pricing plans, set the quantity_supported
attribute to true
to indicate that customers can subscribe to this plan by providing the number of units they what to subscribe to.
curl -v -k -X POST https://api.sandbox.paypal.com/v1/billing/plans \
-H "Accept: application/json" \
-H "Authorization: Bearer Access-Token" \
-H "PayPal-Request-Id: PLAN-18062019-001" \ // merchant generated ID, optional and needed for idempotent samples
-H "Prefer: return=representation" \
-H "Content-Type: application/json" \
-d '{
"product_id": "PROD-6XB24663H4094933M",
"name": "Basic Plan",
"description": "Basic plan",
"billing_cycles": [
{
"frequency": {
"interval_unit": "MONTH",
"interval_count": 1
},
"tenure_type": "TRIAL",
"sequence": 1,
"total_cycles": 1
},
{
"frequency": {
"interval_unit": "MONTH",
"interval_count": 1
},
"tenure_type": "REGULAR",
"sequence": 2,
"total_cycles": 12,
"pricing_scheme": {
"fixed_price": {
"value": "10",
"currency_code": "USD"
}
}
}
],
"payment_preferences": {
"auto_bill_outstanding": true,
"setup_fee": {
"value": "10",
"currency_code": "USD"
},
"setup_fee_failure_action": "CONTINUE",
"payment_failure_threshold": 3
},
"taxes": {
"percentage": "10",
"inclusive": false
}
}'
curl -v -k -X POST https://api.sandbox.paypal.com/v1/billing/plans \
-H "Accept: application/json" \
-H "Authorization: Bearer Access-Token" \
-H "PayPal-Request-Id: PLAN-18062019-001" \ // merchant generated ID, optional and needed for idempotent samples
-H "Prefer: return=representation" \
-H "Content-Type: application/json" \
-d '{
"product_id": "PROD-XXCD1234QWER65782",
"name": "Basic Plan",
"description": "Basic plan",
"billing_cycles": [
{
"frequency": {
"interval_unit": "MONTH",
"interval_count": 1
},
"tenure_type": "TRIAL",
"sequence": 1,
"total_cycles": 1
},
{
"frequency": {
"interval_unit": "MONTH",
"interval_count": 1
},
"tenure_type": "REGULAR",
"sequence": 2,
"total_cycles": 12,
"pricing_scheme": {
"fixed_price": {
"value": "10",
"currency_code": "USD"
}
}
}
],
"payment_preferences": {
"service_type": "PREPAID",
"auto_bill_outstanding": true,
"setup_fee": {
"value": "10",
"currency_code": "USD"
},
"setup_fee_failure_action": "CONTINUE",
"payment_failure_threshold": 3
},
"quantity_supported": true,
"taxes": {
"percentage": "10",
"inclusive": false
}
}'
A successful request returns the HTTP 201 Created
status code with a JSON response body that shows subscription details.
{
"id": "P-2UF78835G6983425GLSM44MA",
"product_id": "PROD-6XB24663H4094933M",
"name": "Basic Plan",
"status": "ACTIVE",
"description": "Basic plan",
"billing_cycles": [
{
"frequency": {
"interval_unit": "MONTH",
"interval_count": 1
},
"tenure_type": "TRIAL",
"sequence": 1,
"total_cycles": 1
},
{
"pricing_scheme": {
"fixed_price": {
"currency_code": "USD",
"value": "10.00"
}
},
"frequency": {
"interval_unit": "MONTH",
"interval_count": 1
},
"tenure_type": "REGULAR",
"sequence": 2,
"total_cycles": 12
}
],
"payment_preferences": {
"auto_bill_outstanding": true,
"setup_fee": {
"currency_code": "USD",
"value": "10.00"
},
"setup_fee_failure_action": "CONTINUE",
"payment_failure_threshold": 3
},
"taxes": {
"percentage": "10.00",
"inclusive": false
},
"quantity_supported": false,
"create_time": "2019-03-26T07:01:04Z",
"update_time": "2019-03-26T07:01:04Z",
"links": [
{
"href": "https://api.sandbox.paypal.com/v1/billing/plans/P-2UF78835G6983425GLSM44MA",
"rel": "self",
"method": "GET"
},
{
"href": "https://api.sandbox.paypal.com/v1/billing/plans/P-2UF78835G6983425GLSM44MA",
"rel": "edit",
"method": "PATCH"
},
{
"href": "https://api.sandbox.paypal.com/v1/billing/plans/P-2UF78835G6983425GLSM44MA/deactivate",
"rel": "self",
"method": "POST"
}
]
}
{
"id": "P-2UF78835G6983425GLSM44MA",
"product_id": "PROD-XYAB12ABSB7868434",
"name": "Basic Plan",
"status": "ACTIVE",
"description": "Basic plan",
"billing_cycles": [
{
"frequency": {
"interval_unit": "MONTH",
"interval_count": 1
},
"tenure_type": "TRIAL",
"sequence": 1,
"total_cycles": 1
},
{
"pricing_scheme": {
"fixed_price": {
"currency_code": "USD",
"value": "10.0"
}
},
"frequency": {
"interval_unit": "MONTH",
"interval_count": 1
},
"tenure_type": "REGULAR",
"sequence": 2,
"total_cycles": 12
}
],
"payment_preferences": {
"auto_bill_outstanding": true,
"setup_fee": {
"currency_code": "USD",
"value": "10.0"
},
"setup_fee_failure_action": "CONTINUE",
"payment_failure_threshold": 3
},
"taxes": {
"percentage": "10.0",
"inclusive": false
},
"quantity_supported": false,
"create_time": "2019-03-26T07:01:04Z",
"update_time": "2019-03-26T07:01:04Z",
"links": [
{
"href": "https://api.sandbox.paypal.com/v1/billing/plans/P-2UF78835G6983425GLSM44MA",
"rel": "self",
"method": "GET"
},
{
"href": "https://api.sandbox.paypal.com/v1/billing/plans/P-2UF78835G6983425GLSM44MA",
"rel": "edit",
"method": "PATCH"
},
{
"href": "https://api.sandbox.paypal.com/v1/billing/plans/P-2UF78835G6983425GLSM44MA/deactivate",
"rel": "self",
"method": "POST"
}
]
}
If creating a plan succeeds, it triggers the BILLING.PLAN.CREATED
webhook.
4. Create a subscription
PayPal recommends using Subscriptions with Smart Payment Buttons as it gives your buyers a simplified and secure subscription experience. PayPal presents payment types to your buyers automatically, making it easier for them to complete their purchase using methods like Pay with Venmo, PayPal Credit, and credit card payments without reintegration as they are made available. You can also use the Subscriptions API.
Subscriptions with Smart Payment Buttons
To use Subscriptions with Smart Payment Buttons:
- Add the PayPal script to your web page.
- Render the Smart Payment Button.
- Create the subscription.
Add the PayPal script
Add the PayPal script to your web page and add your sandbox client_id
to the script
tag.
<!DOCTYPE html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
</head>
<body>
<script
src="https://www.paypal.com/sdk/js?client-id=SB_CLIENT_ID&vault=true">
</script>
</body>
Make sure you:
- Add the
<!DOCTYPE html>
tag for optimal browser compatibility. - Add the
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
meta tag to the page for optimal Internet Explorer compatibility. - Add the
<meta name="viewport" content="width=device-width, initial-scale=1">
tag to the page to ensure optimal rendering on mobile devices.
You can customize your integration by passing different query parameters to https://www.paypal.com/sdk/js
Option | Example value | Default | Description |
---|---|---|---|
client-id |
sb |
required | Your PayPal REST client ID. This identifies your PayPal account and determines where transactions are paid to. While you're testing in sandbox, you can use client-id=sb as a shortcut. |
vault |
true , false |
false |
Set to true for subscriptions. |
See Customize the SDK for a complete list of available parameters and values.
Render the Smart Payment Button
Next, render the PayPal Smart Payment Buttons to a container element on your page.
<body>
<script
src="https://www.paypal.com/sdk/js?client-id=SB_CLIENT_ID&vault=true">
</script>
<div id="paypal-button-container"></div>
<script>
paypal.Buttons().render('#paypal-button-container');
</script>
</body>
Create the subscription
Finally, implement the createSubscription
function that's called when the buyer clicks the PayPal button. This function:
- Calls PayPal using
actions.subscription.create()
to create a subscription for your plan and includes the plan ID, subscriber details, shipping, and other details. - Launches the PayPal subscription window so the buyer can log in and approve the subscription on www.paypal.com.
paypal.Buttons({
createSubscription: function(data, actions) {
return actions.subscription.create({
'plan_id': 'P-2UF78835G6983425GLSM44MA'
});
},
onApprove: function(data, actions) {
alert('You have successfully created subscription ' + data.subscriptionID);
}
}).render('#paypal-button-container');
Handle errors and customer drop off using the following handlers:
Use the Subscriptions API
To create a subscription for a plan in active status, call /subscriptions
. The buyer must consent to the subscription to activate it.
curl -v -k -X POST https://api.sandbox.paypal.com/v1/billing/subscriptions \
-H "Accept: application/json" \
-H "Authorization: Bearer Access-Token" \
-H "PayPal-Request-Id: SUBSCRIPTION-21092019-001" \
-H "Prefer: return=representation" \
-H "Content-Type: application/json" \
-d '{
"plan_id": "P-2UF78835G6983425GLSM44MA",
"start_time": "2019-03-27T06:00:00Z",
"subscriber": {
"name": {
"given_name": "John",
"surname": "Doe"
},
"email_address": "customer@example.com"
},
"application_context": {
"brand_name": "example",
"locale": "en-US",
"shipping_preference": "SET_PROVIDED_ADDRESS",
"user_action": "SUBSCRIBE_NOW",
"payment_method": {
"payer_selected": "PAYPAL",
"payee_preferred": "IMMEDIATE_PAYMENT_REQUIRED"
},
"return_url": "https://example.com/returnUrl",
"cancel_url": "https://example.com/cancelUrl"
}
}'
curl -v -k -X POST https://api.sandbox.paypal.com/v1/billing/subscriptions \
-H "Accept: application/json" \
-H "Authorization: Bearer Access-Token" \
-H "PayPal-Request-Id: SUBSCRIPTION-21092019-001" \
-H "Prefer: return=representation" \
-H "Content-Type: application/json" \
-d '{
"plan_id": "P-4ML8771254154362WXNWU5BC",
"start_time": "2018-11-01T00:00:00Z",
"quantity": "20",
"shipping_amount": {
"currency_code": "USD",
"value": "10.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": "example",
"locale": "en-US",
"shipping_preference": "SET_PROVIDED_ADDRESS",
"user_action": "SUBSCRIBE_NOW",
"payment_method": {
"payer_selected": "PAYPAL",
"payee_preferred": "IMMEDIATE_PAYMENT_REQUIRED"
},
"return_url": "https://example.com/returnUrl",
"cancel_url": "https://example.com/cancelUrl"
}
}'
A successful request returns the HTTP 201 Created
status code and a JSON response body that shows subscription details:
{
"id": "I-KK24TMKLGR0P",
"plan_id": "P-2UF78835G6983425GLSM44MA",
"start_time": "2019-03-27T06:00:00Z",
"subscriber": {
"name": {
"given_name": "John",
"surname": "Doe"
},
"email_address": "customer@example.com"
},
"create_time": "2019-03-26T07:37:44Z",
"links": [
{
"href": "https://www.sandbox.paypal.com/webapps/billing/subscriptions?ba_token=BA-5G371300PF745064S",
"rel": "approve",
"method": "GET"
},
{
"href": "https://api.sandbox.paypal.com/v1/billing/subscriptions/I-KK24TMKLGR0P",
"rel": "edit",
"method": "PATCH"
},
{
"href": "https://api.sandbox.paypal.com/v1/billing/subscriptions/I-KK24TMKLGR0P",
"rel": "self",
"method": "GET"
}
],
"status": "APPROVAL_PENDING",
"status_update_time": "2019-03-26T07:37:44Z"
}
{
"id": "I-BW452GLLEP1G",
"status": "APPROVAL_PENDING",
"status_update_time": "2018-12-10T21:20:49Z",
"plan_id": "P-4ML8771254154362WXNWU5BC",
"start_time": "2018-11-01T00:00:00Z",
"quantity": "20",
"shipping_amount": {
"currency_code": "USD",
"value": "10.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"
}
}
},
"create_time": "2018-12-10T21:20:49Z",
"links": [
{
"href": "https://www.paypal.com/webapps/billing/subscriptions?ba_token=BA-2M539689T3856352J",
"rel": "approve",
"method": "GET"
},
{
"href": "https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G",
"rel": "edit",
"method": "PATCH"
},
{
"href": "https://api.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G",
"rel": "self",
"method": "GET"
}
]
}
If creating a subscription succeeds, it triggers the BILLING.SUBSCRIPTION.CREATED
webhook.
HATEOAS links
To redirect the buyer to log in to their PayPal account to approve the subscription, use the HATEOAS link from the response.
Example of HATEOAS URL:
GET https://www.paypal.com/webapps/billing/subscriptions?ba_token={BA-Token-ID}
5. Go live
To launch your subcription into production, complete these steps:
Create a PayPal business account
Note: If you already have a PayPal business account, skip to Replace sandbox credentials with live credentials.
- Go to the PayPal home page and click Sign Up.
- Select Business Account and follow the on-screen instructions.
Replace sandbox credentials with live credentials
-
Change any API calls from
https://api.sandbox.paypal.com
tohttps://api.paypal.com
and use your production access token for these calls. -
Change the
https://www.paypal.com/sdk/js
script tag to use your live client ID.<script src="https://www.paypal.com/sdk/js?client-id=LIVE_CLIENT_ID&vault=true"> </script>
Next
See the full list of features you can add to your integration.