Skip to main content

Card Payments — Using Elements

Ozura Elements lets you build a card form that lives on your own page — your brand, your layout — while keeping raw card data completely off your servers. Input fields run inside isolated iframes served from Ozura’s domain. Tokenization happens in the browser; you receive a vault token (and an optional CVC session) that your backend can use to process payment.
Want to skip the client-side integration? If you prefer a fully hosted payment page, see Checkout instead. If you need to tokenize from your backend, see Using the API.

How It Works

Card data travels directly from the browser to the Ozura Vault — your server only ever sees a token.

Install the SDK

npm install @ozura/elements

Quick Start

1. Get your credentials

Get your Vault API Key from ozuravault.com → your project → Applications. Your first vault project is a test project by default. To create a production project, use the project dropdown in the top-left → Create new project → enable the Production switch.
CredentialRequiredWhere
Vault API KeyAlwaysozuravault.com → Applications
Vault Pub KeyProduction onlyProvided when you set up a production project — contact ammar@ozura.com
Test/sandbox vault API key? No pub key needed — you can omit pubKey entirely. Production vault API key? Pass your production pub key as pubKey. Do not hardcode credentials in source code; use environment variables.See Sandbox for how to create a Test project at ozuravault.com and grab a test vault key.

2. Initialize the vault and mount card fields

<!DOCTYPE html>
<html>
<head>
  <script type="module">
    import { OzVault } from 'https://elements.ozura.com/oz-elements.esm.js';

    // pubKey is only required for production vault API keys.
    // Omit it entirely when using a test/sandbox vault API key.
    let vault;
    try {
      vault = await OzVault.create({
        pubKey:     'YOUR_PUB_KEY',         // production vault keys only — remove this line for test vault keys
        sessionUrl: '/api/oz-session',
      });
    } catch (err) {
      document.getElementById('pay-btn').textContent = 'Payment unavailable';
      document.getElementById('pay-btn').disabled = true;
      throw err;
    }

    // Create card elements
    const cardNumber = vault.createElement('cardNumber');
    const expiry     = vault.createElement('expirationDate');
    const cvv        = vault.createElement('cvv');

    // Mount into your DOM
    cardNumber.mount('#card-number');
    expiry.mount('#expiry');
    cvv.mount('#cvv');

    // Tokenize on submit
    document.getElementById('pay-btn').addEventListener('click', async () => {
      const { token, cvcSession } = await vault.createToken({
        billing: {
          firstName: 'Jane',
          lastName:  'Smith',
        },
      });

      // Send token + cvcSession to your backend
      await fetch('/api/charge', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token, cvcSession }),
      });
    });
  </script>
</head>
<body>
  <div id="card-number"></div>
  <div id="expiry"></div>
  <div id="cvv"></div>
  <button id="pay-btn">Pay</button>
</body>
</html>

3. Process the payment on your backend

Your backend receives the token and cvcSession and proxies them to your payment processor:
curl -X POST https://api.ozuravault.com/proxy/transaction \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_VAULT_API_KEY" \
  -d '{
    "token": "tok_...",
    "cvc_session_id": "YOUR_CVC_SESSION",
    "proxy_url": "https://api.yourpsp.com/charges",
    "request_data": {
      "amount": 5000,
      "currency": "usd",
      "card": {
        "number":    "${cardNumber}",
        "exp_month": "${expirationMonth}",
        "exp_year":  "${expirationYear}",
        "cvc":       "${cvv}"
      }
    }
  }'

React Integration

Using React? The OzElements provider and hooks make wiring up card fields straightforward:
import { OzElements, useOzElements, OzCardNumber, OzExpiry, OzCvv } from '@ozura/elements/react';

function CheckoutForm() {
  const { createToken, ready } = useOzElements();

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const { token, cvcSession } = await createToken({
      billing: { firstName: 'Jane', lastName: 'Smith' },
    });
    // send to backend…
  };

  return (
    <form onSubmit={handleSubmit}>
      <OzCardNumber />
      <OzExpiry />
      <OzCvv />
      <button type="submit" disabled={!ready}>Pay</button>
    </form>
  );
}

export default function App() {
  return (
    // Omit `pubKey` when using a test vault key from a Test project at ozuravault.com.
    <OzElements
      pubKey="YOUR_PUB_KEY"
      sessionUrl="/api/oz-session"
    >
      <CheckoutForm />
    </OzElements>
  );
}

Field Validation & UX

Elements fire change events so you can reflect validation state in your UI without ever seeing the raw value:
cardNumber.on('change', ({ complete, valid, error, cardBrand }) => {
  document.getElementById('card-wrap').classList.toggle('invalid', !valid);
  document.getElementById('card-error').textContent = error ?? '';
  // cardBrand: 'visa' | 'mastercard' | 'amex' | …
});

cardNumber.on('focus', () => {
  document.getElementById('card-wrap').classList.add('focused');
});

cardNumber.on('blur', () => {
  document.getElementById('card-wrap').classList.remove('focused');
});
Elements automatically:
  • Format card numbers as the user types (4111 1111 1111 1111)
  • Validate with the Luhn algorithm
  • Detect card brand and adjust the CVV length (3 digits for most, 4 for Amex)
  • Auto-advance focus from card number → expiry → CVV on completion

Styling

Pass a style option to each element to match your design system. All standard CSS properties for text, color, and spacing are supported:
const style = {
  base: {
    color: '#1a1a2e',
    fontSize: '15px',
    padding: '12px 14px',
    backgroundColor: '#f8fafc',
  },
  focus: {
    backgroundColor: '#ffffff',
    caretColor: '#6366f1',
  },
  invalid: {
    color: '#ef4444',
  },
  complete: {
    color: '#22c55e',
  },
  placeholder: {
    color: '#94a3b8',
  },
};

const cardNumber = vault.createElement('cardNumber', { style });
For a full style reference and appearance theming, see the Elements SDK — Styling guide.

Test Cards

Use these test card numbers during integration:
BrandNumberCVCExpiry
Visa4111 1111 1111 1111Any 3 digitsAny future date
Mastercard5555 5555 5555 4444Any 3 digitsAny future date
Amex3782 822463 10005Any 4 digitsAny future date
See the full list in Test Credentials.

Next Steps

Elements SDK Reference

Complete API reference — all methods, options, events, and TypeScript types.

Styling & Appearance

Customize fonts, colors, and states to match your brand.

Proxy

Forward the token to your payment processor.

API Reference — Tokenize

Token response shape and all tokenize options.