Skip to main content
RapidDev - Software Development Agency
v0-integrationsNext.js API Route

How to Integrate Braintree with V0

To use Braintree with V0, generate your payment UI in V0 using the Braintree Drop-in UI, then create two Next.js API routes: one to generate a client token and one to process the transaction using the braintree npm package. Store your Braintree Merchant ID, Public Key, and Private Key in Vercel environment variables. Braintree natively supports PayPal and Venmo alongside credit cards.

What you'll learn

  • How to set up a Braintree sandbox account and get API credentials
  • How to generate a Braintree client token in a Next.js API route
  • How to embed the Braintree Drop-in UI in a V0-generated component
  • How to process payment nonces server-side to complete transactions
  • How to store Braintree credentials securely in Vercel environment variables
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate13 min read35 minutesPaymentApril 2026RapidDev Engineering Team
TL;DR

To use Braintree with V0, generate your payment UI in V0 using the Braintree Drop-in UI, then create two Next.js API routes: one to generate a client token and one to process the transaction using the braintree npm package. Store your Braintree Merchant ID, Public Key, and Private Key in Vercel environment variables. Braintree natively supports PayPal and Venmo alongside credit cards.

Accepting Payments with Braintree Drop-in UI in Your V0 App

Braintree, owned by PayPal, is the payment processor of choice when you need native PayPal and Venmo payment options alongside traditional credit cards. Its Drop-in UI is a pre-built, hosted payment form that renders directly in your React app — customers can pay with a saved PayPal account, Venmo, or any credit card from a single embeddable widget. This means you do not have to build separate payment form components for each payment method.

The Braintree integration follows a server-client handshake pattern. First, your server generates a client token — a temporary, encrypted authorization token that initializes the Drop-in UI on the client side. The Drop-in UI uses this token to communicate directly with Braintree's servers when the customer enters their payment details. After the customer submits, Braintree returns a payment nonce — a single-use token that represents the payment method without exposing sensitive card data. Your server then uses this nonce to finalize the transaction.

This architecture ensures that raw card numbers never pass through your server or V0's generated code. Braintree's Drop-in UI handles PCI compliance for the payment form, and your Next.js API routes handle only the business logic of charging the correct amount. The result is a payment system that supports multiple payment methods with minimal frontend complexity.

Integration method

Next.js API Route

V0 generates the front-end UI while two Next.js API routes handle the Braintree flow server-side: one generates a client token for the Drop-in UI, and one processes the payment nonce returned after the customer fills in their details. The braintree npm package runs exclusively in your Vercel serverless functions, keeping your Private Key out of the browser.

Prerequisites

  • A V0 account with a Next.js project at v0.dev
  • A Braintree sandbox account at sandbox.braintreegateway.com (free to create)
  • Your Braintree Merchant ID, Public Key, and Private Key from the sandbox control panel
  • A Vercel project connected to your V0 app via GitHub for environment variable management
  • Basic familiarity with loading external JavaScript scripts in a Next.js app

Step-by-step guide

1

Set Up Your Braintree Sandbox Account

Braintree provides a full sandbox environment for testing. Go to sandbox.braintreegateway.com and create an account. The sandbox gives you fake card numbers, test PayPal accounts, and simulated Venmo to test every payment scenario without real money. After signing up, go to Account → My User → API Keys in the sandbox control panel. You will find your Merchant ID on this page. Click View under API Keys to see your Public Key and Private Key. Copy all three — you will need them as environment variables. Braintree's sandbox is completely isolated from production. When you are ready to go live, you create a production Braintree account separately and get new credentials. The same code works for both environments — you just switch the credentials and remove the sandbox initialization flag. Optionally, in the sandbox control panel under Processing → PayPal, link a PayPal sandbox account to test PayPal checkout. Under Processing → Venmo, you can enable Venmo in sandbox mode to test the Venmo button in the Drop-in UI.

Pro tip: Braintree provides test card numbers in their documentation at developer.paypal.com/braintree/docs/guides/credit-cards/testing. Use 4111111111111111 for a successful card charge.

Expected result: You have your Braintree Merchant ID, Public Key, and Private Key from the sandbox control panel.

2

Generate Your Payment UI with V0

Use V0 to generate the payment page layout. The key element is a div container where Braintree's Drop-in UI will mount itself. This div needs a specific id attribute (like dropin-container) so the Braintree JavaScript SDK knows where to render the payment form. Ask V0 to generate the checkout page with the product or order details, the drop-in container div, and a submit button. The submit button should be disabled until the Drop-in UI has fully loaded and the customer has entered valid payment information. The Braintree Drop-in SDK is loaded from Braintree's CDN as a script tag. In Next.js, you load external scripts either in the page's head using Next.js Script component or programmatically in a useEffect hook. Ask V0 to add the Script component importing https://js.braintreegateway.com/web/dropin/1.43.0/js/dropin.min.js and initialize the Drop-in UI after it loads. The Drop-in initialization flow works like this: first load the script, then fetch the client token from /api/braintree/client-token, then call braintree.dropin.create() with the client token and container selector. The create() callback gives you a dropin instance — save this to a React ref so you can call dropin.requestPaymentMethod() when the user clicks Submit.

V0 Prompt

Create a checkout page with an order summary card on the left showing product name and $49.00 price. On the right, show a payment card with a div id='dropin-container' where Braintree Drop-in UI will render, and a Pay $49.00 button below. Load the Braintree Drop-in script from https://js.braintreegateway.com/web/dropin/1.43.0/js/dropin.min.js using Next.js Script component. After the script loads, fetch a client token from /api/braintree/client-token and initialize the Drop-in UI. When the Pay button is clicked, call dropin.requestPaymentMethod() and POST the nonce to /api/braintree/checkout.

Paste this in V0 chat

Pro tip: Store the dropin instance in a useRef rather than useState to avoid triggering re-renders when the instance is created.

Expected result: V0 generates a checkout page with a Drop-in container, a Pay button, and the script loading logic wired to your API routes.

3

Create the Client Token API Route

The client token route is the first API call in the Braintree flow. Your React component calls this endpoint to get a token that authorizes the Drop-in UI to run in the browser. This route runs server-side using the braintree Node.js npm package. Install the braintree package: add 'braintree' to your package.json or ask V0 to scaffold the route with the correct import. The braintree package is the official Braintree server-side SDK for Node.js. The gateway object is configured with your Merchant ID, Public Key, and Private Key from environment variables. You also specify the environment — Braintree.Environment.Sandbox for testing or Braintree.Environment.Production for live transactions. Call gateway.clientToken.generate({}) to create a client token. The result contains a clientToken string that you return as JSON to the browser. The client token is short-lived (24 hours) and single-use. Each time a customer loads your checkout page, you generate a fresh token. You can optionally pass a customerId to gateway.clientToken.generate() to create a token tied to a stored Braintree customer, which enables features like vaulted payment methods (saved cards).

V0 Prompt

Create a Next.js API route at app/api/braintree/client-token/route.ts that uses the braintree npm package to create a Braintree gateway with BRAINTREE_MERCHANT_ID, BRAINTREE_PUBLIC_KEY, and BRAINTREE_PRIVATE_KEY from environment variables using Braintree.Environment.Sandbox. Call gateway.clientToken.generate({}) and return the clientToken string as JSON.

Paste this in V0 chat

app/api/braintree/client-token/route.ts
1// app/api/braintree/client-token/route.ts
2import { NextResponse } from 'next/server';
3import braintree from 'braintree';
4
5const gateway = new braintree.BraintreeGateway({
6 environment: braintree.Environment.Sandbox,
7 merchantId: process.env.BRAINTREE_MERCHANT_ID!,
8 publicKey: process.env.BRAINTREE_PUBLIC_KEY!,
9 privateKey: process.env.BRAINTREE_PRIVATE_KEY!,
10});
11
12export async function GET() {
13 try {
14 const result = await gateway.clientToken.generate({});
15 return NextResponse.json({ clientToken: result.clientToken });
16 } catch (error) {
17 console.error('Braintree client token error:', error);
18 return NextResponse.json(
19 { error: 'Failed to generate client token' },
20 { status: 500 }
21 );
22 }
23}

Pro tip: When going to production, change braintree.Environment.Sandbox to braintree.Environment.Production and update your credentials to live keys.

Expected result: GET /api/braintree/client-token returns a JSON object with a clientToken string. The Drop-in UI initializes successfully in the browser using this token.

4

Create the Checkout Transaction API Route

The checkout route receives the payment nonce from the Drop-in UI and processes the actual transaction. This is where money moves — the nonce represents the customer's selected payment method and Braintree handles the charge using it. The route accepts a POST request with the payment nonce and the amount to charge. Call gateway.transaction.sale() with the nonce, amount (as a string with decimal places), and options.submitForSettlement set to true. The submitForSettlement flag tells Braintree to capture the funds immediately rather than just authorizing them. Braintree returns a result object with a success boolean. If success is true, the transaction went through and result.transaction contains the transaction details including the transaction ID. If success is false, result.errors contains detailed error information about why the charge failed — for example, the card was declined, insufficient funds, or the PayPal account was restricted. Return a meaningful response to the client: on success, return the transaction ID so you can store it in your database and display a confirmation. On failure, return the specific error message from Braintree so your UI can show a helpful message rather than a generic error. Store successful transaction IDs in your database immediately — this is your audit trail for charges. For production apps, consider wrapping the entire checkout flow in a try-catch and logging errors to a monitoring service. A failed transaction that is not logged is a customer who could not pay — this directly affects revenue.

V0 Prompt

Create a Next.js API route at app/api/braintree/checkout/route.ts that accepts POST with { nonce, amount }. Use the same Braintree gateway from the client token route to call gateway.transaction.sale() with the nonce, amount as string, and submitForSettlement: true. Return { success: true, transactionId } on success or { success: false, error } with status 400 on failure.

Paste this in V0 chat

app/api/braintree/checkout/route.ts
1// app/api/braintree/checkout/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3import braintree from 'braintree';
4
5const gateway = new braintree.BraintreeGateway({
6 environment: braintree.Environment.Sandbox,
7 merchantId: process.env.BRAINTREE_MERCHANT_ID!,
8 publicKey: process.env.BRAINTREE_PUBLIC_KEY!,
9 privateKey: process.env.BRAINTREE_PRIVATE_KEY!,
10});
11
12export async function POST(request: NextRequest) {
13 try {
14 const { nonce, amount } = await request.json();
15
16 if (!nonce || !amount) {
17 return NextResponse.json(
18 { error: 'nonce and amount are required' },
19 { status: 400 }
20 );
21 }
22
23 const result = await gateway.transaction.sale({
24 amount: parseFloat(amount).toFixed(2),
25 paymentMethodNonce: nonce,
26 options: {
27 submitForSettlement: true,
28 },
29 });
30
31 if (result.success) {
32 return NextResponse.json({
33 success: true,
34 transactionId: result.transaction.id,
35 });
36 } else {
37 const errorMessage = result.errors?.deepErrors()?.[0]?.message
38 || result.message
39 || 'Transaction failed';
40 return NextResponse.json(
41 { success: false, error: errorMessage },
42 { status: 400 }
43 );
44 }
45 } catch (error) {
46 console.error('Braintree checkout error:', error);
47 return NextResponse.json(
48 { error: 'Internal server error' },
49 { status: 500 }
50 );
51 }
52}

Pro tip: After a successful transaction, immediately save the transactionId to your database before showing the success screen — this ensures you have a record even if the user closes the browser window.

Expected result: POSTing to /api/braintree/checkout with a valid nonce and amount returns a JSON object with success: true and a transactionId from Braintree.

5

Add Environment Variables in Vercel

Your Braintree API routes need three environment variables. Add them in Vercel Dashboard → Settings → Environment Variables, setting scope to Production, Preview, and Development. BRAINTREE_MERCHANT_ID: your Braintree Merchant ID from the sandbox or production control panel. This identifies your merchant account. BRAINTREE_PUBLIC_KEY: your Public Key. This is used in combination with the Private Key to authenticate API requests. While called 'public,' it should still be server-side only — never add NEXT_PUBLIC_ prefix. BRAINTREE_PRIVATE_KEY: your Private Key. This is the most sensitive credential — it authorizes API calls to process real transactions. Treat it with the same care as a database password. For local development, add these variables to a .env.local file. Use sandbox credentials for Development and Preview environments in Vercel, and only add production credentials to the Production environment once you have thoroughly tested all payment flows in sandbox. After saving the variables, trigger a redeployment. Test the complete flow in sandbox: load the checkout page, confirm the Drop-in UI renders, enter the test card number 4111111111111111, click Pay, and verify the transaction appears in your Braintree sandbox control panel under Transactions.

Pro tip: Before going live, change braintree.Environment.Sandbox to braintree.Environment.Production in both API routes — this is the single switch from sandbox to production.

Expected result: Vercel shows all three Braintree variables. The complete checkout flow works in sandbox: Drop-in UI renders, test payment processes, and the transaction appears in the Braintree control panel.

Common use cases

Single Product Checkout with PayPal Option

A founder selling a digital course wants to offer PayPal checkout as an alternative to card payment. V0 generates the product page and order summary. The Braintree Drop-in UI renders a payment form with card fields and a PayPal button, giving customers their preferred payment method.

V0 Prompt

Create a checkout page for a digital course priced at $149. Show an order summary on the left with course name, what's included, and price. On the right, include a payment section div with id='dropin-container' where the Braintree Drop-in UI will render, and a Pay Now button that submits the payment nonce to /api/braintree/checkout. Show a loading state on the button during processing.

Copy this prompt to try it in V0

E-commerce Cart Checkout

An online store built with V0 needs a checkout flow that accepts multiple payment methods. The cart total is calculated server-side and passed to the Braintree transaction API. After successful payment, the order is created in the database.

V0 Prompt

Build a cart checkout page showing an itemized order summary table with product names, quantities, and prices, a subtotal, tax, and total row. Below the order summary, add a payment section with a div id='dropin-container' and a Confirm Order button. The button should submit the nonce from the Braintree Drop-in to /api/braintree/checkout with the cartId. Show an order confirmation screen after success.

Copy this prompt to try it in V0

Subscription with Venmo for Gen Z Audience

A creator platform targeting a younger demographic wants to accept Venmo payments for monthly subscriptions. Braintree's Drop-in UI surfaces the Venmo payment option automatically when enabled, making it the easiest way to offer Venmo without building a custom integration.

V0 Prompt

Create a subscription signup page with three plan cards: Basic ($9/mo), Pro ($19/mo), Business ($49/mo). When a user selects a plan, show a payment modal with a Braintree Drop-in container and a Subscribe button. POST the nonce and planId to /api/braintree/subscribe. Show a success message with the subscription start date after completion.

Copy this prompt to try it in V0

Troubleshooting

Drop-in UI container is blank or shows no payment fields

Cause: The Braintree Drop-in script has not loaded before dropin.create() is called, or the client token fetch failed and the initialization was not awaited properly.

Solution: Ensure the dropin.create() call runs inside the Script component's onLoad callback or after the token fetch Promise resolves. Add console.log to verify the clientToken value is a non-empty string before calling create().

AUTHENTICATION error when calling the client token API route

Cause: One or more of BRAINTREE_MERCHANT_ID, BRAINTREE_PUBLIC_KEY, or BRAINTREE_PRIVATE_KEY is missing or incorrect in Vercel environment variables.

Solution: Open Vercel Dashboard → Settings → Environment Variables and verify all three credentials match exactly what is shown in the Braintree control panel under Account → API Keys. Check that the environment is set to Sandbox credentials when using braintree.Environment.Sandbox.

Transaction sale call succeeds but result.success is false with processor decline

Cause: The test card number used triggered a simulated decline. Braintree sandbox uses specific card numbers to simulate different decline scenarios.

Solution: Use card number 4111111111111111 for a successful sandbox transaction. Check Braintree's testing documentation for specific card numbers that simulate declines (e.g., 4000111111111115 for processor declined).

Cannot find module 'braintree' error in the API route

Cause: The braintree npm package is not installed in your project's dependencies.

Solution: Add braintree to your package.json dependencies and run npm install (or push to GitHub to trigger a fresh Vercel build). Also add @types/braintree for TypeScript type support.

typescript
1// package.json
2"dependencies": {
3 "braintree": "^3.24.0"
4},
5"devDependencies": {
6 "@types/braintree": "^3.0.0"
7}

Best practices

  • Always use submitForSettlement: true unless you specifically need to authorize now and capture later
  • Generate a fresh client token each time the checkout page loads — do not cache tokens across sessions
  • Log Braintree transaction IDs in your database immediately after a successful sale before returning the response
  • Handle result.success === false explicitly and surface the specific error message to the user rather than a generic payment failure
  • Use Braintree's sandbox test cards for all development and staging testing — never use real card numbers in sandbox
  • When going to production, switch the environment flag in both API routes simultaneously to avoid a mixed sandbox/production state
  • Consider using Braintree's customer vault to store payment methods for returning customers, enabling one-click checkout

Alternatives

Frequently asked questions

Does Braintree support PayPal and Venmo in the same Drop-in UI?

Yes, this is Braintree's primary differentiator. The Drop-in UI automatically shows a PayPal button, a Venmo button (on supported mobile browsers), and card entry fields based on your account configuration. Customers choose their preferred payment method from a single form without you building separate UI components.

Do I need a separate PayPal account to use Braintree?

For sandbox testing, Braintree provides test PayPal accounts automatically. For production, you link your existing PayPal Business account to your Braintree account during the onboarding process. The PayPal payments processed through Braintree settle into your PayPal account balance.

What is the difference between a payment nonce and a payment token?

A nonce is a single-use, time-limited (24 hours) string representing a payment method that the Drop-in UI generated. It is safe to send from the browser to your server because it cannot be used more than once. Your server exchanges the nonce for an actual charge using gateway.transaction.sale(). A vaulted token, by contrast, is a permanent reference to a stored payment method in Braintree's vault.

How do I handle refunds with Braintree?

Use gateway.transaction.refund(transactionId) in a server-side API route. You can refund the full amount or a partial amount. Refunds can only be issued on settled transactions — transactions that have completed their settlement window, typically the next business day. For same-day refunds on unsettled transactions, use gateway.transaction.void(transactionId) instead.

Is Braintree PCI compliant?

Yes. The Braintree Drop-in UI is hosted and managed by Braintree, meaning raw card numbers are entered directly into Braintree's servers — they never pass through your Next.js app or Vercel functions. This qualifies your integration for SAQ A compliance, the simplest PCI compliance level, because you never handle raw cardholder data.

What fees does Braintree charge?

Braintree's standard pricing is 2.59% + $0.49 per transaction for US cards, with PayPal payments charged at standard PayPal rates. For high-volume merchants, Braintree offers custom interchange-plus pricing. There are no monthly fees or setup fees for the standard plan.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.