- First-time users should refer to Get started with PayPal REST APIs Postman setup details, and the API suite configuration.
- Configure your server to make Orders v2 API calls. Do not call the APIs directly from the browser or client-side.
Save payment methods for recurring payments
Last updated: Aug 11th, 7:23pm
Merchants initiate recurring payments based on a schedule or other criteria such as service usage. Common recurring payment examples include:
- Subscriptions such as streaming media or pet food delivery.
- Automatic bill payments, such as utilities or mobile phone services.
- Auto reloads, such as road tolls or prepaid cards.
The industry classifies recurring payments into specific types based on factors such as amount variation, frequency changes between payments, and whether the payment has a fixed duration or remains open-ended.
Type | Amount | Billing frequency | Duration |
Subscriptions | Fixed | Regular schedule | No fixed duration |
Recurring | Variable | Regular schedule | No fixed duration |
Unscheduled account on file | Fixed or variable | Variable | No fixed duration |
Merchant-managed installments | Fixed | Defined schedule | No fixed duration |
Know before you code
Implement recurring payments
Recurring payments with PayPal use PayPal payment tokens, also known as vault tokens, for the vaulting with the purchase checkout flow. PayPal's vaulting with purchase checkout flow operates as a single-stage process. When merchants complete a purchase, PayPal saves a payment token and returns it to the merchant. This token is called the PayPal Vault ID. See the following steps to implement recurring payments.
- Create and save the payment token through Orders: When customers choose to save their payment source in an application, use the Orders v2 API to save their funding instrument in their PayPal wallet after customers complete checkout. PayPal returns a payment token that merchants should store against the customer's account. Use this token to initiate payments when needed.
- Initiate subsequent payments with the saved payment token: When customers return to an application, merchants use the stored payment token to initiate payments against their PayPal account.
Recurring payment during initial purchase
The following steps show the complete flow for setting up recurring payments during a customer's first purchase, including vault token creation and storage:
- The payer selects PayPal Checkout, and chooses to save their payment method.
- The merchant client starts the checkout process and includes recurring payment details.
- The merchant server creates an order with the recurring payment information by calling the Orders v2 API.
- PayPal processes the order and creates a vault token for the payment method.
- PayPal sends the order ID and the vault token to the merchant.
- The merchant stores the order ID and vault token for future transactions.
Process subsequent payments with stored tokens
For subsequent transactions, the merchant server creates orders using the stored vault_id
and credential information from the initial purchase. PayPal processes the payment and returns the completed transaction details.
Create payment method tokens
Initiate payment token creation during PayPal Checkout when customers sign up for services or add PayPal as a payment method for existing recurring arrangements. Include the following recurring payment information:
- Use recurring indicators. This flags the payment token for future recurring payments and customizes PayPal Checkout content to inform customers about the recurring nature of the payment.
- Recurring Billing Agreement (RBA) plan information. This provides customers with key summary information in PayPal Checkout about the recurring arrangement they are entering.
Recurring indicator
Set the recurring indicator value that represents the most appropriate type of RBA. This information sets payment network indicators correctly and must accurately represent the customer agreement to ensure compliance with payment network regulations.
Set the recurring indicator through the Create Order API's usage_pattern
value at payment_source.paypal.usage_pattern
during payment token creation for initial or subsequent purchases. Additional required fields are outlined in separate sections.
usage_pattern
in payment_source.paypal.attributes.vault
. For subsequent transactions, use usage_pattern
in payment_source.paypal.stored_credential
.
RBA type | Description | Usage pattern values | Examples |
Subscription | Represents agreements where customers are charged a fixed amount on a regular schedule with no end date. |
|
|
Recurring | Represents RBAs where customers are charged a variable amount on a regular schedule with no end date. |
|
|
Unscheduled | Represents RBAs where customers are charged a fixed or variable amount on an irregular schedule with no end date. |
|
|
Installment | Represents RBAs where customers are charged a fixed amount on a fixed schedule with a defined end date. |
|
|
RBA plan information
Set RBA plan information to present customers with a key information summary about their recurring billing agreement during PayPal Checkout. This increases conversion by maintaining customer confidence about the agreement terms.
Integration requirements
Pass RBA plan information only during payment token creation for customer visibility during PayPal Checkout. Exclude RBA information in subsequent merchant-initiated payment requests.
PayPal's RBA plan information structure supports simple to complex multi-tier arrangements through the purchase_units.items.billing_plan
object in the Create Order API call.
Field description
The following table shows the parameters to pass to the Orders v2 API to configure the checkout experience for customers.
What to pass | Payer experience | Ideal scenario | Example |
|
PayPal displays the new Review Your Payment layout showing plan details, billing cycles, plan name, item amount, amount breakdown including shipping and taxes, and recurring indicator during payment method token creation. | Use this to display plan information at checkout, especially in recurring billing scenarios. | Consumer purchases a phone and subscribes to a $8.99/month phone plan starting today. |
|
Not supported because at least one billing cycle is required for RBA. | N/A | N/A |
|
PayPal displays the standard checkout experience without recurring payment indicators. | Use this configuration for one-time transactions only. Do not use it for recurring payments. | Consumer pays for their trip on a ride-share app. |
RBA data structure
The RBA plan contains three components: plan name, billing cycle information, and one-time charges. Pass this data using purchase_units.items[]
, purchase_units.items[].billing_plan
, and payment_source.paypal.attributes.vault
objects. See the following table for product field reference.
Field name | Description | Example |
Plan name |
|
VidStream offers a $10/month streaming service plan with internal reference US-HDMNTH. When initiating PayPal Checkout, VidStream sets purchase_units.items.billing_plan.name to HD Premium - Monthly Plan. |
Billing cycles |
|
|
One-time charges |
Use one-time charges to communicate certain fees that don't form part of the ongoing recurring payment arrangement. Pass information about non-recurring charges that customers incur when they initiate their recurring payment arrangement. For example, use one-time charges to communicate:
|
|
Pass all information using paypal.attributes.vault
, purchase_units.items[]
, purchase_units.items[].billing_plan
, purchase_units.amount
, and purchase_units.amount.breakdown
.
Implementation requirements
See the following requirements when implementing RBA plan information.
Data structure requirements:
-
Use only one item with
billing_plan
. Multiple billing plans are not supported. -
Set item name to
Billing Plan
to differentiate from actual products.
Billing cycle requirements:
- Include at least 1 regular tenure type in billing cycles.
-
Do not pass
start_date
inbilling_plan.billing_cycles
if you want the billing plan to start on the same day it was created.
Amount calculation:
- Add the plan price to the total order amount if the plan starts on the same day as the payment token creation.
RBA plan data fields
Use these fields to structure your recurring billing plan data and communicate plan details to customers during checkout.
Plan name
The plan name is an optional description of the product or service customers purchase using the plan name field.
Use the field purchase_units.items.billing_plan.name
to set this value.
See the following table for product field reference.
Data element | Field name | Length | Type | Priority |
Plane name | purchase_units.items[].billing_plan.name |
127 characters | string | Mandatory |
Product details
Pair a product with your billing plan. For example, customers can purchase an iPhone and a Verizon phone plan together.
Add a new item in purchase_units.items[]
to specify product details such as name, description, and quantity. You can also specify the product price by referring to the one-time charges section for pricing details.
See the following table for product field reference.
Data element | Description | Field name | Length | Type | Priority |
Product description | Defines the description of the product associated with the RBA. | purchase_units.items[].name |
127 characters | string | Mandatory if the product is present in the cart. |
Product quantity | Defines the quantity of the product associated with the RBA. | purchase_units.items[].quantity |
32 characters | string | Mandatory if the product is present in the cart. |
Recurring billing cycle charges
Billing cycles define attributes for amount and duration in your recurring payment arrangement. Most arrangements use 1 or 2 billing cycles, but PayPal supports up to 3 billing cycles for complex arrangements.
Use the field purchase_units.items.billing_plan.billing_cycles
to configure billing cycles.
Add purchase_units.items.billing_plan.billing_cycles.pricing_scheme.price
to the total unit amount of the billing plan item when your plan starts on the same day as creation.
See the following table for billing cycle field reference:
Data element | Description | Field name | Type and values | Priority |
Billing cycle sequence number | The unique sequence number for each billing cycle when the RBA includes multiple billing cycles. | purchase_units.items[].billing_plan.billing_cycles.sequence |
integer
|
Optional
|
Billing cycle type | This indicates whether this is a trial cycle or a regular cycle. | purchase_units.items[].billing_plan.billing_cycles.tenure_type |
enum
|
You need at least one tenure type. |
Pricing scheme | Pricing parameters for the billing cycle. | purchase_units.items[].billing_plan.billing_cycles.pricing_scheme |
enum
|
|
Pricing model | Price model for the billing cycle. | purchase_units.items[].billing_plan.billing_cycles.pricing_scheme.pricing_model |
enum
|
Mandatory |
Price | Price amount for the billing cycle. | purchase_units.items[].billing_plan.billing_cycles.pricing_scheme.pricing_model.price.value |
integer or decimal | Mandatory |
Price currency code | Currency code for the price amount. | purchase_units.items[].billing_plan.billing_cycles.pricing_scheme.pricing_model.price.currency_code |
string |
Mandatory |
Reload threshold amount | Threshold amount that triggers a reload for auto-reload Unscheduled Card on File (UCOF) arrangements. | purchase_units.items[].billing_plan.billing_cycles.reload_threshold_amount.value |
integer or decimal |
Optional
|
Reload threshold amount currency code | Currency code for the reload threshold amount in auto-reload UCOF arrangements. | purchase_units.items[].billing_plan.billing_cycles.reload_threshold_amount.currency_code |
string |
Optional
|
Billing cycle frequency unit | Time unit for the frequency count. | purchase_units.items[].billing_plan.billing_cycles.billing_frequency_unit |
enum
|
Mandatory for all usage patterns except |
Billing cycle frequency count | Duration of the billing cycle using the frequency unit. | purchase_units.items[].billing_plan.billing_cycles.billing_frequency |
integer
|
Maximum values:
|
Expected billing cycles count | Number of times the billing cycle runs. | purchase_units.items[].billing_plan.billing_cycles.number_of_executions |
integer
|
Mandatory
|
Start date | Start date for the billing cycle. | purchase_units.items[].billing_plan.billing_cycles.start_date |
string
|
Optional
|
Setup fee configuration
One-time charges communicate information about non-recurring fees that customers pay when starting RBA. These might include setup costs or similar initial expenses.
Pass setup fee information using the field purchase_units.shipping.items.billing_plan.setup_fee
. If the billing plan is Item[0]
, add the setup fee to the total unit amount in items[0].unit_amount.value
. See the following table for product field reference.
Data element | Description | Field name | Type and values | Priority |
Setup fee | One-time fee charged to customers when they first establish their recurring billing arrangement. | purchase_units.items[].billing_plan.setup_fee.value |
integer or decimal | Optional |
Setup fee currency code | Currency code for the setup fee amount. | purchase_units.items[].billing_plan.setup_fee.currency_code |
string |
Optional |
Product purchases
Include product information when customers purchase physical products alongside their recurring billing plan, such as buying a mobile phone while signing up for a wireless service plan.
Add products using the items[]
in purchase_unit
as a separate item from the billing plan. For example, if the billing plan item is items[0]
, this should be items[1]
.
Important limitations:
- Recurring billing supports only one product item.
- Do not use multiple product items.
- Include the
unit_amount
field in the total amount breakdown inpurchase_units.amount.breakdown
asitem_total
, including any billing plan amount fields such as setup fees or plan prices.
Product purchase fields
For detailed amount information, such as shipping and taxes, use purchase_units.amount.breakdown.shipping
and purchase_units.amount.breakdown.tax_total
.
See the following table for product field reference.
Data element | Description | Field | Type and values | Priority |
Product price | The price of the product that customers purchase alongside the billing plan, such as a phone bought with a wireless service plan. For multiple quantity products, specify unit_amount with item quantity. |
purchase_units.items[].unit_amount.value |
integer or decimal | Required if the merchant’s cart contains a product. |
Product price currency code | Currency code for the product price. | purchase_units.items[].unit_amount.currency_code |
string
|
Required if the merchant’s cart contains a product. |
Order amount breakdown
For detailed amount information such as shipping and taxes, use purchase_units.amount.breakdown.shipping
and purchase_units.amount.breakdown.tax_total
.
handling
, insurance
, discount
, and shipping_discount
are not supported for recurring purchases.
Data element | Description | Field name | Type and values | Priority |
Shipping fee | The shipping fee for all items within a given purchase_unit.shipping.value can not be a negative number. |
purchase_units.amount.breakdown.shipping.value |
string
|
Optional |
Shipping fee currency code | The three-character ISO-4217 currency code that identifies the currency. | purchase_units.amount.breakdown.shipping.currency_code |
string | Optional |
Taxes | The total tax for all items. Required if the request includes purchase_units.items.tax. Must equal the sum of (items[].tax * items[].quantity ) for all items. The tax_total.value can not be a negative number. |
purchase_units.amount.breakdown.tax_total.value |
string | Optional |
Tax currency code | The three-character ISO-4217 currency code that identifies the currency. | purchase_units.amount.breakdown.tax_total.currency_code |
string | Optional |
Total amount | The value, which might be: An integer for currencies like JPY that are not typically fractional.A decimal fraction for currencies like TND that are subdivided into thousandths. For the required number of decimal places for a currency code, see Currency Codes. |
purchase_units.amount.value |
string |
Mandatory
|
Total currency code | The three-character ISO-4217 currency code that identifies the currency. | purchase_units.amount.currency_code |
string | Mandatory |
Payment token configuration
Use the following attributes to create the payment token. This is a prerequisite for RBA plan metadata.
Object: payment_source.paypal.attributes.vault
The following sample code shows the required attributes for payment token vaulting.
1"store_in_vault": "ON_SUCCESS", //To create a vaulted token2 "usage_type": "MERCHANT", //Merchant or Platform3 "usage_pattern": "SUBSCRIPTION_POSTPAID", //Recurring Indicator
See the following table for payment token configuration field reference.
Data element | Description | Field name | Type and values | Priority |
store_in_vault |
Vaulting instruction that creates a payment token only when at least one authorization or capture using that payment_source succeeds. |
payment_source.paypal.attributes.vault.store_in_vault |
enum
|
Mandatory for vaulting use cases. |
usage_type |
Identifies the person or party who initiated the payment. Use MERCHANT if the payment token will be used by the merchant directly. Use PLATFORM for future transactions on a platform such as a marketplace where customers can purchase from multiple merchants. |
payment_source.paypal.attributes.vault.usage_type |
enum
|
Mandatory for vaulting use cases. |
usage_pattern |
Pricing model of the payment token that determines the recurring billing experience. | paypal.attributes.vault.usage_pattern |
enum
|
Mandatory for a new RBA. |
Common use cases
The use cases show common recurring billing scenarios using the Create Order API with different use cases and configurations.
- Supported APIs: Create Order API
-
Supported intents:
Capture
andAuthorize
Use case: Subscription
In this scenario, the consumer subscribes to a $5.00/month plan, starting today, and purchases an iPhone.
- Request payload
- Response
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/2-H "Content-Type: application/json"3-H "Authorization: Bearer ACCESS_TOKEN"4-d '{5 "intent": "CAPTURE",6 "purchase_units": [7 {8 "amount": {9 "currency_code": "USD",10 "value": "238",11 "breakdown": {12 "item_total": {13 "currency_code": "USD",14 "value": "215"15 },16 "shipping": {17 "currency_code": "USD",18 "value": "3"19 },20 "tax_total": {21 "currency_code": "USD",22 "value": "20"23 }24 }25 },26 "items": [27 {28 "name": "iPhone 13",29 "description": "iPhone 13 with Verizon plan",30 "sku": "259483234816",31 "unit_amount": {32 "currency_code": "USD",33 "value": "200"34 },35 "tax": {36 "currency_code": "USD",37 "value": "20"38 },39 "quantity": "1",40 "category": "DIGITAL_GOODS"41 },42 {43 "name": "Billing Plan",44 "description": "Billing plan for subscriptions",45 "unit_amount": {46 "currency_code": "USD",47 "value": "15"48 },49 "quantity": "1",50 "billing_plan": {51 "name": "Verizon",52 "setup_fee": {53 "value": "10",54 "currency_code": "USD"55 },56 "billing_cycles": [57 {58 "tenure_type": "REGULAR",59 "pricing_scheme": {60 "price": {61 "value": "5",62 "currency_code": "USD"63 },64 "pricing_model": "FIXED"65 },66 "frequency": {67 "interval_unit": "MONTH",68 "interval_count": 169 },70 "total_cycles": 0,71 "sequence": 172 }73 ]74 }75 ]76 }77 ],78 "payment_source": {79 "paypal": {80 "attributes": {81 "vault": {82 "store_in_vault": "ON_SUCCESS",83 "usage_type": "MERCHANT",84 "usage_pattern": "SUBSCRIPTION_PREPAID"85 }86 },87 "experience_context": {88 "return_url": "https://example.com/returnUrl",89 "cancel_url": "https://example.com/cancelUrl"90 }91 }92 }93 }94 }'
Use case: Subscription with trial
In this scenario, the consumer subscribes to a $10/month plan with a 7-day free trial.
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/2-H "Content-Type: application/json"3-H "Authorization: Bearer ACCESS_TOKEN"4-d '{5 "intent": "CAPTURE",6 "purchase_units": [7 {8 "amount": {9 "currency_code": "USD",10 "value": "10"11 },12 "items": [1314 {15 "name": "Billing Plan",16 "description": "Billing plan for subscriptions",1718 "unit_amount": {19 "currency_code": "USD",20 "value": "10"21 },22 "quantity": "1",23 "billing_plan": {2425 "name": "Verizon Subscription",26 "setup_fee": {27 "value": "10",28 "currency_code": "USD"29 },30 "billing_cycles": [31 {32 "tenure_type": "TRIAL",33 "pricing_scheme": {34 "price": {35 "value": "5",36 "currency_code": "USD"37 },38 "pricing_model": "FIXED"39 },40 "frequency": {41 "interval_unit": "DAY",42 "interval_count": 743 },44 "sequence": 1,45 "start_date": "2024-01-21"46 }47 ]48 }49 ]50 ]51 }52 ],53 "payment_source": {54 "paypal": {55 "attributes": {56 "vault": {57 "store_in_vault": "ON_SUCCESS",58 "usage_type": "MERCHANT",59 "usage_pattern": "SUBSCRIPTION_PREPAID"6061 }62 },63 "experience_context": {64 "return_url": "https://example.com/returnUrl",65 "cancel_url": "https://example.com/cancelUrl"66 }67 }68 }69 }70 }'
Use case: Subscription start date and one-time setup fee
In this scenario, the consumer subscribes to a $5.00/month plan and a one-time setup charge of $10.00 with a future start date.
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/2-H "Content-Type: application/json"3-H "Authorization: Bearer ACCESS_TOKEN"4-d '{5 "intent": "CAPTURE",6 "purchase_units": [7 {8 "amount": {9 "currency_code": "USD",10 "value": "10"11 },12 "items": [{13 "unit_amount": {14 "currency_code": "USD",15 "value": "10"16 },17 "quantity": "1",18 "billing_plan": {1920 "name": "Verizon Subscription",21 "setup_fee": {22 "value": "10",23 "currency_code": "USD"24 },25 "billing_cycles": [26 {27 "tenure_type": "REGULAR",28 "pricing_scheme": {29 "price": {30 "value": "5",31 "currency_code": "USD"32 },33 "pricing_model": "FIXED"34 },35 "frequency": {36 "interval_unit": "DAY",37 "interval_count": 738 },39 "sequence": 1,40 "start_date": "2024-01-21"41 }42 ]43 }44 ]45 ]46 }47 ],48 "payment_source": {49 "paypal": {50 "attributes": {51 "vault": {52 "store_in_vault": "ON_SUCCESS", //To create a vaulted token53 "usage_type": "MERCHANT", //Merchant or Customer54 "usage_pattern": "SUBSCRIPTION_PREPAID", //Recurring Indicator5556 }57 },58 "experience_context": {59 "return_url": "https://example.com/returnUrl",60 "cancel_url": "https://example.com/cancelUrl"61 }62 }63 }64 }65 }'
Use case: Default subscription
In this scenario, the consumer creates a subscription of $6.99 for their Netflix plan starting today.
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/2-H "Content-Type: application/json"3-H "Authorization: Bearer ACCESS_TOKEN"4-d '{5 "intent": "CAPTURE",6 "payment_source": {7 "paypal": {8 "attributes": {9 "vault": {10 "store_in_vault": "ON_SUCCESS",11 "usage_type": "MERCHANT",12 "usage_pattern": "SUBSCRIPTION_PREPAID"13 },14 "experience_context": {15 "landing_page": "LOGIN",16 "user_action": "PAY_NOW",17 "email_address": "buyer@example.com",18 "return_url": "https://example.com/returnUrl",19 "cancel_url": "https://example.com/cancelUrl"20 }21 }22 }23 },24 "purchase_units": [25 {26 "items": [27 {28 "name": "Netflix subscription plan",29 "description": "Netflix subscription plan. Paid Monthly",30 "sku": "259483234816",31 "unit_amount": {32 "currency_code": "USD",33 "value": "6.99"34 },35 "quantity": "1",36 "category": "DIGITAL_GOODS",37 "billing_plan": {38 "billing_cycles": [39 {40 "tenure_type": "REGULAR",41 "pricing_scheme": {42 "price": {43 "value": "6.99",44 "currency_code": "USD"45 },46 "pricing_model": "FIXED"47 },48 "frequency": {49 "interval_unit": "MONTH",50 "interval_count": 151 },52 "total_cycles": 0,53 "sequence": 154 }55 ]56 }57 }58 ],59 "amount": {60 "currency_code": "USD",61 "value": "6.99",62 "breakdown": {63 "item_total": {64 "currency_code": "USD",65 "value": "6.99"66 }67 }68 }69 }70 ]71}'
Use case: Subscription with early cancellation fees
In this scenario, the customer receives a fee if they decide to cancel the subscription early.
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/2-H "Content-Type: application/json"3-H "Authorization: Bearer ACCESS_TOKEN"4-d '{5 "intent": "CAPTURE",6 "payment_source": {7 "paypal": {8 "attributes": {9 "vault": {10 "store_in_vault": "ON_SUCCESS",11 "usage_type": "MERCHANT",12 "usage_pattern": "SUBSCRIPTION_POSTPAID"13 },14 "experience_context": {15 "landing_page": "LOGIN",16 "user_action": "PAY_NOW",17 "email_address": "buyer@example.com",18 "return_url": "https://example.com/returnUrl",19 "cancel_url": "https://example.com/cancelUrl"20 }21 }22 }23 },24 "purchase_units": [25 {26 "items": [27 {28 "name": "Adobe subscription plan",29 "description": "Adobe postpaid subscription plan. Paid Monthly",30 "sku": "259483234816",31 "unit_amount": {32 "currency_code": "USD",33 "value": "6.99"34 },35 "quantity": "1",36 "category": "DIGITAL_GOODS",37 "billing_plan": {38 "billing_cycles": [39 {40 "tenure_type": "REGULAR",41 "pricing_scheme": {42 "price": {43 "value": "6.99",44 "currency_code": "USD"45 },46 "pricing_model": "FIXED"47 },48 "frequency": {49 "interval_unit": "MONTH",50 "interval_count": 151 },52 "total_cycles": 0,53 "sequence": 154 }55 ]56 }57 }58 ],59 "amount": {60 "currency_code": "USD",61 "value": "6.99",62 "breakdown": {63 "item_total": {64 "currency_code": "USD",65 "value": "6.99"66 }67 }68 }69 }70 ]71}72'
Use case: Subscription with multiple rates
In this scenario, the subscription price changes after a certain number of months.
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/2-H "Content-Type: application/json"3-H "Authorization: Bearer ACCESS_TOKEN"4-d '{5 "intent": "CAPTURE",6 "payment_source": {7 "paypal": {8 "attributes": {9 "vault": {10 "store_in_vault": "ON_SUCCESS",11 "usage_type": "MERCHANT",12 "usage_pattern": "INSTALLMENT_PREPAID"13 },14 "experience_context": {15 "landing_page": "LOGIN",16 "user_action": "PAY_NOW",17 "email_address": "buyer@example.com",18 "return_url": "https://example.com/returnUrl",19 "cancel_url": "https://example.com/cancelUrl"20 }21 }22 }23 },24 "purchase_units": [25 {26 "items": [27 {28 "name": "Best Buy subscription plan",29 "description": "Best Buy subscription plan with varied rates",30 "sku": "2594832348",31 "unit_amount": {32 "currency_code": "USD",33 "value": "8.99"34 },35 "quantity": "1",36 "category": "DIGITAL_GOODS",37 "billing_plan": {38 "billing_cycles": [39 {40 "tenure_type": "TRIAL",41 "pricing_scheme": {42 "price": {43 "value": "8.99",44 "currency_code": "USD"45 },46 "pricing_model": "FIXED"47 },48 "frequency": {49 "interval_unit": "MONTH",50 "interval_count": 151 },52 "total_cycles": 3,53 "sequence": 154 },55 {56 "tenure_type": "REGULAR",57 "pricing_scheme": {58 "price": {59 "value": "11.99",60 "currency_code": "USD"61 },62 "pricing_model": "FIXED"63 },64 "frequency": {65 "interval_unit": "MONTH",66 "interval_count": 167 },68 "total_cycles": 0,69 "sequence": 2,70 "start_date": "2024-07-16"71 }72 ]73 }74 }75 ],76 "amount": {77 "currency_code": "USD",78 "value": "8.99",79 "breakdown": {80 "item_total": {81 "currency_code": "USD",82 "value": "8.99"83 }84 }85 }86 }87 ]88}'
Use case: Consumer creates auto-reload plan
In this scenario, the consumer creates an auto-reload plan for their coffee program prepaid card. The system reloads $25 every time their prepaid card balance drops below $10.
1{2 "intent": "CAPTURE",3 "payment_source": {4 "paypal": {5 "attributes": {6 "vault": {7 "store_in_vault": "ON_SUCCESS",8 "usage_type": "MERCHANT",9 "usage_pattern": "UNSCHEDULED_PREPAID"10 },11 "experience_context": {12 "landing_page": "LOGIN",13 "user_action": "PAY_NOW",14 "email_address": "buyer@example.com",15 "return_url": "https://example.com/returnUrl",16 "cancel_url": "https://example.com/cancelUrl"17 }18 }19 }20 },21 "purchase_units": [22 {23 "items": [24 {25 "name": "Starbucks subscription plan",26 "description": "Starbucks subscription plan with auto reload",27 "sku": "259483234",28 "unit_amount": {29 "currency_code": "USD",30 "value": "25"31 },32 "quantity": "1",33 "category": "DIGITAL_GOODS",34 "billing_plan": {35 "billing_cycles": [36 {37 "tenure_type": "REGULAR",38 "pricing_scheme": {39 "price": {40 "value": "25",41 "currency_code": "USD"42 },43 "reload_threshold_amount": {44 "currency_code": "USD",45 "value": "10.0"46 },47 "pricing_model": "AUTO_RELOAD"48 },49 "frequency": {50 "interval_unit": "MONTH",51 "interval_count": 152 },53 "total_cycles": 0,54 "sequence": 1,55 "start_date": "2024-04-16"56 }57 ]58 }59 }60 ],61 "amount": {62 "currency_code": "USD",63 "value": "25",64 "breakdown": {65 "item_total": {66 "currency_code": "USD",67 "value": "25"68 }69 }70 }71 }72 ]73}
Process recurring payments
Use the payment method token created as an output to charge customers for recurring payments.
Call the Order endpoint of the Orders v2 API with the payment_source
= paypal
object to process recurring charges. This API requires the following inputs:
-
Intent: Indicates whether to capture payment immediately or authorize it for later capture. Use
CAPTURE
for sale transactions andAUTHORIZE
for auth-capture. - Vault ID: The PayPal-generated ID for the saved payment token.
- Amount: The total order amount.
- Stored credential: Provides additional details for recurring transactions when processing payments with PayPal wallet vaulted payment methods.
Field name | Values | Description |
stored_credential.payment_initiator |
|
The person or party who initiated or triggered the payment. Use MERCHANT for merchant-initiated transactions where the payer is not present and CUSTOMER for payer-present scenarios. (Mandatory) |
stored_credential.usage |
|
The following values specify the payment sequence:
|
stored_credential.usage_pattern |
|
Defines the billing pattern for stored payments. |
Stored credential
Use the following structure to process recurring payments with stored payment methods.
1"stored_credential": {2 "payment_initiator": "MERCHANT",3 "usage": "SUBSEQUENT",4 "usage_pattern": "SUBSCRIPTION_PREPAID"5 }
Complete request payload
Include the stored credential object in the Orders v2 API request to charge customers for recurring payments. The usage pattern is optional for subsequent transactions. Include it only if you want to change the pattern from when you originally created the subscription.
Authorize prepaid subscription payments
Include the stored credential object in the Orders v2 API request to process recurring subscription payments.
- Request
- Response
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/checkout/orders/2-H "Content-Type: application/json"3-H "Authorization: Bearer ACCESS_TOKEN"4-d '{5 "intent": "CAPTURE",6 "purchase_units": [7 {8 "description": "HD Premium Plan",9 "invoice_id": "test-invoice-id",10 "amount": {11 "currency_code": "USD",12 "value": "100.00"13 }14 }15 ],16 "payment_source": {17 "paypal": {18 "vault_id": "VAULT-ID",19 "stored_credential": {20 "payment_initiator": "MERCHANT",21 "usage": "SUBSEQUENT",22 "usage_pattern": "SUBSCRIPTION_PREPAID"23 }24 }25 }26 }27}'
For multi-step Order API integrations, include stored_credential
information in Capture, Authorize, and Confirm API calls.
Error scenarios
Handle all HTTP failure codes in your implementation, including 4xx
client errors and 5xx
server errors. PayPal also returns 422 status codes for custom business logic errors, as shown in the subsequent transactions section.
Unsupported patterns
Your implementation must avoid the following patterns:
-
Do not pass multiple items in the
purchase_units.items[]
array. - Do not pass multiple purchase units in a single order.
-
Avoid
items[]
with billing plan quantities greater than 1. - Use single-step order creation for recurring purchases.
- Multi-step processes are not supported.
- Include payment source information when creating orders.
- Do not use setup or product price fields in Confirm, Authorize, or Capture operations.
- Do not include billing plan data in patch operations.
Amount-related errors
-
Amount breakdown fields such as handling, discount, shipping discount, and insurance are not supported in
purchase_units.amount.breakdown
. -
When the billing plan start date matches the vaulted payment creation date and you include setup fees or product prices in your request, add these amounts to
items[].unit_amount
and include the total inpurchase_units.amount.value
. -
PayPal validates that shipping, tax, and unit amounts add up to
purchase_units.amount.value
. Be sure to include separate values for these amounts inpurchase_units.amount.breakdown
.
PayPal does not support the following amount breakdown fields in purchase_units.amount.breakdown
: handling, discount, shipping discount, and insurance.
- When the billing plan start date matches the vaulted payment creation date and you include setup fees or product prices in your request, add these amounts to
items[].unit_amount
and include the total inpurchase_units.amount.value
. -
PayPal validates that shipping, tax, and unit amounts add up to
purchase_units.amount.value
. Be sure to include separate values for these amounts inpurchase_units.amount.breakdown
.
API execution
Use a single step order creation process to pass the payment source information with billing plan details in the create order request.
Billing plan specifications
Review these billing plan requirements to ensure your integration handles recurring payments correctly and avoids common configuration errors.
Usage pattern | Supported | Auto reload support | Trial billing cycle | Notes |
SUBSCRIPTION |
Requires at least one regular billing cycle. | |||
RECURRING |
Requires at least one regular billing cycle. | |||
INSTALLMENT |
Requires at least one regular billing cycle. | |||
UNSCHEDULED_PREPAID |
Supports auto reload. | |||
UNSCHEDULED_POSTPAID |
Supports auto reload. |
Subsequent transactions
The following sample code shows a common 422
error that occurs when required vault credentials are missing from a subsequent transaction request.
1{2 "title": "Create Order - 422 Unprocessable Entity Error - Missing Required parameter - Billing_Agreement_Id or Vault_Id with PayPal wallet stored credentials",3 "description": "This code sample attempts to create an order with PayPal wallet stored credentials but it does not contain a valid billing agreement id or a vault id. The request fails.",4 "runnable": true,5 "operationId": "orders.create",6 "request": {7 "method": "POST",8 "path": "v2/checkout/orders",9 "headers": {10 "Content-Type": "application/json",11 "Authorization": "Bearer ACCESS-TOKEN"12 },13 "body": {14 "intent": "CAPTURE",15 "purchase_units": [16 {17 "reference_id": "PUHF",18 "amount": {19 "currency_code": "USD",20 "value": "10.00"21 }22 }23 ],24 "payment_source": {25 "paypal": {26 "paypal": {27 "stored_credential": {28 "payment_initiator": "MERCHANT",29 "usage": "SUBSEQUENT",30 "usage_pattern": "SUBSCRIPTION_PREPAID"31 }32 }33 }34 }35 }36 },37 "response": {38 "status": "422 Unprocessable Entity",39 "headers": {40 "Content-Type": "application/json"41 },42 "body": {43 "name": "UNPROCESSABLE_ENTITY",44 "message": "Request is not well-formed, syntactically incorrect, or violates schema.",45 "debug_id": "10398537340c8",46 "details": [47 {48 "field": "/payment_source/paypal/vault_id",49 "location": "body",50 "issue": "PAYPAL_STORED_CREDENTIAL_MISSING_REQUIRED_PARAMETER",51 "description": "A 'billing_agreement_id' or 'vault_id' is required for the recurring billing scenario when the merchant uses payment_source.paypal.stored_credential."52 }53 ],54 "links": [55 {56 "href": "https://developer.paypal.com/docs/api/orders/v2/#error-PAYPAL_STORED_CREDENTIAL_MISSING_REQUIRED_PARAMETER",57 "rel": "information_link"58 }59 ]60 }61 }62}