> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ozura.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Card Payments — Using Elements

> Embed secure card fields in your own checkout UI and tokenize in the browser. Card data never touches your server.

# 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.

<Info>
  **Want to skip the client-side integration?** If you prefer a fully hosted payment page, see [Checkout](/guides/vault/card-payments/checkout) instead. If you need to tokenize from your backend, see [Using the API](/guides/vault/card-payments/using-the-api).
</Info>

***

## How It Works

```mermaid theme={null}
flowchart LR
  A["1. INSTALL\nAdd @ozura/elements\nto your page"] --> B["2. RENDER\nMount card fields\nin your form"]
  B --> C["3. SUBMIT\nSDK tokenizes\nin the browser"]
  C --> D["4. CHARGE\nBackend uses token\nwith Proxy or OzuraPay API"]
```

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

***

## Install the SDK

<CodeGroup>
  ```bash npm theme={null}
  npm install @ozura/elements
  ```

  ```bash yarn theme={null}
  yarn add @ozura/elements
  ```

  ```html Script tag (CDN) theme={null}
  <script src="https://elements.ozura.com/oz-elements.umd.js"></script>
  ```
</CodeGroup>

***

## Quick Start

### 1. Get your credentials

Get your **Vault API Key** from [ozuravault.com](https://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.

| Credential        | Required        | Where                                                                                                 |
| ----------------- | --------------- | ----------------------------------------------------------------------------------------------------- |
| **Vault API Key** | Always          | ozuravault.com → Applications                                                                         |
| **Vault Pub Key** | Production only | Provided when you set up a production project — contact **[ammar@ozura.com](mailto:ammar@ozura.com)** |

<Note>
  **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](/guides/sandbox) for how to create a Test project at ozuravault.com and grab a test vault key.
</Note>

### 2. Initialize the vault and mount card fields

```html theme={null}
<!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:

```bash theme={null}
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:

```tsx theme={null}
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:

```js theme={null}
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:

```js theme={null}
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](/sdks/elements/styling).

***

## Test Cards

Use these test card numbers during integration:

| Brand      | Number                | CVC          | Expiry          |
| ---------- | --------------------- | ------------ | --------------- |
| Visa       | `4111 1111 1111 1111` | Any 3 digits | Any future date |
| Mastercard | `5555 5555 5555 4444` | Any 3 digits | Any future date |
| Amex       | `3782 822463 10005`   | Any 4 digits | Any future date |

See the full list in [Test Credentials](/guides/test-credentials).

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Elements SDK Reference" icon="code" href="/sdks/elements/overview">
    Complete API reference — all methods, options, events, and TypeScript types.
  </Card>

  <Card title="Styling & Appearance" icon="palette" href="/sdks/elements/styling">
    Customize fonts, colors, and states to match your brand.
  </Card>

  <Card title="Proxy" icon="arrow-right-left" href="/guides/vault/proxy/overview">
    Forward the token to your payment processor.
  </Card>

  <Card title="API Reference — Tokenize" icon="terminal" href="/api-reference/vault/tokenize">
    Token response shape and all tokenize options.
  </Card>
</CardGroup>
