API Checkout
Learn how to automate API-driven checkout flows using virtual cards, network tokens, or raw credit card data through BT AI’s secure proxy system. This guide covers different credential types for API integration based on your merchant’s capabilities.
Overview
Basis Theory AI enabels the generation and use of different types of credentials for API-based transactions. Choose the appropriate credential type based on your target API’s capabilities:
- Virtual Card: Generate a virtual card for APIs that accept standard card data
- Network Token: Generate a network token for APIs that support tokenized payments
- Raw Credit Card: Use the original card data through BT AI’s secure proxy when no other option works
Prerequisites
Before implementing API checkout, ensure you have:
Successfully Implemented Payment Method Collection
You must have completed the Collecting Payment Methods guide and successfully created at least one Payment Method. This guide assumes you have:
- A working JWT creation system for both public and private roles
- Successfully implemented the card collection flow
- At least one
card
type Payment Method available for your entity - The Payment Method ID from your collection implementation
Using Virtual Card with an API
When your target API accepts standard credit card data (it should also accept a Virtual Card), you can generate a virtual card credential to forward to the API for transaction completion.
Creating a Purchase Intent from the Backend
Generate Private JWT for Backend Access
import { jwt } from '@basistheory/ai-sdk';
// Generate private JWT for backend operations
const privateJWT = jwt.generatePrivate(
privateKey,
externalId,
expiration = '1m'
);
Request Purchase Intent Creation
To generate a virtual card credential for API integration, you’ll need to create a Purchase Intent from your backend. This requires sending the details outlined in the Create Purchase Intent API.
curl -X POST \
https://api.basistheory.ai/tenants/your-tenant-id/purchase-intent \
-H 'Authorization: Bearer your-private-jwt-token' \
-H 'Content-Type: application/json' \
-d '{
"credentialType": "virtual-card",
"paymentMethodId": "26859380-7829-4ee1-8a0a-38927881e7ef",
"mandates": [
{
"type": "maxAmount",
"value": "100",
},
{
"type": "currency",
"value": "USD"
}
{
"type": "mcc",
"value": "444"
}
]
}'
Handle Purchase Intent Response
The response will determine your next steps. The Purchase Intent can return in two states:
Active State (Ready to Use)
If the response status is "active"
, you immediately have access to the virtual card credential:
{
"id": "0b1ac700-c1a7-46b0-a166-809e5aac4dc3",
"entityId": "94c94330-94fd-4832-a106-e8474a274fe4",
"credentialType": "virtual-card",
"status": "active",
"card": {
"number": "2222030198005808",
"expirationMonth": "07",
"expirationYear": "2028",
"cvc": "211"
},
"createdAt": "2025-06-16T14:00:00Z",
"expiresAt": "2025-06-13T18:42:01Z"
}
Verify State (Verification Required)
If the response status is "verify"
, additional verification is required:
{
"id": "46c029d2-485a-4928-83b5-4326c4866722",
"entityId": "94c94330-94fd-4832-a106-e8474a274fe4",
"credentialType": "virtual-card",
"status": "verify",
"createdAt": "2025-06-16T14:00:00Z",
"expiresAt": "2025-06-13T18:42:01Z"
}
Verify the Purchase Intent
When a Purchase Intent requires verification (status: "verify"
), you’ll need to use the frontend SDK to complete the verification process. This ensures network requirements are met to verify ownership of the Payment Method.
Generate a JWT in Backend
Assuming you no longer have an active JWT from collecting the Payment Method, you’ll need to generate a JWT in your backend to grant your frontend SDK access.
import { jwt } from '@basistheory/ai-sdk';
const jwt = jwt.generatePublic(privateKey, externalId, expiration = '1m');
Frontend Verification Flow
You’ll now use this JWT to initiate the verification steps for this Purchase Intent. Depending on the network - this may take form of the following, all of which are handled seamlessly with our verifyPurchaseIntent
function:
- Token and Device binding
- 2FA text message, email, or mobile verification
- Passkey setup and binding to device
import { btAi } from '@btai/js-sdk';
// ... get signed jwt from your backend
// initialize sdk
const btAi = await btAi.init(jwt);
const purchaseIntent = await verifyPurchaseIntent("tenant_1234", "purchase_intent_1234");
Verification Flow Experience
The verification process ensures network requirements are met and may include several steps:
Verification Steps Include:
- Two-Factor Authentication: SMS or authenticator app verification
- Passkey Setup: Biometric authentication setup for future use
- Network Verification: Card network-specific verification requirements
- Device Registration: Secure device binding for future transactions

2FA Verification

Passkey Setup
Once the verification promise resolves, the verification has succeeded and your backend can now request the credentials.
Get the Credential from Purchase Intent
After verification is complete, your backend needs to retrieve the now-active credential using a private JWT:
Request Purchase Intent to Get Credential
Once verification is complete, retrieve the activated Purchase Intent with credentials:
curl -X GET \
https://api.basistheory.ai/tenants/:tenant_id/purchase-intent/46c029d2-485a-4928-83b5-4326c4866722 \
-H 'Authorization: Bearer your-private-jwt-token'
Successful Response with Virtual Card:
{
"id": "0b1ac700-c1a7-46b0-a166-809e5aac4dc3",
"entityId": "94c94330-94fd-4832-a106-e8474a274fe4",
"credentialType": "virtual-card",
"status": "active",
"card": {
"number": "2222030198005808",
"expirationMonth": "07",
"expirationYear": "2028",
"cvc": "211"
},
"createdAt": "2025-06-16T14:00:00Z",
"expiresAt": "2025-06-13T18:42:01Z"
}
Use Virtual Card with Target API
Once you have the virtual card credentials, forward them to your target API:
// Forward virtual card to target API
const response = await fetch('https://api.merchant.com/payments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 1000,
currency: 'usd',
card: {
number: purchaseIntent.card.number,
exp_month: purchaseIntent.card.expirationMonth,
exp_year: purchaseIntent.card.expirationYear,
cvc: purchaseIntent.card.cvc
}
})
});
Using a Network Token with an API
When your target API supports tokenized payments, you can generate a network token credential for enhanced security.
Request Purchase Intent Creation
curl -X POST \
https://api.basistheory.ai/tenants/your-tenant-id/purchase-intent \
-H 'Authorization: Bearer your-private-jwt-token' \
-H 'Content-Type: application/json' \
-d '{
"credentialType": "network-token",
"paymentMethodId": "26859380-7829-4ee1-8a0a-38927881e7ef",
"mandates": [
{
"type": "maxAmount",
"value": "100"
},
{
"type": "currency",
"value": "USD"
},
{
"type": "mcc",
"value": "444"
}
]
}'
Handle Network Token Response
Most likely your Network Token will require no additional verification, although if it were to require it - you will follow the same steps as laid out in the Virtual Card steps above.
Active State:
{
"id": "46c029d2-485a-4928-83b5-4326c4866722",
"credentialType": "network-token",
"status": "active",
"token": {
"number": "2222030198005808",
"expirationMonth": "07",
"expirationYear": "2028",
"cryptogram": "AAnSCQ9UvB3WAA4IVFwEAAADFA=="
}
}
Use Network Token with Target API
// Forward network token to target API
const response = await fetch('https://api.merchant.com/payments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 1000,
currency: 'usd',
payment_method: {
type: 'network_token',
token: {
number: purchaseIntent.token.number,
cryptogram: purchaseIntent.token.cryptogram,
exp_month: purchaseIntent.token.expirationMonth,
exp_year: purchaseIntent.token.expirationYear
}
}
})
});
Using Raw Credit Card with an API
When no other credential option works (or have failed), you can use the original card data through BT AI’s secure proxy system for maximum compatibility.
Generate Private JWT for Proxy Access
import { jwt } from '@basistheory/ai-sdk';
const privateJWT = jwt.generatePrivate(
privateKey,
externalId,
expiration = '1m'
);
Use Proxy Request
curl -X POST \
https://api.basistheory.ai/tenants/your-tenant-id/proxy \
-H 'BT-Authorization: Bearer your-private-jwt-token' \
-H 'BT-Target-URL: https://api.merchant.com/payments' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000,
"currency": "usd",
"payment_method": {
"type": "card",
"card": {
"number": "{{ paymentMethod: 815029c2-29ec-4fc2-8cd4-99feb3ee582c | type: '\''pan'\'' | json: '\''$.number'\'' }}",
"exp_month": "{{ paymentMethod: 815029c2-29ec-4fc2-8cd4-99feb3ee582c | type: '\''pan'\'' | json: '\''$.expirationMonth'\'' }}",
"exp_year": "{{ paymentMethod: 815029c2-29ec-4fc2-8cd4-99feb3ee582c | type: '\''pan'\'' | json: '\''$.expirationYear'\'' }}",
"cvc": "{{ paymentMethod: 815029c2-29ec-4fc2-8cd4-99feb3ee582c | type: '\''pan'\'' | json: '\''$.cvc'\'' }}"
}
}
}'
Next Steps
🎉 Outstanding! You’ve successfully implemented API checkout with BT AI. You now have three different approaches for API integration based on your target system’s capabilities: