# Save cards with the Payment Method Tokens API (/limited-release/commerce-platform/accept-payments/save-payments/purchase-later/payment-tokens-api/save-cards)



No transaction is required when payment methods are saved with the [Payment Method Tokens API](/api/payment-tokens/v3). You can charge payers after a set amount of time. Payers don't need to be present when charged. A common use case is offering a free trial and charging payers after the trial expires.

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

* This server-side integration uses the [Payment Method Tokens API](/api/payment-tokens/v3).
* The Payment Method Tokens API supports saving cards and PayPal Wallets.
* Complete the steps in [Get started](/limited-release/commerce-platform/get-started/) to get the following sandbox account information from the Developer Dashboard:
  * Your sandbox account login information
  * Your access token
* You must be approved and have your account configured for billing agreements to set up a reference transaction. Contact your account manager for details.
* You'll need an existing [advanced credit and debit card payments](/limited-release/commerce-platform/accept-payments/advanced/) integration. PayPal must approve your business account for advanced credit and debit card payments.
* The Payment Method Tokens API requires SAQ D PCI Compliance.

## 1. Create setup token for card [#1-create-setup-token-for-card]

Create a setup token for cards that have:

* No verification
* Smart authorization
* 3D Secure verification

When saving a card for the first time for a payer, the response to the setup token request returns the `customer.id` and the `setup_token_id`.

> **Note:** **Tip:** For a payer with previously stored `payment_sources`, pass the PayPal-generated `customer.id` in the setup token request. Then you can link additional `payment_sources` to this payer.

### Platform: No verification [#platform-no-verification]

#### Setup token for card with no verification [#setup-token-for-card-with-no-verification]

There's usually no transaction when saving a card and creating a setup token. The data passed to the API is only checked for format.

#### Sample request and response [#sample-request-and-response]

#### Sample request

```text lineNumbers
curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/setup-tokens \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ACCESS-TOKEN' \
  -H 'PayPal-Partner-Attribution-Id: BN-CODE' \
  -H 'PayPal-Auth-Assertion: AUTH-ASSERTION-JWT' \
  -H 'PayPal-Request-Id: REQUEST-ID' \
  -d '{
    "payment_source": {
      "card": {
        "number": "4111111111111111",
        "expiry": "2027-02",
        "name": "Firstname Lastname",
        "billing_address": {
          "address_line_1": "2211 N First Street",
          "address_line_2": "17.3.160",
          "admin_area_1": "CA",
          "admin_area_2": "San Jose",
          "postal_code": "95131",
          "country_code": "US"
        },
        "experience_context": {
          "brand_name": "YourBrandName",
          "locale": "en-US",
          "return_url": "https://example.com/returnUrl",
          "cancel_url": "https://example.com/cancelUrl"
        }
      }
    }
  }'
```

#### Sample response

```text lineNumbers
{
  "id": "5C991763VB2771612",
  "customer": {
    "id": "customer_4029352050"
  },
  "status": "APPROVED",
  "payment_source": {
    "card": {
      "name": "Firstname Lastname"
      "last_digits": "1111",
      "expiry": "2027-02",
      "billing_address": {
        "address_line_1": "2211 N First Street",
        "address_line_2": "17.3.160",
        "admin_area_2": "San Jose",
        "admin_area_1": "CA",
        "postal_code": "95131",
        "country_code": "US"
      }
    }
  },
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/setup-tokens/5C991763VB2771612",
      "rel": "self",
      "method": "GET",
      "encType": "application/json"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens",
      "rel": "confirm",
      "method": "POST",
      "encType": "application/json"
    }
  ]
}
```

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

1. Copy the sample request code.
2. Change `ACCESS-TOKEN` to your [sandbox access token](/api/rest/authentication/).
3. Change `BN-CODE` to your [PayPal Attribution ID](/api/rest/requests/#paypal-partner-attribution-id) to receive revenue attribution. To find your BN code, see [Code and Credential Reference](/platforms/create-account/#link-bncode).
4. Change `AUTH-ASSERTION-JWT` to your [PayPal-Auth-Assertion](/api/rest/requests/#paypal-auth-assertion) token.
5. Change `REQUEST-ID` to a set of unique alphanumeric characters such as a time stamp.

#### Step result [#step-result]

A successful request returns the following:

* HTTP response code `HTTP 2xx` or `HTTP 200`.
* The ID of the token in the `id` field.
* HATEOAS links:

| Rel       | Method | Description                                                                                         |
| --------- | ------ | --------------------------------------------------------------------------------------------------- |
| `self`    | `GET`  | Make a GET request to this link to retrieve payment source data associated with the setup token ID. |
| `confirm` | `POST` | Make a POST request to generate the payment token using the approved setup token.                   |

### Platform: Smart authorization [#platform-smart-authorization]

#### Setup token for card with smart authorization [#setup-token-for-card-with-smart-authorization]

You can use the POST action to run smart authorization against the card. In countries where the issuing banks support it, smart authorization runs a zero-value authorization against the card.

If zero-value authorization is not supported, an authorization for a minimal value in the local currency is requested. Authorizations for minimal amounts aren't automatically voided and create a temporary hold against the payer's card.

To request verification of card data, add the `verification_method` parameter on the `POST` [setup-tokens](/api/payment-tokens/v3#setup-tokens) call.

#### Sample request and response [#sample-request-and-response-1]

#### Sample request

```text lineNumbers
curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/setup-tokens \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ACCESS-TOKEN' \
  -H 'PayPal-Partner-Attribution-Id: BN-CODE' \
  -H 'PayPal-Auth-Assertion: AUTH-ASSERTION-JWT' \
  -H 'PayPal-Request-Id: REQUEST-ID' \
  -d '{
    "payment_source": {
      "card": {
        "number": "4111111111111111",
        "expiry": "2027-02",
        "name": "Firstname Lastname",
        "billing_address": {
          "address_line_1": "2211 N First Street",
          "address_line_2": "17.3.160",
          "admin_area_1": "CA",
          "admin_area_2": "San Jose",
          "postal_code": "95131",
          "country_code": "US"
        },
        "verification_method": "SCA_WHEN_REQUIRED",
        "experience_context": {
          "brand_name": "YourBrandName",
          "locale": "en-US",
          "return_url": "https://example.com/returnUrl",
          "cancel_url": "https://example.com/cancelUrl"
        }
      }
    }
  }'
```

#### Sample response

```text lineNumbers
{
  "id": "5C991763VB2771612",
  "customer": {
    "id": "customer_4029352050"
  },
  "status": "APPROVED",
  "payment_source": {
    "card": {
      "brand": "VISA",
      "last_digits": "1111",
      "verification_status": "VERIFIED",
      "verification": {
        "network_transaction_id": "20286098380002303",
        "time": "2020-10-07T22:44:41.000Z",
        "amount": {
          "value": "0.00",
          "currency_code": "USD"
        },
        "processor_response": {
          "avs_code": "M",
          "cvv_code": "P"
        }
      }
    }
  },
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-token",
      "rel": "confirm",
      "method": "POST",
      "encType": "application/json"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/setup-tokens/5C991763VB2771612",
      "rel": "self",
      "method": "GET",
      "encType": "application/json"
    }
  ]
}
```

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

1. Copy the sample request code.
2. Change `ACCESS-TOKEN` to your sandbox access token.
3. Change `BN-CODE` to your [PayPal Attribution ID](/api/rest/requests/#paypal-partner-attribution-id) to receive revenue attribution. To find your BN code, see [Code and Credential Reference](/platforms/create-account/#link-bncode).
4. Change `AUTH-ASSERTION-JWT` to your [PayPal-Auth-Assertion](/api/rest/requests/#paypal-auth-assertion) token.
5. Change `REQUEST-ID` to a set of unique alphanumeric characters such as a time stamp.
6. Use the card as the payment source and complete the rest of the source object for your use case and business.
7. Pass the `verification_method` parameter to verify card data.
8. Update the `return_url` value with the URL where the payer is redirected after they approve the flow.
9. Update the `cancel_url` value with the URL where the payer is redirected after they cancel the flow.

Pass one of the following `verification_method` attributes to verify card data:

| Verification Method | Description                                                                                                                                            |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| SCA\_WHEN\_REQUIRED | Returns a 3D Secure contingency when it is a mandate in the region where you operate. This is the default when neither parameter is explicitly passed. |
| `SCA_ALWAYS`        | Triggers 3D Secure for every transaction.                                                                                                              |

#### Step result [#step-result-1]

A successful request returns the following:

* HTTP response code `HTTP 2xx` or `HTTP 200`.
* Status of `APPROVED`.
* HATEOAS links:

| Rel       | Method | Description                                                                                                          |
| --------- | ------ | -------------------------------------------------------------------------------------------------------------------- |
| `confirm` | `POST` | Make a POST request to generate the payment token using the approved setup token.                                    |
| `self`    | `GET`  | Make a GET request to get information about the temporarily saved payment source associated with the setup token ID. |

If the request and authorization succeed, the setup token is approved and additional parameters are returned in the response.

### Platform: 3D Secure verification [#platform-3d-secure-verification]

#### Setup token for card with 3D Secure verification [#setup-token-for-card-with-3d-secure-verification]

Use [3D Secure authentication](/limited-release/commerce-platform/accept-payments/advanced/customize/use-3d-secure/) to reduce the likelihood of fraud and improve transaction performance with supported cards. In some countries, authorizing a card can trigger a [3D Secure contingency](/limited-release/commerce-platform/accept-payments/advanced/customize/use-3d-secure/orders-api/#1-include-a-contingency-for-3d-secure). 3D Secure verification may occur in PSD2 countries, including members of the EU. For 3D Secure verification, pass `SCA_ALWAYS` or `SCA_WHEN_REQUIRED` in the `payment_source.card.attributes.verification.method` field for the create order request. The API response returns the order status as `PAYER_ACTION_REQUIRED`.

#### Sample request

```text lineNumbers
curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/setup-tokens \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ACCESS-TOKEN' \
  -H 'PayPal-Partner-Attribution-Id: BN-CODE' \
  -H 'PayPal-Auth-Assertion: AUTH-ASSERTION-JWT' \
  -H 'PayPal-Request-Id: REQUEST-ID' \
  -d '{
    "payment_source": {
      "card": {
        "number": "4111111111111111",
        "expiry": "2027-02",
        "name": "Firstname Lastname",
        "billing_address": {
          "address_line_1": "2211 N First Street",
          "address_line_2": "17.3.160",
          "admin_area_1": "CA",
          "admin_area_2": "San Jose",
          "postal_code": "95131",
          "country_code": "US"
        },
        "verification_method": "SCA_WHEN_REQUIRED",
        "experience_context": {
          "brand_name": "YourBrandName",
          "locale": "en-US",
          "return_url": "https://example.com/returnUrl",
          "cancel_url": "https://example.com/cancelUrl"
        }
      }
    }
  }'
```

#### Sample response

```text lineNumbers
{
  "id": "5C991763VB2771612",
  "customer": {
    "id": "customer_4029352050"
  },
  "status": "PAYER_ACTION_REQUIRED",
  "payment_source": {
    "card": {
      "last_digits": "1111",
      "brand": "VISA",
      "type": "CREDIT",
      "expiry": "2027-02"
    }
  },
  "links": [
    {
      "href": "https://paypal.com/webapps/helios?action=authenticate&validate_session_id=82cf4a87-5c40-0a27-1a09-4ffbb0d05fdc",
      "rel": "approve",
      "method": "GET",
      "encType": "application/json"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-token",
      "rel": "confirm",
      "method": "POST",
      "encType": "application/json"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/setup-tokens/5C991763VB2771612",
      "rel": "self",
      "method": "GET",
      "encType": "application/json"
    }
  ]
}
```

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

1. Copy the sample request code.
2. Change `ACCESS-TOKEN` to your sandbox access token.
3. Change `PAYPAL-AUTH-ASSERTION` to your [PayPal-Auth-Assertion](/api/rest/requests/#paypal-auth-assertion) token.
4. Change `BN-CODE` to your [PayPal Attribution ID](/api/rest/requests/#paypal-partner-attribution-id) to receive revenue attribution. To find your BN code, see [Code and Credential Reference](/platforms/create-account/#link-bncode).
5. Change `REQUEST-ID` to a set of unique alphanumeric characters such as a time stamp.
6. Use a card as the payment source and complete the rest of the source object for your use case and business.
7. Pass the `verification_method` parameter with `SCA_WHEN_REQUIRED` to verify card data.
8. Update the `return_url` value with the URL where the payer is redirected after they approve the flow.
9. Update the `cancel_url` value with the URL where the payer is redirected after they cancel the flow.

### Step result [#step-result-2]

A successful request returns the following:

* HTTP response code `HTTP 2xx` or `HTTP 200`.
* Status of `PAYER_ACTION_REQUIRED`.
* HATEOAS links:

| Rel       | Method | Description                                                                                                 |
| --------- | ------ | ----------------------------------------------------------------------------------------------------------- |
| `approve` | `GET`  | Use this link to take your payer through the card approval flow.                                            |
| `confirm` | `POST` | Make a POST request to use an approved setup token to save the payment method and generate a payment token. |
| `self`    | `GET`  | Make a GET request to view the state of your setup token and payment method details.                        |

### Merchant: No verification [#merchant-no-verification]

#### Setup token for card with no verification [#setup-token-for-card-with-no-verification-1]

There is usually no transaction when saving a card and creating a setup token. The data passed to the API is checked only for format.

> **Note:** **Note:** When saving a card for the first time for a payer, the response to the setup token request returns the `customer.id` and the `vault.id`. Store the `vault.id` in your system for future use.

#### Sample request and response [#sample-request-and-response-2]

#### Sample request

```text lineNumbers
curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/setup-tokens \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ACCESS-TOKEN' \
  -H 'PayPal-Partner-Attribution-Id: BN-CODE' \
  -H 'PayPal-Auth-Assertion: AUTH-ASSERTION-JWT' \
  -H 'PayPal-Request-Id: REQUEST-ID' \
  -d '{
    "payment_source": {
      "card": {
        "number": "4111111111111111",
        "expiry": "2027-02",
        "name": "Firstname Lastname",
        "billing_address": {
          "address_line_1": "2211 N First Street",
          "address_line_2": "17.3.160",
          "admin_area_1": "CA",
          "admin_area_2": "San Jose",
          "postal_code": "95131",
          "country_code": "US"
        },
        "experience_context": {
          "brand_name": "YourBrandName",
          "locale": "en-US",
          "return_url": "https://example.com/returnUrl",
          "cancel_url": "https://example.com/cancelUrl"
        }
      }
    }
  }'
```

#### Sample response

```text lineNumbers
{
  "id": "5C991763VB2771612",
  "customer": {
    "id": "customer_4029352050"
  },
  "status": "APPROVED",
  "payment_source": {
  "card": {
    "name": "Firstname Lastname",
    "last_digits": "1111",
    "expiry": "2027-02",
    "billing_address": {
      "address_line_1": "2211 N First Street",
      "address_line_2": "17.3.160",
      "admin_area_2": "San Jose",
      "admin_area_1": "CA",
      "postal_code": "95131",
      "country_code": "US"
    }
  },
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/setup-tokens/5C991763VB2771612",
      "rel": "self",
      "method": "GET",
      "encType": "application/json"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens",
      "rel": "confirm",
      "method": "POST",
      "encType": "application/json"
    }
  ]
}
```

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

1. Copy the sample request code.
2. Change `ACCESS-TOKEN` to your [sandbox access token](/api/rest/authentication).
3. Change `BN-CODE` to your [PayPal Attribution ID](/api/rest/requests/#paypal-partner-attribution-id) to receive revenue attribution. To find your BN code, see [Code and Credential Reference](/platforms/create-account/#link-bncode).
4. Change `AUTH-ASSERTION-JWT` to your [PayPal-Auth-Assertion](/api/rest/requests/#paypal-auth-assertion) token.
5. Change `REQUEST-ID` to a set of unique alphanumeric characters such as a time stamp.

#### Step result [#step-result-3]

A successful request returns the following:

* HTTP response code `HTTP 2xx` or `HTTP 200`.
* The ID of the token is in the `id` field.
* HATEOAS links:

| Rel       | Method | Description                                                                                             |
| --------- | ------ | ------------------------------------------------------------------------------------------------------- |
| `self`    | `GET`  | Make a GET request to this link to retrieve the payment source data associated with the setup token ID. |
| `confirm` | `POST` | Make a POST request to generate the payment token using the approved setup token.                       |

### Merchant: Smart authorization [#merchant-smart-authorization]

#### Setup token for card with smart authorization [#setup-token-for-card-with-smart-authorization-1]

You can use the POST action to run smart authorization against the card. In countries where the issuing banks support it, smart authorization runs a zero-value authorization against the card.

If zero-value authorization is not supported, an authorization for a minimal value in the local currency is requested. Authorizations for minimal amounts aren't automatically voided and create a temporary hold against the payer's card.

To request verification of card data, modify the `POST` on the [setup-tokens](/api/payment-tokens/v3#setup-tokens) call by adding the `verification_method` parameter:

#### Sample request and response [#sample-request-and-response-3]

#### Sample request

```text lineNumbers
curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/setup-tokens \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ACCESS-TOKEN' \
  -H 'PayPal-Partner-Attribution-Id: BN-CODE' \
  -H 'PayPal-Auth-Assertion: AUTH-ASSERTION-JWT' \
  -H 'PayPal-Request-Id: REQUEST-ID' \
  -d '{
    "payment_source": {
      "card": {
        "number": "4111111111111111",
        "expiry": "2027-02",
        "name": "Firstname Lastname",
        "billing_address": {
          "address_line_1": "2211 N First Street",
          "address_line_2": "17.3.160",
          "admin_area_1": "CA",
          "admin_area_2": "San Jose",
          "postal_code": "95131",
          "country_code": "US"
        },
        "verification_method": "SCA_WHEN_REQUIRED",
        "experience_context": {
          "brand_name": "YourBrandName",
          "locale": "en-US",
          "return_url": "https://example.com/returnUrl",
          "cancel_url": "https://example.com/cancelUrl"
        }
      }
    }
  }'
```

#### Sample response

```text lineNumbers
{
  "id": "5C991763VB2771612",
  "status": "APPROVED",
  "customer": {
    "id": "customer_4029352050"
  },
  "payment_source": {
    "card": {
      "brand": "VISA",
      "last_digits": "1111",
      "verification_status": "VERIFIED",
      "verification": {
        "network_transaction_id": "20286098380002303",
        "time": "2020-10-07T22:44:41.000Z",
        "amount": {
          "value": "0.00",
          "currency_code": "USD"
        },
        "processor_response": {
          "avs_code": "M",
          "cvv_code": "P"
        }
      }
    }
  },
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-token",
      "rel": "confirm",
      "method": "POST",
      "encType": "application/json"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/setup-tokens/5C991763VB2771612",
      "rel": "self",
      "method": "GET",
      "encType": "application/json"
    }
  ]
}
```

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

1. Copy the sample request code.
2. Change `ACCESS-TOKEN` to your sandbox access token.
3. Change `BN-CODE` to your [PayPal Attribution ID](/api/rest/requests/#paypal-partner-attribution-id) to receive revenue attribution. To find your BN code, see [Code and Credential Reference](/platforms/create-account/#link-bncode).
4. Change `AUTH-ASSERTION-JWT` to your [PayPal-Auth-Assertion](/api/rest/requests/#paypal-auth-assertion) token.
5. Change `REQUEST-ID` to a set of unique alphanumeric characters such as a time stamp.
6. Use the card as the payment source and complete the rest of the source object for your use case and business.
7. Pass the `verification_method` parameter to verify card data.
8. Update the `return_url` value with the URL where the payer is redirected after they approve the flow.
9. Update the `cancel_url` value with the URL where the payer is redirected after they cancel the flow.

Pass one of the following `verification_method` attributes to verify card data:

| Verification Method | Description                                                                                                                                            |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| SCA\_WHEN\_REQUIRED | Returns a 3D Secure contingency when it is a mandate in the region where you operate. This is the default when neither parameter is explicitly passed. |
| `SCA_ALWAYS`        | Triggers 3D Secure for every transaction.                                                                                                              |

#### Step result [#step-result-4]

A successful request returns the following:

* HTTP response code `HTTP 2xx` or `HTTP 200`.
* Status of `APPROVED`.
* HATEOAS links:

| Rel       | Method | Description                                                                                                          |
| --------- | ------ | -------------------------------------------------------------------------------------------------------------------- |
| `confirm` | `POST` | Make a POST request to generate the payment token using the approved setup token.                                    |
| `self`    | `GET`  | Make a GET request to get information about the temporarily saved payment source associated with the setup token ID. |

If the request and authorization succeed, the setup token is approved and additional parameters are returned in the response.

#### Testing AVS and CVV response codes [#testing-avs-and-cvv-response-codes]

When running tests in the sandbox, you can generate AVS and CVV response codes.

When testing saved cards in the sandbox, use these [test cards](/sandbox-testing/card-testing).

Set Address Line 1 to the following values to generate an AVS response. Not all AVS codes are supported by all card types:

| Address Line 1 | AVS Response | Visa | Mastercard | American Express | Discover |
| -------------- | ------------ | ---- | ---------- | ---------------- | -------- |
| AVS\_A\_971    | A            | Yes  | Yes        | Yes              | Yes      |
| AVS\_B\_972    | B            | Yes  | No         | No               | No       |
| AVS\_C\_973    | C            | Yes  | No         | No               | No       |
| AVS\_D\_974    | D            | Yes  | No         | Yes              | No       |
| AVS\_E\_975    | E            | No   | Yes        | Yes              | No       |
| AVS\_F\_976    | F            | Yes  | No         | Yes              | No       |
| AVS\_G\_977    | G            | Yes  | No         | No               | Yes      |
| AVS\_I\_979    | I            | Yes  | No         | No               | No       |
| AVS\_K\_981    | K            | No   | No         | Yes              | No       |
| AVS\_L\_982    | L            | No   | No         | Yes              | No       |
| AVS\_M\_983    | M            | Yes  | No         | Yes              | No       |
| AVS\_N\_984    | N            | Yes  | Yes        | Yes              | Yes      |
| AVS\_O\_985    | O            | No   | No         | Yes              | No       |
| AVS\_P\_986    | P            | Yes  | No         | No               | No       |
| AVS\_R\_988    | R            | Yes  | Yes        | Yes              | Yes      |
| AVS\_S\_989    | S            | Yes  | Yes        | Yes              | Yes      |
| AVS\_U\_991    | U            | Yes  | Yes        | Yes              | Yes      |
| AVS\_W\_993    | W            | Yes  | Yes        | Yes              | Yes      |
| AVS\_X\_994    | X            | Yes  | Yes        | No               | Yes      |
| AVS\_Y\_995    | Y            | Yes  | Yes        | Yes              | Yes      |
| AVS\_Z\_996    | Z            | Yes  | Yes        | Yes              | Yes      |

Set the CVV to the following values to generate a CVV response:

| CVV | CVV response | Description                                                        |
| --- | ------------ | ------------------------------------------------------------------ |
| 115 | M            | CVV2/CVC2/CID Match                                                |
| 116 | N            | CVV2/CVC2/CID No Match                                             |
| 120 | P            | Not Processed                                                      |
| 123 | S            | CVV2 should be on the card, but merchant indicated that it was not |
| 125 | U            | Unknown/Issuer does not participate                                |
| 130 | X            | Server provider did not respond (default)                          |

### Merchant: 3D Secure verification [#merchant-3d-secure-verification]

#### Setup token for card with 3D Secure verification [#setup-token-for-card-with-3d-secure-verification-1]

If [3D Secure](/limited-release/commerce-platform/accept-payments/advanced/customize/use-3d-secure/) is required, the `POST` action to the `setup-tokens` endpoint returns `PAYER_ACTION_REQUIRED`.

#### Sample request

```text lineNumbers
curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/setup-tokens \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ACCESS-TOKEN' \
  -H 'PayPal-Partner-Attribution-Id: BN-CODE' \
  -H 'PayPal-Auth-Assertion: AUTH-ASSERTION-JWT' \
  -H 'PayPal-Request-Id: REQUEST-ID' \
  -d '{
    "payment_source": {
      "card": {
        "number": "4111111111111111",
        "expiry": "2027-02",
        "name": "Firstname Lastname",
        "billing_address": {
          "address_line_1": "2211 N First Street",
          "address_line_2": "17.3.160",
          "admin_area_1": "CA",
          "admin_area_2": "San Jose",
          "postal_code": "95131",
          "country_code": "US"
        },
        "verification_method": "SCA_WHEN_REQUIRED",
        "experience_context": {
          "brand_name": "YourBrandName",
          "locale": "en-US",
          "return_url": "https://example.com/returnUrl",
          "cancel_url": "https://example.com/cancelUrl"
        }
      }
    }
  }'
```

#### Sample response

```text lineNumbers
{
  "id": "5C991763VB2771612",
  "customer": {
    "id": "customer_4029352050"
  },
  "status": "PAYER_ACTION_REQUIRED",
  "payment_source": {
    "card": {
      "last_digits": "1111",
      "brand": "VISA",
      "type": "CREDIT",
      "expiry": "2027-02"
    }
  },
  "links": [
    {
      "href": "https://paypal.com/webapps/helios?action=authenticate&validate_session_id=82cf4a87-5c40-0a27-1a09-4ffbb0d05fdc",
      "rel": "approve",
      "method": "GET",
      "encType": "application/json"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-token",
      "rel": "confirm",
      "method": "POST",
      "encType": "application/json"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/setup-tokens/5C991763VB2771612",
      "rel": "self",
      "method": "GET",
      "encType": "application/json"
    }
  ]
}
```

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

1. Copy the sample request code.
2. Change `ACCESS-TOKEN` to your sandbox access token.
3. Change `PAYPAL-AUTH-ASSERTION` to your [PayPal-Auth-Assertion](/api/rest/requests/#paypal-auth-assertion) token.
4. Change `BN-CODE` to your [PayPal Attribution ID](/api/rest/requests/#paypal-partner-attribution-id) to receive revenue attribution. To find your BN code, see [Code and Credential Reference](/platforms/create-account/#link-bncode).
5. Change `REQUEST-ID` to a set of unique alphanumeric characters such as a time stamp.
6. Use a card as the payment source and complete the rest of the source object for your use case and business.
7. Pass the `verification_method` parameter with `SCA_WHEN_REQUIRED` to verify card data.
8. Update the `return_url` value with the URL where the payer is redirected after they approve the flow.
9. Update the `cancel_url` value with the URL where the payer is redirected after they cancel the flow.

### Step result [#step-result-5]

A successful request returns the following:

* An HTTP response code `HTTP 2xx` or `HTTP 200`.
* A status of `PAYER_ACTION_REQUIRED`.
* HATEOAS links:

| Rel       | Method | Description                                                                                                            |
| --------- | ------ | ---------------------------------------------------------------------------------------------------------------------- |
| `approve` | `GET`  | Use this link to take your payer through the card approval flow.                                                       |
| `confirm` | `POST` | Make a POST request to use an approved setup token to save the underlying payment method and generate a payment token. |
| `self`    | `GET`  | Make a GET request to view the state of your setup token and payment method details.                                   |

After the payer completes verification, make a `POST` request on the [payment-token](/api/payment-tokens/v3#create-a-payment-token) endpoint to convert the approved setup token to a payment token.

To retrieve 3D Secure verification data associated with a setup token, make a `GET` request on a [setup-token](/api/payment-tokens/v3#setup-token).

#### Sample request

```text lineNumbers
curl -v -k -X GET https://api-m.sandbox.paypal.com/v3/vault/setup-tokens/5C991763VB2781612 \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ACCESS-TOKEN' \
  -H 'PayPal-Partner-Attribution-Id: BN-CODE' \
  -H 'PayPal-Auth-Assertion: AUTH-ASSERTION-JWT' \
  -H 'PayPal-Request-Id: REQUEST-ID'
```

#### Sample response

```text lineNumbers
{
  "id": "5C991763VB2771612",
  "status": "APPROVED",
  "customer": {
    "id": "customer_4029352050"
  },
  "payment_source": {
    "card": {
      "brand": "VISA",
      "last_digits": "1111",
      "verification_status": "VERIFIED",
      "verification": {
        "network_transaction_id": "20286098380002303",
        "time": "2020-10-07T22:44:41.000Z",
        "amount": {
          "value": "0.00",
          "currency_code": "USD"
        },
        "processor_response": {
          "avs_code": "M",
          "cvv_code": "P"
        },
        "three_d_secure": {
          "type": "THREE_DS_AUTHENTICATION",
          "eci_flag": "FULLY_AUTHENTICATED_TRANSACTION",
          "card_brand": "VISA",
          "enrolled": "Y",
          "pares_status": "Y",
          "three_ds_version": "2",
          "authentication_type": "DYNAMIC",
          "three_ds_server_transaction_id": "3d-secure-txn-id"
        }
      }
    }
  },
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-token",
      "rel": "confirm",
      "method": "POST",
      "encType": "application/json"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/setup-tokens/5C991763VB2771612",
      "rel": "self",
      "method": "GET",
      "encType": "application/json"
    }
  ]
}
```

### Step result [#step-result-6]

A successful request returns the following:

* HTTP response code of `200 OK`.
* Status of `APPROVED`.

| Parameter             | Description                                                                                                                                                                         |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `verification_method` | The verification method value from the request is returned in the response.                                                                                                         |
| `verification_status` | If the card is authorized, the status is `VERIFIED`.                                                                                                                                |
| `authorization`       | Details from the authorization are returned in an `authorization` object. This includes the amount and currency requested, and the AVS and CVV results from the processor response. |

The response will return the Merchant Customer ID information if it was saved in the setup token.

The issuing bank can still issue an authorization if a card fails the AVS and CVV checks. If the card fails the checks, the setup token is created with an `APPROVED` status and the processor responses are returned to you. The `eci_flag` parameter of an authentication block indicates that 3D Secure was not completed.

You can choose whether to use a card that did not complete 3D Secure or failed AVS and CVV checks:

* To use the card, make a `POST` request on the [add-payment-token](/api/payment-tokens/v3#payment-tokens_create) endpoint and convert the approved setup token to a full payment token.
* To reject the card, don't add the payment token or convert it to a full payment token.

### Testing with 3D Secure [#testing-with-3d-secure]

When running tests in the sandbox, generate a 3D Secure token while creating a setup token and validating a card by using card data from [3D Secure test scenarios](/limited-release/commerce-platform/accept-payments/advanced/customize/test-scenarios/).

## 2. Create payment token [#2-create-payment-token]

Use an approved setup token to save the payer's credit or debit card. Then, copy the sample request code to generate a payment token.

### Sample requests and response [#sample-requests-and-response]

#### Platform sample API request

```text lineNumbers
curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/payment-tokens \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ACCESS-TOKEN' \
  -H 'PayPal-Partner-Attribution-Id: BN-CODE' \
  -H 'PayPal-Auth-Assertion: AUTH-ASSERTION-JWT' \
  -H 'PayPal-Request-Id: REQUEST-ID' \
  -d '{
    "payment_source": {
      "token": {
        "id": "5C991763VB2781612",
        "type": "SETUP_TOKEN"
      }
    }
  }'
```

#### Merchant sample API request

```text lineNumbers
curl -v -k -X POST https://api-m.sandbox.paypal.com/v3/vault/payment-tokens \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ACCESS-TOKEN' \
  -H 'PayPal-Partner-Attribution-Id: BN-CODE' \
  -H 'PayPal-Auth-Assertion: AUTH-ASSERTION-JWT' \
  -H 'PayPal-Request-Id: REQUEST-ID' \
  -d '{
    "payment_source": {
      "token": {
        "id": "5C991763VB2781612",
        "type": "SETUP_TOKEN"
      }
    }
  }'
```

#### Sample API response

```text lineNumbers
{
  "id": "dnbbj3g",
  "customer": {
    "id": "customer_4029352050"
  },
  "payment_source": {
    "card": {
      "name": "Firstname Lastname",
      "last_digits": "1111",
      "brand": "VISA",
      "expiry": "2027-02",
      "billing_address": {
        "address_line_1": "2211 N First Street",
        "address_line_2": "17.3.160",
        "admin_area_2": "San Jose",
        "admin_area_1": "CA",
        "postal_code": "95131",
        "country_code": "US"
      }
    }
  },
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/dnbbj3g",
      "rel": "self",
      "method": "GET",
      "encType": "application/json"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/dnbbj3g",
      "rel": "delete",
      "method": "DELETE",
      "encType": "application/json"
    }
  ]
}
```

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

1. Copy the code sample.
2. Change `ACCESS-TOKEN` to your sandbox access token.
3. Change `BN-CODE` to your [PayPal Attribution ID](/api/rest/requests/#paypal-partner-attribution-id) to receive revenue attribution. To find your BN code, see [Code and Credential Reference](/platforms/create-account/#link-bncode).
4. Change `AUTH-ASSERTION-JWT` to your [PayPal-Auth-Assertion](/api/rest/requests/#paypal-auth-assertion) token.
5. Change `REQUEST-ID` to a set of unique alphanumeric characters such as a time stamp.
6. Use `token` as the `payment source` and complete the rest of the source object for your use case and business.
7. Use your setup token ID to pass in the payment source parameter and `type` as the `SETUP_TOKEN`.

### Step result [#step-result-7]

A successful request returns the following:

* An HTTP response code `HTTP 2xx` or `HTTP 200`.
* The `ID` of the payment token and associated payment method information.
* HATEOAS links:

| Rel      | Method   | Description                                                                      |
| -------- | -------- | -------------------------------------------------------------------------------- |
| `self`   | `GET`    | Make a GET request to this link to retrieve data about the saved payment method. |
| `delete` | `DELETE` | Make a DELETE request to delete the payment token from the vault.                |

## 3. Use saved payment token [#3-use-saved-payment-token]

After you create a payment method token, use the token instead of the payment method to create a purchase and capture the payment with the Orders API.

You can store a Merchant Customer ID aligned with your system to simplify the mapping of customer information within your system and PayPal. This is an optional field that will return the value shared in the response.

Set the `payment_source` to specify the payment source type. Set the `vault_id` to the payment method token you received.

### Sample requests and response [#sample-requests-and-response-1]

#### Platform sample API request

```text lineNumbers
curl -v -X POST https://api-m.sandbox.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-JWT' \
  -H 'PayPal-Request-Id: REQUEST-ID' \
  -d '{
    "intent": "CAPTURE",
    "purchase_units": [
      {
        "amount": {
          "currency_code": "USD",
          "value": "100.00"
        },
        "payee": {
          "merchant_id": "MERCHANT-ID"
        }
      }
    ],
    "payment_source": {
      "card": {
        "vault_id": "dnbbj3g"
      }
    }
  }'
```

#### Merchant sample API request

```text lineNumbers
curl -v -X POST https://api-m.sandbox.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-JWT' \
  -H 'PayPal-Request-Id: REQUEST-ID' \
  -d '{
    "intent": "CAPTURE",
    "purchase_units": [
      {
        "amount": {
          "currency_code": "USD",
          "value": "100.00"
        }
      }
    ],
    "payment_source": {
      "card": {
        "vault_id": "dnbbj3g"
      }
    }
  }'
```

#### Sample API response

```text lineNumbers
{
  "id": "5O190127TN364715T",
  "status": "COMPLETED",
  "payment_source": {
    "card": {
      "attributes": {
          "customer": {
              "id": "customer_4029352050"
          }
      }
      "brand": "VISA",
      "last_digits": "1111"
    }
  }
  "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": "NOT_ELIGIBLE"
            },
            "final_capture": true,
            "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.sandbox.paypal.com/v2/payments/captures/3C679366HH908993F",
                "rel": "self",
                "method": "GET"
              },
              {
                "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/3C679366HH908993F/refund",
                "rel": "refund",
                "method": "POST"
              },
              {
                "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
                "rel": "up",
                "method": "GET"
              }
            ]
          }
        ]
      }
    }
  ],
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5O190127TN364715T",
      "rel": "self",
      "method": "GET"
    }
  ]
}
```

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

1. Copy the code sample.
2. Change `ACCESS-TOKEN` to your [sandbox access token](/api/rest/authentication).
3. Change `BN-CODE` to your [PayPal Attribution ID](/api/rest/requests/#paypal-partner-attribution-id) to receive revenue attribution. See [Retrieve BN code](/limited-release/commerce-platform/get-started/#retrieve-bn-code).
4. Change `AUTH-ASSERTION-JWT` to your [PayPal-Auth-Assertion](/api/rest/requests/#paypal-auth-assertion) token.
5. Change `REQUEST-ID` to a set of unique alphanumeric characters such as a time stamp.
6. Use the ID of your payment method token as the `vault.id`.

## Use payment token on behalf of payer [#use-payment-token-on-behalf-of-payer]

When the payer isn't present to check out, you can use the payment method token to create an order on behalf of the payer.

### 1. Retrieve a payer's payment method token [#1-retrieve-a-payers-payment-method-token]

If you stored the payment token the payer created on your site, skip this step.

To make a payment on behalf of the payer, retrieve the payment token they created. You'll need the customer ID that you assigned to this payer when saving the payment method.

#### Sample requests and response [#sample-requests-and-response-2]

#### Platform sample API request

```text lineNumbers
curl -v -k -X GET https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?customer_id=customer_4029352050 \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ACCESS-TOKEN' \
  -H 'PayPal-Partner-Attribution-Id: BN-CODE' \
  -H 'PayPal-Auth-Assertion: AUTH-ASSERTION-JWT'
```

#### Merchant sample API request

```text lineNumbers
curl -v -k -X GET https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?customer_id=customer_4029352050 \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ACCESS-TOKEN' \
  -H 'PayPal-Partner-Attribution-Id: BN-CODE' \
  -H 'PayPal-Auth-Assertion: AUTH-ASSERTION-JWT'
```

#### Sample API response

```text lineNumbers
{
  "customer": {
    "id": "customer_4029352050"
  },
  "payment_tokens": [
    {
      "id": "jwgvx42",
      "customer": {
        "id": "customer_4029352050",
        "merchant_customer_id": "customer@merchant.com"
      },
      "payment_source": {
        "paypal": {
          "description": "Description for PayPal to be shown to PayPal 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_type": "MERCHANT",
          "customer_type": "CONSUMER",
          "name": {
            "given_name": "Firstname",
            "surname": "Lastname",
            "full_name": "Firstname Lastname"
          },
          "email_address": "email@example.com",
          "payer_id": "AJM9JTWQJCFTA",
          "phone": {
            "phone_number": {
              "country_code": "US",
              "national_number": "408-208-9263"
            }
          }
        }
      },
      "links": [
        {
          "rel": "self",
          "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/jwgvx42",
          "method": "GET",
          "encType": "application/json"
        },
        {
          "rel": "delete",
          "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens/jwgvx42",
          "method": "DELETE",
          "encType": "application/json"
        }
      ]
    }
  ],
  "links": [
    {
      "rel": "self",
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?customer_id=customer_4029352050&page=1&page_size=5&total_required=false",
      "method": "GET",
      "encType": "application/json"
    },
    {
      "rel": "first",
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?customer_id=customer_4029352050&page=1&page_size=5&total_required=false",
      "method": "GET",
      "encType": "application/json"
    },
    {
      "rel": "last",
      "href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?customer_id=customer_4029352050&page=1&page_size=5&total_required=false",
      "method": "GET",
      "encType": "application/json"
    }
  ]
}
```

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

1. Copy the code sample.
2. Change `ACCESS-TOKEN` to your [sandbox access token](/api/rest/authentication).
3. Change `BN-CODE` to your [PayPal Attribution ID](/api/rest/requests/#paypal-partner-attribution-id) to receive revenue attribution. To find your BN code, see [Code and Credential Reference](/platforms/create-account/#link-bncode).
4. Change `AUTH-ASSERTION-JWT` to your [PayPal-Auth-Assertion](/api/rest/requests/#paypal-auth-assertion) token.
5. Pass the PayPal-generated `customer_id` to retrieve the payment token details associated with the payer.
6. The response will return the Merchant Customer ID if it was passed during payment token creation.

#### Step result [#step-result-8]

A successful request returns the following:

* HTTP response code `HTTP 2xx` or `HTTP 200`.
* Payment method details and status for the payment token.
* JSON response body that includes all payment method tokens.
* HATEOAS links:

| Rel      | Method   | Description                                                                      |
| -------- | -------- | -------------------------------------------------------------------------------- |
| `self`   | `GET`    | Make a GET request to this link to retrieve data about the saved payment method. |
| `delete` | `DELETE` | Make a DELETE request to delete the saved payment token.                         |

### 2. Use payment method token with checkout [#2-use-payment-method-token-with-checkout]

After you get the payment method token ID, you can use a payment method token with checkout to create your order.

## Webhooks for saving payment methods [#webhooks-for-saving-payment-methods]

| Event                                    | Trigger                                                                                                                                  | Payment methods  |
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| `VAULT.PAYMENT-TOKEN.CREATED`            | A payment token is created to save a payment method.                                                                                     | Cards and PayPal |
| `VAULT.PAYMENT-TOKEN.DELETED`            | A payment token is deleted. The payer's payment method is no longer saved to the PayPal vault.                                           | Cards and PayPal |
| `VAULT.PAYMENT-TOKEN.DELETION-INITIATED` | A request to delete a payment token has been submitted to the [Payment Method Tokens API](/api/payment-tokens/v3#payment-tokens_delete). | PayPal           |

For more information on webhooks, see [webhooks](/api/rest/webhooks/).

## See also [#see-also]

> **Info:** * [Set up payment buttons](/limited-release/commerce-platform/accept-payments/standard/)
> * [Advanced credit and debit cards payments](/limited-release/commerce-platform/accept-payments/advanced/)
> * [Errors](/api/payment-tokens/v3#errors/)
> * To keep saved cards up to date, see the [Real-time account updater](/limited-release/commerce-platform/accept-payments/advanced/customize/use-real-time-updation/)
