Co-Badge Support
Some cards carry more than one payment network — for example a domestic network alongside Visa or Mastercard. Co-badge support lets the cardNumber and card elements detect these networks and choose, or let the user choose, which one processes the payment.
This is distinct from co-brand detection: co-brand detection resolves which brand a partially typed number belongs to (for example Mastercard vs. Maestro), while co-badging selects between the multiple networks a fully identified card supports.
How networks are detected
Network detection relies on BIN enrichment — a lookup based on the card's BIN (the first six digits). Enrichment is enabled by either of two options:
binLookup— turns BIN enrichment on.coBadge— configures network selection. Setting it enables BIN enrichment automatically, so you do not also need to setbinLookup.
When enrichment is active and the card participates in more than one network, the change event reports the available networks and the selectedNetwork.
When the card is tokenized, additional card brands are returned in the Token's card.additional array. For a Cartes Bancaires co-badge, an entry has brand set to cartes-bancaires.
binLookup
binLookup turns BIN enrichment on. It is not specific to co-badging — enrichment also returns the issuer metadata described in BIN enrichment. You only need it here if you want to tune debounceMs, since setting coBadge enables enrichment on its own.
coBadge
Use coBadge when you want to control which network is selected, or render a selector for the user.
| Field | Type | Description |
|---|---|---|
preferredNetworks | string[] | Priority order used to pick the network automatically. The first available network that matches is selected. When omitted, a default priority order is used: visa, mastercard, amex, discover, jcb, diners, cartes-bancaires, unionpay, elo, maestro, mir, hiper, hipercard. If nothing in the list matches the card's networks, the first network in the enrichment response is selected. |
mode | 'auto' | 'manual' | 'auto' (default) selects a network automatically using preferredNetworks. 'manual' renders a built-in network selector inside the element for the user to choose. To style it, see Style the built-in selector. |
const cardNumberEl = bt.createElement('cardNumber', {
coBadge: {
preferredNetworks: ['cartes-bancaires', 'visa'],
mode: 'auto',
},
});
await cardNumberEl.mount('#card-number-container');
Network identifiers are lowercase, kebab-case strings — for example visa and cartes-bancaires. Matching against preferredNetworks and setNetwork() is case-insensitive.
Reading the selected network
When enrichment is active, the change event adds two fields to event.detail:
| Field | Type | Description |
|---|---|---|
networks | string[] | Payment networks the card participates in. Populated only for multi-network (co-badged) cards. |
selectedNetwork | string | The currently selected network, when the card participates in more than one. |
For a co-badged card, event.detail looks like this:
{
isValid: true,
isEmpty: false,
error: null,
cardBrand: 'visa',
last4: '0008',
bin: '403550',
cvvLengths: [3],
potentialBrands: ['visa'],
matchStrength: 1,
networks: ['visa', 'cartes-bancaires'],
selectedNetwork: 'cartes-bancaires',
}
cardNumberEl.on('change', (event) => {
const { networks, selectedNetwork } = event.detail;
if (networks && networks.length > 1) {
// Co-badged card — surface the selected network
console.log('Available networks:', networks, 'selected:', selectedNetwork);
}
});
The networkChanged event
The networkChanged event fires whenever the selected network changes — through automatic selection, the built-in selector, or a call to setNetwork(). Only cardNumber and card elements emit it.
| Field | Type | Description |
|---|---|---|
network | string | The newly selected network. |
previousNetwork | string | The network selected before this change, if any. |
availableNetworks | string[] | All networks the card supports. |
selectionMode | 'auto' | 'user' | How the selection was made: 'auto' for automatic selection, or 'user' when the user picks a network via the built-in selector or setNetwork. |
When the user switches from Visa to Cartes Bancaires, event.detail looks like this:
{
network: 'cartes-bancaires',
previousNetwork: 'visa',
availableNetworks: ['visa', 'cartes-bancaires'],
selectionMode: 'user',
}
- Web Elements
- React Elements
cardNumberEl.on('networkChanged', (event) => {
const { network, availableNetworks } = event.detail;
console.log('Network is now', network, 'of', availableNetworks);
});
import { CardNumberElement } from '@basis-theory/react-elements';
<CardNumberElement
id="card-number"
coBadge={{ preferredNetworks: ['cartes-bancaires', 'visa'] }}
onNetworkChanged={(event) => {
const { network, availableNetworks } = event.detail;
console.log('Network is now', network, 'of', availableNetworks);
}}
/>
Style the built-in selector
With mode: 'manual', a co-badged card shows a chevron next to its brand icon. Selecting the icon or the chevron opens a list of the card's networks, and the user's choice becomes the selected network. By default the list takes its colors from the field's theme. To match it to your form independently of the input fields, pass networkSelector in the theme when you initialize the SDK:
const bt = BasisTheory('<PUBLIC_API_KEY>', {
theme: {
networkSelector: {
panel: {
background: { color: '#ffffff' },
border: { color: '#d1d5db', radius: '12px' },
shadow: '0 4px 12px rgba(0, 0, 0, 0.12)',
},
option: {
text: { color: '#111827' },
hover: { background: { color: '#f3f4f6' } },
selected: {
background: { color: '#2563eb' },
text: { color: '#ffffff' },
},
},
},
},
});
Every token is optional. A token you leave out keeps the selector's default.
| Token | Type | Description |
|---|---|---|
panel.background.color | string | Surface of the list. Defaults to colors.background.default over an opaque base, so a transparent field background never leaves the list see-through. |
panel.border.color | string | Color of the list's 1px border. Defaults to colors.border.default. |
panel.border.radius | string | Corner radius of the list. Defaults to 8px. |
panel.shadow | string | Shadow of the list, as any CSS box-shadow value. Defaults to 0 10px 28px rgba(0, 0, 0, 0.35) in cardNumber and 0 10px 28px rgba(0, 0, 0, 0.12) in card. |
option.text.color | string | Color of the network name in each row. Defaults to colors.text.primary. |
option.hover.background.color | string | Background of the row under the pointer or keyboard focus. Defaults to colors.background.hover. |
option.selected.background.color | string | Background of the selected network's row. Defaults to colors.background.focus. |
option.selected.text.color | string | Color of the selected network's name. Defaults to option.text.color. |
Color tokens take CSS color values, such as hex, rgb(), or hsl(). When you pass a darkTheme, dark mode reads only darkTheme.networkSelector, so colors set in theme don't carry into the dark theme. Without darkTheme.networkSelector, the list follows your dark field colors.
In manual mode the brand icon sits 9px further from the field's edge than in auto mode, which leaves room for the chevron. The icon keeps that position whether or not the selector is showing, so it doesn't move as the user types.
Make room for the open list
The list opens inside the element's iframe, so the iframe grows to show it. cardNumber grows to fit the list and returns to its own height when the list closes. card keeps the height of the container you mount it in. When the open list doesn't fit inside that container, card grows to show it and returns to the container's height when the list closes.
With an automatic container height, the list pushes the content below the element down while it is open. To render it over that content instead, give the container a fixed height, overflow: visible, and position: relative with a z-index. An overflow: hidden on the container or any of its ancestors clips the list.
Build your own network picker
With mode: 'manual' the element renders a built-in selector. To render your own selector instead, read networks from the change event to populate your UI, then call setNetwork() to apply the user's choice. setNetwork() requires the element to be mounted.
- Web Elements
- React Elements
// When the user picks a network in your UI:
await cardNumberEl.setNetwork('cartes-bancaires');
setNetwork is exposed on the element ref:
import { useRef } from 'react';
import { CardNumberElement } from '@basis-theory/react-elements';
function PaymentForm() {
const cardNumberRef = useRef(null);
const chooseNetwork = (network) => cardNumberRef.current?.setNetwork(network);
return (
<CardNumberElement
ref={cardNumberRef}
coBadge={{ mode: 'auto', preferredNetworks: ['cartes-bancaires', 'visa'] }}
/>
);
}