Save Payments

SDK

Last updated: Aug 1st, 11:24am

This guide walks you through integrating PayPal's Vault Without Payment flow using the Web SDK v6. This flow allows you to save (or “vault”) a user’s PayPal account for future payments — without charging them immediately.

When a user approves the save, PayPal returns a vault setup token, which your backend exchanges for a payment token. You can then store this token securely and use it later to initiate payments at your discretion — no further user interaction required at the time of payment.

This approach is ideal for:

  • Subscription onboarding

  • Deferred billing

  • "One-click" future purchases

In this guide, you'll:

  • Load the PayPal Web SDK v6

  • Allow the user to approve vaulting their PayPal account

  • Exchange setup tokens for reusable payment tokens

  • Prepare your system to charge the user at a later date

No money is collected during the vaulting step — the user simply gives permission for future charges.

Start with your index.html

This HTML file provides the basic structure for the PayPal vaulting integration. It includes a custom element, which serves as the placeholder for the PayPal button. The button is initially hidden and will only be shown if PayPal is determined to be an eligible payment method. At the bottom of the file, the PayPal Web SDK v6 is loaded asynchronously. Once the SDK finishes loading, it automatically calls the onPayPalLoaded function via the onload attribute, which kicks off the setup process for the integration.

    1<!doctype html>
    2<html lang="en">
    3 <head>
    4 <meta charset="UTF-8" />
    5 <title>Save Payment - PayPal Web SDK</title>
    6 <meta name="viewport" content="width=device-width, initial-scale=1" />
    7 <style>
    8 .buttons-container {
    9 display: flex;
    10 flex-direction: column;
    11 gap: 12px;
    12 }
    13 </style>
    14 </head>
    15 <body>
    16 <h1>Save Payment Recommended Integration</h1>
    17 <div class="buttons-container">
    18 <paypal-button id="paypal-button" hidden></paypal-button>
    19 </div>
    20
    21 <script src="app.js"></script>
    22 <script
    23 async
    24 src="https://www.sandbox.paypal.com/web-sdk/v6/core"
    25 onload="onPayPalLoaded()"
    26 ></script>
    27 </body>
    28</html>

    The code in your app.js file handles the core logic for initializing the PayPal SDK, checking eligibility, displaying the PayPal button, and managing the vaulting flow. It securely retrieves necessary tokens from your backend, starts the save-payment session when the user clicks the button, and handles approval, cancellation, and error events. This ensures a secure and seamless experience for saving a user's PayPal payment method for future use.

      1async function onPayPalLoaded() {
      2 try {
      3 const clientToken = await getBrowserSafeClientToken();
      4 const sdkInstance = await window.paypal.createInstance({
      5 clientToken,
      6 components: ["paypal-payments"],
      7 pageType: "checkout",
      8 });
      9
      10 const paymentMethods = await sdkInstance.findEligibleMethods({
      11 currencyCode: "USD",
      12 paymentFlow: "VAULT_WITHOUT_PAYMENT",
      13 });
      14
      15 if (paymentMethods.isEligible("paypal")) {
      16 setupPayPalButton(sdkInstance);
      17 }
      18 } catch (error) {
      19 console.error(error);
      20 }
      21}
      22
      23const paymentSessionOptions = {
      24 async onApprove(data) {
      25 console.log("onApprove", data);
      26 const createPaymentTokenResponse = await createPaymentToken(
      27 data.vaultSetupToken,
      28 );
      29 console.log("Create payment token response: ", createPaymentTokenResponse);
      30 },
      31 onCancel(data) {
      32 console.log("onCancel", data);
      33 },
      34 onError(error) {
      35 console.log("onError", error);
      36 },
      37};
      38
      39async function setupPayPalButton(sdkInstance) {
      40 const paypalPaymentSession = sdkInstance.createPayPalSavePaymentSession(
      41 paymentSessionOptions,
      42 );
      43
      44 const paypalButton = document.querySelector("#paypal-button");
      45 paypalButton.removeAttribute("hidden");
      46
      47 paypalButton.addEventListener("click", async () => {
      48 try {
      49 await paypalPaymentSession.start(
      50 { presentationMode: "auto" },
      51 createSetupToken(),
      52 );
      53 } catch (error) {
      54 console.error(error);
      55 }
      56 });
      57}
      58
      59async function getBrowserSafeClientToken() {
      60 const response = await fetch("/paypal-api/auth/browser-safe-client-token", {
      61 method: "GET",
      62 headers: {
      63 "Content-Type": "application/json",
      64 },
      65 });
      66 const { accessToken } = await response.json();
      67
      68 return accessToken;
      69}
      70
      71async function createSetupToken() {
      72 const response = await fetch("/paypal-api/vault/setup-token/create", {
      73 method: "POST",
      74 headers: {
      75 "Content-Type": "application/json",
      76 },
      77 });
      78 const { id } = await response.json();
      79
      80 return { setupToken: id };
      81}
      82
      83async function createPaymentToken(vaultSetupToken) {
      84 const response = await fetch("/paypal-api/vault/payment-token/create", {
      85 method: "POST",
      86 headers: {
      87 "Content-Type": "application/json",
      88 },
      89 body: JSON.stringify({ vaultSetupToken }),
      90 });
      91 const data = await response.json();
      92
      93 return data;
      94}


      Below you will find a description of each function we are calling above to complete the flow. 

      Function/Constant Description
      onPayPalLoaded() Initializes the PayPal SDK once it's loaded. Fetches a client token, creates the SDK instance, checks for eligible payment methods, and sets up the PayPal button if applicable.
      clientToken A short-lived access token fetched from your backend. It authorizes the browser to safely use PayPal SDK features without exposing sensitive credentials.
      createInstance() The initialized PayPal SDK instance created using the clientToken. It is used to manage payment flows and UI components.
      findEligibleMethods()An API call which returns an object representing which PayPal methods are available for the current user and configuration (e.g. based on location or currency).
      paymentSessionOptionsYour callbacks you set up for various stages of the PayPal flow.
      setupPayPalButton(sdkInstance) Prepares and reveals the PayPal button. Attaches a click listener that starts the vaulting flow when clicked.
      createSetupToken() Sends a POST request to your backend to create a vault setup token, which represents the user's consent to save their payment method.
      createPaymentToken(vaultSetupToken) Sends a POST request to your backend to exchange a setup token for a reusable payment token. This token can be stored and used to charge the user later.

      Summary

      This guide covered how to integrate PayPal’s Web SDK v6 to securely vault a user’s PayPal account for future payments—without charging them at the time of save.

      If you’re looking for a complete end-to-end working example, including frontend and backend code, please visit our official GitHub examples repo here:

      PayPal Web SDK v6 - Save Payment Integration