---
title: Inline Checkout
description: Embed a ZevPay payment modal directly on your page with the browser SDK. No server step required. Uses your public key, handles session creation, method selection, and polling.
---

# Inline Checkout

Embed a payment modal directly on your website. The browser SDK creates the checkout session, renders the modal, collects the payment, and polls for confirmation using your public API key. No server step is required to start a payment.

If you want us to host the whole page instead, use [Standard Checkout](/checkout/standard).

## Install

### Script tag (recommended)

```html
<script src="https://js.zevpaycheckout.com/v1/inline.js"></script>
```

### npm

```bash
npm install @zevpay/inline
```

## Quick start

```html
<button id="pay-btn">Pay ₦5,000</button>

<script src="https://js.zevpaycheckout.com/v1/inline.js"></script>
<script>
  document.getElementById('pay-btn').addEventListener('click', function () {
    var checkout = new ZevPay.ZevPayCheckout();
    checkout.checkout({
      apiKey: 'pk_test_your_public_key',
      email: 'customer@example.com',
      amount: 500000, // ₦5,000 in kobo
      currency: 'NGN',
      reference: 'order_12345', // optional
      firstName: 'John', // optional
      lastName: 'Doe',   // optional
      onSuccess: function (reference) {
        console.log('Payment successful:', reference);
        // Verify the payment on your server before fulfilling the order.
      },
      onClose: function () {
        console.log('Checkout closed');
      },
    });
  });
</script>
```

## Options

Pass these to `checkout(options)`.

| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `apiKey` | string | Yes | Your public API key (`pk_test_...` or `pk_live_...`). Sent from the browser, so configure allowed domains on the key. |
| `email` | string | Yes | Customer's email address. |
| `amount` | integer | Yes | Amount in kobo. `500000` is ₦5,000. |
| `currency` | string | No | Currency code. Only `"NGN"` is accepted. Defaults to `"NGN"`. |
| `reference` | string | No | Your unique transaction reference. Generated for you if omitted. |
| `firstName` | string | No | Combined with `lastName` and stored as the session's customer name. |
| `lastName` | string | No | Combined with `firstName`. |
| `metadata` | object | No | Custom data attached to the transaction. Returned in webhooks and on verify. |
| `paymentMethods` | string or string[] | No | Which methods to offer. Defaults to the methods configured for your key. See below. |
| `onInitialize` | function | No | Fires once the session is created and the modal is ready. |
| `onSuccess` | function | No | Fires when the payment is confirmed. Receives the transaction reference. |
| `onError` | function | No | Fires on a validation, network, or API error. Receives an error with `code` and `message`. |
| `onFailure` | function | No | Fires when a payment fails after a method was selected. |
| `onExpired` | function | No | Fires when the session expires. |
| `onClose` | function | No | Fires when the customer closes the modal. |

### Choosing payment methods

Control which methods appear in the modal:

```js
// All methods your key allows (default behaviour)
paymentMethods: 'all'

// A specific set
paymentMethods: ['bank', 'payid']

// A single method. The picker is skipped and the method is auto-selected.
paymentMethods: ['bank']
```

| Value | Method |
|-------|--------|
| `'bank'` | [Bank transfer](/payment-methods/bank-transfer) via a virtual account |
| `'payid'` | [ZevPay ID](/payment-methods/zevpay-id), paid from the ZevPay app |
| `'card'` | [Card](/payment-methods/card). Not yet live. Hidden while it is disabled. |

::: info Auto-selection
When exactly one method is enabled and it is not `payid`, the SDK selects it and skips the picker screen.
:::

### Metadata

Attach custom data to the transaction. It is returned in webhooks and on the verify endpoint:

```js
checkout.checkout({
  // ...
  metadata: {
    orderId: 'order_12345',
    customerId: 'cust_789',
  },
});
```

## Callbacks

### onSuccess(reference)

Fires when the payment is confirmed. `reference` is our transaction reference.

```js
onSuccess: function (reference) {
  // Verify on your server before fulfilling.
  fetch('/api/verify-payment', {
    method: 'POST',
    body: JSON.stringify({ reference }),
  });
}
```

::: warning Always verify on your server
A client callback is not proof of payment. Confirm the payment from your server using the [Verify Session](/api/verify-session) endpoint before you fulfil an order.
:::

### onError(error)

Fires on a validation, network, or API error. Read `error.code` for programmatic handling.

```js
onError: function (error) {
  console.error(error.code, error.message);
}
```

Common error codes: `MISSING_FIELD`, `INVALID_INPUT`, `INVALID_CREDENTIALS`, `FORBIDDEN`, `EXPIRED_SESSION`, `SERVICE_UNAVAILABLE`, `TOO_MANY_REQUESTS`.

### onFailure(error), onExpired(), onClose(), onInitialize()

`onFailure` fires when a payment fails after a method was selected. `onExpired` fires when the session times out. `onClose` fires when the customer dismisses the modal. `onInitialize` fires once the modal is ready.

## Validation

The SDK checks these before it makes any API call:

| Rule | Error code |
|------|------------|
| `apiKey` is required | `MISSING_FIELD` |
| `amount` is required | `MISSING_FIELD` |
| `email` is required | `MISSING_FIELD` |
| `currency`, if set, must be `"NGN"` | `INVALID_INPUT` |
| `amount` must be at least 10000 kobo (₦100) | `INVALID_INPUT` |

::: tip Card has a higher minimum
The card method is hidden in the picker when the amount is below ₦1,000, even where other methods are shown.
:::

## How it works

1. The customer clicks your pay button.
2. The SDK creates a checkout session with your public key. No server step is needed.
3. The modal renders the available payment methods.
4. The customer selects a method and sees the payment details, such as a bank account number.
5. The customer completes the transfer.
6. The SDK polls for confirmation every 5 seconds.
7. On confirmation, `onSuccess` fires with the transaction reference.
8. The modal closes shortly after.

## Domain whitelisting

The SDK sends your public key from the browser. To stop other sites from using your key, set allowed domains on the key in the [dashboard](https://business.zevpay.ng).

- Exact match: `mystore.com` allows only `mystore.com`.
- Wildcard: `*.mystore.com` allows `shop.mystore.com`, `mystore.com`, and other subdomains.

See [Domain Whitelisting](/guide/authentication#domain-whitelisting) for the full rules.

::: tip Production
Always set allowed domains on your live public keys.
:::

## Related

- [Standard Checkout](/checkout/standard), the hosted redirect alternative
- [Payment Methods](/payment-methods/overview)
- [Verify Session](/api/verify-session)
- [React SDK](/sdks/react), a component wrapper around this SDK
- [Webhook Events](/webhooks/events)
