SDK quickstart

Collect card data in the browser and get a token reference in minutes with the Tokeflow Bridge SDK — minimal Vanilla JS and React examples you can copy and paste.

The Bridge SDK collects payment details in the browser without exposing your servers to raw card data. Tokeflow's secure fields run inside isolated, cross-origin iframes; card data is encrypted in the browser and never touches your servers. The SDK returns a token reference that you send to your backend to charge.

This page gets you to a working tokenization flow with two minimal, end-to-end examples — one in Vanilla JavaScript, one in React. For the full SDK surface (elements, wallets, checkout context, error handling), see the Bridge SDK overview.

Initialize the SDK with a public key (pk_…). Public keys are restricted to client-safe scopes and are safe to ship in browser code. Never put a secret key (sk_…) in the browser — see Authentication.

How it works

The SDK handles card collection and encryption in the browser. Your backend never sees the card — it only ever receives a token reference (tok_…) that it uses to charge.

The token reference is short-lived and single-use. Always send token.tokenId to your server; the actual charge happens server-side with your secret key.

Install

Add the SDK from your package manager, or load the CDN build with a script tag.

npm install @tokeflow_com/bridge-js
# or: yarn add @tokeflow_com/bridge-js
# or: pnpm add @tokeflow_com/bridge-js

The CDN build exposes a global Tokeflow object (Tokeflow.TokeflowBridge, Tokeflow.TokeflowError, Tokeflow.TokeflowErrorCode):

<script src="https://unpkg.com/@tokeflow_com/bridge-js/dist/tokeflow.min.js"></script>

Vanilla JavaScript

A complete page: a form with a card element, SDK init, mount, and tokenize-on-submit. On submit, the SDK returns a token reference — send token.tokenId to your server to charge.

<!DOCTYPE html>
<html>
  <head>
    <title>Payment Form</title>
  </head>
  <body>
    <form id="payment-form">
      <div id="card-element"></div>
      <button type="submit">Pay</button>
    </form>

    <script src="https://unpkg.com/@tokeflow_com/bridge-js/dist/tokeflow.min.js"></script>
    <script>
      const tokeflow = new Tokeflow.TokeflowBridge({
        publicKey: "pk_live_mer_xxxxxxxxxxxxxxxx",
      });

      async function init() {
        // Creates a session and loads the secure elements runtime.
        await tokeflow.init();

        // Combined card element (number, expiry, CVC in one iframe).
        const cardElement = tokeflow.createCardElement();
        cardElement.mount("#card-element");

        document
          .getElementById("payment-form")
          .addEventListener("submit", async (e) => {
            e.preventDefault();

            const token = await tokeflow.cards.tokenize({ card: cardElement });
            console.log("Token:", token.tokenId); // tok_…

            // Send token.tokenId to YOUR server to create the charge.
            await fetch("/api/payments", {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ tokenId: token.tokenId }),
            });
          });
      }

      init();
    </script>
  </body>
</html>

Using a module bundler instead of the CDN? Import the class directly: import { TokeflowBridge } from "@tokeflow_com/bridge-js"; and use new TokeflowBridge({ publicKey }).

React

Wrap your tree in TokeflowProvider, render a CardElement, and read the bridge instance with the useTokeflow hook. Pass the element's underlying instance (via the ref's .element) to tokenize().

import { useRef, useState, FormEvent } from "react";
import {
  TokeflowProvider,
  useTokeflow,
  CardElement,
  CardElementRef,
} from "@tokeflow_com/bridge-js/react";

function PaymentForm() {
  const { tokeflow, isReady } = useTokeflow();
  const cardRef = useRef<CardElementRef>(null);
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (e: FormEvent) => {
    e.preventDefault();
    if (!tokeflow || !cardRef.current?.element) return;

    setLoading(true);
    try {
      const token = await tokeflow.cards.tokenize({
        card: cardRef.current.element,
      });
      console.log("Token:", token.tokenId); // tok_…

      // Send token.tokenId to YOUR server to create the charge.
      await fetch("/api/payments", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ tokenId: token.tokenId }),
      });
    } finally {
      setLoading(false);
    }
  };

  if (!isReady) return <div>Loading payment form…</div>;

  return (
    <form onSubmit={handleSubmit}>
      <CardElement ref={cardRef} id="card-element" />
      <button type="submit" disabled={loading}>
        {loading ? "Processing…" : "Pay"}
      </button>
    </form>
  );
}

export default function App() {
  return (
    <TokeflowProvider config={{ publicKey: "pk_live_mer_xxxxxxxxxxxxxxxx" }}>
      <PaymentForm />
    </TokeflowProvider>
  );
}

The provider initializes the bridge for you. Wait for isReady before calling tokenize() — until the session is created and the secure fields are mounted, the bridge is not ready to tokenize.

The token response

tokeflow.cards.tokenize(...) resolves to a CardToken. The only field you send onward is tokenId (a tok_… reference); the rest is non-sensitive display metadata.

// {
//   tokenId: 'tok_a1b2c3d4e5',  // the reference you send to your server
//   type: 'card',
//   brand: 'visa',
//   last4: '4242',
//   expiryMonth: '12',
//   expiryYear: '2029',
//   bin: '424242',
//   createdAt: '2026-01-01T00:00:00.000Z'
// }
FieldTypeDescription
tokenIdstringThe Tokeflow token reference (tok_…). Send this to your server to charge.
typestringAlways card for card tokens.
brandstringCard brand, e.g. visa, mastercard.
last4stringLast four digits, for display.
expiryMonthstringExpiry month, e.g. 12.
expiryYearstringExpiry year, e.g. 2029.
binstringBank identification number (optional).
createdAtstringISO 8601 timestamp (optional).

Charge the token from your server

The token reference is not a charge — it's a handle. Your backend creates the transaction with your secret key, referencing the token via card_ciphertext_id. Send an Idempotency-Key so a retry never double-charges.

curl -X POST https://api.tokeflow.com/api/v1/transactions \
  -H "Authorization: Bearer sk_live_mer_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_2026_0623_attempt_1" \
  -d '{
    "customer_id": "cust_a1b2c3d4e5",
    "amount": 9900,
    "currency": "BRL",
    "payment_method": "credit_card",
    "charge_type": "payment",
    "country": "BR",
    "capture": true,
    "card_ciphertext_id": "tok_a1b2c3d4e5"
  }'

The full charge flow — checkout sessions, capture, refunds, and reading the attempt timeline — lives in Transactions. For the end-to-end path from keys to webhook, see the Quickstart.

Never send raw card numbers, CVCs, or expiry dates to your own backend. Only the SDK-produced tok_… reference should leave the browser.

Next steps

  • Bridge SDK overview — elements, wallets, localization, and the full configuration model.
  • Authentication — public vs secret keys and the SDK auth headers.
  • Transactions — charge the token, then capture, void, or refund.
  • Quickstart — the complete zero-to-payment walkthrough.

On this page