Skip to main content
You can accept Venmo for secure payments from US customers with the JavaScript SDK v6. This guide shows you how to set up your environment, review eligibility requirements, add Venmo payments, and work with advanced features.

Prerequisites

Before beginning your integration, meet these requirements:
  • Create a PayPal developer account.
  • Use a PayPal business account to accept Venmo payments
  • Set up your sandbox credentials.
Note: You’ll use your sandbox credentials to create a .env file during the Development setup.

Eligibility

  • US-based merchants and US-based consumers only.
  • Payment must be in USD.

Development setup

Configure your local development environment with the required dependencies and credentials. Install project dependencies:
cd client/components/googlePayPayments/oneTimePayment/html
npm install
Create environment configuration:
# .env file
PAYPAL_SANDBOX_CLIENT_ID=your_client_id
PAYPAL_SANDBOX_CLIENT_SECRET=your_client_secret
Start the development server:
npm start
To load the application, see http://localhost:3000.

Implementation steps

Step 1: HTML structure setup

Create your HTML page and include the PayPal SDK script.
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>One-Time Payment - Venmo - PayPal JavaScript SDK</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style>
      .buttons-container {
        display: flex;
        flex-direction: column;
        gap: 12px;
      }
    </style>
  </head>
  <body>
    <h1>One-Time Payment Venmo Integration</h1>

    <div class="buttons-container">
      <!-- Venmo button is initially hidden until eligibility is confirmed -->
      <venmo-button id="venmo-button" type="pay" hidden></venmo-button>
    </div>
    
    <script src="app.js"></script>

    <!-- Load PayPal SDK -->
    <script
      async
      src="https://www.sandbox.paypal.com/web-sdk/v6/core"
      onload="onPayPalWebSdkLoaded()"
    ></script>
  </body>
</html>

Step 2: Initialize PayPal SDK

Set up the PayPal SDK with the Venmo component after it loads.
async function onPayPalWebSdkLoaded() {
  try {
    // Get client token for authentication
    const clientToken = await getBrowserSafeClientToken();
    
    // Create PayPal SDK instance with Venmo component
    const sdkInstance = await window.paypal.createInstance({
      clientToken,
      components: ["venmo-payments"],
      pageType: "checkout",
    });

    // Check payment method eligibility
    const paymentMethods = await sdkInstance.findEligibleMethods({
      currencyCode: "USD",
    });

    // Only setup Venmo button if eligible
    if (paymentMethods.isEligible("venmo")) {
      setupVenmoButton(sdkInstance);
    } else {
      console.log("Venmo is not eligible for this session");
    }
  } catch (error) {
    console.error("SDK initialization error:", error);
  }
}

Step 3: Configure Venmo button

Create the Venmo payment session and set up the button.
async function setupVenmoButton(sdkInstance) {
  // Create Venmo payment session with callback options
  const venmoPaymentSession = sdkInstance.createVenmoOneTimePaymentSession(
    paymentSessionOptions,
  );
  
  // Get reference to the Venmo button element
  const venmoButton = document.querySelector("#venmo-button");
  
  // Show the button since Venmo is eligible
  venmoButton.removeAttribute("hidden");

  // Add click handler to start payment flow
  venmoButton.addEventListener("click", async () => {
    try {
      // Start the payment session
      await venmoPaymentSession.start(
        { 
          presentationMode: "auto" // Auto-detects best presentation mode
        },
        createOrder() // Create order and return order details
      );
    } catch (error) {
      console.error("Payment start error:", error);
      handlePaymentError(error);
    }
  });
}

Step 4. Configure payment session callbacks

Define callback handlers for payment approval, cancellation, and error scenarios.
const paymentSessionOptions = {
  // Called when payment is approved by the user
  async onApprove(data) {
    console.log("Payment approved:", data);
    try {
      // Capture the order on your server
      const orderData = await captureOrder({
        orderId: data.orderId,
      });
      console.log("Payment captured successfully:", orderData);
      
      // Handle successful payment (e.g., redirect, show success message)
      handlePaymentSuccess(orderData);
    } catch (error) {
      console.error("Payment capture failed:", error);
      handlePaymentError(error);
    }
  },
  
  // Called when user cancels the payment
  onCancel(data) {
    console.log("Payment cancelled:", data);
    // Handle cancellation (e.g., show message, return to cart)
    handlePaymentCancellation();
  },
  
  // Called when an error occurs during payment
  onError(error) {
    console.error("Payment error:", error);
    // Handle error (e.g., show error message, retry option)
    handlePaymentError(error);
  },
};

Step 5. Choose presentation mode

The presentation mode determines how the payment UI appears for the customer.
// Auto mode - automatically chooses the best presentation mode
await venmoPaymentSession.start(
  { presentationMode: "auto" },
  createOrder()
);

// Popup mode - opens payment in a popup window
await venmoPaymentSession.start(
  { presentationMode: "popup" },
  createOrder()
);

// Modal mode - opens payment in an overlay modal
await venmoPaymentSession.start(
  { presentationMode: "modal" },
  createOrder()
);

// Redirect mode - redirects to Venmo for payment
await venmoPaymentSession.start(
  { presentationMode: "redirect" },
  createOrder()
);
Note: Use "auto" mode to let Venmo attempt popup first and automatically fall back to modal if popups are blocked.

API endpoints

The integration requires these server-side endpoints.

Client token endpoint

// GET /paypal-api/auth/browser-safe-client-token
async function getBrowserSafeClientToken() {
  const response = await fetch("/paypal-api/auth/browser-safe-client-token", {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  });
  const { accessToken } = await response.json();
  return accessToken;
}

Create order endpoint

// POST /paypal-api/checkout/orders/create-with-sample-data
async function createOrder() {
  const response = await fetch(
    "/paypal-api/checkout/orders/create-with-sample-data",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
    },
  );
  const { id } = await response.json();
  
  return { orderId: id };
}

Capture order endpoint

// POST /paypal-api/checkout/orders/{orderId}/capture
async function captureOrder({ orderId }) {
  const response = await fetch(
    `/paypal-api/checkout/orders/${orderId}/capture`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
    },
  );
  const data = await response.json();
  return data;
}

Key components

Integrate Venmo effectively by understanding the essential parts of the JavaScript SDK v6 workflow.
Key componentPurposeDetails
PayPal SDK instanceMain entry point for PayPal functionality
  • Includes venmo-payments component
  • Requires client token from server
Eligibility checkDetermines if Venmo is available
  • Based on user location, device type, currency, and account status
  • Always check before showing Venmo button
Payment sessionManages Venmo payment flow and callbacks
  • Handles approve, cancel, and error scenarios
  • Created once and reused for multiple payment attempts
Presentation modesDefines how Venmo is displayed
  • Auto — Best mode selected automatically (Recommended)
  • Popup — Opens in popup window that may be blocked
  • Modal — Opens in overlay modal
  • Redirect — Full page redirect to Venmo

Security considerations

  • Request client tokens from your server only.
  • Never expose client secrets in frontend code.
  • Process all payments through PayPal’s servers.
  • Use HTTPS in production.

Testing

  • Run transactions across desktop and mobile devices.
  • Verify eligibility logic and Venmo button rendering.
  • Test payment approval, cancellation, and error handling.

Advanced features

Enhance your Venmo integration with advanced capabilities.

Custom order creation

Create a custom order endpoint to control purchase details and items more precisely. Use this pattern when your integration or product requires flexible order payloads.
async function createCustomOrder(orderDetails) {
  const orderPayload = {
    intent: "CAPTURE",
    purchase_units: [
      {
        amount: {
          currency_code: "USD",
          value: orderDetails.amount,
          breakdown: {
            item_total: {
              currency_code: "USD",
              value: orderDetails.amount,
            },
          },
        },
        items: orderDetails.items,
      },
    ],
  };

  const response = await fetch("/paypal-api/checkout/orders/create", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(orderPayload),
  });
  
  const { id } = await response.json();
  return { orderId: id };
}

Error handling best practices

Establish error handling for your payment flows. The following approach provides user-friendly messages and optional actions on payment failure, success, and cancellation.
function handlePaymentError(error) {
  // Log error for debugging
  console.error("Payment error details:", error);
  
  // Show user-friendly error message
  const errorMessage = getErrorMessage(error);
  showErrorToUser(errorMessage);
  
  // Optionally, provide retry mechanism
  showRetryOption();
}

function getErrorMessage(error) {
  switch (error.code) {
    case 'PAYMENT_CANCELLED':
      return 'Payment was cancelled. Please try again.';
    case 'NETWORK_ERROR':
      return 'Network error occurred. Please check your connection and try again.';
    case 'VENMO_NOT_AVAILABLE':
      return 'Venmo is not available. Please try a different payment method.';
    default:
      return 'An unexpected error occurred. Please try again.';
  }
}

function handlePaymentSuccess(orderData) {
  // Show success message
  showSuccessMessage('Payment completed successfully!');
  
  // Redirect to success page or update UI
  redirectToSuccessPage(orderData.id);
  
  // Track conversion for analytics
  trackPaymentSuccess(orderData);
}

function handlePaymentCancellation() {
  // Show cancellation message
  showInfoMessage('Payment was cancelled. Your order is still in your cart.');
  
  // Return user to checkout or cart
  returnToCheckout();
}

React integration

Integrate Venmo payments for React applications.
import { useEffect, useState } from 'react';

function VenmoButton({ orderDetails, onSuccess, onError, onCancel }) {
  const [isEligible, setIsEligible] = useState(false);
  const [paymentSession, setPaymentSession] = useState(null);

  useEffect(() => {
    async function initializeVenmo() {
      try {
        const clientToken = await getBrowserSafeClientToken();
        const sdkInstance = await window.paypal.createInstance({
          clientToken,
          components: ["venmo-payments"],
          pageType: "checkout",
        });

        const paymentMethods = await sdkInstance.findEligibleMethods({
          currencyCode: "USD",
        });

        if (paymentMethods.isEligible("venmo")) {
          setIsEligible(true);
          
          const session = sdkInstance.createVenmoOneTimePaymentSession({
            onApprove: onSuccess,
            onCancel: onCancel,
            onError: onError,
          });
          
          setPaymentSession(session);
        }
      } catch (error) {
        console.error("Venmo initialization error:", error);
        onError(error);
      }
    }

    initializeVenmo();
  }, []);

  const handleClick = async () => {
    if (paymentSession) {
      try {
        await paymentSession.start(
          { presentationMode: "auto" },
          createOrder(orderDetails)
        );
      } catch (error) {
        onError(error);
      }
    }
  };

  if (!isEligible) {
    return null; // Don't render if Venmo is not eligible
  }

  return (
    <venmo-button 
      type="pay" 
      onClick={handleClick}
    />
  );
}

Resources

I