Skip to main content

npm / yarn

Pre-release builds (@next): The next dist-tag contains unreleased changes before they reach latest. It is intended for Ozura-coordinated testing only — production credentials will not work with it. If you have been given access to pre-release testing, contact ammar@ozura.com for the matching staging credentials and setup instructions.
npm install @ozura/elements (no tag) always resolves latest@next has no impact on production installs.
Then import in your JavaScript or TypeScript:
For React components:
@ozura/elements/react requires React 17 or later as a peer dependency. If React is not already in your project, install it first:
For server-side usage (Node.js, Deno, Bun):

CDN (Script Tag)

The Ozura CDN blocks localhost origins. If you load the CDN script on http://localhost, the browser will reject it with a CORS error (No 'Access-Control-Allow-Origin' header). The CDN is for deployed origins only. See Local Development below.
If you’re not using a bundler, load the UMD build directly from the Ozura CDN:
Or use the ESM build with a native module script:

Local Development

The CDN blocks localhost. For local development you have two options depending on how you load the SDK: If your project uses a bundler (webpack, Vite, Next.js, etc.), @ozura/elements is imported directly from node_modules — no CDN involved, no workaround needed. The iframes load from elements.ozura.com at runtime, but that uses <iframe src> which is not subject to the same CORS restriction.

CDN script tag on localhost

If you want to use the CDN <script> tag during local development, you need to serve the SDK file from the same origin as your page. Install the npm package and add a single route to your local server:
Then change the <script src> in your HTML from:
to:
The iframes (/frame/tokenizer-frame.js, /frame/element-frame.js) still load from elements.ozura.com — they are fetched via <iframe src>, not fetch, so CORS does not apply.

TypeScript

The package ships with full TypeScript definitions — no @types package needed. Import types directly:
For server-side code:

Vault Project Types and the Pub Key

When you sign up at ozuravault.com, your first project is a test project by default. To create a production project, open the project dropdown in the top-left, select Create new project, and enable the Production switch. Test vault API key (test project): No pub key is required. You can omit pubKey entirely from OzVault.create(). This is the easiest way to get started — create an application in your test project and use that key for local development and testing. Production vault API key: A pub key is required and is tied to your registered domain. Production pub keys have domain restrictions and will not work on localhost. Contact ammar@ozura.com to obtain a production pub key for your domain.
If you’re testing with a production vault API key on localhost, OzVault.create() will fail due to domain restrictions — and without a try/catch, the failure is silent. Use a test vault API key (test project) for local development instead.
Frame updates are automatic and backward compatible. The SDK always loads iframe files from https://elements.ozura.com. Updates are delivered transparently — no npm update is required. frameBaseUrl is a local development option only — do not set it in production code.

Credentials

Which credentials do you need? You need credentials from the Ozura Dashboard. If you are not routing payments through OzuraPay you only need the vault API key (backend), plus a pub key if you are using a production vault key.
Testing? Use a test vault key (no pub key needed) and fill fields with a test card number. See Test Credentials for card numbers and expected outcomes.
The vault API secret must never be sent to the browser. The SDK’s session mechanism exists specifically so your server can create a short-lived credential without exposing the secret. See the Server SDK for setup.

Quick Initialization

OzVault.create() is the public factory method — it sets up the vault and initializes the payment session. It resolves once the session is ready; you can create and mount elements immediately after. The vault is ready to tokenize once onReady fires (or vault.isReady === true).
onReady can fire while OzVault.create() is still pending. Vault initialization has two parallel steps — session fetch and iframe load. Either can finish first. If the iframe loads before the session resolves, onReady fires while await OzVault.create(...) is still in progress and vault is still undefined. Do not reference vault inside onReady. Declare any readiness flags before calling create() so they are in scope when the callback runs.
Always wrap OzVault.create() in a try/catch. If initialization fails (e.g. pub key blocked, session endpoint unreachable, backend error) the promise rejects. Without a catch, the failure is a silent unhandled rejection and the fields appear to hang.
sessionUrl is the simplest integration option — just pass your session endpoint path and the SDK handles everything. See Server SDK — Session route for the matching backend route. To provide custom headers or auth tokens, use getSessionKey instead:

OzVault.create() Options

¹ Exactly one of sessionUrl, getSessionKey, or fetchWaxKey is required. ² pubKey is required when using a production vault API key. If your vault API key was created for the test/sandbox environment, you can omit pubKey entirely — see Pub Key for Local Development.
Keep sessionLimit in sync between client and server. If VaultOptions.sessionLimit on the client differs from the value passed to ozura.createSession() on your server, the proactive refresh timing will be off. The vault may reject a tokenization attempt before the client expects a refresh, causing a user-visible delay. Both default to 3 — only change one if you change the other.
The optional signal parameter is an AbortSignal for advanced teardown scenarios. The React OzElements provider handles this automatically — vanilla JS integrations rarely need it.

Content Security Policy (CSP)

If your site sets a Content-Security-Policy header, you need to allow the Ozura iframe and tokenizer origins. Without this the iframes are blocked before they load and OzVault.create() will reject. Add these directives to your CSP:
If you use frameBaseUrl to point at a custom or staging deployment, substitute that origin for https://elements.ozura.com. If you load custom fonts via the fonts option (e.g. Google Fonts), add the font CDN origins too:
Full header example (Express):
The connect-src entry covers requests made by the Ozura iframe for tokenization.

Next.js App Router

When using Next.js with the App Router (app/ directory), the vault and card fields require a client component boundary because they use browser APIs.
The examples below show a production setup with a pubKey. If you are integrating against a test vault key (from a Test project at ozuravault.com), omit pubKey from OzVault.create() and the <OzElements> provider — no pub key is required.

Client component wrapper

Or use the React provider — this is the recommended approach and handles lifecycle automatically:

Session route (app/api/oz-session/route.ts)

Environment variables (.env.local)

NEXT_PUBLIC_ prefix exposes the pub key to the browser bundle. All other credentials stay server-side only.

Production Checklist

Before you go live, confirm each of the following: Credentials
  • Production pub key registered to your domain (contact ammar@ozura.com)
  • VAULT_API_KEY set in server environment — never in browser code or committed to git
  • OzuraPay merchants: MERCHANT_API_KEY and MERCHANT_ID also set server-side
Session route
  • POST /api/oz-session (or your equivalent path) is deployed and reachable
  • Route uses createSessionHandler / createSessionMiddleware or manually calls ozura.createSession()
  • sessionLimit on the server matches sessionLimit in VaultOptions (both default to 3 — only change one if you change the other)
  • Session route is CSRF-safe (the SDK helpers enforce POST + Content-Type: application/json)
Security
  • CSP includes frame-src and connect-src for https://elements.ozura.com (see CSP above)
  • Charge route reads amount from your database, not from the request body
  • getClientIp used (or equivalent) when calling ozura.cardSale() so the OzuraPay API gets the real client IP
Error handling
  • OzVault.create() is wrapped in try/catch with a fallback UI
  • Payment form disables the submit button until vault.isReady and all field 'ready' events fire
  • vault.reset() is called on tokenization error so the customer can re-enter card data
  • frameBaseUrl is not set in production code (local development option only)
Testing
  • Tested end-to-end on localhost using a test vault API key (test project) — no pub key needed
  • If using a production vault API key: tested with the production pub key on your staging/preview domain before going live

Next Steps

Card Elements

Mount card number, expiry, and CVV fields.

Bank Elements

Mount account number and routing number fields.

React

OzElements provider and pre-built components.

Server SDK

Process payments and query transactions on your backend.