# Save Venmo with the JavaScript SDK (/platforms/checkout/save-payment-methods/during-purchase/js-sdk/venmo)



After customers save their Venmo account, they can select it for faster checkout. Customers won't have to enter payment details for future transactions.

## Availability [#availability]

Venmo is available only in the US.

## Know before you code [#know-before-you-code]

This integration requires a PayPal Developer account.

|                                                                                                                                                                                                                                                         |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Note:** The API URLs shown in the following examples point to a live environment. Venmo is not fully supported in the sandbox environment. For more information, refer to the [Venmo testing guidelines](/v5/venmo/integrate#test-and-go-live).<br /> |

## How it works [#how-it-works]

PayPal encrypts payment method information and stores it in a digital vault for that customer.

1. The payer saves their payment method.
2. For a first-time payer, PayPal creates a customer ID.
3. Store this within your system for future use.
4. When the customer returns to your website and is ready to check out, pass their PayPal-generated customer ID to the JavaScript SDK. The customer ID tells the JavaScript SDK to save or reuse a saved payment method.
5. The payer completes a billing agreement.
6. The JavaScript SDK populates the checkout page with each saved payment method. Each payment method appears as a one-click button next to other ways to pay.

The checkout process is now shorter because it uses saved payment information.

## Return payer experience [#return-payer-experience]

The following is an example of what a payer sees after they save their Venmo account on your site. Returning payers can select their saved payment method at checkout to pay faster.

<img src="https://www.paypalobjects.com/devdoc/save_venmo_sdk.png" alt="image" />

## Use cases [#use-cases]

Businesses save payment methods if they want customers to:

* Check out without re-entering a payment method
* Pay after use, for example, ride-sharing and food delivery

> **Warning:** PayPal requires Risk Data Acquisition (RDA) to reduce fraud. You must implement risk data collection for all customer-initiated transactions (CIT) that use PayPal and Venmo Payment Tokens. Payment attempts that are missing RDA data are likely to be declined due to insufficient risk identifiers. Use the PayPal 
>
> [FraudNet](/ratepay/fraudnet)
>
>  and 
>
> [Magnes](/limited-release/magnes)
>
>  libraries to collect and pass RDA data during payment processing.

## 1. Generate a user ID token for the payer [#1-generate-a-user-id-token-for-the-payer]

The OAuth 2.0 API to retrieve an `access_token` has an additional parameter, `response_type`, that can be set to `id_token`. Include the `id_token` and `access_token` in the response.

#### Platform [#platform]

### First-time payer [#first-time-payer]

A payer wants to save a payment method for the first time. Modify the following code to generate a user ID token for the payer:

```text lineNumbers
curl -s -X POST "https://api-m.paypal.com/v1/oauth2/token" \
  -u CLIENT_ID:CLIENT_SECRET \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -d "grant_type=client_credentials" \
 -d "response_type=id_token"
```

### Modify the code [#modify-the-code]

1. Copy the sample request code.
2. Change `CLIENT_ID` to your client ID.
3. Change `CLIENT_SECRET` to your client secret.

#### Platform [#platform-1]

### Returning Payer [#returning-payer]

A payer wants to use a saved payment method. Use the saved PayPal-generated customer ID in the POST body parameter target\_customer\_id. The target\_customer\_id is:

* a unique ID for a customer generated when the payment\_source is saved to the vault
* available when capturing the order or retrieving saved payment information.

|                                                                                                                                              |
| -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Note:** Use the customer identifier generated by PayPal and not the identifier that you use to identify the customer in your system.<br /> |

```text lineNumbers
curl -s -X POST https://api-m.paypal.com/v1/oauth2/token \
 -u CLIENT_ID:CLIENT_SECRET \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -d "grant_type=client_credentials" \
 -d "response_type=id_token" \
 -d "target_customer_id=4029352050" \ // PayPal-generated customer ID
```

### Modify the code [#modify-the-code-1]

1. Copy the sample request code.
2. Change CLIENT\_ID to your client ID.
3. Change CLIENT\_SECRET to your client secret.
4. Replace the PayPal-generated customer ID with the actual one that was stored in your system.

#### Merchant [#merchant]

### First-time payer [#first-time-payer-1]

A payer wants to save a payment method for the first time. Modify the following code to generate a user ID token for the payer:

#### Sample server-side user ID token request [#sample-server-side-user-id-token-request]

```text lineNumbers
curl -s -X POST https://api-m.paypal.com/v1/oauth2/token \
 -u CLIENT_ID:CLIENT_SECRET \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -H "PayPal-Auth-Assertion: AUTH-ASSERTION-TOKEN" \
 -d "grant_type=client_credentials" \
 -d "response_type=id_token"
```

### Modify the code [#modify-the-code-2]

1. Copy the sample request code.
2. Change CLIENT\_ID to your client ID.
3. Change CLIENT\_SECRET to your client secret.

#### Merchant [#merchant-1]

### Returning Payer [#returning-payer-1]

A payer wants to use a saved payment method. Use the saved PayPal-generated customer ID in the POST body parameter target\_customer\_id. The target\_customer\_id is:

* a unique ID for a customer generated when the payment\_source is saved to the vault
* available when capturing the order or retrieving saved payment information.

|                                                                                                                                              |
| -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Note:** Use the customer identifier generated by PayPal and not the identifier that you use to identify the customer in your system.<br /> |

#### Sample server-side user ID token request with a PayPal-generated customer ID [#sample-server-side-user-id-token-request-with-a-paypal-generated-customer-id]

```text lineNumbers
curl -s -X POST https://api-m.paypal.com/v1/oauth2/token \
 -u CLIENT_ID:CLIENT_SECRET \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -H "PayPal-Auth-Assertion: AUTH-ASSERTION-TOKEN" \
 -d "grant_type=client_credentials" \
 -d "response_type=id_token" \
 -d "target_customer_id=4029352050" // PayPal-generated customer ID
```

## 2. Add Venmo button [#2-add-venmo-button]

1. Add the JavaScript SDK code to show the Venmo button on your product and checkout pages.
2. Determine where the SDK should show the Venmo button.

Use configuration attributes to control the layout of the button. Use the `data-user-id-token` to pass the `id_token` from your server to the PayPal JavaScript SDK.

```text lineNumbers
<!-- Set up a container element for the button -->
  <div id="venmo-button-container"></div>
  <!-- Include the PayPal JavaScript SDK. Replace 'YOUR_CLIENT_ID' with your client ID.-->
  <!-- Pass 'enable-funding=venmo' as a query parameter. -->
  <!-- Replace 'YOUR_ID_TOKEN' with the id_token from your server. -->
  <script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&enable-funding=venmo" data-user-id-token="YOUR_ID_TOKEN"></script>
  <script>
    // Render the Venmo button into the #paypal-button-container
    paypal.Buttons().render('#venmo-button-container')
  </script>
```

## 3. Create an order [#3-create-an-order]

> **Warning:** PayPal requires Risk Data Acquisition (RDA) to reduce fraud. You must implement risk data collection for all customer-initiated transactions (CIT) that use PayPal and Venmo Payment Tokens. Payment attempts that are missing RDA data are likely to be declined due to insufficient risk identifiers. Use the PayPal 
>
> [FraudNet](/ratepay/fraudnet)
>
>  and 
>
> [Magnes](/limited-release/magnes)
>
>  libraries to collect and pass RDA data during payment processing.

Create an order on the client and server side.

> **Warning:** The following JavaScript functions are incompatible with Pay with Venmo when saving payment methods to the vault:
>
> * `onShippingAddressChange`
> * `onShippingChange`
> * `onShippingOptionsChange`

### Client side [#client-side]

Include client-side callbacks to:

* Manage interactions with APIs
* Manage payer approval flows
* Handle any events that lead to cancellation or error during payer approval

```text lineNumbers
<script>
    paypal.Buttons({
       // Call your server to set up the transaction
       createOrder: function(data, actions) {
            return fetch('/yourserver.com/createOrder', {
            method: 'post'
       }).then(function(res) {
           return res.json();
       }).then(function(orderData) {
           return orderData.id;
       });
       },
       // Authorize or capture the transaction after the payer approves
       onApprove: (data, actions) => {
           return actions.order.capture().then(function(orderData) {
              //Authorize or Capture API
              return fetch('/yourserver.com/order/' + data.orderID + '/capture/', {
              method: 'post'
          })
       },
       onCancel(data, actions) {
          console.log(`Order Canceled - ID: ${data.orderID}`);
       },
       onError(err) {
          console.error(err);
       }
     }).render('#paypal-button-container');
   </script>
```

### Server side [#server-side]

Set up your server to call the Create Order API. The button that the payer selects determines the `payment_source` sent in the following sample. To save Venmo as a payment method, use `payment_source.venmo.attributes` with the value `ON_SUCCESS` to pass appropriate attributes.

#### Platform [#platform-2]

### Request [#request]

Create an order with Venmo as a payment source:

```text lineNumbers
curl -v -X POST https://api-m.paypal.com/v2/checkout/orders \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer ACCESS-TOKEN" \
 -H "PayPal-Partner-Attribution-ID: BN-CODE" \
 -d '{
    "intent": "CAPTURE",
    "purchase_units": [
      {
        "amount": {
          "currency_code": "USD",
          "value": "100.00"
      }
      "payee:" {
        "merchant_id": "MERCHANT-ID"
      },
    }
  ],
    "payment_source": {
      "venmo": {
        "email_address": "customer@example.com",
        "experience_context": {
          "shipping_preference": "SET_PROVIDED_ADDRESS",
          "brand_name": "EXAMPLE INC"
        },
        "attributes": {
          "vault": {
            "store_in_vault": "ON_SUCCESS",
            "usage_type": "PLATFORM"
          }
        }
      }
    }
  }'
```

#### Merchant [#merchant-2]

### Request [#request-1]

Create an order with Venmo as a payment source:

```text lineNumbers
curl -v -X POST https://api-m.paypal.com/v2/checkout/orders \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer ACCESS-TOKEN" \
 -H "PayPal-Partner-Attribution-ID: BN-CODE" \
 -H "PayPal-Auth-Assertion: AUTH-ASSERTION-TOKEN" \
 -d '{
    "intent": "CAPTURE",
    "purchase_units": [{
      "amount": {
        "currency_code": "USD",
        "value": "100.00"
      }
    }
  ],
    "payment_source": {
      "venmo": {
        "email_address": "customer@example.com",
        "experience_context": {
          "shipping_preference": "SET_PROVIDED_ADDRESS",
          "brand_name": "EXAMPLE INC"
        },
        "attributes": {
          "vault": {
            "store_in_vault": "ON_SUCCESS",
            "usage_type": "MERCHANT"
          }
        }
      }
    }
  }'
```

### Response [#response]

Check the status of the response. Return the id to your client to call the payer approval flow if the `payment_source` needs payer approval.

The payer is redirected to the `payer_action` URL.

```text lineNumbers
{
    "id": "5O190127TN364715T",
    "status": "PAYER_ACTION_REQUIRED",
    "payment_source": {
      "venmo": {
        "email_address": "customer@example.com"
      }
    },
    "links": [{
      "href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
      "rel": "self",
      "method": "GET"
    }]
  }
```

## 4. Payer approval [#4-payer-approval]

The SDK prompts the payer to switch to Venmo. In Venmo, the payer agrees to save their account as a payment method.

If the payer doesn't have Venmo installed or uses a desktop, the SDK presents the payer with a QR code. The payer scans the code with a mobile device camera or the Venmo in-app scanning feature.

## 5. Authorize or capture order [#5-authorize-or-capture-order]

After the payer approves, the `onApprove` function is called in the JavaScript SDK. Depending on the intent passed, the server calls the following APIs:

* Capture Order API if the `intent` passed was `CAPTURE`
* Authorize Order API if the `intent` passed was `AUTHORIZE` as part of your Create Order call.

If authorization or capture is successful, a vault.id is also created.

### Authorize order request call [#authorize-order-request-call]

#### Platform [#platform-3]

```text lineNumbers
curl -v -X POST https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T/authorize \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer ACCESS-TOKEN" \
 -H "PayPal-Partner-Attribution-ID: BN-CODE" \
 -d '{}'
```

#### Merchant [#merchant-3]

```text lineNumbers
curl -v -X POST https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T/authorize \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer ACCESS-TOKEN" \
 -H "PayPal-Partner-Attribution-ID: BN-CODE" \
 -H "PayPal-Auth-Assertion: AUTH-ASSERTION-TOKEN" \
 -d '{}'
```

### Capture order request call [#capture-order-request-call]

#### Platform [#platform-4]

```text lineNumbers
curl -v -X POST https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T/capture \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer ACCESS-TOKEN" \
 -H "PayPal-Partner-Attribution-ID: BN-CODE" \
 -d '{}'
```

#### Merchant [#merchant-4]

```text lineNumbers
curl -v -X POST https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T/capture \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer ACCESS-TOKEN" \
 -H "PayPal-Partner-Attribution-ID: BN-CODE" \
 -H "PayPal-Auth-Assertion: AUTH-ASSERTION-TOKEN" \
 -d '{}'
```

### Capture order response [#capture-order-response]

The HTTP response codes HTTP 2xx or HTTP 200 are returned for a successful request.

The capture is successful if the `purchase_units[0].payments.captures.status` is `COMPLETED`. You can confirm with the payer that the payment has been captured.

In the response from the authorize or capture request, the Orders v2 API interacts with the Payment Method Tokens v3 API. The Payment Method Tokens v3 API allows a Venmo account to be saved. The response from the Orders v2 API contains the:

* `vault.id`
* `customer.id`
* `vault.status`
* `links` for the payment token of a recently saved Venmo account.

On a successful response, the `payment_source.venmo.attribute.vault.status` is set to `VAULTED` along with the vault ID at `payment_source.venmo.attribute.vault.id.`

Capture order response:

```text lineNumbers
{
    "id": "5O190127TN364715T",
    "status": "COMPLETED",
    "payment_source": {
      "venmo": {
        "user_name": "nickname",
        "name": {
          "given_name": "Firstname",
          "surname": "Lastname"
        },
        "email_address": "customer@example.com",
        "phone_number": {
          "national_number": "2025212022"
        },
        "account_id": "QYR5Z8XDVJNXQ",
        "address": {
          "address_line_1": "123 Townsend St",
          "address_line_2": "Floor 6",
          "admin_area_2": "San Francisco",
          "admin_area_1": "CA",
          "postal_code": "94107",
          "country_code": "US"
        },
        "attribute": {
          "vault": {
            "id": "ckfmsf",
           "customer": {
               "id": "4029352050"
           },
            "status": "VAULTED",
            "links": [{
                "href": "https://api-m.paypal.com/v3/vault/payment-tokens/ckfmsf",
                "rel": "self",
                "method": "GET"
              },
              {
                "href": "https://api-m.paypal.com/v3/vault/payment-tokens/ckfmsf",
                "rel": "delete",
                "method": "DELETE"
              },
              {
                "href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
                "rel": "up",
                "method": "GET"
              }
            ]
          }
        }
      }
    },
    "purchase_units": [{
      "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
      "payments": {
        "captures": [{
          "id": "3C679366HH908993F",
          "status": "COMPLETED",
          "amount": {
            "currency_code": "USD",
            "value": "100.00"
          },
          "seller_protection": {
            "status": "ELIGIBLE",
            "dispute_categories": [
              "ITEM_NOT_RECEIVED",
              "UNAUTHORIZED_TRANSACTION"
            ]
          },
          "final_capture": true,
          "disbursement_mode": "INSTANT",
          "seller_receivable_breakdown": {
            "gross_amount": {
              "currency_code": "USD",
              "value": "100.00"
            },
            "paypal_fee": {
              "currency_code": "USD",
              "value": "3.00"
            },
            "net_amount": {
              "currency_code": "USD",
              "value": "97.00"
            }
          },
          "create_time": "2022-01-01T21:20:49Z",
          "update_time": "2022-01-01T21:20:49Z",
          "links": [{
              "href": "https://api-m.paypal.com/v2/payments/captures/3C679366HH908993F",
              "rel": "self",
              "method": "GET"
            },
            {
              "href": "https://api-m.paypal.com/v2/payments/captures/3C679366HH908993F/refund",
              "rel": "refund",
              "method": "POST"
            },
            {
              "href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
              "rel": "up",
              "method": "GET"
            }
          ]
        }]
      }
    }]
  }
```

### Save approved payment source [#save-approved-payment-source]

If the payment has been authorized or captured, the payer does not need to be present to save a `payment_source`. To keep checkout times as short as possible, the Orders API responds as soon as payment is captured.

If the `attributes.vault.status` returned after payment is `APPROVED`, you won't have a `vault.id` yet. An example of the attributes object from this scenario is in the following sample:

```text lineNumbers
"attributes": {
        "vault": {
          "status": "APPROVED",
          "links": [
            {
              "href": "https://api-m.paypal.com/v2/checkout/orders/5O190127TN364715T",
              "rel": "up",
              "method": "GET"
            }
          ]
        }
      }
```

The Payment Method Tokens API still saves the payment source even after the Orders API returns its response and sends a webhook after the payment source is saved.

In order to retrieve a `vault_id` when an `APPROVED` status is returned, you'll need to subscribe to the `VAULT.PAYMENT-TOKEN.CREATED` webhook.

The Payment Method Tokens API sends a webhook after the payment source is saved. An example of the `VAULT.PAYMENT-TOKEN.CREATED` webhook payload is shown in the following sample:

### Vault webhook payload sample [#vault-webhook-payload-sample]

```text lineNumbers
{
  "id": "WH-54U753518P812093G-3GD69489S94654234",
  "event_version": "1.0",
  "create_time": "2022-10-13T23:04:17.378Z",
  "resource_type": "payment_token",
  "resource_version": "3.0",
  "event_type": "VAULT.PAYMENT-TOKEN.CREATED",
  "summary": "A payment token has been created.",
  "resource": {
                "create_time": "2018-12-11T21:21:49.000Z",
                "update_time": "2018-12-11T21:21:49.000Z",
                "id": "ckfmsf",
                "customer": {
                    "id": "4029352050"
                },
                "payment_source": {
                    "venmo": {
                        "description": "Description for Venmo to be shown to Venmo payer",
                        "shipping": {
                            "name": {
                                "full_name": "Firstname Lastname"
                            },
                            "address": {
                                "address_line_1": "2211 N First Street",
                                "address_line_2": "Building 17",
                                "admin_area_2": "San Jose",
                                "admin_area_1": "CA",
                                "postal_code": "95131",
                                "country_code": "US"
                            }
                        },
                        "usage_pattern": "IMMEDIATE",
                        "usage_type": "MERCHANT",
                        "customer_type": "CONSUMER",
                        "email_address": "firstname.lastname@example.com",
                        "payer_id": "VYYFH3WJ4JPJQ",
                        "user_name": "firstnamelastname"
                    }
                },
                "links": [
                    {
                        "rel": "self",
                        "href": "https://api-m.paypal.com/v3/vault/payment-tokens/ckfmsf",
                        "method": "GET"
                    },
                    {
                        "rel": "delete",
                        "href": "https://api-m.paypal.com/v3/vault/payment-tokens/ckfmsf",
                        "method": "DELETE"
                    }
                ]
    },
  "links": [
    {
      "href": "https://api-m.paypal.com/v1/notifications/webhooks-events/WH-54U753518P812093G-3GD69489S94654234",
      "rel": "self",
      "method": "GET"
    },
    {
      "href": "https://api-m.paypal.com/v1/notifications/webhooks-events/WH-54U753518P812093G-3GD69489S94654234/resend",
      "rel": "resend",
      "method": "POST"
    }
  ]
}
```

In the previous example, the `resource.id` field is the vault ID. The `resource.customer.id` is the PayPal-generated customer ID.

## 6. Test your integration [#6-test-your-integration]

Run the following tests in your live environment to ensure you can save Venmo as a payment method:

### Save payment method [#save-payment-method]

1. On your checkout page, click the Venmo button.
2. Log in to the payer account and approve the payment. Refer to the [Venmo testing guidelines](/v5/venmo/integrate#test-and-go-live) for more details.
3. Capture the transaction.
4. Store the PayPal-generated customer ID in your system.
5. Log in to [your live environment](https://www.paypal.com/) with your merchant account and verify the transaction.
6. Refresh the page that contains the Venmo button. Ensure the JavaScript SDK is initialized with the PayPal-generated customer ID.
7. Ensure the Venmo button displays the payer's Venmo ID and user handle (@firstnamelastname).
8. Ensure that the payment method you just saved is visible with the other buttons.
9. Select the Venmo button again to test the return payer flow.

## Next steps [#next-steps]

* [Test and go live](/api/rest/production/) with this integration. Note that Venmo is not available in the sandbox environment.
* You can [create orders](/api/orders/v2/orders-create) without the `payment_source.venmo.attributes.vault` for subsequent or recurring transactions.
* You can [get a payment token](/api/payment-tokens/v3#payment-tokens_get), [list all payment tokens](/api/payment-tokens/v3#payment-tokens_payment-tokens), [delete a payment token](/api/payment-tokens/v3#payment-tokens_delete), and more with the Payment Method Tokens API.
