Skip to main content

Issue Cards

Whether you're building a fintech platform, corporate expense management system, digital wallet solution, or any application requiring card issuance capabilities, you may face hurdles while integrating with card issuers or BaaS (Banking as a Service) providers, including limited customization options, user experience constraints, and complex PCI-DSS compliance requirements. It is also fair to mention that truly owning the cardholder data is rarely possible without building your own Cardholder Data Environment (CDE) to perform simple tasks, like shipping the card information to a card switcher service or rewards program.

In this guide, we will leverage the Basis Theory Proxy API to set up a thin layer for handling the Issuer API responses and storing the newly issued cardholder data in a secure vault using tokenization. By following a small series of simple steps, we can unlock possibilities for using this sensitive data in various scenarios without taking on any unnecessary compliance scope.

Issue Cards

Getting Started

To get started, you will need to create a Basis Theory Account and a TEST Tenant.

Make sure to use your work email (e.g.,

Provisioning Resources

In this section, we will explore the bare minimum resources necessary to call the Issuer API and securely store the card details.

Management Application

To create all subsequent resources, you will need a Management Application.

Click here to create a Management Application or login to your Basis Theory account and create a new application with the following settings:

  • Name - Resource Creator
  • Application Type - Management
  • Permissions: application:create, proxy:create
Save the API Key from the created Management Application as it will be used later in this guide.

Private Application

Next you will need a Private Application to create tokens within the Proxy, and invoke it from your servers. This application represents your Backend.

Using the Management Application key to authorize the request, call Basis Theory API to create a new Private Application:

curl "" \
-X "POST" \
-H "Content-Type: application/json" \
-d '{
"name": "Backend",
"type": "private",
"permissions": [ "token:create", "token:read", "token:use" ]
Be sure to replace <API_KEY> with the Management API Key you created previously.
Save the key and id from the created Private Application as it will be used later in this guide.

Pre-Configured Proxy

Now we will create a Proxy that intercepts the HTTP response from the Issuer API, which contains sensitive cardholder data that we need to store in our Basis Theory Tenant. To achieve that, we will leverage a Response Transform code that handles the response body to tokenize and redact the cardholder data, and include the new token:

module.exports = async function (req) {
const { bt, args, configuration } = req;
const { body, headers } = args;
const { token: lithicToken, pan, exp_month, exp_year, cvv, } = body;

const token = await bt.tokens.create({
id: lithicToken, // (optional) use the Lithic card token as Basis Theory card token
type: 'card',
data: {
number: pan,
expiration_month: exp_month,
expiration_year: exp_year,
cvc: cvv
fingerprintExpression: '{{ data.number }}',
deduplicateToken: true,

return {
body: {,
token, // replaces the Lithic token in the response to the Basis Theory token object

Lithic Create Card Docs

Notice how we are using fingerprintExpression and deduplicateToken properties to make sure we only create one card token per unique each card number, also known as Primary Account Number (PAN). Click here to learn more about deduplication.

Let's store the contents of the responseTransform.js file into a variable:

response_transform_code=$(cat responseTransform.js)

And call Basis Theory API to create the Proxy:

curl "" \
-X "POST" \
-H "Content-Type: application/json" \
-d '{
"name": "Issuer Proxy",
"destination_url": "",
"response_transform": {
"code": '"$(echo $response_transform_code | jq -Rsa .)"'
"application": {
"id": "45c124e7-6ab2-4899-b4d9-1388b0ba9d04"

Important things to notice in the request above:

  1. <API_KEY> is the Management Application Key, used to authenticate the request;
  2. 45c124e7-6ab2-4899-b4d9-1388b0ba9d04 is the id of the Private Application, which is used to initialize the bt instance injected in the req parameter;
  3. response_transform_code is passed in plaintext form.
Save the key from the created Proxy as it will be used later to invoke it.

Done! These are all the resources necessary. Let's see how to use them.

Calling the Issuer API

This is the last step of this guide, and it's also the one that your services will likely perform repeatedly based on your business requirements. Let's call the Issuer API through the Proxy, passing the Private Application key to authenticate the request, and the payload the endpoint expects:

Create Card Request
curl '' \
-X "POST" \
-H "Content-Type: application/json" \
-H "Authorization: 5c2150b7-1c86-4f34-9d27-7f4465837e8d" \
-d '{
"type": "VIRTUAL"

The Authorization header includes Lithic API Key.

Create Card (Transformed) Response
"created": "2023-05-25T13:15:15Z",
"last_four": "3671",
"hostname": "",
"memo": "VIRTUAL card",
"type": "VIRTUAL",
"spend_limit": 0,
"spend_limit_duration": "TRANSACTION",
"state": "OPEN",
"funding": {
"created": "2021-10-06T21:25:13Z",
"token": "2b191150-1a75-451a-a5fa-52e3cba2a5f6",
"state": "ENABLED",
"nickname": "",
"account_name": "Sandbox",
"last_four": "1883"
"auth_rule_tokens": [],
"token": {
"id": "d2cbc1b4-5c3a-45a3-9ee2-392a1c475ab4",
"type": "card",
"tenant_id": "15f48eb5-8b52-4cdd-a396-608f7cf001d0",
"data": {
"number": "XXXXXXXXXXXX4242",
"expiration_month": 12,
"expiration_year": 2025
"created_by": "4a6ae2a6-79f8-4640-968f-88db913743df",
"created_at": "2023-04-17T12:54:44.8320458+00:00",
"mask": {
"number": "{{ data.number | reveal_last: 4 }}",
"expiration_month": "{{ data.expiration_month }}",
"expiration_year": "{{ data.expiration_year }}"
"search_indexes": [],
"containers": [

Lithic Create Card Docs

Be sure to replace <API_KEY> with the Private Application Key and TDEyQmkhQMpGiZd13FSRQ9 with the Proxy Key you created previously.

Key Considerations


You are not restricted to the Card Issuers listed above. As long as your partner can send you the card information through an API response, you can redact and tokenize it using the Pre-Configured Proxy.

CVC Retention

Card tokens retain verification code for 1 hour. This limitation is enforced by default to comply with PCI-DSS guidelines. However, depending on your business case, extending this period or implementing technical workarounds may be possible upon analysis. Please, reach out to our support team for assistance with this or other subjects.

Issuer Requirements

If you find that the Issuer API expects any form of Personal Identifiable Information (PII) in the Request Payload, you can also use the Proxy to detokenize sensitive data before hitting the downstream endpoint.

It's important to note that for some Issuers, inbound connections are only accepted from whitelisted IP addresses provided by the client. To help with this, here you can find a compiled list of our IP addresses that you can send to your acquirer. In cases of more restrictive integrations, Basis Theory can provide dedicated IPs upon request. If you're interested in this option, please don't hesitate to contact us.


A major benefit of vaulting issued cards is the ability to work with their data and send it anywhere. You may find useful to offer value-added services to your users, like a rewards program, the ability to monitor transactions, manage expenses or update payment methods in 3rd party services.

Check out this guide to learn how to route stored cards to 3rd party APIs. While it is mainly geared towards payments processing, the concepts are virtually the same.

Display Card to End User

By vaulting your issued cards with Basis Theory you automatically unlock the ability to display them to your end users using our highly customizable and developer-friendly Elements.

Check out this guide to learn how to securely display cards in your Web or Mobile application.


By using our Pre-Configured Proxy, you can confidently receive cardholder data from a Card Issuer via API requests without ever touching the card details yourself. This approach not only improves security and reduces compliance risks but also provides the flexibility to establish your own relationships with Issuers and decide what to do with the issued cards' data.

Learn More