Skip to main content
Staging only, reveal only. Secure Elements is under active development. Everything on this page and the Card Reveal page runs against Fluz’s staging environment — production hosts aren’t confirmed yet. This section documents the Card Reveal capability only; collecting a physical card (tokenization) isn’t covered here yet.

What Secure Elements is

Secure Elements is a JavaScript SDK, @fluz/secure-elements, that mounts an isolated, Fluz-hosted frame directly into a container element on your page. The frame renders card data; your page and your servers only ever hold a short-lived, opaque token that authorizes one specific action. This is a third way to show a user their own card details, alongside the two you already have:
If you’re already using the Embedded Widget for everything, you don’t need this. Secure Elements is for headless or API-driven integrations that still need to show a user their PAN, expiry, and CVV without opening the full widget modal or pursuing PCI_COMPLIANCE.

How it works

Your backend mints a client token

Exchange your existing Fluz OAuth access token for a short-lived client token, scoped to a single reveal.

Your frontend mounts the frame

Hand the client token to @fluz/secure-elements, which mounts the Fluz-hosted frame into a container you provide — inline in your page, not a modal.

The SDK reports back via callbacks

Your page never reads the raw card data. It only sees success, error, or mount events.

Prerequisites

  • Your application is registered with Fluz and has the CREATE_VIRTUALCARD scope enabled on your access token.
  • You have an ACTIVE virtual card id, owned by the account you’re revealing, to pass when minting a client token.
Ask Fluz to allow-list your origin before you write any code. The frame refuses to render from an origin Fluz hasn’t pre-approved — there’s no self-serve toggle for this today, so it’s the one prerequisite that can block you if you leave it for later.Email partnerships@fluz.app (or your account manager, if you have one) with your application name or ID and every origin you need approved — each http://localhost:PORT you develop against, plus your staging and production domains. Fluz allow-lists them on the backend; there’s nothing to configure on your side once that’s done.

Environments

Reveal currently returns simulated results on staging while Fluz’s processor integration is finalized. Use staging to validate your integration end to end — production availability will be confirmed separately.
frameHostOrigin is optional on createCardViewer — omit it and it defaults to production (https://secure.fluz.app). Pass it explicitly to target staging. Only these two exact origins are accepted; anything else throws a FluzElementsError (error.code === "INVALID_FRAME_HOST_ORIGIN") as soon as you call createCardViewer, before any frame is mounted.

Loading the SDK

@fluz/secure-elements isn’t published to npm — load it as a browser global (IIFE) build from Fluz’s CDN with a <script> tag. It exposes a FluzSecureElements global:
Every code sample on this page and on Card Reveal assumes you’ve loaded the script tag and destructured what you need off FluzSecureElements, as above. Each release publishes to an immutable, version-pinned path (.../v0.1.0/index.global.js) and a floating .../latest/index.global.js that always points at the newest release. Pin to a specific version for anything beyond a prototype — latest can change under you without notice.
Only the staging CDN host is live so far (secure-cdn-staging.fluz.app). Production hosting will be confirmed alongside production API availability.

Mint a client token

Your backend calls this using the Fluz OAuth access token you already obtain through the standard OAuth grant flow. Never send that access token to the browser — only the clientToken / loadToken pair this endpoint returns should reach your frontend.
A successful mint returns 201. Both tokens are single-purpose and short-lived — mint a new pair for every reveal. clientToken is what authorizes the reveal itself (expiresIn seconds, 300 by default); loadToken is scoped even tighter (60 seconds) since it travels in a URL — see the note in Card Reveal — and is rejected everywhere except loading the frame. Pass both straight into createCardViewer, and never put clientToken in a URL yourself — the SDK already keeps it out of one.

Styling fields

createCardViewer accepts an optional style object, applied to every field it mounts:
style is validated before anything is sent to the frame. If a value doesn’t match what’s documented below, await viewer.mount(...) rejects with a FluzElementsError (error.code === "INVALID_STYLE") — wrap your mount() call in a try/catch if you’re accepting configurable style input yourself. fontFamily must be an exact, case-sensitive match for one of two allowlists:
  • System fonts — common OS/web-safe stacks (system-ui, -apple-system, Helvetica Neue, Arial, Georgia, Menlo, and the generic monospace / serif / sans-serif keywords, among others). These render immediately, with no network request.
  • Google Fonts — any family from the Google Fonts catalog ("Roboto", "Inter", "IBM Plex Mono", and so on), passed exactly as Google lists it. The SDK loads the font for you — you don’t need a <link> tag or @font-face rule.
A Google Font is fetched after the field mounts, not bundled up front, so there’s a brief window on a cold cache where the field renders in the browser’s fallback font before swapping in your chosen one. A system font has no such delay.
Both lists are exported if you want to validate a font choice, or build a font picker, yourself:

Content Security Policy

If your page sets a CSP, allow the frame host you’re targeting:

Security model

  • Your OAuth access token never leaves your servers.
  • The client token your frontend holds is opaque and single-purpose — it carries no card data and can’t be replayed for a different card or action.
  • Card data is only ever readable inside the Fluz-hosted frame, isolated from your page’s own JavaScript. Each configured field mounts as its own sandboxed (allow-scripts allow-same-origin allow-forms), referrerPolicy="no-referrer" iframe — the SDK never puts card data in the DOM outside of them.
  • The frame only renders inside origins you’ve pre-registered with Fluz.

Next steps

Card Reveal

Create the card viewer, mount it, and control which fields are revealed.

Live demo

See the card viewer running against staging, including reveal, reveal-CVV-only, and mask.

Example integrations

Runnable plain-HTML and React examples, both calling real staging infrastructure.

OAuth applications

How to obtain the access token you’ll exchange for a client token.