@brexhq/brex-js
v4.1.1
Published
A JavaScript SDK for integrating Brex issuing card elements into web applications. This library provides secure, iframe-based components for displaying sensitive card information.
Readme
@brexhq/brex-js
A JavaScript SDK for integrating Brex issuing card elements into web applications. This library provides secure, iframe-based components for displaying sensitive card information.
Quick Start
import Brex from '@brexhq/brex-js';
// Initialize Brex
const brex = Brex();
const elements = brex.elements();
// Create a card number display element
const cardNumber = elements.create('issuingCardNumberDisplay', {
issuingCard: 'your_issuing_card_id',
ephemeralKeySecret: 'your_ephemeral_key'
});
// Mount it to a container
cardNumber.mount('#card-number-container');
// Listen for events
cardNumber.on('complete', () => {
console.log('Card number is ready');
});Available Elements
The library provides several elements for displaying card information:
issuingCardNumberDisplay: Displays the card numberissuingCardCvcDisplay: Displays the CVC/security codeissuingCardExpiryDisplay: Displays the expiration dateissuingCardPinDisplay: Displays the PINissuingCardCopyButton: Creates a button to copy card details
Styling Elements
You can customize the appearance of elements using supported style properties:
const element = elements.create('issuingCardNumberDisplay', {
issuingCard: 'your_issuing_card_id',
ephemeralKeySecret: 'your_ephemeral_key',
style: {
fontSize: '16px',
fontFamily: 'Arial, sans-serif',
color: '#333333',
fontWeight: 'normal',
letterSpacing: 'normal',
lineHeight: '1.5',
padding: '10px'
}
});
// Update styles later
element.update({
fontSize: '18px',
color: '#000000'
});Copy Button
The copy button element allows users to copy card details:
const copyButton = elements.create('issuingCardCopyButton', {
issuingCard: 'your_issuing_card_id',
ephemeralKeySecret: 'your_ephemeral_key',
toCopy: 'number' // 'number', 'cvc', 'expiry', or 'pin'
});
copyButton.mount('#copy-button-container');
copyButton.on('copied', () => {
console.log('Card number copied');
});Event Handling
All elements support the following events:
complete: Fired when the element is fully loadedloading: Fired when the element is loadingerror: Fired when an error occurscopied: Fired when content is copied (for copy buttons)
element.on('complete', () => {
console.log('Element is ready');
});
element.on('error', () => {
console.log('Something went wrong');
});Preloading the requester iframe (optional)
Behind the scenes, Brex(...).elements() mounts a hidden "requester" iframe the
first time create() is called. The iframe needs to download and parse its
own bundle before it can fetch sensitive details, which can add ~1-2 seconds
to the time the user waits for the card PAN to appear on first view.
If your UI knows ahead of time that a card view is imminent (for example, a
user has just navigated to a wallet/cards route), you can call prewarm()
to mount the requester iframe early so its bootstrap happens off the user's
critical path:
import Brex from '@brexhq/brex-js';
const elements = Brex().elements();
// Some time before the user actually opens a card. Idempotent and cheap.
elements.prewarm();
// Later — when the user opens the card. The requester is already
// mounted, so this skips the iframe-boot step and goes straight to
// fetching card details.
const cardNumber = elements.create('issuingCardNumberDisplay', {
issuingCard: 'your_issuing_card_id',
ephemeralKeySecret: 'your_ephemeral_key',
});
cardNumber.mount('#card-number-container');Notes:
- Idempotent: calling
prewarm()multiple times only mounts one iframe. Safe to call from per-component effects without coordination. - No card data is sent:
prewarm()takes no arguments and transmits noissuingCard,ephemeralKeySecret, or any other user/card identifier. Onlycreate()does that. - Client-side only: appends an iframe to
document.body; calling during SSR will throw. - No-op after
create(): if the requester is already mounted, subsequentprewarm()calls do nothing and emit no events.
When using instrumentation (see below), prewarming emits a single
requesterPrewarmed event so you can measure how long the iframe takes to
become ready in real-user sessions.
Instrumentation (optional)
Brex can emit lifecycle events covering the requester iframe handshake, the visible element iframes, and the postMessage round-trips between them. Use this to measure SDK timings and forward them to your RUM/telemetry pipeline.
import Brex from '@brexhq/brex-js';
const brex = Brex({
environment: 'production',
// Called for every lifecycle event. Keep it cheap.
onEvent: (event) => {
// event = { type, timestamp, key?, elementType?, issuingCard?, metadata? }
datadogRum.addAction('brex_js_event', event);
},
// Optional: also mirror events to console.debug. Default false.
debug: process.env.NODE_ENV !== 'production',
});Emitted event types include:
- Requester iframe:
requesterPrewarmed(only whenprewarm()is called),requesterCreated,requesterReady,requesterPortTransferred,requestCardDetailsSent,cardDetailsReceived,cardDetailsForwarded - Visible element iframe:
elementCreated,elementReady,elementPortTransferred,elementMounted,elementUnmounted,elementDestroyed - Errors:
elementError
Each event carries a timestamp, and where applicable the iframe key,
elementType, and the consumer-supplied issuingCard for correlation.
The timestamp is performance.timeOrigin + performance.now() (a high-res
absolute timestamp on the same epoch as Date.now()). The SDK uses iframes
under the hood — each iframe has its own performance.timeOrigin, so plain
performance.now() values would not be comparable between the parent window
and the iframes. Adding timeOrigin produces values you can subtract across
realms. Within the same realm, subtracting two timestamps yields the same
result as performance.now() arithmetic (the origin cancels). See
MDN: Synchronizing time between contexts.
The ephemeral key secret and card details are never included in any event payload.
If neither onEvent nor debug is supplied, the SDK uses a no-op emitter
and incurs no runtime cost.
Complete Example
Here's a complete example showing how to display all card information:
import Brex from '@brexhq/brex-js';
const brex = Brex();
const elements = brex.elements();
// Common configuration
const config = {
issuingCard: 'your_issuing_card_id',
ephemeralKeySecret: 'your_ephemeral_key',
style: {
fontSize: '16px',
fontFamily: 'Arial, sans-serif',
color: '#333333'
}
};
// Create elements
const cardNumber = elements.create('issuingCardNumberDisplay', config);
const cardCvc = elements.create('issuingCardCvcDisplay', config);
const cardExpiry = elements.create('issuingCardExpiryDisplay', config);
const cardPin = elements.create('issuingCardPinDisplay', config);
// Mount elements
cardNumber.mount('#card-number-container');
cardCvc.mount('#card-cvc-container');
cardExpiry.mount('#card-expiry-container');
cardPin.mount('#card-pin-container');
// Add copy buttons
const copyNumber = elements.create('issuingCardCopyButton', {
...config,
toCopy: 'number'
});
copyNumber.mount('#copy-number-button');
// Event handling
cardNumber.on('complete', () => console.log('Card number ready'));
copyNumber.on('copied', () => console.log('Card number copied'));Required HTML:
<div id="card-number-container"></div>
<div id="copy-number-button">Copy</div>
<div id="card-cvc-container"></div>
<div id="card-expiry-container"></div>
<div id="card-pin-container"></div>