Card Issuing

Card Reveal

API Documentation

Column's card reveal SDKs show a card's full number, CVV, expiry and cardholder name to the cardholder, in your web page or your React Native app. The card data never passes through your code or your servers, so showing it doesn't bring them into PCI scope.

  • Web: @column-na/card-reveal, from npm or as a hosted script.
  • React Native and Expo: @column-na/card-reveal-react-native.

The card reveal SDKs are proprietary and require an agreement with Column. Contact your Column representative to get started.

How It Works

  1. Your server creates a single-use reveal token for the card with create card reveal token, using your API key, and sends only the token's id to the browser or app.
  2. The SDK reveals the card with that token. It generates a one-time key for each reveal and calls Column's API directly. Column encrypts the card details end to end to that key, so nothing between Column and the SDK can read them.
    • On the web, each value renders inside its own iframe, served by Column from https://reveal.column.com. Your page's JavaScript can't read it.
    • In React Native, each value renders inside the SDK's own text component. No callback, ref or return value exposes it.

A reveal token is valid for one minute and works once, for one card. Create a new token for every reveal.

Server: Create a Reveal Token

Create the token right before you show the card, and only after you've checked that the signed-in user may see it.

curl 'https://api.column.com/issuing/cards/<card_id>/reveal-tokens' \
  -XPOST \
  -u :<YOUR API KEY>
{
  "id": "crtk_2Z1qT1aB2cD3eF4gH5iJ6kL7mN8",
  "card_id": "card_2Z1qT0kM6yX9wB3nV5cR8sL4pA7",
  "expires_at": "2026-10-23T18:01:00Z"
}

Send the token id and the card ID to the browser or app. Don't call GET /issuing/cards/:card_id/reveal yourself: only Column's SDKs can call it, because the response is encrypted to a key the SDK generates. Fetching card details on your servers would also put them in PCI scope.

Web

Install

Install from npm, pinned to an exact version:

npm install --save-exact @column-na/card-reveal@0.6.0

Or load the hosted script, pinned to an exact version with Subresource Integrity↗. The hosted script won't create a client unless its <script> tag has an integrity attribute. Each version is published once and never changes.

<script
  src="https://reveal.column.com/0.6.0/card-reveal.js"
  integrity="sha384-Ep7c7/UaCPL1WbDDj1eKtsEttBjBCSwCttMpCPyk0A+XyMn9Gk9Vzl8A0xikWQuW"
  crossorigin="anonymous"
></script>
Version
Script
Integrity
0.6.0
https://reveal.column.com/0.6.0/card-reveal.js
sha384-Ep7c7/UaCPL1WbDDj1eKtsEttBjBCSwCttMpCPyk0A+XyMn9Gk9Vzl8A0xikWQuW

Reveal a Card

import { createCardRevealClient, CardRevealError } from '@column-na/card-reveal';
// Hosted script: const { createCardRevealClient, CardRevealError } = window.ColumnCardReveal;
 
// Create one client and reuse it.
const client = createCardRevealClient({ environment: 'live' }); // or 'sandbox'
 
const { ready, unmount } = client.reveal({
  cardId: 'card_2Z1qT0kM6yX9wB3nV5cR8sL4pA7',
  revealToken: 'crtk_2Z1qT1aB2cD3eF4gH5iJ6kL7mN8',
  fields: {
    pan: '#card-number',
    cvv: '#cvv',
    cardholder_name: '#name',
    expiration_month: '#exp-month',
    expiration_year: '#exp-year',
  },
  style: { color: '#fff', 'font-family': 'ui-monospace, monospace', 'font-size': '15px' },
  fieldStyles: { pan: { 'font-size': '19px' } },
  format: { pan: 'spaced', expirationYear: 'YY' },
});
 
try {
  await ready;
} catch (error) {
  if (CardRevealError.is(error)) showMessage(error.code);
}
 
// When the cardholder hides the card, or the page or component goes away:
unmount();

Each field renders as an iframe that fills its container, so give each container a width and height. In React, call reveal in an effect and return unmount as its cleanup.

Content Security Policy

If your page has a Content Security Policy, allow Column's reveal frame:

script-src  'self' https://reveal.column.com;
frame-src   https://reveal.column.com;

Leave https://reveal.column.com out of script-src if you install from npm. Your page doesn't need any connect-src entry or 'unsafe-inline' for the SDK, in sandbox or live.

React Native

The React Native SDK is pure JavaScript with no native module. It works in Expo Go, Expo development builds and bare React Native, and needs React 19.1 and React Native 0.81 or later.

Install

npx expo install @column-na/card-reveal-react-native@0.6.0 react-native-get-random-values

Check that package.json lists "@column-na/card-reveal-react-native": "0.6.0" with no ^ or ~, or install with npm install --save-exact @column-na/card-reveal-react-native@0.6.0 react-native-get-random-values.

Each reveal generates a one-time key, which needs a secure random source. Import the polyfill once, at the top of your app's entry file, before anything else:

import 'react-native-get-random-values';

Without it, reveal() throws invalid_options.

Reveal a Card

import { useEffect, useMemo, useRef } from 'react';
import { View } from 'react-native';
import {
  CardRevealError,
  CardRevealText,
  createCardRevealClient,
  type CardRevealTextHandle,
} from '@column-na/card-reveal-react-native';
 
export function CardDetails({ cardId, revealToken }: { cardId: string; revealToken: string }) {
  const client = useMemo(() => createCardRevealClient({ environment: 'live' }), []); // or 'sandbox'
  const pan = useRef<CardRevealTextHandle>(null);
  const cvv = useRef<CardRevealTextHandle>(null);
 
  useEffect(() => {
    const { ready, unmount } = client.reveal({
      cardId,
      revealToken, // single use: create a new one for every reveal
      fields: { pan, cvv },
      style: { color: '#fff', fontFamily: 'Menlo' },
      format: { pan: 'spaced' },
    });
    ready.catch((error) => {
      if (CardRevealError.is(error)) console.warn('Card reveal failed:', error.code);
    });
    return unmount;
  }, [client, cardId, revealToken]);
 
  return (
    <View>
      <CardRevealText ref={pan} placeholder="•••• •••• •••• ••••" />
      <CardRevealText ref={cvv} placeholder="•••" />
    </View>
  );
}

CardRevealText shows its placeholder before the reveal and after unmount. Set selectable to let the cardholder select and copy the value. React Native Web isn't supported for live reveals; use the web SDK instead.

Reference

Reveal Options

Option
Description
cardId
The card's ID (card_...).
revealToken
The reveal token ID (crtk_...) from your server.
fields
Maps any of pan, cvv, cardholder_name, expiration_month and expiration_year to where it renders: a CSS selector on the web, a CardRevealText ref in React Native. Include only the fields you want to show.
style
Styles for every field. On the web, CSS properties (kebab-case or camelCase), plus '&:hover', @media and @font-face blocks. In React Native, text styles.
fieldStyles
Per-field styles, applied on top of style.
format.pan
'spaced' (default, 4111 1111 1111 1111) or 'plain'.
format.expirationYear
'YYYY' (default) or 'YY'.
timeoutMs
How long ready waits before it rejects with timeout. Default 15000, maximum 120000.

ready and unmount

  • ready resolves once every requested field shows its value.
  • If any field fails or the timeout passes, ready rejects and every field is removed. A reveal shows all of its fields or none of them.
  • unmount() removes every field. If ready is still pending, it rejects with unmounted.
  • Invalid options throw invalid_options synchronously from reveal().

Errors

Every error is a CardRevealError with a stable code. Check with CardRevealError.is(error). field and the HTTP status are set when known. Messages never contain the token or card data, and the SDKs never log either.

Code
Meaning
invalid_options
Bad options, or an unsupported environment. Thrown synchronously.
integrity_required
Web hosted script only: its <script> tag has no integrity attribute.
script_load_failed
Web only: Column's reveal frame couldn't load. The next reveal() retries.
container_not_found
A field's container doesn't exist: no element matches the selector, or the ref isn't attached.
reveal_failed
The reveal request failed. A 401 status means the token is missing, invalid, already used, expired or for a different card.
timeout
timeoutMs passed before every field showed its value.
unmounted
unmount() was called before the reveal finished.

Sandbox

Sandbox works the same way, with a client created with environment: 'sandbox' and a reveal token for a sandbox card, so you can build and test the whole flow before going live. See Card Sandbox Simulation to create a sandbox card.

Versions

The web and React Native SDKs follow semantic versioning and release together at the same version. Pin an exact version. Each request tells Column which SDK and version made it, and Column may require a minimum version to keep revealing cards. Versions before 0.5.0 no longer reveal cards; upgrade to the latest version.