Skip to content
Create account
or
Sign in
The Stripe Docs logo
/
Ask AI
Create account
Sign in
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Developer tools
Get started
Payments
Finance automation
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Overview
Start an integration
Products
Global Payouts
Capital
Issuing cards
    Overview
    How Issuing works
    Global availability
    Manage fraud
    Cards
    Choose your card type
    Virtual cards
    Issue virtual cards
    Physical cards
    Manage cards
    Digital wallets
    Replacement cards
    Card programs
    Program management
    Customize your card program
    Add funds to your card program
    Credit Consumer Issuing
    Controls
    Spending controls
    Advanced fraud tools
    3DS
    Fraud challenges
    Real-time authorizations
    PIN management
    Issuing Elements
    Token Management
    Funding
    Balance
    Postfund your integration with Stripe
    Postfund your integration with Dynamic Reserves
    Purchases
    Authorizations
    Transactions
    Disputes
    Testing
    Merchant categories
    ATM Usage
    Issuing with Connect
    Set up an Issuing and Connect integration
    Update terms of service acceptance
    Connect funding
    Connected accounts, cardholders, and cards
    Embed card management UI
    Credit
    Overview
    Set up connected accounts
    Manage credit terms
    Report other credit decisions and manage AANs
    Report required regulatory data for credit decisions
    Manage account obligations
    Test credit integration
    Additional information
    Choose a cardholder type
    Customer support for Issuing and Treasury
    Issuing watchlist
    Marketing guidance (Europe/UK)
    Product and marketing compliance guidance (US)
Treasury
Manage money
HomeMoney managementIssuing cards

Using Issuing Elements

Learn how to display card details in your web application in a PCI-compliant way.

Copy page

Stripe.js includes a browser-side JavaScript library you can use to display the sensitive data of your Issuing cards on the web in compliance with PCI requirements. The sensitive data renders inside Stripe-hosted iframes and never touches your servers.

Note

Stripe.js collects extra data to protect our users. Learn more about how Stripe collects data for advanced fraud detection.

Ephemeral key authentication

Stripe.js uses ephemeral keys to securely retrieve Card information from the Stripe API without publicly exposing your secret keys. You need to do some of the ephemeral key exchange on the server-side to set this up.

The ephemeral key creation process begins in the browser, by creating a nonce using Stripe.js. A nonce is a single-use token that creates an ephemeral key. This nonce is sent to your server, where you exchange it for an ephemeral key by calling the Stripe API (using your secret key).

After creating an ephemeral key server-side, pass it back to the browser for Stripe.js to use.

Create a secure endpoint
Server-side

The first step to integrating with Issuing Elements is to create a secure, server-side endpoint to generate ephemeral keys for the card you want to show. Your Issuing Elements web integration calls this endpoint.

Here’s how you might implement an ephemeral key creation endpoint in web applications framework across various languages:

server.js
Node
// This example sets up an endpoint using the Express framework. // Watch this video to get started: https://youtu.be/rPR2aJ6XnAc const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.urlencoded({ extended: true })); const stripe = require('stripe')(
'sk_test_BQokikJOvBiI2HlWgH4olfQ2'
); app.post('/ephemeral-keys', async (request, response) => { const { card_id, nonce } = request.body; const ephemeralKey = await stripe.ephemeralKeys.create({ nonce: nonce, issuing_card: card_id, }, { apiVersion: '2025-04-30.basil', }); response.json({ ephemeralKeySecret: ephemeralKey.secret, }); });

Note

You must specify the API version when creating ephemeral keys. Currently, the required version is 2020-03-02. You must also pass in an ephemeral key nonce, which you can create in your web integration.

Web API integration
Client-side

First, include Stripe.js on your page. For more information on how to set up Stripe.js, refer to including Stripe.js.

Create a Stripe instance and an ephemeral key nonce for the card you want to retrieve using stripe.createEphemeralKeyNonce. Use the nonce to retrieve the ephemeral key by calling the server-side endpoint that you created:

const stripe = Stripe(
'pk_test_TYooMQauvdEDq54NiTphI7jx'
); // Initialize Elements which you'll need later const elements = stripe.elements(); // Use Stripe.js to create a nonce const cardId = 'ic_1ITi6XKYfU8ZP6raDAXem8ql'; const nonceResult = await stripe.createEphemeralKeyNonce({ issuingCard: cardId, }); const nonce = nonceResult.nonce; // Call your ephemeral key creation endpoint to fetch the ephemeral key const ephemeralKeyResult = await fetch('/ephemeral-keys', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ card_id: cardId, nonce: nonce, }) }); const ephemeralKeyResponse = await ephemeralKeyResult.json(); const ephemeralKeySecret = ephemeralKeyResponse.ephemeralKeySecret;

Now that you have an ephemeral key, you’re ready to show sensitive card details. You can do so using any of the following Elements, and you can re-use the same nonce and ephemeral key pair for multiple Elements on the same page:

ElementNameAvailability
Number (PAN)issuingCardNumberDisplayVirtual cards only
CVCissuingCardCvcDisplayVirtual cards only
Expiry dateissuingCardExpiryDisplayVirtual cards only
PINissuingCardPinDisplayPhysical cards only

Each Element takes the following configuration:

NameTypeUsage
styleStyle objectKeep in mind that some variants, pseudo-classes, and properties are for input Elements and won’t apply to these Elements. An example of an input-only pseudo-class is ::placeholder.
issuingCardstringThe ID of your issued card (for example, ic_abc123)
noncestringYour ephemeral key nonce
ephemeralKeySecretstringThe secret component of your ephemeral key

Note

If you decide to use issuingCardPinDisplay, then you must implement appropriate methods to ensure that access is limited to your authorized users. In particular, you must apply two-factor authentication (2FA) before providing access to a page using issuingCardPinDisplay. If Stripe decides that you don’t have sufficient security measures in place, we might suspend your access to this Element.

The following is an example of how to display one of these Elements, using the nonce and ephemeral key pair created in the example above:

const number = elements.create('issuingCardNumberDisplay', { issuingCard: cardId, nonce: nonce, ephemeralKeySecret: ephemeralKeySecret, style: { base: { color: '#fff', fontSize: '16px' }, }, }); number.mount('#card-number');

Adding a copy button

In addition to the “card data display elements” that we’ve already described, we also provide an issuingCardCopyButton element. This takes a toCopy argument and renders a transparent “copy to clipboard” button that takes up the space of its parent <div>. This allows it to intercept all click events with a click handler that takes the corresponding card data specified at initialization and copies it to the clipboard.

With this, you can display “copy to clipboard” buttons next to the card number, expiry, and cvc, which prevents your cardholders from manually copying card data. We restrict the copy functionality to Stripe’s PCI-compliant <iframe>.

The issuingCardCopyButton element takes the following configuration:

NameTypeUsage
styleStyle objectKeep in mind that some variants, pseudo-classes, and properties are for input Elements and won’t apply to these Elements. An example of an input-only pseudo-class is ::placeholder.
toCopy'expiry' or 'cvc' or 'number' or 'pin'

An example of how to use this component is below:

const cardNumber = elements.create('issuingCardNumberDisplay', { issuingCard: cardId, nonce: nonce, ephemeralKeySecret: ephemeralKeySecret, }); cardNumber.mount('#card-number'); const cardNumberCopy = elements.create('issuingCardCopyButton', { toCopy: 'number', style: { base: { fontSize: '12px', lineHeight: '24px', }, }, }); cardNumberCopy.mount('#card-number-copy');

If you’re having trouble with your button responding to clicks, be sure to line up the iframe to your button correctly. You can customize your image and containing <div> in your stylesheets however you want.

#card-number-copy { height: 24px; width: 24px; position: relative; background-repeat: no-repeat; background-position: center; background-size: contain; background-image: url('data:image/svg+xml;base64,...'); }

As a last step, provide an “after click feedback” option to your users. To do so, use the issuingCardCopyButton Element’s on click event. This could be temporarily showing a new icon as shown below.

#card-number-copy-success { display: none; height: 24px; width: 24px; background-image: url('data:image/svg+xml;base64,...'); background-size: 100%; }
// Example of hiding, replacing, and re-showing icons upon click const timeout = (ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; const hideAndShowSuccess = (iconElementId, successIconElementId) => { const el = document.getElementById(iconElementId); el.style.display = 'none'; const elSuccess = document.getElementById(successIconElementId); elSuccess.style.display = 'block'; timeout(2000).then(() => { elSuccess.style.display = 'none'; el.style.display = 'block'; }); }; cardNumberCopy.on('click', () => { hideAndShowSuccess('card-number-copy', 'card-number-copy-success'); });

Additional details

The returned card object has PCI fields (such as the number) fully removed from the result.issuingCard payload.

In addition to .mount() in the example above, the Elements also support the following methods:

  • .destroy()
  • .unmount()
  • .update({style})

Issuing Elements and native applications

Issuing Elements does not directly support native application platforms such as iOS, Android, or React Native.

To display sensitive card details with Issuing Elements in your native app, use a web view. Build a web integration on your servers following this guide, and then point a web view’s URL to that integration. To learn about implementing web views for native apps, see these external resources:

  • iOS and iPadOS: WKWebView
  • Android: WebView
  • React Native: react-native-webview
  • Flutter: webview-flutter
Was this page helpful?
YesNo
Need help? Contact Support.
Join our early access program.
Check out our changelog.
Questions? Contact Sales.
LLM? Read llms.txt.
Powered by Markdoc