Vault with the Payment Method Tokens API
Last updated: Sept 23rd, 4:07pm
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:
- Payment Tokens REST API - payment tokens endpoint
- 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.
- Log in to the Developer Dashboard.
- Under REST API apps, click your app name.
- Under SANDBOX APP SETTINGS, check Accept payments and then click Advanced options.
- 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
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/vault/payment-tokens \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer <Access-Token>" \4 -H "PayPal-Request-Id: <Request-Id>" \5 -d '{6 "customer_id": "testcustomer1",7 "source": {8 "card": {9 "number": "4111111111111111",10 "expiry": "2021-06",11 "security_code": "123"12 }13 }14 }'
Modify the code
- Copy the sample request code.
- Change
Access-Token
to your sandbox access token. - Change
Request-Id
to a unique alphanumeric set of characters, a time stamp for example. - 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.
- The
source
must becard
when saving a card, otherwise usepaypal
.
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:
Rel | Method | Description |
---|---|---|
self |
GET |
You can make a GET request to this link to retrieve data about the saved instrument. |
delete |
DELETE |
You can make a DELETE request to delete the payment token from the vault. |
Sample response
1{2 "id": "8kk845",3 "customer_id": "testcustomer1",4 "status": "CREATED",5 "source": {},6 "links": [7 {8 "rel": "self",9 "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",10 "method": "GET"11 },12 {13 "rel": "delete",14 "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",15 "method": "DELETE"16 }17 ]18 }
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 initialPOST
on thepayment-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
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/vault/payment-tokens \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer <Access-Token>" \4 -H "PayPal-Request-Id: <Request-Id>" \5 -d '{6 "customer_id": "testcustomer1",7 "source": {8 "paypal": {9 "usage_type": "MERCHANT"10 }11 },12 "application_context": {13 "locale": "en-US",14 "return_url": "https://example.com/returnUrl",15 "cancel_url": "https://example.com/cancelUrl"16 }17}'
Modify the code
- Copy the sample request code.
- Change
Access-Token
to your sandbox access token. - Change
Request-Id
to a unique alphanumeric set of characters, a time stamp for example. - 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.
- Use PayPal as the
source
and complete the rest of the source object as appropriate for your use case and business. - Update the
return_url
value with the URL where the customer is redirected after the customer approves and leaves the flow. - 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:
Rel | Method | Description |
---|---|---|
approve |
GET |
Use this link to take your customer through a PayPal hosted contingency flow. |
confirm |
POST |
You can make a POST request to save an approved approval token and vault the underlying instrument. |
status |
GET |
You 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
1{2 "status": "CUSTOMER_ACTION_REQUIRED",3 "links": [4 {5 "href": "https://www.sandbox.paypal.com/webapps/agreements/approve?approval_session_id=03G5603316814781B",6 "rel": "approve",7 "method": "GET"8 },9 {10 "href": "https://api-m.sandbox.paypal.com/v2/vault/approval-tokens/5C991763VB2771612/confirm-payment-token",11 "rel": "confirm",12 "method": "POST"13 },14 {15 "href": "https://api-m.sandbox.paypal.com/v2/vault/approval-tokens/5C991763VB2771612",16 "rel": "status",17 "method": "GET"18 }19 ]20}
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:
1curl -v -k -X GET 'https://api-m.sandbox.paypal.com/v2/vault/approval-tokens/{approval_token_id}/confirm-payment-token' \2 -H "Authorization: Bearer FULL_scoped_access_token" \3 -H "Content-Type: application/json"4 -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
1curl -v -X POST https://api-m.sandbox.paypal.com/v2/vault/payment-tokens \2 -H "Content-Type: application/json" \3 -H "Authorization: Bearer <Access-Token>" \4 -H "PayPal-Request-Id: <Request-Id>" \5 -d '{6 "customer_id": "testcustomer1",7 "source": {8 "card": {9 "number": "4111111111111111",10 "expiry": "2021-06",11 "security_code": "123",12 "verification_method": "SCA_WHEN_REQUIRED"13 }14 }15 }'
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.
Parameter | Description |
---|---|
verification_method |
The verification method value from the request is echoed in the response. |
verification_status |
If the card is authorized the status is set to VERIFIED . |
authorization |
Details 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. |
1{2 "id": "8kk845",3 "customer_id": "testcustomer1",4 "status": "CREATED",5 "source": {6 "card": {7 "brand": "VISA",8 "last_digits": "1111",9 "verification_method": "SCA_WHEN_REQUIRED",10 "verification_status": "VERIFIED",11 "verification": {12 "authorization": {13 "network_transaction_id": "20286098380002303",14 "verification_time": "2021-10-07T22:44:41.000Z",15 "amount": {16 "value": "0.00",17 "currency_code": "USD"18 },19 "processor_response": {20 "avs_code": "M",21 "cvv_code": "P"22 }23 }24 }25 }26 },27 "links": [28 {29 "rel": "self",30 "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",31 "method": "GET"32 },33 {34 "rel": "delete",35 "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",36 "method": "DELETE"37 },38 {39 "rel": "edit",40 "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",41 "method": "PATCH"42 }43 ]44}
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
1{2 "id": "8kk845",3 "customer_id": "testcustomer1",4 "status": "CREATED",5 "source": {6 "card": {7 "brand": "VISA",8 "last_digits": "1111",9 "verification_status": "VERIFIED",10 "verification_method": "SCA_WHEN_REQUIRED",11 "verification": {12 "authorization": {13 "network_transaction_id": "20286098380002303",14 "verification_time": "2020-10-07T22:44:41.000Z",15 "amount": {16 "value": "0.00",17 "currency_code": "EUR"18 },19 "processor_response": {20 "avs_code": "M",21 "cvv_code": "P"22 }23 },24 "authentication": {25 "three_d_secure": {26 "type": "THREE_DS_AUTHENTICATION",27 "eci_flag": "FULLY_AUTHENTICATED_TRANSACTION",28 "card_brand": "VISA",29 "enrolled": "Y",30 "pares_status": "Y",31 "three_ds_version": "2",32 "authentication_type": "DYNAMIC",33 "three_ds_server_transaction_id": "3d-secure-txn-id"34 }35 }36 }37 }38 },39 "links": [40 {41 "rel": "self",42 "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",43 "method": "GET"44 },45 {46 "rel": "delete",47 "href": "https://api-m.sandbox.paypal.com/v2/vault/payment-tokens/8kk845",48 "method": "DELETE"49 }50 ]51}
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:
1{2 "name": "UNPROCESSABLE_ENTITY",3 "message": "The requested action could not be performed, semantically incorrect, or failed business validation.",4 "debug_id": "360ee42996992",5 "details": [6 {7 "issue": "CARD_AUTHORIZATION_FAILED",8 "description": "The card failed to be authorized by the issuer. Please check the card details or use another card.",9 "location": "body"10 }11 ],12 "links": [13 {14 "href": "https://developer.paypal.com/docs/api/vault/v2/#error-CARD_AUTHORIZATION_FAILED",15 "rel": "information_link",16 "method": "GET"17 }18 ]19}
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 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 the desired 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)
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.
Sample API request
Copy the following code sample and modify it.
1curl -v -X POST ' https://api-m.sandbox.paypal.com/v2/checkout/orders' \2 -H "PayPal-Request-Id: <Request-Id>" \3 -H "Authorization: Bearer <Access-Token>" \4 -H "Content-Type: application/json" \5 -d '{6 "intent": "CAPTURE",7 "payment_source": {8 "token": {9 "type": "PAYMENT_METHOD_TOKEN",10 "id": "<id>"11 }12 },13 "purchase_units": [14 {15 "amount": {16 "currency_code": "USD",17 "value": "100.00"18 }19 }20 ]21}'
Modify the code
- Copy the sample request code.
- Change
Access-Token
to your sandbox access token. - Change
Request-Id
to a unique alphanumeric set of characters, a time stamp for example. - 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
1curl -v -X GET 'https://api-m.sandbox.paypal.com/v2/vault/payment-tokens?customer_id=`{customer_id}`' \2 -H 'Authorization: Bearer Access-Token' \3 -H 'Content-Type: application/json' \4 -H "PayPal-Request-Id: <Request-Id>" \
Modify the code
- Copy the code sample.
- Change
Access-Token
to your sandbox access token. - Replace
customer_id
with the unique customer ID you assigned to this buyer. - 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
1{2 "customer_id": "customer_4029352050",3 "payment_tokens": [4 {5 "id": "8kk845",6 "status": "CREATED",7 "source": {8 "card": {9 "brand": "VISA",10 "last_digits": "1111"11 }12 },13 ...14 }]15}
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:
Issue | Response code | Description |
---|---|---|
TOKEN_PROVIDED_NOT_SUPPORTED |
422 Unprocessable Entity | The token provided is not currently supported. |
INVALID_SECURITY_CODE |
422 Unprocessable Entity | The security code provided does not match the card number provided. |
CARD_EXPIRY_INVALID |
422 Unprocessable Entity | The card is expired. |
NO_PAYMENT_METHOD_PROVIDED |
422 Unprocessable Entity | At least one payment method is required within the source. |
APPROVAL_TOKEN_CONFIRMED |
422 Unprocessable Entity | The approval token has already been confirmed. |
CUSTOMER_ACTION_REQUIRED |
422 Unprocessable Entity | The 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_SOURCE |
422 Unprocessable Entity | The API caller or the merchant on whose behalf the API call is initiated is not allowed to vault the given source. |
ACCOUNT_LOCKED_OR_CLOSED |
422 Unprocessable Entity | The merchant on whose behalf the API call is initiated is locked or closed. |
ACCOUNT_RESTRICTED |
422 Unprocessable Entity | The merchant on whose behalf the API call is initiated is restricted. |
PAYPAL_REQUEST_ID_PREVIOUSLY_USED |
422 Unprocessable Entity | The PayPal-Request-ID has already been used for another request. |
CANCEL_URL_REQUIRED |
422 Unprocessable Entity | The cancel URL is required when attempting to vault this source. |
RETURN_URL_REQUIRED |
422 Unprocessable Entity | The return URL is required when attempting to vault this source. |
SHIPPING_ADDRESS_REQUIRED |
422 Unprocessable Entity | The shipping preference mandates a shipping address to be provided. |
PERMISSION_DENIED |
403 Forbidden | You do not have permission to access or perform operations on this resource. |
Webhooks
You can configure the following vault-specific webhooks:
Webhook | Payment methods |
---|---|
VAULT.PAYMENT-TOKEN.CREATED |
Card and PayPal |
VAULT.PAYMENT-TOKEN.DELETION-INITIATED |
PayPal |
VAULT.PAYMENT-TOKEN.DELETED |
Card and PayPal |
To learn more about webhooks, see the webhooks documentation.
Next steps
- Test and go live with this integration.
- Complete production onboarding to be eligible to process cards with your live PayPal account.
- Remember to swap the credentials and API URL from sandbox to production when going live with your integration.
- You can confirm a payment token, delete a payment token, and more with the Payment Method Tokens API.