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"
      }
    }
  }
}