Venmo

Client-Side Implementationanchor

Choose an integration methodanchor

You can set up your client-side either with our Drop-in UI or with a custom integration.

Drop-in integrationanchor

Our Drop-in UI is the fastest way to set up your client-side integration.

For full details, see Drop-in Setup and Integration.

Custom integrationanchor

Alternatively, you can add Venmo to your current custom integration. Keep in mind, for compliance purposes, we require you to present the customer with an order summary before and after purchase.

The pre-purchase summary should include:

  • The items ordered
  • The total order price
  • An indication of Venmo as the payment method

The post-purchase summary can either be shown in the UI or sent via email. It should include:

  • The items purchased
  • The total purchase price
  • The customer's name
  • The customer's Venmo username

Failing to comply with these guidelines can lead to an interruption of your Venmo service.

note

Click here to download Venmo's brand guidelines, and be sure to follow them when configuring the Venmo button or making any other references to Venmo in your app.

note

It's best practice to display the customer's Venmo username alongside their Venmo payment method in your checkout UI – like you would the last 4 digits of a credit card number.

Mobile and Desktop Browsersanchor

note

The Venmo desktop flows require version 3.88.4 or higher of the Braintree web SDK.

Mobile Experienceanchor

Venmo app-based authenticationanchor

For mobile, the default payment flow starts in the mobile web browser and switches to the Venmo app to authorize payment. After authorization, the app returns the customer to the browser and the SDK returns a payment method nonce. If the Venmo app is not installed, the customer will be directed to the Venmo website asking them to download the app.

Mobile Web Fallbackanchor

note

This flow currently requires a full page redirect, which means to utilize this flow your page will need to be able to handle the checkout session across different pages.

This configuration allows you to provide a web-based login experience for customers that don't have the Venmo app installed on their mobile device. When tokenization is initiated and the Venmo app is not installed, customers will see a popup to authenticate themselves by logging into their Venmo account.

To enable this, add the following parameter when creating the Venmo component:

  • mobileWebFallBack: true

Desktop Experienceanchor

Desktop Web Loginanchor

This configuration allows customers to pay with Venmo while using a desktop browser. When choosing to pay with Venmo, customers will be able to log in to their Venmo account directly on the web and authorize the payment.

The flow is kicked off by the tokenize call. A browser popup is opened with the Venmo web login page where customers can login to Venmo and authorize payment. Once authorized, the popup will close and the nonce payload will be retrieved.

To enable this, add the following parameter when creating the Venmo component:

If you are switching from the Desktop QR Code to Web Login, you should remove the following parameters as they will be ignored:

  • allowDesktop: true

Desktop QR Codeanchor

note

We strongly recommend using the Desktop Web Login flow instead of the Desktop QR Code flow as the former offers a better customer experience and improves conversion rates.

This configuration also allow customers to pay with Venmo while using a desktop browser. A QR code will display in a modal over the website which the customer must scan with their mobile device. When successfully scanned, the customer will be directed to authorize the payment in the Venmo app on their mobile device. Once authorized, a nonce will be returned to the browser on the desktop and the QR code will be dismissed.

To enable this, add the following parameter when creating the Venmo component:

  • allowDesktop: true

The allowDesktopWebLogin: true configuration takes precedence over allowDesktop: true, so when both are set, customers will see the Desktop Web Login flow instead of the Desktop QR Code flow.

Installationanchor

To set up the Braintree JavaScript v3 SDK, see the installation guide.

Then, load the venmo and data-collector components. If you are using script tags to load files, be sure to at least include:

  1. HTML
<script src="https://js.braintreegateway.com/web/3.111.0/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.111.0/js/venmo.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.111.0/js/data-collector.min.js"></script>

Initializationanchor

  1. Initialize a client using either a tokenization key or a client token from your server
  2. Create a Venmo component
  1. Callback
  2. Promise
// Create a client.
  braintree.client.create({
    authorization: CLIENT_AUTHORIZATION
  }, function (clientErr, clientInstance) {
    // Stop if there was a problem creating the client.
    // This could happen if there is a network error or if the authorization
    // is invalid.
    if (clientErr) {
      console.error('Error creating client:', clientErr);
      return;
    }

    // Create a Venmo component.
    braintree.venmo.create({
      client: clientInstance,
      allowDesktop: true,
      mobileWebFallBack: true,
      allowDesktopWebLogin: true,
      paymentMethodUsage: 'multi_use'
    }, function (venmoErr, venmoInstance) {

      // Stop if there was a problem creating Venmo.
      // This could happen if there was a network error or if it's incorrectly
      // configured.
      if (venmoErr) {
        console.error('Error creating Venmo:', venmoErr);
        return;
      }
      // ...
    });
  });

Verifying mobile browser supportanchor

note

Verifying browser support includes steps to detect webviews that could be problematic depending on your use case. See Webview Detection for more details.

Venmo is currently supported for most Android and iOS mobile web browsers. It does not support webviews.

When returning from the Venmo app, some mobile browsers can return customers to the same tab, while others relaunch your checkout page in a new tab. Each flow has tradeoffs:

  • Returning to the same tab is a more seamless user experience, but is only supported by iOS Safari and Android Chrome
  • Returning to a new tab is supported by most iOS and Android browsers, but may break the checkout flow for some integrations, such as single-page applications

To see which browsers and versions are supported, see Overview

To verify browser support:

  1. Determine if your checkout page supports returning to a new tab
    • If new tabs are supported, call hasTokenizationResult; if it returns true, call tokenize to receive the tokenization result immediately
    • If new tabs are not supported, pass allowNewBrowserTab as false when calling Venmo create
  2. Call isBrowserSupported to verify that the customer's browser supports Venmo
  3. For desktop flow support, set allowDesktop: true for the QR Code flow, or allowDesktopWebLogin: true for the Desktop Web Login flow.
  4. Show Venmo as a payment option if the browser is supported
  1. Callback
  2. Promise
var venmoButton = document.getElementById('venmo-button');

  braintree.venmo.create({
    client: clientInstance,
    allowDesktop: true,
    allowDesktopWebLogin: true,
    paymentMethodUsage: 'multi_use',
    mobileWebFallBack: true,
    // Add allowNewBrowserTab: false if your checkout page does not support
    // relaunching in a new tab when returning from the Venmo app. This can
    // be omitted otherwise.
    // allowNewBrowserTab: false
  }, function (venmoErr, venmoInstance) {
    if (venmoErr) {
      console.error('Error creating Venmo:', venmoErr);
      return;
    }

    // Verify browser support before proceeding.
    if (!venmoInstance.isBrowserSupported()) {
      console.log('Browser does not support Venmo');
      return;
    }

    displayVenmoButton(venmoInstance);

    // Check if tokenization results already exist. This occurs when your
    // checkout page is relaunched in a new tab. This step can be omitted
    // if allowNewBrowserTab is false.
    if (venmoInstance.hasTokenizationResult()) {
      venmoInstance.tokenize(function (tokenizeErr, payload) {
        if (err) {
          handleVenmoError(tokenizeErr);
        } else {
          handleVenmoSuccess(payload);
        }
      });
      return;
    }
  });

  function displayVenmoButton(venmoInstance) {
    // Assumes that venmoButton is initially display: none.
    venmoButton.style.display = 'block';

    venmoButton.addEventListener('click', function () {
      venmoButton.disabled = true;

      venmoInstance.tokenize(function (tokenizeErr, payload) {
        venmoButton.removeAttribute('disabled');

        // ...
      });

    });
  }

  function handleVenmoError(err) {
    // ...
  }

  function handleVenmoSuccess(payload) {
    // ...
  }
note

Click here to download Venmo's brand guidelines, and be sure to follow them when configuring the Venmo button or making any other references to Venmo in your app.

Webview Detectionanchor

There are scenarios in which current browser detection methods cannot detect certain mobile browser configurations.

The JS SDK uses user agents to try to detect which browsers can support Pay with Venmo. There are some scenarios where the SDK is unable to definitively determine whether an iOS browser environment is supported.

In iOS, the various browser environments are:

  • iOS Safari
  • Safari Webviews (including 3rd party browsers such as Chrome, Firefox)
  • In-App Browsers (also known as Safari View Controller)

If a web page is loaded from a third-party, native iOS application, and that third-party app uses an in-app browser to load your page, at present our SDK can not distinguish this from native browsers.

This is problematic because when your page is loaded within one of these webviews from a third-party app, and the Venmo app is automatically opened to authorize payment, there is no way for the Venmo app to return to your page within that third-party app. What occurs instead is that the Venmo native app is launched, payment is authorized, and the return to your page will instead be opened in a new tab on the customer's default native browser.

The context of the checkout experience that initiated the flow is still left in the third-party app's webview. If your checkout page can handle the session changing contexts this will still work as you'll still have the nonce and customer details, but it will move the customer to the native browser from where they originally started.

Additionally, this presents an issue if you want to avoid webviews entirely. If you set allowWebviews: false when creating the Venmo component there is a possibility of false-positives detected for browser support via isBrowserSupported. For example:

  1. JavaScript
braintree.venmo
    .create({
      client: clientInstance,
      allowWebviews: false,
    })
    .then(function (venmoInstance) {
      // ...
    });

Launching Venmo payment flowanchor

Mobileanchor

  1. Add a click event listener to the Venmo button that calls tokenize, which starts the payment flow.
    • The Venmo app must be installed to authorize payment; if it is not installed, tokenize opens a new browser tab with a Venmo landing page
      note

      Unlike with the iOS and Android integrations, it is not possible to determine if the Venmo app is installed on a device before displaying the Venmo button and initiating the flow.

  2. If the app is installed, the customer will be prompted to authorize the payment
  3. Upon completion, the app returns to the checkout page in the browser.

Desktop QR flow:anchor

  1. Add a click event listener to the Venmo button that calls tokenize, which starts the payment flow.
    • The Venmo app must be installed on the device scanning the QR code; if it is not installed, scanning the QR code opens a new browser tab with a Venmo landing page.
  2. If the app is installed, the customer will be prompted to authorize the payment.

Desktop Web Login flow:anchor

  1. Add a click event listener to the Venmo button that calls tokenize, which starts the payment flow.
    • This will open a browser popup to the Venmo login page.
  2. The customer will be prompted to login and authorize payment.
  3. Upon completion, the popup will be closed
  1. Callback
  2. Promise
function displayVenmoButton(venmoInstance) {
    venmoButton.style.display = 'block';

    venmoButton.addEventListener('click', function () {
      venmoButton.disabled = true;

      venmoInstance.tokenize(function (tokenizeErr, payload) {
        venmoButton.removeAttribute('disabled');

        if (tokenizeErr) {
          handleVenmoError(tokenizeErr);
        } else {
          handleVenmoSuccess(payload);
        }
      });

    });
  }

  function handleVenmoError(err) {
    if (err.code === 'VENMO_CANCELED') {
      console.log('App is not available or user aborted payment flow');
    } else if (err.code === 'VENMO_APP_CANCELED') {
      console.log('User canceled payment flow');
    } else {
      console.error('An error occurred:', err.message);
    }
  }

  function handleVenmoSuccess(payload) {
    // Send payload.nonce to your server.
    console.log('Got a payment method nonce:', payload.nonce);
    // Display the Venmo username in your checkout UI.
    console.log('Venmo user:', payload.details.username);
  }

Payment method usageanchor

Starting in Braintree JS v3.77.0, you should specify how you will use the customer's Venmo account by passing paymentMethodUsage in the create call:

  • multi_use: Request authorization for future payments (vaulting allowed)
  • single_use: Request authorization for a one-time payment (vaulting not allowed)

If neither of these options has been specified, vaulting will be supported, but customers will see a legacy UI flow in the Venmo app. We recommend using multi_use or single_use for the best customer experience.

The payment method usage will affect the customer flow by:

  • Displaying different phrases to the customer on the transaction consent page (e.g. "Authorize Business Name to pay with Venmo" vs. "Authorize Business Name to pay with Venmo for future purchases" where Business Name is the business name submitted in the Venmo application form).
  • Not displaying a merchant connection on the Connected Businesses page in the Venmo app when the paymentMethodUsage property is single_use.
  • Allowing customers to update their funding instrument on the Connected Businesses page in the Venmo app when the paymentMethodUsage property is multi_use.
note

If paymentMethodUsage is set to single_use:

  • A validation error will be returned if attempting to vault via PaymentMethod.create or Customer.create.
  • The transaction will be processed normally but the nonce will not be vaulted if store-in-vault or store-in-vault-on-success is passed during transaction.sale.
  1. Callback
  2. Promise
braintree.venmo.create({
    client: clientInstance,
    paymentMethodUsage: 'multi_use'
  }, function (venmoErr, venmoInstance) {
    // ...
  });

Multiple profilesanchor

If you have a custom integration and have onboarded multiple websites for Venmo processing with a single Braintree gateway, you'll need to pass the profile_id to specify which Venmo profile to present during the payment flow.

You'll also need to pass the profile_id when creating the transaction on the server side.

  1. Callback
  2. Promise
braintree.venmo.create({
    client: clientInstance,
    profileId: 'YOUR_VENMO_PROFILE_ID',
    paymentMethodUsage: 'multi_use' // available in v3.77.0+
  }, function (venmoErr, venmoInstance) {
    // ...
  });
note

If you have multiple business profiles, the profile_id for each profile can be found by logging into the Control Panel, clicking the gear icon in the top right corner, selecting Processing from the drop-down menu, scrolling to Venmo, and clicking the Options link.

Collect device dataanchor

You must collect information about the customer's device before creating each transaction.

  1. Callback
  2. Promise
braintree.dataCollector.create({
    client: clientInstance,
    paypal: true
  }, function (dataCollectorErr, dataCollectorInstance) {
    if (dataCollectorErr) {
      // Handle error in creation of data collector.
      return;
    }

  // At this point, you should access the dataCollectorInstance.deviceData value and provide it
  // to your server, e.g. by injecting it into your form as a hidden input.
  var deviceData = dataCollectorInstance.deviceData;
  });

You'll need to pass this deviceData when creating the Venmo transaction from your server.

important

Be sure to pass device data as close to the transaction creation as possible. Doing so will help reduce decline rates.

Shipping and Billing Address collectionanchor

Starting in Braintree JS v3.96.1, you can specify if you wish to receive a customer's Venmo shipping and billing address by passing the collectCustomerBillingAddress and collectCustomerShippingAddress flags during the create call. When these flags are enabled, Venmo will collect the required addresses from the consumer and send them back in the response object.

To receive shipping address, add the following parameter when creating the Venmo component:

  • collectCustomerShippingAddress: true

To receive billing address, add the following parameter when creating the Venmo component:

  • collectCustomerBillingAddress: true
  1. Callback
  2. Promise
// Create a client.
  braintree.venmo.create({
    client: clientInstance,
    paymentMethodUsage: 'multi_use',
    collectCustomerBillingAddress: true,
    collectCustomerShippingAddress: true
  }, function (venmoErr, venmoInstance) {
    // ...
  });
note

You will only be able to collect customer addresses if you have Enriched Customer Data (ECD) enabled in the Control Panel. Details about how to enable ECD can be found in this support article. A validation error will be returned if attempting to collect customer addresses without enabling ECD.

Once the create call is successful, the shipping and billing addresses will be returned in the response payload under a payerInfo object.

  1. Callback
  2. Promise
function handleVenmoSuccess(payload) {
    console.log('Got a payment method nonce:', payload.nonce);
    // Display the shipping address:
    // payload.details.payerInfo.shippingAddress = {
    //      addressLine1: "",
    //      addressLine2: "",
    //      adminArea2: "",
    //      adminArea1: "",
    //      postalCode: "" 
    // }
    console.log("Venmo user shippingAddress:", payload.details.payerInfo.shippingAddress);

    // Display the billing address:
    // payload.details.payerInfo.billingAddress = {
    //      addressLine1: "",
    //      addressLine2: "",
    //      adminArea2: "",
    //      adminArea1: "",
    //      postalCode: "" 
    // }
    console.log("Venmo user billingAddress:", payload.details.payerInfo.billingAddress);
  }
note

For desktop, this feature is currently only available for the web login flow and not for the QR code flow.

Amounts and Line Itemsanchor

Starting in Braintree JS v3.96.1, if the create call is made in the context of a purchase, you will need to pass the total amount of the transaction which will be displayed to the user on the Venmo paysheet. Additionally, you can also pass other transaction details that you would like to render to the user such as subtotal, discount, taxes, shipping amount and line items.

  1. Callback
  2. Promise
braintree.venmo.create({
    client: clientInstance,
    paymentMethodUsage: 'multi_use',
    totalAmount: '10.00',
    subTotalAmount: '8.00',
    taxAmount: '1.00',
    discountAmount: '1.00',
    shippingAmount: '2.00',
    lineItems: [
      {
        name; 'item-name',
        quantity: 2,
        unitAmount: '5.00',
        type: 'DEBIT'
      },
      {
        name; 'credited-item-name',
        quantity: 1,
        unitAmount: '2.00',
        type: 'CREDIT'
      }
    ]
  }, function (venmoErr, venmoInstance) {
    // ...
  });
note

All amount and line-item fields are optional except for totalAmount, which is required in the context of purchase. If the create call is for vaulting only, totalAmount can be omitted.

important

The following validations will be performed on the provided transaction details:

  • All amounts are expected to be in USD
  • All amounts must be non-negative
  • All amounts must be of string type and must contain either a whole number or a number with two decimal places
  • Line-item should have four properties: item name, quantity, unit amount and type
  • Line-item type must be either CREDIT or DEBIT
  • The amounts for all individual line items present must add up to the total amount, or sub-total when present
  • All individual amounts (discount, shipping, tax, sub-total) must add up to the total amount

Full exampleanchor

This is a full example of the integration between Braintree and Venmo. This example will allow you to get started, and provides a reference while integrating into your existing code base.

  1. Callback
  2. Promise
var venmoButton = document.getElementById('venmo-button');

  // Create a client.
  braintree.client.create({
  authorization: CLIENT_AUTHORIZATION
  }, function (clientErr, clientInstance) {
    // Stop if there was a problem creating the client.
    // This could happen if there is a network error or if the authorization
    // is invalid.
    if (clientErr) {
      console.error('Error creating client:', clientErr);
      return;
    }

    braintree.dataCollector.create({
    client: clientInstance,
    paypal: true
    }, function (dataCollectorErr, dataCollectorInstance) {
      if (dataCollectorErr) {
        // Handle error in creation of data collector.
        return;
      }

      // At this point, you should access the deviceData value and provide it
      // to your server, e.g. by injecting it into your form as a hidden input.
      console.log('Got device data:', dataCollectorInstance.deviceData);

    });

    braintree.venmo.create({
      client: clientInstance,
      allowDesktop: true,
      paymentMethodUsage: 'multi_use' // available in v3.77.0+
      // Add allowNewBrowserTab: false if your checkout page does not support
      // relaunching in a new tab when returning from the Venmo app. This can
      // be omitted otherwise.
      // allowNewBrowserTab: false
    }, function (venmoErr, venmoInstance) {
      if (venmoErr) {
        console.error('Error creating Venmo:', venmoErr);
        return;
      }

      // Verify browser support before proceeding.
      if (!venmoInstance.isBrowserSupported()) {
        console.log('Browser does not support Venmo');
        return;
      }

      displayVenmoButton(venmoInstance);

      // Check if tokenization results already exist. This occurs when your
      // checkout page is relaunched in a new tab. This step can be omitted
      // if allowNewBrowserTab is false.
      if (venmoInstance.hasTokenizationResult()) {
        venmoInstance.tokenize(function (tokenizeErr, payload) {
          if (err) {
            handleVenmoError(tokenizeErr);
          } else {
            handleVenmoSuccess(payload);
          }
        });
        return;
      }

    });
  });

  function displayVenmoButton(venmoInstance) {
    // Assumes that venmoButton is initially display: none.
    venmoButton.style.display = 'block';

    venmoButton.addEventListener('click', function () {
      venmoButton.disabled = true;

      venmoInstance.tokenize(function (tokenizeErr, payload) {
        venmoButton.removeAttribute('disabled');

        if (tokenizeErr) {
          handleVenmoError(tokenizeErr);
        } else {
          handleVenmoSuccess(payload);
        }
      });

    });
  }

  function handleVenmoError(err) {
    if (err.code === 'VENMO_CANCELED') {
      console.log('App is not available or user aborted payment flow');
    } else if (err.code === 'VENMO_APP_CANCELED') {
      console.log('User canceled payment flow');
    } else {
      console.error('An error occurred:', err.message);
    }
  }

  function handleVenmoSuccess(payload) {
    // Send the payment method nonce to your server, e.g. by injecting
    // it into your form as a hidden input.
    console.log('Got a payment method nonce:', payload.nonce);
    // Display the Venmo username in your checkout UI.
    console.log('Venmo user:', payload.details.username);
  }

Next Page: Server-side