Web Elements Services
Basis Theory Web Elements offers a set of services that enable you to securely collect, manage, and share sensitive data without exposing it to your application code. This document explains the available services and how to use them in your applications.
Overview
The services provided by Basis Theory Web Elements fall into four main categories:
- Data Collection - Securely collect and tokenize sensitive data
- Data Retrieval - Safely detokenize and reveal sensitive data
- Session Management - Create and manage temporary access sessions
- Third-Party Integration - Securely interact with third-party APIs
Element Methods
Elements provide several methods for interacting with and manipulating their values securely. These methods allow you to programmatically control elements while maintaining the security boundary.
For detailed documentation on all available methods, see the Element Methods reference.
Data Collection
Tokenizing Data
Basis Theory Elements can securely tokenize sensitive data without exposing it to your application. You can tokenize data using two primary approaches:
1. Create a Single Token
The tokens.create
method creates a single token with your sensitive data:
// Create a token containing sensitive data
bt.tokens
.create({
type: "token", // Specify the token type
data: {
// Include element instances containing sensitive data
sensitiveData: sensitiveDataElement, // Data remains in secure iframe
// Include non-sensitive data directly
nonSensitiveData: "plainText",
// Nested data structures are supported
otherData: {
someInteger: 20,
someBoolean: false,
},
someOtherData: ["plainText1", "plainText2"],
},
// Optional metadata (non-sensitive)
metadata: {
nonSensitiveField: "nonSensitiveValue",
},
})
.then((token) => {
// Save the token ID for future reference
console.log(token.id);
// Full response includes masked/redacted data
console.log(JSON.stringify(token));
});
plainText
values, data will be HTML encoded before storage for security reasons.Create a Card Token
For payment card data, you can use either the combined CardElement
or individual card elements:
// Option 1: Using the combined CardElement
bt.tokens
.create({
type: "card", // Specific type for cards
data: cardElement, // Pass the entire card element
})
.then((token) => {
console.log(token.id); // Token to store
console.log(JSON.stringify(token.data)); // Contains masked card data
});
// Option 2: Using individual card elements
bt.tokens
.create({
type: "card",
data: {
// Each piece of card data in a separate element
number: cardNumberElement,
expiration_month: cardExpirationDateElement.month(), // Using the data parsing method
expiration_year: cardExpirationDateElement.year(),
cvc: cardVerificationCodeElement
}
})
.then((token) => {
console.log(token.id);
console.log(JSON.stringify(token.data)); // Masked card data
});
Create a Bank Account Token
For bank account information:
bt.tokens
.create({
type: "bank",
data: {
routingNumber: routingNumberElement,
accountNumber: accountNumberElement,
},
})
.then((token) => {
console.log(token.id); // Token to store
console.log(JSON.stringify(token.data)); // Contains redacted bank data
});
2. Tokenize Multiple Values at Once
The tokenize
method allows you to create multiple tokens in a single operation:
// Tokenize multiple pieces of data at once
bt.tokenize({
// Create two card tokens with different approaches
card1: {
type: "card",
data: cardElement, // Using the combined card element
},
card2: {
type: "card",
data: {
// Using individual card elements
number: cardNumberElement,
expiration_month: cardExpirationDateElement.month(),
expiration_year: cardExpirationDateElement.year(),
cvc: cardVerificationCodeElement,
},
},
// Create a generic token
sensitiveData: sensitiveDataElement,
// Include non-sensitive data
nonSensitiveData: "plainText",
otherData: {
someInteger: 20,
someBoolean: false,
},
someOtherData: ["plainText1", "plainText2"],
}).then((tokens) => {
// Multiple token IDs returned in the response
console.log(tokens.card1.id, tokens.card2.id, tokens.sensitiveData);
// Full response with all tokens
console.log(JSON.stringify(tokens));
});
Updating Tokens
You can update existing tokens with new values from Elements:
// Update an existing token with a new value
bt.tokens
.update("ca9f3fd7-3906-4087-83aa-9a6129221297", { // Token ID to update
data: cardElement, // New data from an element
})
.then((token) => {
// Response contains redacted/masked updated data
console.log(JSON.stringify(token.data));
});
Creating Token Intents
Token Intents provide a way to create tokens that require additional verification before being usable:
// Create a token intent for a card
bt.tokenIntents
.create({
type: "card",
data: cardElement // Pass the card element
})
.then((tokenIntent) => {
// Use this ID to validate and convert to a token
console.log(tokenIntent.id);
});
// Alternative: Create with individual elements
bt.tokenIntents
.create({
type: "card",
data: {
number: cardNumberElement,
expiration_month: cardExpirationDateElement.month(),
expiration_year: cardExpirationDateElement.year(),
cvc: cardVerificationCodeElement
}
})
.then((tokenIntent) => {
console.log(tokenIntent.id);
});
Data Retrieval
Retrieving and Displaying Tokenized Data
To securely retrieve and display tokenized data, use the tokens.retrieve
method with the Element's setValue
method:
// First, create an element to display the data
const textElement = bt.createElement("text", {
targetId: "text-element",
});
// Retrieve the token and set its value into the element
bt.tokens
.retrieve("ca9f3fd7-3906-4087-83aa-9a6129221297", {
apiKey: "<SESSION_API_KEY>", // Session key with appropriate permissions
})
.then((token) => {
// Set the tokenized data into the element
textElement.setValue(token.data);
});
data
attribute in the token returned by retrieve
is not the actual data, but a synthetic representation. The real sensitive data remains secure within the Element.metadata
are directly accessible from the response.Displaying Card Data
For card data, you can populate either a combined CardElement or individual card elements:
// Option 1: Display in a combined CardElement
const cardElement = bt.createElement("card");
bt.tokens
.retrieve("ca9f3fd7-3906-4087-83aa-9a6129221297", {
apiKey: "<SESSION_API_KEY>",
})
.then((token) => {
// Set the entire card data object
cardElement.setValue(token.data);
});
// Option 2: Display in individual elements
const cardNumberElement = bt.createElement("cardNumber", {
targetId: "card-number",
});
const cardExpirationDateElement = bt.createElement("cardExpirationDate", {
targetId: "card-expiration-date"
});
bt.tokens
.retrieve("ca9f3fd7-3906-4087-83aa-9a6129221297", {
apiKey: "<SESSION_API_KEY>",
})
.then((token) => {
// Set each piece into the appropriate element
cardNumberElement.setValue(token.data.number);
cardExpirationDateElement.setValue({
month: token.data.expiration_month,
year: token.data.expiration_year,
});
});
Session Management
Sessions provide a secure way to grant temporary elevated access to tokenized data on the frontend, enabling features like:
- Displaying masked card data to users
- Allowing users to update saved payment methods
- Verifying identity with sensitive information
Learn more about sessions and access controls.
Creating Sessions
You can create a new session for a Public Application:
// Create a session for temporary elevated access
const session = await bt.sessions.create();
Third-Party Integration
Proxy Service
The Proxy Service allows you to securely forward Element data to third-party APIs without exposing the sensitive data to your application.
// Create elements for the request and response
const submitElement = bt.createElement("text", {
targetId: "submitElement", // Element containing data to send
});
const revealElement = bt.createElement("text", {
targetId: "revealElement", // Element to display the response
});
// Make a POST request through the proxy
bt.proxy
.post({
headers: {
"BT-PROXY-KEY": "e29a50980ca5", // Your pre-configured proxy key
},
body: {
sensitiveValue: submitElement, // Element containing sensitive data
nonSensitiveValue: "plainText", // Regular data
},
apiKey: "<SESSION_API_KEY>", // Session key with appropriate permissions
})
.then((response) => {
// Display the response data in the reveal element
revealElement.setValue(response.value);
});
Supported HTTP Methods
The Proxy Service supports all standard HTTP methods:
// GET request
bt.proxy.get(options);
// POST request
bt.proxy.post(options);
// PUT request
bt.proxy.put(options);
// PATCH request
bt.proxy.patch(options);
// DELETE request
bt.proxy.delete(options);
Proxy Request Options
Option | Type | Required | Description |
---|---|---|---|
path | string | No | String appended to the end of the proxied URL path |
query | object | No | Key/value pairs added as query parameters |
headers | object | No | Key/value pairs added as HTTP headers |
body | object | No | Payload sent to the proxied URL (can contain Elements) |
apiKey | string | No | BasisTheory API Key for authentication |
correlationId | string | No | ID for request correlation |
idempotencyKey | string | No | Key for request idempotency |
Accessing Non-Sensitive Proxy Responses Beta
Our Elements enable you to convert proxy responses into plain text, which is ideal for non-sensitive data handling. This enhancement streamlines your data processing workflows and facilitates an easier understanding of the returned data, bypassing decryption or tokenization.
This feature is currently invite-only. If you're interested, please get in touch for an invitation.
HTTP Client Service
The HTTP Client Service enables you to make requests to third-party APIs with Element data in the payload:
// Initialize BasisTheory
const bt = await basistheory("<API_KEY>");
// Make a POST request with sensitive data
bt.client.post(
"https://www.api.thirdpartydomain.com/resources",
{
sensitiveData: sensitiveDataElement, // Element containing sensitive data
nonSensitiveData: "plainText",
otherData: {
someInteger: 20,
someBoolean: false,
}
},
{
headers: {
"Content-Type": "application/json"
}
}
).then((response) => {
// Full plaintext response is accessible
console.log(JSON.stringify(response));
});
Supported HTTP Methods
The HTTP Client Service supports all standard HTTP methods:
// GET request
bt.client.get(url, options);
// POST request
bt.client.post(url, body, options);
// PUT request
bt.client.put(url, body, options);
// PATCH request
bt.client.patch(url, body, options);
// DELETE request
bt.client.delete(url, options);
Error Handling
Basis Theory Service Errors
When using Basis Theory services, you may encounter two main types of errors:
import { BasisTheoryApiError, BasisTheoryValidationError } from "@basis-theory/web-elements/common";
bt.tokenize({
card1: {
type: "card",
data: cardElement1,
},
card2: {
type: "card",
data: cardElement2,
},
ssn: textElement,
}).catch((error) => {
if (error instanceof BasisTheoryValidationError) {
// Client-side validation failure
// Example: incomplete or invalid element data
console.error("Validation error:", error.details);
// Check specific field errors
if (error.details.card1?.number?.type === 'invalid') {
// Handle invalid card number
}
} else if (error instanceof BasisTheoryApiError) {
// Server-side error
console.error(`API error ${error.status}:`, error.data);
}
});
HTTP Client Service Errors
HTTP client services can throw similar validation errors, plus HTTP-specific errors:
import { HttpClientError, BasisTheoryValidationError } from "@basis-theory/web-elements/common";
const bt = await basistheory("<API_KEY>");
bt.client.post(
"https://api.example.com/data",
{
sensitiveData: textElement,
}
).catch((error) => {
if (error instanceof BasisTheoryValidationError) {
// Client-side validation failure
console.error("Validation error:", error.details);
} else if (error instanceof HttpClientError) {
// HTTP error from the third-party API
console.error(`HTTP error ${error.status}:`, error.data);
console.log("Response headers:", error.headers);
}
});
Error Types Reference
BasisTheoryValidationError
{
name: "BasisTheoryValidationError",
details: {
card1: {
number: {
type: 'invalid' // The field is invalid
},
cvc: {
type: 'incomplete' // The field is not complete
}
},
card2: {
// No issues with card2
}
},
validation: [] // deprecated
}
BasisTheoryApiError
{
name: "BasisTheoryApiError",
data: {
// Full API response body from Basis Theory
},
status: 400 // HTTP status code
}
HttpClientError
{
name: "HttpClientError",
data: {
// Response body from the third-party API
},
status: 400, // HTTP status code
headers: {
// Response headers from the third-party API
}
}
name
property as an alternative to using instanceof
for type checking.If you encounter issues during tokenization such as timeout errors or validation failures, refer to our troubleshooting guide for detailed solutions.