Vault with the Payment Method Tokens API

DocsCurrentLast updated: June 21st 2023, @ 12:28:18 pm


Version notice: This integration uses Vault v2. Vault v3 is now available in the United States. Payment tokens created with Vault v2 are fully compatible with Vault v3. You can upgrade to v3 at any time.

Important: Vaulting payment methods is a limited-release solution available to select merchants and partners as a pilot. Contact your sales or account manager to inquire about the pilot. You may need to configure your developer account to use vaulting in both the sandbox and production environments separately. To use vaulted card information in a transaction, you must follow the onboarding and vetting process for advanced credit and debit card processing. To vault a PayPal wallet you must be approved for PayPal Billing Agreements.

Vaulting securely saves your buyers' payment instrument and streamlines their checkout experience.

Use the Payment Method Tokens API to save a payment method without creating a transaction.

Know before you code

  • The Payment Method Tokens API currently supports PayPal and card payment methods only.
  • To vault payment methods, you must uniquely identify your buyers. For example, buyers create an account and log in to your site.
  • Complete the steps in 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 for and have your account configured to create and use billing agreements if you want to create transactions when the buyer isn't present.
  • You need a buyer's consent to make charges with a saved payment method and there are messages that you must show to your buyers. See Messaging to include when the buyer is not present.
  • This server-side integration uses the following:
  • The Payment Tokens API requires SAQ D PCI Compliance.

1. Set up your account for vault

Ensure your account is enabled for vault in both sandbox and production.

  1. Log in to the Developer Dashboard.
  2. Under REST API apps, click your app name.
  3. Under SANDBOX APP SETTINGS, check Accept payments and then click Advanced options.
  4. Check Vault and click Save.

2. Create a payment method token

To save the buyer's payment method and get a payment token in return, copy the following code and modify it:

Sample API request

curl -v -X POST https://api-m.sandbox.paypal.com/v2/vault/payment-tokens \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <Access-Token>" \
  -H "PayPal-Request-Id: <Request-Id>" \
  -d '{
    "customer_id": "testcustomer1",
    "source": {
      "card": {
        "number": "4111111111111111",
        "expiry": "2021-06",
        "security_code": "123"
      }
    }
  }'

Modify the code

  1. Copy the sample request code.
  2. Change Access-Token to your sandbox access token.
  3. Change Request-Id to a unique alphanumeric set of characters, a time stamp for example.
  4. Replace testcustomer1 with a unique customer ID for your buyer. Make sure the customer ID:
    • Is an alphanumeric value that is unique for each buyer.
    • Never changes for the same buyer in future checkout sessions.
  5. The source must be card when saving a card, otherwise use paypal.

Step result

A successful request results in an http response of 201 created. The ID of the token is in the id field. The API returns the following HATEOAS links:

RelMethodDescription
selfGETYou can make a GET request to this link to retrieve data about the saved instrument.
deleteDELETEYou can make a DELETE request to delete the payment token from the vault.

Sample response

  {
    "id": "8kk845",
    "customer_id": "testcustomer1",
    "status": "CREATED",
    "source": {},
    "links": [
      {
        "rel": "self",
        "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",
        "method": "GET"
      },
      {
        "rel": "delete",
        "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",
        "method": "DELETE"
      }
    ]
  }

As you're including vault capability for payment methods, consider the following use cases:

Create payment token when buyer action is required

For some use cases, saving a payment method requires the buyer to take additional action.

For example, when saving PayPal as a payment method, the buyer must authenticate and approve the creation of a billing agreement.

In this case, the following actions are completed:

  • A CUSTOMER_ACTION_REQUIRED status is returned from the initial POST on the payment-tokens call.
  • A temporary token is created.
  • The buyer is redirected to the approve URL to complete the necessary action.

Once the buyer has completed the approval flow, the temporary token can be upgraded to a full payment method token with the confirm-payment-tokens call.

To create a payment token that triggers a buyer action, copy the following code and modify it:

Sample API request

curl -v -X POST https://api-m.sandbox.paypal.com/v2/vault/payment-tokens \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <Access-Token>" \
  -H "PayPal-Request-Id: <Request-Id>" \
  -d '{
    "customer_id": "testcustomer1",
    "source": {
      "paypal": {
         "usage_type": "MERCHANT"
      }
    },
    "application_context": {
        "locale": "en-US",
        "return_url": "https://example.com/returnUrl",
        "cancel_url": "https://example.com/cancelUrl"
    }
}'

Modify the code

  1. Copy the sample request code.
  2. Change Access-Token to your sandbox access token.
  3. Change Request-Id to a unique alphanumeric set of characters, a time stamp for example.
  4. Replace testcustomer1 with a unique customer ID for each buyer. Make sure the customer ID:
    • Is an alphanumeric value that is unique for each buyer.
    • Never changes for the same buyer in future checkout sessions.
  5. Use PayPal as the source and complete the rest of the source object as appropriate for your use case and business.
  6. Update the return_url value with the URL where the customer is redirected after the customer approves and leaves the flow.
  7. Update the cancel_url value with the URL where the customer is redirected after the customer cancels or quits the flow.

Step result

A successful request results in the following:

  • An http response code of 200 OK
  • A status of CUSTOMER_ACTION_REQUIRED
  • The following HATEOAS links:
RelMethodDescription
approveGETUse this link to take your customer through a PayPal hosted contingency flow.
confirmPOSTYou can make a POST request to save an approved approval token and vault the underlying instrument.
statusGETYou can make a GET request to view the state of your approval token which can be one of: CUSTOMER_ACTION_REQUIRED, (the customer hasn't completed the contingency flow); APPROVED, the customer has successfully completed the contingency but the payment instrument has not been saved yet; CREATED, the instrument has been vaulted.

Sample response

{
  "status": "CUSTOMER_ACTION_REQUIRED",
  "links": [
    {
      "href": "https://www.sandbox.paypal.com/webapps/agreements/approve?approval_session_id=03G5603316814781B",
      "rel": "approve",
      "method": "GET"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v2/vault/approval-tokens/5C991763VB2771612/confirm-payment-token",
      "rel": "confirm",
      "method": "POST"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v2/vault/approval-tokens/5C991763VB2771612",
      "rel": "status",
      "method": "GET"
    }
  ]
}

After the buyer successfully completes the approval flow, make an API call to convert the approval token to a payment token. The approval token expires after three hours. To confirm the approval token, use the following code:

curl -v -k -X GET 'https://api-m.sandbox.paypal.com/v2/vault/approval-tokens/{approval_token_id}/confirm-payment-token' \
 -H "Authorization: Bearer FULL_scoped_access_token" \
 -H "Content-Type: application/json"
 -H "PayPal-Request-Id: <Request-Id>" \

Verify a card while vaulting

When vaulting a card with the Payment Method Tokens API, there is usually no associated transaction, and the data passed to the API is checked only for format.

As an optional feature, the POST action can be requested to subject the card to a smart authorization. In countries where the issuing banks support it, this smart authorization runs a zero value authorization against the card. Where the zero 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 result in a temporary hold against the customer's card for that minimal amount.

A separate verification step doesn't apply when vaulting a PayPal wallet because the account is verified as part of the approval flow.

To request verification of card data, modify the POST on the payment-tokens call by adding the verification_method parameter:

Sample API request

curl -v -X POST https://api-m.sandbox.paypal.com/v2/vault/payment-tokens \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <Access-Token>" \
  -H "PayPal-Request-Id: <Request-Id>" \
  -d '{
    "customer_id": "testcustomer1",
    "source": {
      "card": {
        "number": "4111111111111111",
        "expiry": "2021-06",
        "security_code": "123",
        "verification_method": "SCA_WHEN_REQUIRED"
      }
    }
  }'

Step result for successful request

A successful request and authorization results in the payment method being vaulted and additional parameters being returned in the response. This data isn't returned if the authorization attempt fails.

ParameterDescription
verification_methodThe verification method value from the request is echoed in the response.
verification_statusIf the card is authorized the status is set to VERIFIED.
authorizationDetails from the auth are returned in an authorization object, including the amount and currency that that was requested in the auth, and the AVS and CVV results from the processor response.
{
  "id": "8kk845",
  "customer_id": "testcustomer1",
  "status": "CREATED",
  "source": {
    "card": {
      "brand": "VISA",
      "last_digits": "1111",
      "verification_method": "SCA_WHEN_REQUIRED",
      "verification_status": "VERIFIED",
      "verification": {
        "authorization": {
          "network_transaction_id": "20286098380002303",
          "verification_time": "2021-10-07T22:44:41.000Z",
          "amount": {
            "value": "0.00",
            "currency_code": "USD"
          },
          "processor_response": {
            "avs_code": "M",
            "cvv_code": "P"
          }
        }
      }
    }
  },
  "links": [
    {
      "rel": "self",
      "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",
      "method": "GET"
    },
    {
      "rel": "delete",
      "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",
      "method": "DELETE"
    },
    {
      "rel": "edit",
      "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",
      "method": "PATCH"
    }
  ]
}

Step result for 3D Secure

In some countries the authorization of a card can trigger a 3D Secure contingency. This can happen in the EU and some other countries. If 3D Secure is required, the POST action to the payment-tokens endpoint returns a PAYER_ACTION_REQUIRED contingency. In this case, follow the guidelines for buyer action required.

Once the buyer has successfully completed the additional action, you will have called POST on the confirm-payment-token endpoint to convert the approval token to a full payment token. A response from this call returns additional information about the card, the authorization, and the 3D Secure authentication.

Sample response

{
  "id": "8kk845",
  "customer_id": "testcustomer1",
  "status": "CREATED",
  "source": {
    "card": {
      "brand": "VISA",
      "last_digits": "1111",
      "verification_status": "VERIFIED",
      "verification_method": "SCA_WHEN_REQUIRED",
      "verification": {
        "authorization": {
          "network_transaction_id": "20286098380002303",
          "verification_time": "2020-10-07T22:44:41.000Z",
          "amount": {
            "value": "0.00",
            "currency_code": "EUR"
          },
          "processor_response": {
            "avs_code": "M",
            "cvv_code": "P"
          }
        },
        "authentication": {
          "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": [
    {
      "rel": "self",
      "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",
      "method": "GET"
    },
    {
      "rel": "delete",
      "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",
      "method": "DELETE"
    }
  ]
}

Step result for failed authorization

If the authorization of the card is rejected by the issuing bank, the card will not be saved. In this case the API response will look like the following:

{
  "name": "UNPROCESSABLE_ENTITY",
  "message": "The requested action could not be performed, semantically incorrect, or failed business validation.",
  "debug_id": "360ee42996992",
  "details": [
    {
      "issue": "CARD_AUTHORIZATION_FAILED",
      "description": "The card failed to be authorized by the issuer. Please check the card details or use another card.",
      "location": "body"
    }
  ],
  "links": [
    {
      "href": "https://developer.paypal.com/docs/api/vault/v2/#error-CARD_AUTHORIZATION_FAILED",
      "rel": "information_link",
      "method": "GET"
    }
  ]
}

NOTE: A card can fail the AVS and CVV checks, but the issuing bank can still issue an authorization. In this case, the card is vaulted and the processor responses on these checks are returned to you. Similarly, the eci_flag parameter of an authentication block can indicate that 3DS was not completed. You can choose whether or not to trust the card. If you don't want to use the card, delete the payment token.

Testing AVS and CVV response codes

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

  • Use these test cards when testing card vaulting in sandbox.

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

    Address Line 1AVS ResponseVisaMastercardAmerican ExpressDiscover
    AVS_A_971AYesYesYesYes
    AVS_B_972BYesNoNoNo
    AVS_C_973CYesNoNoNo
    AVS_D_974DYesNoYesNo
    AVS_E_975ENoYesYesNo
    AVS_F_976FYesNoYesNo
    AVS_G_977GYesNoNoYes
    AVS_I_979IYesNoNoNo
    AVS_K_981KNoNoYesNo
    AVS_L_982LNoNoYesNo
    AVS_M_983MYesNoYesNo
    AVS_N_984NYesYesYesYes
    AVS_O_985ONoNoYesNo
    AVS_P_986PYesNoNoNo
    AVS_R_988RYesYesYesYes
    AVS_S_989SYesYesYesYes
    AVS_U_991UYesYesYesYes
    AVS_W_993WYesYesYesYes
    AVS_X_994XYesYesNoYes
    AVS_Y_995YYesYesYesYes
    AVS_Z_996ZYesYesYesYes
  • Set the CVV to the following values to generate the desired CVV response:

    CVVCVV responseDescription
    115MCVV2/CVC2/CID Match
    116NCVV2/CVC2/CID No Match
    120PNot Processed
    123SCVV2 should be on the card, but merchant indicated that it was not
    125UUnknown/Issuer does not participate
    130XServer provider did not respond (Default)

Testing with 3D Secure

When running tests in PayPal sandbox, you can generate a 3D Secure contingency while vaulting and validating a card by using card data from 3D Secure test scenarios.

3. Create order with the payment method token

Now that you've created a payment method token, create the order and capture the payment with the Orders API using the payment method token, rather than the payment method the buyer provided. Regardless of the type of saved payment method, set the payment_source to be a token of type PAYMENT_METHOD_TOKEN and the id to be ID of the token you received.

NOTE: Collecting device data from your customers is required when initiating non-recurring transactions from payment method tokens. Collecting and passing this data with transactions helps reduce decline rates. To collect device data, refer to the document most applicable to your integration:

Sample API request

Copy the following code sample and modify it.

curl -v -X POST ' https://api-m.sandbox.paypal.com/v2/checkout/orders' \
 -H "PayPal-Request-Id: <Request-Id>" \
 -H "Authorization: Bearer <Access-Token>" \
 -H "Content-Type: application/json" \
 -d '{
  "intent": "CAPTURE",
  "payment_source": {
      "token": {
        "type": "PAYMENT_METHOD_TOKEN",
        "id": "<id>"
      }
    },
  "purchase_units": [
    {
      "amount": {
        "currency_code": "USD",
        "value": "100.00"
      }
    }
  ]
}'

Modify the code

  1. Copy the sample request code.
  2. Change Access-Token to your sandbox access token.
  3. Change Request-Id to a unique alphanumeric set of characters, a time stamp for example.
  4. For id, enter the ID of your payment method token.

Create an order when your buyer is not present

When your buyer isn't present to checkout, you can use the payment method token to create an order.

However, if your checkout integration uses the JavaScript SDK, you must retrieve your buyer's payment method tokens to create buyer-not-present transactions.

1. Retrieve a buyer's payment method token

If you captured and saved your buyer's payment method using a JavaScript SDK integration, you won't receive a payment token in return.

To make a payment on behalf of your buyer, you'll first have to get the payment token they created. You'll need the customer ID you assigned to this buyer when you were saving the payment method.

If you already have the payment tokens stored on your site, you can skip this step.

Sample request

API endpoint used: Payment tokens

curl -v -X GET 'https://api-m.sandbox.paypal.com/v2/vault/payment-tokens?customer_id=`{customer_id}`' \
 -H 'Authorization: Bearer Access-Token' \
 -H 'Content-Type: application/json' \
 -H "PayPal-Request-Id: <Request-Id>" \

Modify the code

  1. Copy the code sample.
  2. Change Access-Token to your sandbox access token.
  3. Replace customer_id with the unique customer ID you assigned to this buyer.
  4. Change Request-Id to a unique alphanumeric set of characters, a time stamp for example.

Step result

A JSON response body that includes the payment method tokens for your customer.

Sample response

{
  "customer_id": "customer_4029352050",
  "payment_tokens": [
    {
      "id": "8kk845",
      "status": "CREATED",
      "source": {
        "card": {
          "brand": "VISA",
          "last_digits": "1111"
        }
      },
      ...
    }]
}

2. Create order using a vaulted payment token

You can now use the payment method token to create an order and capture payment.

Messaging to include when the buyer is not present

You need a buyer's consent to make charges with a saved payment method. Charging a saved payment method when the buyer isn't present requires clear messaging for the buyer. The messaging should contain:

  • That your customer is consenting to let you create charges when they aren’t present during the transaction.
  • When and why those charges will be made.
  • The amount of the charges.
  • How charges display in their statements.
  • How your customer can see, amend, or cancel the consent they have given to you.

Additional information

Errors

If you experience errors, use these codes and their descriptions to troubleshoot:

IssueResponse codeDescription
TOKEN_PROVIDED_NOT_SUPPORTED422 Unprocessable EntityThe token provided is not currently supported.
INVALID_SECURITY_CODE422 Unprocessable EntityThe security code provided does not match the card number provided.
CARD_EXPIRY_INVALID422 Unprocessable EntityThe card is expired.
NO_PAYMENT_METHOD_PROVIDED422 Unprocessable EntityAt least one payment method is required within the source.
APPROVAL_TOKEN_CONFIRMED422 Unprocessable EntityThe approval token has already been confirmed.
CUSTOMER_ACTION_REQUIRED422 Unprocessable EntityThe customer has yet to approve the token and must go through the approval experience prior to the approval token being confirmed for a payment token.
NOT_ENABLED_FOR_VAULT_SOURCE422 Unprocessable EntityThe API caller or the merchant on whose behalf the API call is initiated is not allowed to vault the given source.
ACCOUNT_LOCKED_OR_CLOSED422 Unprocessable EntityThe merchant on whose behalf the API call is initiated is locked or closed.
ACCOUNT_RESTRICTED422 Unprocessable EntityThe merchant on whose behalf the API call is initiated is restricted.
PAYPAL_REQUEST_ID_PREVIOUSLY_USED422 Unprocessable EntityThe PayPal-Request-ID has already been used for another request.
CANCEL_URL_REQUIRED422 Unprocessable EntityThe cancel URL is required when attempting to vault this source.
RETURN_URL_REQUIRED422 Unprocessable EntityThe return URL is required when attempting to vault this source.
SHIPPING_ADDRESS_REQUIRED422 Unprocessable EntityThe shipping preference mandates a shipping address to be provided.
PERMISSION_DENIED403 ForbiddenYou do not have permission to access or perform operations on this resource.

Webhooks

You can configure the following vault-specific webhooks:

WebhookPayment methods
VAULT.PAYMENT-TOKEN.CREATEDCard and PayPal
VAULT.PAYMENT-TOKEN.DELETION-INITIATEDPayPal
VAULT.PAYMENT-TOKEN.DELETEDCard and PayPal

To learn more about webhooks, see the webhooks documentation.

Next steps

See also