On this page
No Headings
Last updated: June 25, 2026
No transaction is required when payment methods are saved with the Payment Method Tokens API. 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.
Set up your sandbox and live business accounts to save payment methods:
Create a setup token for cards that have:
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.
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.
There's usually no transaction when saving a card and creating a setup token. The data passed to the API is checked only for format.
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-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"
}
}
}
}'ACCESS-TOKEN to your sandbox access token.REQUEST-ID to a unique alphanumeric set of characters, for example, a time stamp.A successful request returns the following:
200 or 201. Returns 200 for an idempotent request.id field.| 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. |
{
"id": "5C991763VB2781612",
"customer": {
"id": "customer_4029352050"
},
"status": "APPROVED",
"payment_source": {
"card": {
"last_digits": "1111",
"expiry": "2027-02",
"name": "Firstname Lastname",
"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/5C991763VB2781612",
"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"
}
]
}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 call.
curl -v -k -X POST 'https://api-m.sandbox.paypal.com/v3/vault/setup-tokens'\
-H "Authorization: Bearer ACCESS-TOKEN"\
-H "PayPal-Request-Id: REQUEST-ID"\
-H 'Content-Type: application/json'\
-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"
}
}
}
}'ACCESS-TOKEN to your sandbox access token.REQUEST-ID to a set of unique alphanumeric characters such as a time stamp.verification_method parameter with SCA_WHEN_REQUIRED to verify card data.return_url value with the URL where the payer is redirected after they approve the flow.cancel_url value with the URL where the payer is redirected after they cancel the flow.A successful request results in the following:
200 or 201. Returns 200 for an idempotent request.APPROVED.| 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 this link to retrieve the payment source data associated with the setup token ID. |
If the request and authorization succeed:
{
"id": "5C991763VB2781612",
"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/5C991763VB2781612",
"rel": "self",
"method": "GET",
"encType": "application/json"
}
]
}When running tests in the PayPal sandbox, you can generate AVS and CVV response codes.
When testing saved cards in the sandbox, use these test cards.
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 |
| 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) |
Use 3D Secure authentication 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. 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.
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-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"
}
}
}
}'ACCESS-TOKEN to your sandbox access token.REQUEST-ID to a unique alphanumeric set of characters such as a time stamp.verification_method parameter to verify card data.return_url value with the URL where the payer is redirected after they approve the flow.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 | Triggers 3D Secure when mandated in your operating region. |
SCA_ALWAYS | Triggers 3D Secure for every transaction. |
A successful request results in the following:
200 or 201. Returns 200 for an idempotent request.PAYER_ACTION_REQUIRED.| Rel | Method | Description |
|---|---|---|
approve | GET | Use this link to take the 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. |
{
"id": "5C991763VB2781612",
"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"
}
]
}After the payer completes verification, make a POST request on the 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.
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-Request-Id: REQUEST-ID"\A successful request results in the following:
200 OK.APPROVED.| Parameter | Description |
|---|---|
verification_method | The verification method value from the request is included in the response. |
verification_status | If the card is authorized, the status is set to 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. |
{
"id": "5C991763VB2771612",
"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"
},
"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"
}
]
}The issuing bank can still issue an authorization if a card fails the AVS and CVV checks. In this case, 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:
POST request on add-payment-token. Convert the approved setup token to a full payment token.In the sandbox, create a setup token and a 3D Secure token. Validate a card using card data from 3D Secure test scenarios.
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:
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-Request-Id: REQUEST-ID" \
-d '{
"payment_source": {
"token": {
"id": "5C991763VB2781612",
"type": "SETUP_TOKEN"
}
}
}'ACCESS-TOKEN to your sandbox access token.REQUEST-ID to a unique alphanumeric set of characters such as a time stamp.token as the payment source and complete the rest of the source object as appropriate for your use case and business.type as the SETUP_TOKEN.A successful request results in the following:
HTTP 2xx or HTTP 200.ID of the payment token and the associated payment method information.| Rel | Method | Description |
|---|---|---|
self | GET | Make a GET request to this link to retrieve data about the saved method. |
delete | DELETE | Make a DELETE request to delete the saved payment token. |
{
"id": "dnbbj3g",
"customer": {
"id": "customer_4029352050"
},
"payment_source": {
"card": {
"last_digits": "1111",
"name": "Firstname Lastname",
"expiry": "2027-02",
"brand": "VISA",
"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"
}
]
}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.
Copy the following code sample and modify it.
curl -v -k -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",
"purchase_units": [
{
"amount": {
"currency_code": "USD",
"value": "100.00"
}
}
],
"payment_source": {
"card": {
"vault_id":"dnbbj3g"
}
}
}'ACCESS-TOKEN to your sandbox access token.REQUEST-ID to a set of unique alphanumeric characters such as a time stamp.vault_id, enter the ID of your payment method token.{
"id": "5O190127TN364715T",
"status": "COMPLETED",
"payment_source": {
"card": {
"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"
}
]
}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.
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.
API endpoint used: Payment tokens
curl -v -k -X GET 'https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?customer_id=customer_4029352050' \
-H 'Authorization: Bearer ACCESS-TOKEN' \
-H 'Content-Type: application/json'ACCESS-TOKEN to your sandbox access token.customer.id to retrieve the payment token details associated with the payer.{
"customer": {
"id": "customer_4029352050"
},
"payment_tokens": [
{
"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"
}
]
}
],
"links": [
{
"href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?pageNumber=1&totalRequired=false&customer_id=customer_4029352050&pageSizeInternal=5",
"rel": "self",
"method": "GET",
"encType": "application/json"
},
{
"href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?pageNumber=1&totalRequired=false&customer_id=customer_4029352050&pageSizeInternal=5",
"rel": "first",
"method": "GET",
"encType": "application/json"
},
{
"href": "https://api-m.sandbox.paypal.com/v3/vault/payment-tokens?pageNumber=1&totalRequired=false&customer_id=customer_4029352050&pageSizeInternal=5",
"rel": "last",
"method": "GET",
"encType": "application/json"
}
]
}A successful request results in the following:
200 OK.| Rel | Method | Description |
|---|---|---|
self | GET | Make a GET request to this link to retrieve data about the saved method. |
delete | DELETE | Make a DELETE request to delete the payment token. |
After you get the payment method token ID, you can use a payment method token with checkout to create your order.
| 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. | PayPal |
For more information on webhooks, see webhooks.