Venmo Vaulting: One-Click Repeat Purchases

Save a customer’s Venmo account on their first purchase and charge it with a single click on every purchase after — no Venmo app-switch or approval step.

Overview

Every standard Venmo checkout asks the customer to approve the payment in Venmo — a popup or an app-switch into the Venmo app, and an approval tap before the purchase completes. That context switch is where repeat buyers drop off: they have already trusted you with a purchase, but every subsequent checkout makes them prove it again.

Venmo vaulting removes that step for returning customers. When vaulting is enabled on your account, the customer’s Venmo account is securely saved (“vaulted”) after their first successful payment. From then on, checkouts against that saved account complete in a single click — Coinflow charges the vaulted account directly and the payment is authorized immediately, with no popup, no app-switch, and no approval screen.

The result is a materially lower-friction checkout that converts better where it matters most:

  • One click instead of three-plus steps. The customer never leaves your checkout — no popup to allow, no Venmo app to switch into, no approval screen.
  • Higher repeat-purchase conversion. Each removed step is an exit ramp; vaulting removes all of them for the buyers most likely to purchase again.
  • Mobile-friendly by default. The app-switch approval flow is most fragile on mobile browsers and inside webviews; vaulted checkouts skip it entirely.
  • Instant feedback. The payment is authorized synchronously, so you can show a confirmation the moment the request returns instead of waiting on an approval round-trip.

Vaulting is a per-account setting — contact your Coinflow integrations team to enable it. If you use Coinflow’s prebuilt checkout UI or the CoinflowVenmoButton component, the first-purchase save then happens automatically. Direct API integrations opt in per order with the vault flag described below.

How It Works

  1. Vaulting is enabled on your Coinflow account by the integrations team.
  2. A customer completes a normal Venmo checkout (new or saved) with vault: true and approves the payment in Venmo as usual — the approval discloses that the account will be saved.
  3. As part of that successful payment, the customer’s Venmo account is vaulted and Coinflow stores the resulting vault token against the customer’s saved Venmo account automatically.
  4. On later checkouts, the customer’s saved Venmo account carries vaulted: true — your signal that the one-click path is available.
  5. You call the Venmo Vaulted Checkout endpoint with the saved account’s token and a FraudNet clientMetadataId (see Collecting Fraud Data with FraudNet). Coinflow charges the vaulted account and authorizes the payment immediately — there is no approval step for the customer.
  6. Your backend receives the Authorized webhook right away, followed by Settled when funds are delivered, exactly as with any other Venmo payment.

Requesting Vaulting on a Purchase

Pass vault: true on the new or saved checkout to have the account saved when the payment succeeds. Vaulting orders require both returnUrl and cancelUrl — the processor rejects vaulting orders without redirect URLs, so the request is rejected with a 400 when they are missing.

$curl --location 'https://api-sandbox.coinflow.cash/api/checkout/venmo/<YOUR_MERCHANT_ID>' \
>--header 'accept: application/json' \
>--header 'content-type: application/json' \
>--header 'x-coinflow-auth-session-key: <YOUR_SESSION_KEY>' \
>--data-raw '{
> "subtotal": {
> "cents": 500,
> "currency": "USD"
> },
> "venmo": {
> "email": "customer@example.com"
> },
> "vault": true,
> "returnUrl": "https://example.com/checkout/return",
> "cancelUrl": "https://example.com/checkout/cancel"
>}'

The vault flag is only honored while vaulting is enabled on your Coinflow account — with vaulting disabled, the order proceeds as a normal checkout. The URL values above are examples only; in a popup/SDK integration the customer never navigates to them, but they must still point at one of your merchant account’s whitelisted URLs — a redirect URL on any other origin is rejected with a 403.

Detecting a Vaulted Account

Fetch the customer with Get Customer and check the saved Venmo account for vaulted: true:

$curl --location 'https://api-sandbox.coinflow.cash/api/customer/v2' \
>--header 'accept: application/json' \
>--header 'x-coinflow-auth-session-key: <YOUR_SESSION_KEY>'

Response (truncated):

1{
2 "customer": {
3 "venmo": {
4 "type": "venmo",
5 "alias": "customer@example.com",
6 "token": "EXAMPLE_SAVED_ACCOUNT_TOKEN",
7 "vaulted": true
8 }
9 }
10}

The values above are examples only — read the real token from the API response. The vaulted flag is only returned while vaulting is enabled on your account (the vault token itself never leaves Coinflow’s servers); if the account is not vaulted, fall back to the standard saved checkout approval flow.

Collecting Fraud Data with FraudNet (Required)

Because a vaulted checkout has no Venmo approval step, browser fraud data must be collected on the checkout page instead. This is done with FraudNet, a small PayPal JavaScript library (Venmo payments are processed by PayPal) you embed on the page where the customer confirms the purchase. FraudNet gathers device and browser signals keyed by a client metadata ID (CMID) that you generate, and you pass that same CMID to the vaulted checkout so PayPal Risk can match the payment to the collected data.

The vaulted checkout endpoint requires clientMetadataId — requests without it are rejected with a 400.

If you use Coinflow’s prebuilt checkout UI or the CoinflowVenmoButton component, FraudNet is embedded and the CMID is sent automatically — you can skip this section. Direct API integrations must embed FraudNet themselves as described below.

1

Generate a CMID for the page view

Generate a random ID of up to 32 characters, unique per page view (a UUID with the dashes removed works well). You will use the same value in the FraudNet snippet and the checkout request.

1const clientMetadataId = crypto.randomUUID().replace(/-/g, '');
2

Embed the FraudNet snippet on your checkout page

Add the parameter block and the FraudNet script to the page where the customer confirms the vaulted purchase. The fncls attribute value is mandated by PayPal and must be exactly as shown.

1<script type="application/json" fncls="fnparams-dede7cc5-15fd-4c75-a9f4-36c430ee3a99">
2 {
3 "f": "EXAMPLE_CMID_REPLACE_WITH_YOURS",
4 "s": "YOUR_COMPANY_CHECKOUT_PAGE",
5 "sandbox": true
6 }
7</script>
8<script type="text/javascript" src="https://c.paypal.com/da/r/fb.js"></script>
  • f — the CMID you generated in the previous step.
  • s — a static label you define identifying the page (recommended format <YOUR_COMPANY>_<PAGE_NAME>, max 32 characters). The value above is an example only — choose your own.
  • sandbox — set true when testing against the Coinflow sandbox; omit it in production.

In a single-page app, inject both tags dynamically when the checkout page mounts instead of hardcoding them in the document head:

1function loadFraudNet({clientMetadataId, sandbox}) {
2 if (document.getElementById('fnparams')) return;
3
4 const params = document.createElement('script');
5 params.type = 'application/json';
6 params.id = 'fnparams';
7 params.setAttribute('fncls', 'fnparams-dede7cc5-15fd-4c75-a9f4-36c430ee3a99');
8 params.text = JSON.stringify({
9 f: clientMetadataId,
10 s: 'YOUR_COMPANY_CHECKOUT_PAGE',
11 ...(sandbox ? {sandbox: true} : {}),
12 });
13
14 const script = document.createElement('script');
15 script.type = 'text/javascript';
16 script.async = true;
17 script.src = 'https://c.paypal.com/da/r/fb.js';
18
19 document.head.appendChild(params);
20 document.head.appendChild(script);
21}
3

Pass the CMID on the vaulted checkout

Send the same value as clientMetadataId in the request body of the Venmo Vaulted Checkout call, as shown in the next section.

Generate a fresh CMID per page view (not per customer or per session) and load FraudNet as early as possible — the longer the snippet runs before the customer clicks pay, the more signal PayPal Risk has to approve the payment.

Charging a Vaulted Account

When the saved account is vaulted, call the Venmo Vaulted Checkout endpoint with the saved account’s token and the FraudNet clientMetadataId collected on the page.

$curl --location 'https://api-sandbox.coinflow.cash/api/checkout/venmo/vaulted/<YOUR_MERCHANT_ID>' \
>--header 'accept: application/json' \
>--header 'content-type: application/json' \
>--header 'x-coinflow-auth-session-key: <YOUR_SESSION_KEY>' \
>--data-raw '{
> "subtotal": {
> "cents": 500,
> "currency": "USD"
> },
> "token": "EXAMPLE_SAVED_ACCOUNT_TOKEN",
> "clientMetadataId": "EXAMPLE_CMID_REPLACE_WITH_YOURS"
>}'

Response:

1{
2 "paymentId": "EXAMPLE_PAYMENT_ID"
3}

By the time the response returns, the payment is already authorized — there is no approval link to follow and no SDK session to run.

Do not open the Venmo SDK approval flow for a vaulted checkout. The order is created already payer-approved, so there is nothing for the customer to approve — render your own “Pay” button (or reuse the Venmo-branded button without starting a session) and treat a successful response as the completed purchase.

A clean integration pattern: when the customer’s saved Venmo account is vaulted, route the click to the vaulted endpoint and show your confirmation UI on success; otherwise run the standard saved-checkout approval flow. Coinflow’s prebuilt checkout UI and CoinflowVenmoButton component do exactly this automatically once vaulting is enabled on your account.

Confirming the Payment

Vaulted payments emit the same webhook lifecycle as every other Venmo payment, just without the waiting:

  • Authorized — sent immediately after the vaulted checkout succeeds.
  • Settled — sent when funds are delivered to your configured settlement location. This remains the recommended signal to fulfill the purchase.
  • Failure — sent if the charge is declined or blocked by risk checks.

See Checkout Webhooks for configuring your webhook endpoint.