> ## Documentation Index
> Fetch the complete documentation index at: https://razorpay-881012b3.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Save customer card details on Custom Checkout

> Securely store the card details of the customer as tokens, which can be used for repeat transactions made by the customer.

<div style={{display:"flex",flexWrap:"wrap",alignItems:"center",gap:"0.35rem 0.9rem",border:"1px solid rgba(128,128,128,0.28)",borderRadius:"0.5rem",padding:"0.45rem 0.75rem",margin:"0 0 1.25rem",fontSize:"0.875rem"}}>
  <span style={{fontWeight:600}}>Available in</span>
  <span>🇮🇳 India</span>
</div>

You can save sensitive card information entered by the customer as "tokens" in Razorpay. On a repeat visit, the customers will be able to pay directly just by entering the cvv of the card. This saves the customer the hassle of entering the card details again for every transaction.

## Prerequisites

* Sign up for a Razorpay account.
* [Generate the API Keys on Dashboard](/docs/payments/dashboard/account-settings/api-keys).

Watch the video to see how to generate API key in Test Mode.

<iframe width="495" height="315" src="https://www.youtube.com/embed/6mJnOWZDhDo" title="Generate API Keys using Test Mode" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />

* [Integrate with our Custom Checkout](/docs/payments/payment-gateway/web-integration/custom).

<Warning>
  **PCI DSS Certification**

  A customer's payment information should never reach your servers, unless you are PCI DSS certified.
</Warning>

## Workflow

1. [Enable Flash Checkout on Dashboard](#step-1-enable-flash-checkout-on-razorpay-dashboard).
2. [Create a Customer](#step-2-create-a-customer).
3. [Save Card Details on Checkout](#step-3-save-the-card-details-on-checkout).
4. [Fetch all Tokens of Customer](#step-4-fetch-all-tokens-of-customer).
5. [Create Payments using Saved Card](#step-5-create-payments-using-saved-card).

### Step 1: Enable Flash Checkout on Dashboard

Flash Checkout enables you to save customer card details right on Standard Checkout. Authentication is done using PCI DSS compliant technology to ensure that all the card information is stored with maximum possible security.

**Read more:** [Learn more about Flash Checkout.](/docs/payments/dashboard/account-settings/checkout-features#flash-checkout)

Watch this video to see how to enable or disable Flash Checkout:

<iframe width="560" style={{maxWidth: '100%'}} height="315" src="https://www.youtube.com/embed/Vm_8yjjmN3I" frameBorder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />

### Step 2: Create a Customer

Create a customer whose card details should be saved, from the Dashboard or using the Customers API. You can create customers with basic details such as `email` and `contact` using the following endpoint:

The following endpoint creates or add a customer with basic details such as name and contact details. You can use this API for various Razorpay Solution offerings.

`POST /customers`

<CodeGroup>
  ```bash Curl theme={null}
  curl -u [YOUR_KEY_ID]:[YOUR_KEY_SECRET] \
  -X POST https://api.razorpay.com/v1/customers \
  -H "Content-Type: application/json" \
  -d '{
      "name": "<name>",
      "contact": "<phone>",
      "email": "<email>",
      "fail_existing": "0",
      "notes": {
        "notes_key_1": "Tea, Earl Grey, Hot",
        "notes_key_2": "Tea, Earl Grey… decaf."
    }
  }'
  ```

  ```java Java theme={null}
  RazorpayClient razorpay = new RazorpayClient("[YOUR_KEY_ID]", "[YOUR_KEY_SECRET]");

  JSONObject customerRequest = new JSONObject();
  customerRequest.put("name","<name>");
  customerRequest.put("contact","<phone>");
  customerRequest.put("email","<email>");
  customerRequest.put("fail_existing", "0");
  JSONObject notes = new JSONObject();
  notes.put("notes_key_1","Tea, Earl Grey, Hot");
  notes.put("notes_key_2","Tea, Earl Grey… decaf.");
  customerRequest.put("notes",notes);

  Customer customer = razorpay.customers.create(customerRequest);
  ```

  ```python Python theme={null}
  import razorpay
  client = razorpay.Client(auth=("YOUR_ID", "YOUR_SECRET"))

  client.customer.create({
    "name": "<name>",
    "contact": "<phone>",
    "email": "<email>",
    "fail_existing": "0",
    "notes": {
      "notes_key_1": "Tea, Earl Grey, Hot",
      "notes_key_2": "Tea, Earl Grey… decaf."
    }
  })
  ```

  ```go Go theme={null}
  import ( razorpay "github.com/razorpay/razorpay-go" )
  client := razorpay.NewClient("YOUR_KEY_ID", "YOUR_SECRET")

  data := map[string]interface{}{
      "name": "<name>",
      "contact": "<phone>",
      "email": "<email>",
      "fail_existing": "0",
      "notes": map[string]interface{}{
        "notes_key_1": "Tea, Earl Grey, Hot",
        "notes_key_2": "Tea, Earl Grey… decaf.",
  	},
  }

  body, err := client.Customer.Create(data, nil)
  ```

  ```php PHP theme={null}
  $api = new Api($key_id, $secret);

  $api->customer->create(array('name' => '<name>', 'email' => '<email>','contact'=>'<phone>','notes'=> array('notes_key_1'=> 'Tea, Earl Grey, Hot','notes_key_2'=> 'Tea, Earl Grey… decaf'));
  ```

  ```csharp .NET theme={null}
  RazorpayClient client = new RazorpayClient("[YOUR_KEY_ID]", "[YOUR_KEY_SECRET]");

  Dictionary<string, object> options = new Dictionary<string,object>();

  options.Add("name", "<name>"); 
  options.Add("contact", "<phone>"); 
  options.Add("email", "<email>"); 
  options.Add("fail_existing", "0"); 

  Customer customer = Customer.Create(options);
  ```

  ```ruby Ruby theme={null}
  require "razorpay"
  Razorpay.setup('YOUR_KEY_ID', 'YOUR_SECRET')

  Razorpay::Customer.create({
    "name": "<name>",
    "contact": "<phone>",
    "email": "<email>",
    "fail_existing": "0",
    "notes": {
      "notes_key_1": "Tea, Earl Grey, Hot",
      "notes_key_2": "Tea, Earl Grey… decaf."
    }
  })
  ```

  ```javascript Node.js theme={null}
  var instance = new Razorpay({ key_id: 'YOUR_KEY_ID', key_secret: 'YOUR_SECRET' })

  instance.customers.create({
    name: "<name>",
    contact: "<phone>",
    email: "<email>",
    fail_existing: "0",
    notes: {
      notes_key_1: "Tea, Earl Grey, Hot",
      notes_key_2: "Tea, Earl Grey… decaf."
    }
  })
  ```
</CodeGroup>

<CodeGroup>
  ```json Success Response theme={null}
  {
    "id" : "cust_1Aa00000000004",
    "entity": "customer",
    "name" : "<name>",
    "email" : "<email>",
    "contact" : "<phone>",
    "gstin": null,
    "notes": {
      "notes_key_1":"Tea, Earl Grey, Hot",
      "notes_key_2":"Tea, Earl Grey… decaf."
    },
    "created_at ": 1234567890
  }
  ```

  ```json Failure Response theme={null}
  {
    "error": {
      "code": "BAD_REQUEST_ERROR",
      "description": "Contact number should be at least 8 digits, including country code",
      "source": "business",
      "step": "NA",
      "reason": "invalid_contact_number",
      "metadata": {},
      "field": "contact"
    }
  }
  ```
</CodeGroup>

#### Request Parameters

`name` *optional*
: `string` Customer's name. Alphanumeric value with period (.), apostrophe ('), forward slash (/), at (@) and parentheses are allowed. The name must be between 3-50 characters in length. For example, `Gaurav Kumar`.

`contact ` *optional*
: `string` The customer's phone number. A maximum length of 15 characters including country code. For example, `+919876543210`.

`email ` *optional*
: `string` The customer's email address. A maximum length of 64 characters. For example, `gaurav.kumar@example.com`.

`fail_existing` *optional*
: `string` Possible values:

* `1` (default): If a customer with the same details already exists, throws an error.
* `0`: If a customer with the same details already exists, fetches details of the existing customer.

`gstin` *optional*
: `string` Customer's GST number, if available. For example, `29XAbbA4369J1PA`.

`notes` *optional*
: `object` This is a key-value pair that can be used to store additional information about the entity. It can hold a maximum of 15 key-value pairs, 256 characters (maximum) each. For example, `"note_key": "Beam me up Scotty”`.

**Read More**: [Learn more about Customers API](/docs/api/customers).

### Step 3: Save the Card Details on Checkout

While making the payment, the customer enters the card details in the Checkout form. If the card details should be saved by Razorpay, pass `customer_id` and `save=1` along with the other parameters into the Checkout form.

```javascript Custom Checkout theme={null}
<script src="https://checkout.razorpay.com/v1/razorpay.js"></script>
  <button id="rzp-button1" style="background-color: #3399cc; color: white; font-size: 16px; font-family: sans-serif">Pay</button>
  <script>
       var razorpay = new Razorpay({
        key: "<YOUR_KEY_ID>",
        image: "https://i.imgur.com/n5tjHFD.jpg",
        name: "Crime Master Gogo",
       });
       var data = {
        amount: 6666,
        currency: "INR",
        email: "gaurav.kumar@example.com",
        contact: 9123456780,
        notes: {
          address: "Ground Floor, SJR Cyber, Laskar Hosur Road, Bengaluru",
        },
        customer_id: "cust_1Aa00000000001",
        save: 1,
        method: "card",
        'card[number]': '4242424242424242',
        'card[expiry_month]': '11',
        'card[expiry_year]': '23',
        'card[cvv]': '123',
        'card[name]': 'Gaurav Kumar'
       };

       document.getElementById("rzp-button1").onclick = function(){
        razorpay.createPayment(data);
        razorpay.on("payment.success", function(resp) {
          alert(resp.razorpay_payment_id)
          });
        razorpay.on("payment.error", function(resp){alert(resp.error.description)});
}
</script>
```

Once the payment is complete, token is generated with these card details.

#### Request Parameters

`customer_id` *mandatory*
: `string` Unique identifier of the customer. This can be obtained from the response of the previous step.

`save` *mandatory*
: `integer` Specifies if the card details should be stored as tokens. Possible values are:

* `1`: Saves the card details.
* `0` (default): Does not save the card details.

`card`
: The details of the card that should be entered while making the payment.

`number` *mandatory*
: `integer` Unformatted card number.

`name` *mandatory*
: `string` The name of the cardholder.

`expiry_month` *mandatory*
: `integer` Expiry month for card in MM format.

`expiry_year` *mandatory*
: `integer` Expiry year for card in YY format.

`cvv` *mandatory*
: `integer` CVV printed on the back of the card.

<Info>
  **Handy Tips**

  * CVV is not required by default for tokenised cards across all networks.
  * CVV is optional for tokenised card payments. Do not pass dummy CVV values.
  * To implement this change, skip passing the `cvv` parameter entirely, or pass a `null` or empty value in the CVV field.
  * We recommend removing the CVV field from your checkout UI/UX for tokenised cards.
  * If CVV is still collected for tokenised cards and the customer enters a CVV, pass the entered CVV value to Razorpay.
</Info>

**Read more:** [Learn about the other Checkout parameters](/docs/payments/payment-gateway/web-integration/custom/build-integration) for web integration.

### Step 4: Fetch all Tokens of Customer

To display all the tokens created for a customer, fetch them as follows:

`GET /customers/:customer_id/tokens`

<CodeGroup>
  ```bash Request theme={null}
  curl -u [YOUR_KEY_ID]:[YOUR_KEY_SECRET] \
  -X GET https://api.razorpay.com/v1/customers/:customer_id/tokens
  ```

  ```json Response theme={null}
  {
    "entity" : "collection",
    "count" : 2,
    "items" : [
      {
        "id" : "token_4lsdksD31GaZ09",
        "entity" : "token",
        "method" : "card",
        "card" : {
          "entity" : "card",
          "name" : "Gaurav Kumar",
          "last4" : 1111,
          "network" : "Visa",
          "expiry_month" : 12,
          "expiry_year" : 2021,
          "emi" : true,
          "issuer" : "HDFC"
        },
        "used_at" : 1473765044,
        "created_at" : 1473765044
      },
      {
        "id" : "token_4zwefDSCC829ma",
        "entity" : "token",
        "method" : "card",
        "card" : {
          "entity": "card",
          "name": " Gaurav Kumar",
          "network": "MasterCard",
          "international": false,
          "expiry_month": 9,
          "expiry_year": 2020,
          "last4" : 1221,
          "emi": false
        },
        "used_at": null,
        "created_at" : 1473765043
      }
    ]
  }
  ```
</CodeGroup>

#### Path Parameter

`customer_id`
: `string` Unique identifier of the customer.

### Step 5: Create Payments using Saved Card

After the card is saved, for every online transaction thereafter, customers can quickly complete the payment by entering only the `cvv`. If the card details should be saved by Razorpay, the following additional parameters should be passed into the Checkout form.

```javascript Custom Checkout theme={null}
<script src="https://checkout.razorpay.com/v1/razorpay.js"></script>
  <button id="rzp-button1" style="background-color: #3399cc; color: white; font-size: 16px; font-family: sans-serif">Pay</button>
  <script>
       var razorpay = new Razorpay({
        key: "<YOUR_KEY_ID>",
        image: "https://i.imgur.com/n5tjHFD.jpg",
        name: "Crime Master Gogo",
       });
       var data = {
        amount: 6666,
        currency: "INR",
        email: "gaurav.kumar@example.com",
        contact: 9123456780,
        notes: {
          address: "Ground Floor, SJR Cyber, Laskar Hosur Road, Bengaluru",
        },
        customer_id: "cust_1Aa00000000001",
        token:"token_4zwefDSCC829ma",
        method: "card",
        'card[cvv]': '123'
       };

       document.getElementById("rzp-button1").onclick = function(){
        razorpay.createPayment(data);
        razorpay.on("payment.success", function(resp) {
          alert(resp.razorpay_payment_id)
          });
        razorpay.on("payment.error", function(resp){alert(resp.error.description)});
}
</script>
```

#### Request Parameters

`customer_id`
: `string` Unique identifier of the customer.

`token`
: `string` Token of the saved method. This is generated by Razorpay.

`card[cvv]`
: `integer` cvv for the card.

<Info>
  **Handy Tips**

  * CVV is not required by default for tokenised cards across all networks.
  * CVV is optional for tokenised card payments. Do not pass dummy CVV values.
  * To implement this change, skip passing the `cvv` parameter entirely, or pass a `null` or empty value in the CVV field.
  * We recommend removing the CVV field from your checkout UI/UX for tokenised cards.
  * If CVV is still collected for tokenised cards and the customer enters a CVV, pass the entered CVV value to Razorpay.
</Info>

### Delete Tokens

In situations where your customers want to remove the saved cards from their respective accounts, you can do the same by deleting the tokens at your end.

`DELETE /customers/:customer_id/tokens/:token_id`

<CodeGroup>
  ```bash Request theme={null}
  curl -u [YOUR_KEY_ID]:[YOUR_KEY_SECRET] \
  -X DELETE https://api.razorpay.com/v1/customers/cust_1Aa00000000001/tokens/token_4zwefDSCC829ma
  ```

  ```json Response theme={null}
  {
      "deleted": true
  }
  ```
</CodeGroup>

#### Path Parameters

`customer_id`
: `string` Unique identifier of the customer.

`token`
: `string` Token of the saved method that needs to be deleted.

Customers can [delete their card details by visiting this link and following the on-screen instructions](https://razorpay.com/flashcheckout/manage/).
