Vaulted payments
You can set up vaulted payments to:
- Save the payer’s PayPal payment method credentials for future transactions without processing an immediate payment.
- Set up recurring payments.
This guide explains how to use the Braintree GraphQL APIs to integrate PayPal vaulted payments into your application. Use this integration to:
- Provide faster payment processing for returning customers.
- Set up payment processing for subscriptions.
- Set up recurring billing (for example, automatic top-up or usage-based charges).
Workflow
The following diagram illustrates the process to create PayPal vaulted payments flow.

Create PayPal billing agreement
In your server-side code, use the
createPayPalBillingAgreement
mutation, as shown in the following sample, to initiate a PayPal billing agreement. Pass the following input fields and their values:
returnUrl: The URL to which the payer is redirected after payer authentication, to approve the billing agreement.cancelUrl: The URL to which the payer is redirected if they cancel the billing agreement.
returnUrl and cancelUrl use an approved hostname (such as, *.braintreegateway.com) and are HTTPS URLs.
On successful processing of createPayPalBillingAgreement, Braintree
generates and sends an approval URL to your server. In your client-side code,
use the approval URL to redirect the payer to PayPal to authenticate and
authorize the billing agreement.
API Reference: createPayPalBillingAgreement
- Mutation
mutation CreatePayPalBillingAgreement(
$input: CreatePayPalBillingAgreementInput!
) {
createPayPalBillingAgreement(input: $input) {
billingAgreementToken
approvalUrl
}
}- Variables
{
"input": {
"merchantAccountId": "merchant_account_id",
"returnUrl": "https://merchant_domain_name/paypal/returnURL",
"cancelUrl": "https://merchant_domain_name/paypal/cancelURL"
}
}- Variables
{
"input": {
"merchantAccountId": "merchant_account_id",
"returnUrl": "https://merchant_domain_name/paypal/returnURL",
"cancelUrl": "https://merchant_domain_name/paypal/cancelURL",
"paypalExperienceProfile": {
"collectShippingAddress": true,
"shippingAddressEditable": false,
"brandName": "Empire Co.",
"landingPageType": "DEFAULT",
"locale": "en-US"
}
}
}- Response
{
"data": {
"createPayPalBillingAgreement": {
"billingAgreementToken": "BA-9BJ56481CY242831B",
"approvalUrl": "https://www.paypal.com/agreements/approve?ba_token=BA-9BJ56481CY242831B"
}
}
}Create transaction risk context
You can use the
createTransactionRiskContext
mutation to pass supplementary risk-related data to PayPal and create a transaction risk context that helps in risk management. On successful processing of createTransactionRiskContext, PayPal returns a clientMetadataId and a paypalRiskCorrelationId.
Pass the clientMetadataId in the chargePaymentMethod mutation > riskData.deviceData.correlation_id.
- Mutation
mutation CreateTransactionRiskContext(
$input: CreateTransactionRiskContextInput!
) {
createTransactionRiskContext(input: $input) {
clientMetadataId
paypalRiskCorrelationId
}
}- Variables
{
"input": {
"riskContext": {
"fields": [
{
"name": "sender_account_id",
"value": "xyz123"
},
{
"name": "txn_count_total",
"value": "15987"
}
]
}
}
}- Response
{
"data": {
"createTransactionRiskContext": {
"clientMetadataId": "01e59aa07d2187e13b1bf9cf42a45596",
"paypalRiskCorrelationId": "01e59aa07d2187e13b1bf9cf42a45596"
}
}
}Send payers to PayPal to approve billing agreement
From your server-side code, send the approval URL returned in the createPayPalBillingAgreement response to your client-side code. In your client-side code, include the logic to redirect payers to the PayPal site where they can authorize the billing agreement. After the payer authorizes the billing agreement on the PayPal site:
- Payers are redirected to your
returnUrl. - payment ID, payer ID, and payment token values are sent to the
onApprovecallback function in your server-side code.
Tokenize PayPal billing agreement
In your server-side code's onApprove callback function, use the
tokenizePayPalBillingAgreement
mutation to convert the billing agreement into a tokenized payment method. Use the payment ID, payer ID, and payment token values received in the input payload of tokenizePayPalBillingAgreement.
On successful processing of tokenizePayPalBillingAgreement, Braintree/PayPal returns a paymentMethod.id that represents the tokenized payment method.
API Reference:
tokenizePayPalBillingAgreement
- Mutation
mutation TokenizePayPalBillingAgreement(
$input: TokenizePayPalBillingAgreementInput!
) {
tokenizePayPalBillingAgreement(input: $input) {
paymentMethod {
id
details {
payerId
selectedFinancingOption {
term
monthlyPayment {
currencyCode
value
}
}
}
}
}
}- Variables
{
"input": {
"merchantAccountId": "merchant_account_id",
"billingAgreement": {
"billingAgreementToken": "BA-9BJ56481CY242831B"
}
}
}- Response
{
"data": {
"tokenizePayPalBillingAgreement": {
"paymentMethod": {
"id": "tokencc_bj_hfqww2_rtyn7b_ggmjvs_6c9gd6_k9z",
"details": {
"payerId": "payer-id",
"selectedFinancingOption": {
"term": 12,
"monthlyPayment": {
"currencyCode": "GBP",
"value": "10.0"
}
}
}
}
}
}
}Vault payment method
After tokenization, the payment method can be stored in the vault. Vaulting the payment method creates a persistent record of the payer's PayPal account, allowing you to initiate transactions without the payer's direct involvement.
vaultPaymentMethod mutation, pass the paymentMethodId in the input object. The paymentMethodId is obtained from the tokenizePayPalBillingAgreement or tokenizePayPalOneTimePayment mutation.
API Reference:
vaultPaymentMethod.
- Mutation
mutation VaultPaymentMethod($input: VaultPaymentMethodInput!) {
vaultPaymentMethod(input: $input) {
paymentMethod {
id
customer {
id
}
}
verification {
id
status
}
}
}- Variables
{
"input": {
"paymentMethodId": "tokencc_bj_hfqww2_rtyn7b_ggmjvs_6c9gd6_k9z"
}
}- Response
{
"data": {
"vaultPaymentMethod": {
"paymentMethod": {
"id": "cGF5bWVudG1ldGhvZF9jY182dnB3a20y",
"customer": {
"id": "Y3VzdG9tZXJfNjc3MDI1NzI1"
}
},
"verification": {
"id": "dmVyaWZpY2F0aW9uXzliMHBhc2E3",
"status": "VERIFIED"
}
}
}
}Charge payment method
This final step uses the vaulted payment method to initiate a payment. In your server-side code, use the
chargePaymentMethod
mutation, referencing the vaulted payment method's ID and providing the transaction details.
clientMetadataId returned from the createTransactionRiskContext mutation in the chargePaymentMethod mutation > riskData.deviceData.correlation_id.
API Reference:
chargePaymentMethod
- Mutation
mutation ChargePaymentMethod($input: ChargePaymentMethodInput!) {
chargePaymentMethod(input: $input) {
transaction {
id
status
}
}
}- Variables
{
"input": {
"paymentMethodId": "cGF5bWVudG1ldGhvZF9jY182dnB3a20y",
"transaction": {
"amount": "10.00",
"merchantAccountId": "canvaAU-AUD",
"paymentInitiator": "RECURRING",
"riskData": {
"deviceData": "{\"correlation_id\": \"01e59aa07d2187e13b1bf9cf42a45596\"}"
}
}
}
}- Response
{
"data": {
"chargePaymentMethod": {
"transaction": {
"id": "dHJhbnNhY3Rpb25fZzVmNDY2djE",
"status": "SETTLING"
}
}
}
}