Network Tokens
This guide demonstrates how to implement Network Tokens in your application using the Basis Theory platform to handle PCI-sensitive data operations while delivering enhanced security for payment processing workflows.
What are Network Tokens?
Network Tokens are cryptographically secure payment credentials issued directly by card networks (Visa, Mastercard, American Express, Discover) that replace Primary Account Numbers (PANs) in payment transactions.
Unlike traditional card tokens that are issued by payment processors or gateways, Network Tokens are issued directly by the card networks themselves and adhere to industry-accepted EMVCo specifications. This allows Network Tokens to replace the customer's PAN at every step in the card payment lifecycle—from merchant to acquiring bank to issuing bank.
Why Use Network Tokens?
Network Tokens provide significant advantages over traditional payment methods, particularly for businesses with subscription models or recurring payment needs:
Automated Card Lifecycle Management
Card networks automatically update Network Tokens when underlying cards are reissued or expire:
- Eliminates failed recurring payments from expired credentials
- Reduces customer churn from payment interruptions
- Provides seamless payment experiences without customer re-enrollment
Security Benefits
- Reduces real card data stored in the payment ecosystem
- Network Tokens represent all card details, providing richer transaction context than PAN-only transactions
- Option for transaction-specific cryptograms to provide additional verification per payment
- Reduced PCI DSS compliance scope:
- Card networks manage sensitive data - PANs are stored and secured by Visa, Mastercard, and other networks instead of merchants
- Reduces systems requiring PCI controls - Token-only systems may be considered out-of-scope if properly segmented
- Enables simpler compliance validation - May qualify for reduced Self-Assessment Questionnaires versus full audits
Getting Started
To get started, you will need to create a Basis Theory Account and a TEST Tenant.
Create a Private Application
You will need a Private Application to allow your backend to call Basis Theory APIs for Network Token operations. Click here to create one using the Basis Theory Customer Portal.
This will create an application with the following Access Controls:
network-token:create
network-token:cryptogram
network-token:suspend
network-token:resume
reactor:invoke
Network Token operations require Private Application permissions and are not available through Public Applications.
Implementation Guide
This guide walks through some steps to create a Network Token and process it with Reactors while keeping you in PCI compliance.
Install the SDK
This example demonstrates how to implement a Network Token workflow using BasisTheory Node SDK. You can also use our SDKs for other languages or call our REST APIs directly.
Initialize the Client
import { BasisTheoryClient } from "@basis-theory/node-sdk";
const client = new BasisTheoryClient({
apiKey: "YOUR_PRIVATE_API_KEY"
});
Create a Network Token
Create a Network Token using your Private Application. You can create tokens from existing card Tokens, Token Intents, or raw card data:
import { BasisTheoryClient } from "@basis-theory/node-sdk";
const client = new BasisTheoryClient({
apiKey: "YOUR_PRIVATE_API_KEY"
});
async function createNetworkToken() {
try {
// Using an existing Token ID
const networkToken = await client.networkTokens.create({
tokenId: "c06d0789-0a38-40be-b7cc-c28a718f76f1",
cardholderInfo: {
name: "John Doe",
address: {
line1: "123 Main Street",
line2: "Apt 4B",
line3: "Building 7",
city: "Beverly Hills",
postalCode: "90210",
stateCode: "CA",
countryCode: "USA"
}
}
});
console.log('Network Token created:', networkToken.id);
console.log('Status:', networkToken.status);
return networkToken;
} catch (error) {
console.error('Error creating Network Token:', error);
throw error;
}
}
Generate Cryptogram
A cryptogram is a transaction-specific security code generated by the issuer for a Network Token. You might need to generate this cryptographic proof before processing any payment to provide enhanced validation for each transaction request.
This is usually only required for a one time transaction or when setting up the initial recurring transaction, however this might need to be validated with your payment provider.
async function generateCryptogram(networkTokenId) {
try {
const cryptogram = await client.networkTokens.cryptogram(networkTokenId);
console.log('Cryptogram generated:', cryptogram.cryptogram);
console.log('ECI:', cryptogram.eci);
return cryptogram;
// Response example: { cryptogram: "2z8pd6WGPUi/BBesvjJcyw==", eci: "07" }
} catch (error) {
console.error('Error generating cryptogram:', error);
throw error;
}
}
Process payment using your payment provider API using a Pre-Configured Proxy
This approach keeps all sensitive data processing within Basis Theory's secure environment while allowing you to integrate with any payment provider that accepts external generated network tokens.
For more information of how to setup a proxies follow this page
Adapt the payload structure in the proxy code to match your specific payment provider's API requirements.
- Adyen
const { BasisTheoryClient } = require('@basis-theory/node-sdk-2');
const {Client, Config, CheckoutAPI} = require('@adyen/api-library');
module.exports = async function (req) {
const {applicationOptions: {apiKey}, args, configuration} = req;
const {ADYEN_API_KEY, ADYEN_MERCHANT_ACCOUNT} = configuration;
const bt = new BasisTheoryClient({apiKey});
const {networkToken} = args.body;
const cryptogramData = await bt.networkTokens.cryptogram(networkToken.id);
const requestData = {
amount: {currency: 'USD', value: 100},
reference: 'ORDER-12345',
merchantAccount: ADYEN_MERCHANT_ACCOUNT,
paymentMethod: {
type: 'networkToken',
number: networkToken.number,
expiryMonth: networkToken.expiryMonth,
expiryYear: networkToken.expiryYear,
brand: 'visa',
holderName: 'John Doe',
},
mpiData: {
directoryResponse: 'Y',
authenticationResponse: 'Y',
tokenAuthenticationVerificationValue: cryptogramData.cryptogram,
eci: cryptogramData.eci
},
shopperInteraction: 'Ecommerce',
recurringProcessingModel: 'Subscription',
shopperReference: 'CUSTOMER_ID_123'
};
const config = new Config({
apiKey: ADYEN_API_KEY,
merchantAccount: ADYEN_MERCHANT_ACCOUNT,
environment: "TEST"
});
const client = new Client({config});
const checkoutClient = new CheckoutAPI(client);
const result = await checkoutClient.payments(requestData);
return {
body: result
};
};
curl -L -X POST 'https://api.basistheory.com/proxies/YOUR_PROXY_ID' \
-H 'BT-API-KEY: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{
"name": "Adyen Call with NT proxy",
"destination_url": "https://echo.basistheory.com/anything",
"require_auth": false,
"request_transform": {
"type": "code",
"code": "YOUR_PRE_REQUEST_CODE_HERE"
},
"application": {
"id": "APPLICATION_ID_HERE"
},
"configuration": {
"ADYEN_API_KEY": "YOUR_ADYEN_API_KEY",
"ADYEN_MERCHANT_ACCOUNT": "YOUR_ADYEN_MERCHANT_ACCOUNT"
}
}'
curl -L 'https://api.flock-dev.com/proxy' \
-H 'BT-API-KEY: YOUR_API_KEY' \
-H 'BT-PROXY-KEY: YOUR_PROXY_KEY' \
-H 'Content-Type: application/json' \
-d '{
"networkToken":{
"id": "{{ network_token: YOUR_NETWORK_TOKEN_ID | json: \"$.id\" }}",
"number": "{{ network_token: YOUR_NETWORK_TOKEN_ID | json: \"$.data.number\" }}",
"expiryMonth": "{{ network_token: YOUR_NETWORK_TOKEN_ID | json: \"$.data.expiration_month\" }}",
"expiryYear": "{{ network_token: YOUR_NETWORK_TOKEN_ID | json: \"$.data.expiration_year\" }}"
}
}'
async function completePaymentFlow() {
try {
// Step 1: Create Network Token (assuming you have this function)
const networkToken = await createNetworkToken();
// Step 2: Process payment using the proxy
const response = await fetch('https://api.flock-dev.com/proxy', {
method: 'POST',
headers: {
'BT-API-KEY': 'YOUR_API_KEY',
'BT-PROXY-KEY': 'YOUR_PROXY_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
networkToken: {
id: `{{ network_token: ${networkToken.id} | json: "$.id" }}`,
number: `{{ network_token: ${networkToken.id} | json: "$.data.number" }}`,
expiryMonth: `{{ network_token: ${networkToken.id} | json: "$.data.expiration_month" }}`,
expiryYear: `{{ network_token: ${networkToken.id} | json: "$.data.expiration_year" }}`
}
})
});
const result = await response.json();
if (response.ok) {
console.log('Payment completed successfully!', result);
return result;
} else {
console.log('Payment failed:', result);
throw new Error(result.error || 'Payment failed');
}
} catch (error) {
console.error('Payment flow error:', error);
throw error;
}
}
Token Lifecycle Management
Token Suspension
Temporarily suspend a Network Token to prevent transaction processing while preserving the ability to reactivate:
async function suspendNetworkToken(req) {
const { bt, args } = req;
try {
const result = await bt.networkTokens.suspend(args.network_token_id);
console.log('Network Token suspended:', result.status);
return result;
} catch (error) {
console.error('Error suspending Network Token:', error);
throw error;
}
}
Token Reactivation
Restore transaction capability for a previously suspended Network Token:
async function resumeNetworkToken(req) {
const { bt, args } = req;
try {
const result = await bt.networkTokens.resume(args.network_token_id);
console.log('Network Token resumed:', result.status);
return result;
} catch (error) {
console.error('Error resuming Network Token:', error);
throw error;
}
}
Token Deletion
Eliminates a previously created Network Token
async function deleteNetworkToken(req) {
const { bt, args } = req;
try {
const result = await bt.networkTokens.delete(args.network_token_id);
console.log('Network Token resumed:', result.status);
return result;
} catch (error) {
console.error('Error resuming Network Token:', error);
throw error;
}
}
Event Monitoring via Webhooks
Configure webhook endpoints to receive real-time notifications for critical Network Token lifecycle events. This enables proactive monitoring and automated response to Network Token status changes.
Available webhook events include:
network-token.created
: Triggered when a new Network Token is successfully creatednetwork-token.cryptogram.created
: Triggered when a cryptogram is generated for a Network Tokennetwork-token.deleted
: Triggered when a Network Token is permanently deletednetwork-token.updated
: Triggered when a Network Token is updated by the card network or the state of the Network Token is changed
To configure webhooks for your Network Token events, visit the Basis Theory Customer Portal and set up webhook endpoints for the events you want to monitor.
Development Best Practices
Comprehensive Error Handling
Implement robust error handling for Network Token operations. Basis Theory provides specific error codes and retry guidance to help you handle different failure scenarios appropriately:
try {
const networkToken = await createNetworkToken(cardTokenId);
} catch (error) {
// Handle specific error types with appropriate retry logic
switch (error.title) {
case 'CARD_NOT_ELIGIBLE':
// Card is not eligible for network tokenization - do not retry
console.log('Card not eligible for network tokenization, falling back to regular processing');
// Fall back to regular card processing
break;
case 'CARD_VERIFICATION_FAILED':
// Prompt user to re-enter CVV or card details - retryable
console.log('Card verification failed - request user to re-enter card details');
throw new Error('Please re-enter your card details');
break;
case 'PROVISION_DATA_EXPIRED':
// Request updated card details from user - retryable
console.log('Card data expired - request updated card details');
throw new Error('Please provide updated card information');
break;
// ... additional error types available
// See API documentation for complete list of error codes and retry guidance
default:
// Handle other unexpected errors
console.error('Unexpected error during network tokenization:', error);
throw error;
}
}
Testing
Use the provided test cards to test different scenarios during development. These test cards simulate various success and error conditions you may encounter in production.
Network Token Management
When managing Network Tokens for long-term storage and recurring transactions, consider these best practices to maximize security and operational efficiency:
- Store the Network Token ID in your database, not the raw card data.
- Use the stored token for future transactions, such as recurring billing or card-on-file scenarios.
- Monitor Webhook events for token updates to ensure you react promptly to changes.
- Handle token lifecycle changes appropriately to maintain seamless payment experiences for your customers.
Network Tokens are particularly beneficial for companies with large subscription customer bases who store many cards on file for recurring transactions.
Preparing for Production
When you're ready to move to production:
- Enable Network Tokens: Contact support@basistheory.com to enable Network Tokens for your production environment.
Additional considerations for production deployment:
- Use Real Card Data: Ensure usage in production uses real card data, not test cards. Continue using test environments for development and testing purposes
- Understand Provider Integration: Review how your payment provider accepts external network tokens to determine the appropriate integration approach (Reactors or Proxies)
- Configure Production Webhooks: Set up production webhook endpoints to monitor network token lifecycle events
Conclusion
This guide has explored Network Tokens and their implementation using the Basis Theory platform. The examples and patterns shown demonstrate the concepts and practical approaches for working with Network Tokens in modern payment processing.
Key areas covered:
- Creating and managing Network Tokens through Basis Theory's APIs
- Generating cryptograms for secure transaction processing
- Using Proxies to integrate with payment providers while maintaining PCI compliance