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

# Payment Elements

> Build a consistent browser checkout while keeping AvraAPI credentials, Vault credentials, and payment completion on your server.

Payment Elements is AvraAPI's optional browser package for collecting customer details and presenting payment methods. It is a UI layer only. Your server, using an AvraAPI SDK, still checks availability, creates the payment session, receives provider callbacks, and verifies completion.

Use it when you want a ready-made checkout UI. You can also build your own UI and use the same server-side SDK flow.

<Info>
  The browser code on this page is the same whether your backend uses the PHP, Laravel, or Node.js SDK. The SDK stays on your server; Payment Elements stays in the browser.
</Info>

## The security boundary

<CardGroup cols={2}>
  <Card title="Checkout Page (Frontend)" icon="window-maximize" className="border-2 border-slate-800/60 hover:border-[#0450ff] transition-all duration-700 ease-out">
    * **Payment Elements:** customer form, method selector, provider presentation
    * **Your checkout endpoint:** handles selected gateway, mode, and customer details
  </Card>

  <Card title="Your Backend" icon="server" className="border-2 border-slate-800/60 hover:border-[#0450ff] transition-all duration-700 ease-out">
    * **AvraAPI SDK:** `availability()`, `createOrder()`, `completePayment()`
    * **Your database:** manages orders and fulfilment rules
    * **Provider callback:** receives the verified return handler
  </Card>
</CardGroup>

Never send any of the following to Payment Elements or another browser script:

* AvraAPI Project Client ID or Client Secret;
* Gateway Vault credentials, signing secrets, API keys, or private keys;
* a signed `completionContext`;
* a trusted amount, currency, order state, merchant domain, or gateway environment.

Payment Elements receives only a public payment session created by your backend. A provider browser event is user-interface feedback, not payment confirmation. Your server must call `completePayment()` before it fulfils an order.

## Install the browser bundle

Use the immutable AvraAPI CDN URL and the exact integrity hash published in the matching release manifest.

```html theme={null}
<script
  src="https://cdn.avraapi.com/payment-elements/v1.1.2/avraapi-payment-elements.umd.js"
  integrity="sha384-OFlOd6fgBnHYPoVCXZ9AbKa1VH4GalDBS6fK1Tqib1wecbf2aJ0mMpmJOrma+aSt"
  crossorigin="anonymous"
></script>
```

When you upgrade the package, change the version and integrity value together from that release's `manifest.json`. Do not use a floating URL, alter the bundle, or load logo and flag assets from an unrelated host.

The package exposes `window.AvraAPIPaymentElements` in a browser. Before mounting a checkout, you can verify that it loaded:

```js theme={null}
const Elements = AvraAPIPaymentElements.assertLoaded();
```

If the bundle is unavailable, `assertLoaded()` throws `elements_script_missing`. Show a retry message to the buyer and check your Content Security Policy and the immutable CDN URL.

## Create one checkout instance

Create one instance for a checkout page, then call `renderForm()` and `renderMethods()` on that same instance. The `createOrder` callback is **your application's HTTPS endpoint**. It is not an AvraAPI endpoint, an SDK function, or a second payment implementation.

```js theme={null}
const elements = AvraAPIPaymentElements.create({
  createOrder: async ({ gateway, mode, customer, providerOptions }) => {
    const response = await fetch('/your-checkout-endpoint', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ gateway, mode, customer, providerOptions }),
    });

    const session = await response.json();
    if (!response.ok) {
      throw Object.assign(new Error('Checkout could not be prepared.'), session?.error ?? {});
    }

    return session;
  },
  onStateChange: (event) => {
    // Update buyer-facing UI only. This event never proves a payment succeeded.
    console.info(event.type, event);
  },
  onError: ({ code, message }) => {
    console.error(code, message);
  },
});
```

Your endpoint must authenticate its own buyer session, load the pending order from trusted server-side storage, validate the selected gateway and mode against fresh availability, and call the SDK's `createOrder()`. It must not trust an amount, environment, merchant domain, or order identity supplied by the browser.

## `create()` options

| Option | Type | Default | Purpose |
| - | - | - | - |
| `createOrder` | `async ({ gateway, mode, customer, providerOptions }) => PaymentSession` | Required before `checkout()` | Calls your backend endpoint and returns the public payment session it creates. |
| `onStateChange` | `(event) => void` | None | Receives non-authoritative UI lifecycle events. See [Checkout lifecycle, events & errors](/universal-payment-gateway/payment-elements/checkout-lifecycle). |
| `onError` | `({ code, message }) => void` | None | Receives a safe browser error. Do not expose server diagnostics or credentials in this handler. |
| `directPayContainer` | CSS selector or `Element` | A container inside the method mount | Optional target for DirectPay's `embedded` presentation. It is ignored by other gateways. |
| `onePayOverlayFallback` | boolean | `true` | When the OnePay browser overlay cannot open, redirects the buyer to the provider-hosted URL instead. Set `false` only if your UI deliberately handles the failure without a redirect. |
| `assetBaseUrl` | HTTPS AvraAPI-owned CDN URL | The origin of the loaded bundle, or AvraAPI's CDN | Advanced asset location setting. Production assets must use an AvraAPI-owned HTTPS origin. Do not point it at a third-party or merchant-controlled host. |

`onePaySdkFactory` exists only as an internal package test seam. It is not an integration option and should not be used by applications.

## Shared appearance options

`renderForm()` and `renderMethods()` accept the same appearance options. They apply only to the Elements component they render.

| Option | Accepted values | Default | Notes |
| - | - | - | - |
| `theme` | `light`, `dark`, `auto` | `auto` | Use `light` or `dark` when you require a specific surface. `auto` is accepted as the standard default, but it does not automatically follow the operating system's dark-mode preference. |
| `accentColor` | Any valid CSS colour | `#2563eb` | Focus borders, selected cards, and radio controls. |
| `backgroundColor` | Any valid CSS colour | Theme default | Component background and floating-label background. |
| `textColor` | Any valid CSS colour | Theme default | Primary text colour. |
| `borderColor` | Any valid CSS colour | Theme default | Component, field, selector, and card borders. |
| `padding` | Any valid CSS length | `20px` | Outer component padding, for example `16px`, `1.5rem`, or `24px`. |

Light defaults are a white surface with dark text. Dark defaults use a `#111827` surface with light text. Use accessible colour contrast; custom colours do not alter validation, availability, or payment security.

## Components and checkout flow

| API | What it does | Return value |
| - | - | - |
| `renderForm(target, options)` | Replaces a mount target with the customer-details form. | `{ value(), destroy() }` |
| `renderMethods(target, options)` | Replaces a mount target with configured payment-method cards. | `{ selected(), availability(), markUnavailable(), mount(), destroy() }` |
| `checkout()` | Passes the selected method and form values to `createOrder`, then launches the public provider session. | A promise that resolves after the browser presentation starts or redirects. |
| `destroy()` | Removes the current form and payment-method UI from this Elements instance. | Nothing |

```js theme={null}
elements.renderForm('#payment-customer', { theme: 'dark' });
elements.renderMethods('#payment-methods', { theme: 'dark' });

document.querySelector('#pay-now').addEventListener('click', async () => {
  await elements.checkout();
});
```

The page must receive server-generated availability before `renderMethods()` can safely use its no-`methods` default. Learn how this works in [Render Payment Methods](/universal-payment-gateway/payment-elements/render-methods).

<CardGroup cols={3}>
  <Card title="Render Customer Form" icon="id-card" href="/universal-payment-gateway/payment-elements/render-form">
    Field options, country selection, validation, and normalized phone data.
  </Card>

  <Card title="Render Payment Methods" icon="list-check" href="/universal-payment-gateway/payment-elements/render-methods">
    Safe defaults, explicit methods, availability, sandbox badges, and stale-page handling.
  </Card>

  <Card title="Checkout Lifecycle" icon="arrows-rotate" href="/universal-payment-gateway/payment-elements/checkout-lifecycle">
    Provider presentation, browser events, errors, and the server-side completion boundary.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.