Token onboarding flow
Token onboarding or Token generation can be done during two flows:
- Add Card flow
- Existing Saved Card flow
This onboarding flow is applicable to both.
RBI has mandated that explicit user consent should be taken for token generation. Forced consent / default checkbox are no longer applicable.
For the existing stored cards (card-on-file), bulk migration CANNOT be done.
User consent and AFA (additional factor of authentication) are mandatory for tokenizing a card.
To seamlessly without any integration effort from Merchant's end, Juspay manages consent and 2FA during the first transaction of a customer once tokenization is enabled for the merchant.
Onboarding architecture

Typical token onboarding architecture
Juspay Managed Consent

Juspay consent flow - sample
In current transaction flow, user will be asked for tokenization consent on the webpage before the bank page loads. Consent page would support both mobile, web and landscape form factors.
The same consent page will be shown for both saved card and new card entry.
Enable tokenization
Please contact your Juspay KAM to enable Juspay managed consent and tokenization configurations.
Merchant managed consent
In the case that Merchant wishes to design and take this consent themselves, they may do so after signing an agreement with Juspay to take onus of tokenizing cards only after user consent, as this is mandated by the RBI.

Transaction Flow when Consent is taken by Merchant
The Transaction Flow changes required when Merchant is taking consent themselves are listed below:
1. Check for eligibility
New card flow
The Card Info API will give one extra parameter in response (tokenize_support) which signifies if the card BIN can be tokenized.
Stored card flow
The List Card API will give one extra parameter in response (tokenize_support) which signifies if that card entry can be tokenized.
2. Take user consent
Merchant to show the consent UI to user according to the response of Card Info API / List Card API.
3. Start the transaction
Send a new parameter (tokenize = true / false) in /txns API according to user preference given in consent UI.
Value of tokenize parameter | Flow |
---|---|
true | Consent webpage will not be shown and at the end of transaction, card will be tokenized with card network |
false | Consent webpage will not be shown and at the end of transaction, card will be not tokenized with card network |
null | Consent webpage will be shown in case Juspay_web_consent is enabled for the merchant. |
Support of existing card storage
Pass save_to_locker = true for tokenize = true to support existing stored card flows, till the RBI mandate on stored card kicks in.
Out of band tokenization
Merchant can also introduce consent flows on payment management screen. After collecting consent a penny rupee transaction has to be done to tokenize the saved card.
API Specification
Card Info API
For details about existing specification: specification
curl --location --request GET 'https://sandbox.juspay.in/cardbins/541919?options.check_mandate_support=true&merchant_id=bbstaging&options.check_atm_pin_auth_support=true&options.check_direct_otp_support=true&options.check_tokenize_support=true'
{
"id": "541919",
"object": "cardbin",
"brand": "MASTERCARD",
"bank": "HDFC Bank",
"country": "INDIA",
"type": "DEBIT",
"card_sub_type": "PLATINUM",
"juspay_bank_code": "JP_HDFC",
"tokenize_support”: true
}
List Card API
For details about existing request parameters: specification
curl --location --request GET 'https://sandbox.juspay.in/cards?customer_id=cth_6MXbUUSECcxrswgT' \
--header 'Authorization: Basic RjJEMTU0QkNBRkY0NkY4QjE0MUQ5REZBREZCNkZBOg==' \
{
"customer_id": "cth_6MXbUUSECcxrswgT",
"merchantId": "guest",
"cards": [{
"card_token": "tkn_24c960735fd64cb9b8c0221102392914",
"card_reference": "e46b3e15384db06d446fed103cfeec24",
"card_number": "4335-XXXXXXXX-2216",
"card_isin": "433587",
"card_exp_year": "2023",
"card_exp_month": "04",
"card_type": "CREDIT",
"card_issuer": "SBI",
"card_brand": "VISA",
"nickname": "",
"name_on_card": "name",
"expired": false,
"card_fingerprint": "6uvve3h71mpgrr88848hr4vsat",
"juspay_bank_code": "JP_SBI",
"card_sub_type": "NA",
"card_issuer_country": "INDIA",
"tokenize_support": false,
"provider_category": "CONTAINER",
"provider": "JUSPAY",
"token": {
"card_reference": "e46b3e15384db06d446fed103cfeec24",
"last_four_digits": null,
"card_fingerprint": "6uvve3h71mpgrr88848hr4vsat",
"card_isin": "441962",
"expiry_month": "04",
"expiry_year": "2023",
"par": "4ufhxxw6uvve3h71mpgrr88848hr4vsat23r",
"tokenization_status": "ACTIVE"
}
}]
}
Field level description
Name | Format | Description |
---|---|---|
tokenization_user_consent | boolean | Tells if the consent was given by user to tokenize the card. |
token | JSON | The details of token generated. Present only if the token is generated at end of transaction. |
token.card_reference | String | Juspay's permanent reference to the token generated. |
token.last_four_digits | String | Token's last four. Should not be shown to the user. If there is a requirement then card's last_four_digits should be shown Optional in case of certain networks. |
token.card_fingerprint | String | A string that uniquely identifies the card/tpken across the board. When the same card/token is stored across multiple accounts, same fingerprint will be returned. This can be used to identify duplicates. |
token.card_isin | String | Token's BIN. Should not be shown to user. Can be used for routing, offers etc. Optional in case of certain networks. |
token.expiry_year | String | Token's expiry year. This can be different from card's expiry year. Merchant should still use card's expiry year |
token.expiry_month | String | Token's expiry month. This can be different from card's expiry month. Merchant should still use card's expiry month. |
token.par | String | The PAR value as is received from the network. Can be used to check uniqueness of cards for use case of Offers, EMI etc. |
token.tokenization_status | String | The current status of Token. INITIATED | ACTIVE | INACTIVE | SUSPENDED |
/txns API
- New Card
For details about existing specification: specification
curl --location --request POST 'https://api.juspay.in/txns' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'order_id=null' \
--data-urlencode 'merchant_id={{merchant_id}}' \
--data-urlencode 'payment_method_type=CARD' \
--data-urlencode 'payment_method=CARD' \
--data-urlencode 'card_number=4242424242424242' \
--data-urlencode 'card_exp_month=07' \
--data-urlencode 'card_exp_year=24' \
--data-urlencode 'name_on_card=Juspay' \
--data-urlencode 'card_security_code=111' \
--data-urlencode 'save_to_locker=true' \
--data-urlencode 'redirect_after_payment=true' \
--data-urlencode 'format=json' \
--data-urlencode 'tokenize=true'\
{
"order_id": ":order_id",
"txn_id": ":txn_id",
"status": "PENDING_VBV",
"payment": {
"authentication": {
"method": "GET",
"url": "https://api.juspay.in/pay/start/guest/8646a7a029974fa99995fec00340a507"
}
}
}
- Saved Card
curl -X POST https://api.juspay.in/txns \
-d "order_id=:order_id" \
-d "merchant_id=:merchant_id" \
-d "payment_method_type=CARD" \
-d "card_token=:card_token" \
-d "card_security_code=111" \
-d "redirect_after_payment=true" \
-d "tokenize=true" \
-d "format=json"
{
"order_id": ":order_id",
"txn_id": ":txn_id",
"status": "PENDING_VBV",
"payment": {
"authentication": {
"method": "GET",
"url": "https://api.juspay.in/pay/start/guest/8646a7a029974fa99995fec00340a507"
}
}
}
Order Status API
The "card" block in existing Order Status API will also have the parameters tokenization_user_consent and token JSON block
For details about existing specification: specification
Flow | Order Status API response |
---|---|
Merchant enabled for tokenization, user gives consent (either on Juspay webpage or merchant page) | "tokenization_user_consent" and "token_created" are sent back to merchant |
Merchant enabled for tokenization, user rejects consent (either on Juspay webpage or merchant page) | "tokenization_user_consent" is sent back to merchant |
curl https://api.juspay.in/orders/order1631087270 \
-u your_api_key: \
-H 'version: 2018-10-25' \
-H 'Content-Type: application/x-www-form-urlencoded'\
-H 'x-merchantid: merchant_id'
{
"card": {
"expiry_year": "2023",
"saved_to_locker": false,
"expiry_month": "06",
"name_on_card": "test",
"card_issuer": "Axis Bank",
"last_four_digits": "5449",
"using_saved_card": true,
"card_fingerprint": "41d30s3jus955dj9yyhe5is91",
"card_isin": "526731",
"card_type": "DEBIT",
"card_brand": "MASTERCARD",
"card_sub_type": null,
"tokenization_user_consent": true,
"token": {
"card_reference": "77efb38f3721930e60dby754865619",
"last_four_digits": "7656",
"card_fingerprint": "41d30s3jus955dj9yyhe5is91",
"card_isin": "525876",
"expiry_year": "2023",
"expiry_month": "06",
"par": "6fgd63jus955dj9yyheg4gh6",
"tokenization_status": "ACTIVE"
},
"using_token": false
}
}
Field level description
Name | Format | Description |
---|---|---|
tokenization_user_consent | boolean | Tells if the consent was given by user to tokenize the card. |
token | JSON | The details of token generated. Present only if the token is generated at end of transaction. |
token.card_reference | String | Juspay's permanent reference to the token generated. |
token.last_four_digits | String | Token's last four. Should not be shown to the user. If there is a requirement then card's last_four_digits should be shown Optional in case of certain networks. |
token.card_fingerprint | String | A string that uniquely identifies the card/tpken across the board. When the same card/token is stored across multiple accounts, same fingerprint will be returned. This can be used to identify duplicates. |
token.card_isin | String | Token's BIN. Should not be shown to user. Can be used for routing, offers etc. Optional in case of certain networks. |
token.expiry_year | String | Token's expiry year. This can be different from card's expiry year. Merchant should still use card's expiry year |
token.expiry_month | String | Token's expiry month. This can be different from card's expiry month. Merchant should still use card's expiry month. |
token.par | String | The PAR value as is received from the network. Can be used to check uniqueness of cards for use case of Offers, EMI etc. |
token.tokenization_status | String | The current status of Token. INITIATED | ACTIVE | INACTIVE | SUSPENDED |
Webhook
The new fields added in Order Status API will be also sent in the current webhooks
Updated over 1 year ago