Tokenização
Criptografe dados de cartão no navegador com o Bridge SDK da Tokeflow e troque-os por uma referência de token de uso único que seu backend pode cobrar.
A tokenização transforma dados brutos de cartão em uma referência de token segura de manipular, sem que esses dados jamais toquem seus servidores. Com o Bridge SDK, o portador do cartão digita nos campos seguros da Tokeflow, o SDK criptografa os dados no navegador e tokeflow.cards.tokenize() retorna um CardToken. Você envia apenas o tokenId para o seu backend, que cria uma transação com ele.
Isso mantém os dados sensíveis do cartão fora do escopo da sua aplicação, ao mesmo tempo em que você mantém controle total sobre a UI e o fluxo de pagamento.
Os campos seguros da Tokeflow rodam dentro de iframes isolados e cross-origin; os dados do cartão são criptografados no navegador e nunca tocam seus servidores. Os scripts da página não conseguem ler o PAN, a validade ou o CVC brutos.
Como a tokenização se encaixa
A tokenização é uma etapa do lado do cliente. O token que ela produz é trocado por uma cobrança no seu servidor, onde vive a sua chave secreta.
Nunca envie dados brutos de cartão (PAN, CVC, validade) para o seu próprio backend. Envie apenas o tokenId retornado por tokenize(). O objetivo da tokenização é justamente manter os dados do cartão fora do escopo PCI dos seus servidores.
tokeflow.cards.tokenize(input, options?)
O método cards.tokenize() criptografa os dados coletados pelos seus Elements de cartão e resolve para um CardToken. Ele aceita dois formatos de entrada — combinado ou dividido — mais o nome do portador do cartão e o endereço de cobrança opcionais.
Chame tokenize() somente após o SDK estar inicializado (await tokeflow.init()) e seu(s) elemento(s) de cartão estar(em) montado(s). Consulte o Quickstart para a configuração completa.
Entrada com elemento combinado
Use o CardElement combinado (número, validade e CVC em um único iframe) e passe-o como card:
const cardElement = tokeflow.createCardElement();
cardElement.mount('#card-element');
const token = await tokeflow.cards.tokenize({ card: cardElement });
console.log(token.tokenId); // tok_...Entrada com campos divididos
Quando você coleta o número do cartão, a validade e o CVC em iframes separados, passe cada elemento sob sua própria chave:
const cardNumber = tokeflow.createCardNumberElement();
const cardExpiry = tokeflow.createCardExpirationElement();
const cardCvc = tokeflow.createCardCvcElement();
cardNumber.mount('#card-number');
cardExpiry.mount('#card-expiry');
cardCvc.mount('#card-cvc');
const token = await tokeflow.cards.tokenize({
cardNumber,
expiration: cardExpiry,
cvc: cardCvc,
});A chave da validade é expiration — não expirationDate nem expiry. Usar a chave errada deixa a validade sem definição e a tokenização falha na validação.
Nome do portador do cartão e endereço de cobrança opcionais
Ambas as entradas aceitam um cardholderName e um billingAddress opcionais. Cada campo pode ser fornecido como um elemento montado ou como uma string simples — combine conforme o seu formulário exigir.
const token = await tokeflow.cards.tokenize({
card: cardElement,
cardholderName: cardholderNameElement, // element or 'Jane Doe'
billingAddress: {
line1: addressLine1Element, // element or string
line2: 'Apt 4B', // string
city: cityElement, // element or string
state: 'CA', // string
postalCode: postalCodeElement, // element or string
country: 'US', // ISO 3166-1 alpha-2
},
});| Field | Type | Required | Description |
|---|---|---|---|
card | CardElement | Condicional | O elemento de cartão combinado. Obrigatório para a entrada combinada. |
cardNumber | CardNumberElement | Condicional | Elemento do número do cartão. Obrigatório para a entrada dividida. |
expiration | CardExpirationElement | Condicional | Elemento da validade. Obrigatório para a entrada dividida. Observe que a chave é expiration. |
cvc | CardCvcElement | Condicional | Elemento do CVC. Obrigatório para a entrada dividida. |
cardholderName | CardholderNameElement | string | Não | Nome no cartão, como um elemento montado ou uma string. |
billingAddress | BillingAddressInput | Não | Endereço de cobrança. Cada subcampo é um elemento ou uma string. |
Subcampos de BillingAddressInput: line1, line2, city, state, postalCode, country — cada um deles aceita um elemento ou uma string.
Opções
O segundo argumento opcional carrega metadados não sensíveis para armazenar junto com o token e — desde o SDK 2.6.0 — diz se o cartão pode ser salvo para depois.
type TokenPurpose = 'one_time' | 'instrument_enrollment';
interface TokenizeOptions {
metadata?: Record<string, any>; // custom metadata stored with the token
saveCard?: boolean; // inside a checkout session: enroll the card for later use
purpose?: TokenPurpose; // standalone tokenization: which kind of token to mint
}| Opção | Onde se aplica | Efeito |
|---|---|---|
saveCard | Apenas dentro de uma sessão de checkout (checkoutSessionId definido). | Para uma oferta avulsa, true emite um token instrument_enrollment para que o cartão possa ser salvo como instrumento de pagamento. Uma oferta recorrente sempre cadastra, então a flag é redundante nesse caso. Ignorada fora de uma sessão. |
purpose | Apenas na tokenização standalone (sem sessão de checkout). | one_time (padrão) emite um token de uso único que expira; instrument_enrollment emite um token sem expiração que pode ser salvo. Dentro de uma sessão de checkout o servidor deriva a finalidade da oferta e de saveCard, e ignora esta opção. |
metadata | Em qualquer lugar. | Dados personalizados não sensíveis armazenados com o token. |
// Dentro de uma sessão de checkout — o cliente marcou "salvar meu cartão"
const token = await tokeflow.cards.tokenize(
{ card: cardElement },
{ saveCard: true, metadata: { cartId: 'cart_123' } }
);
// Tokenização standalone — emita um token que possa ser salvo
const token = await tokeflow.cards.tokenize(
{ card: cardElement },
{ purpose: 'instrument_enrollment' }
);As duas opções são omitidas da requisição quando não definidas, então deixá-las de fora não é o mesmo que enviar false. Peça o consentimento do cliente antes de solicitar um token cadastrável.
Nunca coloque PII do portador do cartão ou dados de cartão em metadata. São apenas dados personalizados não sensíveis.
tokenize() sempre retorna um CardToken; ele nunca salva o cartão por conta própria. Se o cartão vira um instrumento reutilizável é decidido no servidor — pela sessão de checkout, por save_payment_instrument na cobrança, ou por uma chamada explícita de cadastro — e cada um deles recusa um token one_time. Leia o purpose do token retornado para saber o que recebeu. Veja Upsells e downsells em um clique para o fluxo completo.
A resposta CardToken
interface CardToken {
tokenId: string; // your Tokeflow token reference, e.g. 'tok_...'
type: 'card';
brand: string; // 'visa', 'mastercard', etc.
last4: string; // last 4 digits of the card
expiryMonth: string; // e.g. '12'
expiryYear: string; // e.g. '2029'
bin?: string; // bank identification number (optional)
createdAt?: string; // ISO 8601 timestamp (optional)
purpose?: TokenPurpose; // 'one_time' | 'instrument_enrollment' — what the server actually minted
}| Field | Type | Description |
|---|---|---|
tokenId | string | A referência de token para enviar ao seu backend. Prefixada com tok_. |
type | 'card' | Sempre card para tokenização de cartão. |
brand | string | Bandeira do cartão detectada (ex.: visa, mastercard). |
last4 | string | Últimos quatro dígitos, seguros para exibição. |
expiryMonth | string | Mês de validade com dois dígitos, como string. |
expiryYear | string | Ano de validade com quatro dígitos, como string. |
bin | string? | Número de identificação do banco, quando disponível. |
createdAt | string? | Timestamp de criação em ISO 8601, quando presente. |
purpose | TokenPurpose? | A finalidade com que o servidor emitiu o token — one_time ou instrument_enrollment. Confira quando você pediu um token cadastrável: uma divergência não falha aqui, mas é recusada depois, no cadastro ou na cobrança. |
Valor de exemplo:
{
"tokenId": "tok_8f3c2a1b9d4e",
"type": "card",
"brand": "visa",
"last4": "4242",
"expiryMonth": "12",
"expiryYear": "2029",
"bin": "424242",
"createdAt": "2026-01-15T12:30:00.000Z",
"purpose": "one_time"
}brand, last4, bin e a validade são não sensíveis e seguros para exibir na sua UI — úteis para uma confirmação do tipo "terminando em 4242". O PAN completo e o CVC nunca são retornados.
Teste o Bridge SDK sem código
Quer um token para experimentar a API antes de conectar o SDK? A Tokeflow hospeda um testador em card.tokeflow.com que roda o Bridge SDK contra o seu merchant e mostra o token retornado — a mesma referência tok_… criptografada que a sua própria integração recebe. Use-o para ver exatamente o que a tokenização retorna e para alimentar valores reais de token nos endpoints de pagamento.
- Abra card.tokeflow.com e informe a chave pública do seu merchant (
pk_test_…oupk_live_…). Chaves secretas nunca são usadas no navegador. - Preencha os campos seguros de cartão e envie. O cartão é criptografado dentro dos iframes isolados e cross-origin da Tokeflow — exatamente como no seu próprio site — de modo que o PAN bruto nunca sai do navegador.
- Inspecione a referência de token retornada (
tok_…) junto com seus detalhes não sensíveis (brand,last4, validade). - Passe esse valor como
card_ciphertext_idpara testar seus endpoints de método de pagamento — por exemploPOST /api/v1/transactions.
Cada token é de uso único e de curta duração — gere um novo para cada cobrança de teste. Use uma chave pública de teste (pk_test_…) durante a integração para que nenhum valor real seja envolvido. Consulte Ambientes e chaves.
Trocando o token por uma cobrança
O token é uma referência, não uma cobrança. Depois que tokenize() resolve, envie o tokenId para o seu próprio backend e deixe seu servidor criar a transação com a sua chave secreta.
1. Tokenize no navegador
const token = await tokeflow.cards.tokenize({ card: cardElement });
await fetch('/api/payments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tokenId: token.tokenId }),
});2. Crie a transação a partir do seu servidor
Seu backend troca o tokenId por uma transação. Use uma chave secreta — nunca a exponha no navegador — e envie um Idempotency-Key para que retentativas não gerem cobrança dupla.
curl -X POST https://api.tokeflow.com/api/v1/transactions \
-H "Authorization: Bearer sk_live_mer_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6b1f7e2c-9a44-4f1e-8c3d-1a2b3c4d5e6f" \
-d '{
"amount": 9900,
"currency": "BRL",
"payment_method": "credit_card",
"card_ciphertext_id": "tok_8f3c2a1b9d4e",
"customer_id": "cust_9f2a1c"
}'Exemplo de resposta de sucesso:
{
"success": true,
"data": {
"id": "tx_4d2e1a9c7b",
"status": "authorized",
"amount": 9900,
"currency": "BRL",
"payment_method": "credit_card",
"charge_type": "payment",
"customer_id": "cust_9f2a1c",
"created_at": "2026-01-15T12:30:01.000Z"
},
"request_id": "req_8f3c2a1b",
"timestamp": "2026-01-15T12:30:01.000Z"
}O valor está em unidades menores inteiras (centavos). 9900 com "currency": "BRL" é R$99,00. Sempre envie a currency em ISO 4217.
Valores monetários e decisões de roteamento são feitos no seu servidor com a sua chave secreta. O navegador nunca vê a chave secreta, nem o valor que ele não pode adulterar, nem o connector que processa a cobrança. Consulte Autenticação para o escopo das chaves.
Tratamento de erros
tokenize() rejeita com um TokeflowError carregando um code legível por máquina. Trate os casos comuns para dar ao portador do cartão um feedback acionável. Consulte a lista completa em Tratamento de erros.
import { TokeflowError, TokeflowErrorCode } from '@tokeflow_com/bridge-js';
try {
const token = await tokeflow.cards.tokenize({ card: cardElement });
// ... send token.tokenId to your backend
} catch (error) {
if (error instanceof TokeflowError) {
switch (error.code) {
case TokeflowErrorCode.ELEMENT_INCOMPLETE:
showError('Please complete all card fields');
break;
case TokeflowErrorCode.INVALID_CARD:
showError('Please check your card number');
break;
case TokeflowErrorCode.EXPIRED_CARD:
showError('This card has expired');
break;
case TokeflowErrorCode.UNSUPPORTED_CARD_BRAND:
showError('This card brand is not supported');
break;
case TokeflowErrorCode.NETWORK_ERROR:
showError('Network error. Please try again.');
break;
default:
showError(error.message);
}
}
}| Code | Quando acontece |
|---|---|
ELEMENT_INCOMPLETE | Um campo de cartão obrigatório não foi totalmente preenchido. |
ELEMENT_INVALID | O valor de um elemento é inválido. |
INVALID_CARD | O número do cartão falhou na validação. |
EXPIRED_CARD | A data de validade do cartão está no passado. |
UNSUPPORTED_CARD_BRAND | A bandeira do cartão não está habilitada para este merchant. |
TOKENIZATION_FAILED | A tokenização não pôde ser concluída. |
NOT_INITIALIZED | tokenize() foi chamado antes de init() resolver. |
ELEMENT_NOT_MOUNTED | Um elemento passado não foi montado no DOM. |
NETWORK_ERROR | A requisição para a Tokeflow falhou na camada de rede. |
Leia o getState() do elemento ({ empty, valid, invalid, complete }) antes de chamar tokenize() e desabilite seu botão de pagamento até que state.complete && state.valid. Isso captura entradas incompletas antes de um ida e volta. Consulte Elements.
Próximos passos
- Elements — crie e estilize os campos seguros que você passa para
tokenize(). - Upsells e downsells em um clique — salve o cartão durante a compra e cobre-o de novo com um clique.
- Checkout — vincule uma sessão criada no backend para conduzir um fluxo de checkout completo.
- Tratamento de erros — a referência completa de
TokeflowErrorCode. - Autenticação — chaves públicas vs. secretas e escopo de chaves.