PIN management
Let your cardholders manage their personal identification numbers.
Some Point-of-Sale and ATM card terminals require cardholders to enter their card’s PIN to authenticate transactions. Cardholders also need to use their PINs with physical cards in many regions of the world. You can use the Stripe API and Stripe Elements to manage and view PINs on your issued cards.
Both physical card and virtual card PINs are set to a random value at creation. Cards created as a replacement for other cards won’t inherit the old card’s PIN. In test mode, all PINs are set to 0000 by default.
Set a card’s initial PIN at creation
When issuing a new card through the API, you can provide a desired PIN to be pre-set on the card. This is optional, and if you don’t provide an initial PIN, we randomly generate one for you. You can always view a card’s PIN.
To pre-set a PIN when issuing a new card, pass it in encrypted form as the pin.
parameter to the Create Card API method:
curl https://api.stripe.com/v1/issuing/cards \ -u
: \ -d "cardholder"="ich_1D4b3fdsa" \ -d "pin[encrypted_number]"="eyJhbGciOiJSU0..." -d "type"="virtual" \ -d "currency"="usd"sk_test_4eC39HqLyjWDarjtT1zdp7dc
See Encrypting PINs for more information about how to encrypt a PIN before passing it to the Stripe API or your own servers.
Note
When setting a card’s initial PIN in a request to the Create Card API method, the response to the creation request won’t return the PIN (in either encrypted or plain-text form).
View a card’s PIN
You can use Issuing Elements to retrieve a card’s PIN in a PCI-DSS-compliant way.
Use Issuing Elements
Stripe provides a browser-side JavaScript library that allows you to display the sensitive data (including PINs) of your Issuing cards in a PCI-compliant manner. The PIN renders inside of a Stripe-hosted iframe
and never touches your servers. Stripe offers this library as a part of Stripe.js.
All Issuing users, whether they’re PCI-compliant or not, can use Issuing Elements to retrieve PINs.
To retrieve a card’s PIN using Issuing Elements, first create an Issuing Elements integration, and then use it to display the issuingCardPinDisplay
Element:
const stripe = Stripe(
); const cardId = 'ic_abc123'; // ID of the issued Card you want to retrieve the PIN for const ephemeralKeyNonce = ...; const ephemeralKey = ...; // create the PIN Element with Stripe.js const pinElement = stripe.elements().create('issuingCardPinDisplay', { issuingCard: cardId, nonce: ephemeralKeyNonce, ephemeralKeySecret: ephemeralKey.secret, }); // Mount the PIN element onto DOM elements on your web page pinElement.mount('#card-pin');"pk_test_TYooMQauvdEDq54NiTphI7jx"
Change a card’s PIN
Change a card’s PIN at an ATM
Cardholders can change the PIN for their Stripe Issuing card at most ATMs. The cardholder must know the card’s current PIN to change it at an ATM. You can retrieve a card’s PIN before changing it. Some countries, such as France, don’t provide PIN management features at ATMs.
Unblock a card’s PIN
If you incorrectly enter a card’s PIN three consecutive times, the PIN becomes blocked. No further PIN-authenticated payments can be made through the card until the PIN is unblocked. Additionally, when a card’s online PIN is blocked, the card’s status is set to inactive
, and no payments of any kind can be made until the card is reactivated.
To unblock a card’s online PIN, and reactivate the card, use the Cards API to set its status to active
. You can also reactivate a card in your Stripe Dashboard.
In most countries, cardholders can unblock a card’s offline PIN at an ATM.
Encrypting PINs
To enable you to set a card’s PIN in a way that doesn’t require it to pass through your servers in plain text, the Stripe API expects you to provide PINs in an encrypted form.
Encrypt the desired PIN (for example, "0123"
) in JWE (JSON Web Encryption) format using Stripe’s RSA public key. When encrypting, use the RSA-OAEP
algorithm for key wrapping and A128CBC-HS256
for content encryption.
Stripe provides its public key for PIN encryption in both PKCS#8 and JWK format. Depending on your client environment and the library used, one might be easier to use than the other.
PIN encryption best practices
- Don’t cache, store, or reuse encrypted PINs for longer than necessary to call the Stripe API.
- Don’t encrypt PINs on your servers. Instead, perform encryption as soon as your user provides the PIN (for example, in your mobile application or in your web application’s frontend) and pass the encrypted form to your servers, and then on to the Stripe API.
- Don’t cache Stripe’s Issuing public key: we can change it or rotate it without notice. Instead, fetch it for every PIN operation you perform on the Stripe API.
- Don’t roll your own cryptography. JWE libraries are available for most common languages and platforms.
PIN encryption examples
The example above encrypts a PIN (0123) using JSON Object Signing and Encryption libraries for various languages. Equivalent libraries exist for other languages:
Language | Library |
---|---|
JavaScript | jose |
Python | jwcrypto |
Ruby | ruby-jose |
Go | go-jose |
Swift | JOSESwift |
Java | jose4j |
.NET | jose-jwt |
Online and offline PINs
The physical cards that Stripe issues have EMV chips. One function of an EMV chip is to store the card’s PIN. This allows card terminals to verify an entered PIN against the card itself, without needing to verify it online, directly with the issuer. This is known as an “offline” PIN (or cardholder) verification.
When a cardholder is asked to enter their PIN, depending on where they’re using it, the card terminal might use either an online or an offline verification. Some countries use online PIN verifications, and others use offline. For example, card terminals in the US and Germany generally use an online PIN verification, while those in the UK, Ireland, or France use offline PIN.
PIN verification during authorization
If a transaction requires PIN verification, the cardholder must enter their card’s PIN on the card terminal. If the cardholder enters their PIN incorrectly, then the transaction is declined, and no issuing_
webhook is sent.
The timing to create PIN verification authorization objects depends on whether the transaction used the card’s online or offline PIN. The authorization’s verification_data.pin_check attribute tells you the type of PIN verification used and the result.
Online PIN verification
Authorizations with online PIN verifications have a pin_
value of online_
or online_
. A mismatch means that the cardholder entered the wrong PIN, so Stripe declined the transaction. Every PIN verification attempt creates an Authorization object.
After three consecutive online PIN verification failures, the card’s online PIN is blocked and the card’s status
is set to inactive
. The cardholder can’t make any further transactions, PIN-verified or otherwise, until the card becomes active again.
Authorizations declined because of a blocked online PIN have a reason
of pin_
in the request_history array.
Offline PIN verification
Authorizations with offline PIN verifications have a pin_
value of offline_
or offline_
. A mismatch means that the cardholder entered the wrong PIN, so Stripe declined the transaction.
However, because the terminal performs offline PIN verification, Stripe isn’t notified of every failed PIN attempt. we only create an Authorization object after authorization either succeeds or the cardholder fails all three PIN attempts.
Three incorrect PIN attempts blocks the card’s offline PIN. The cardholder can’t attempt a PIN-verified transaction until the offline PIN is unblocked. In contrast to online PIN blocks, the cardholder can still use the card for non-PIN-verified transactions (such as e-commerce transactions) while the offline PIN is blocked.
A terminal that performs offline PIN verification won’t attempt to authorize an inserted card with a blocked offline PIN. Instead, the terminal might display a message to the cardholder stating that the card’s PIN is blocked, suggesting that the cardholder contact their issuer.