Skip to content

Standard Checkout

Create a checkout session on your server, redirect the customer to our hosted page, and handle the result when they return. This keeps your secret key on the server and lets us host the payment page.

If you want the checkout to appear as a modal on your own page, use Inline Checkout.

How it works

  1. Your server creates a session with your secret key.
  2. You redirect the customer to the returned checkout_url.
  3. The customer selects a method and pays on our hosted page.
  4. The customer is redirected to your callback_url with the status.
  5. Your server verifies the payment before fulfilling the order.

Step 1: Create a session

Call the initialize endpoint from your server with your secret key.

js
const response = await fetch('https://api.zevpaycheckout.com/v1/checkout/session/initialize', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'sk_test_your_secret_key',
  },
  body: JSON.stringify({
    amount: 500000, // ₦5,000 in kobo
    currency: 'NGN',
    email: 'customer@example.com',
    customer_name: 'John Doe', // optional
    callback_url: 'https://yoursite.com/payment/callback',
    reference: 'order_12345', // optional
    metadata: { orderId: '12345' }, // optional
  }),
});

const { data } = await response.json();
// data.checkout_url  ->  https://secure.zevpaycheckout.com/{sessionId}
// data.session_id    ->  save this for verification
python
import requests

response = requests.post(
    "https://api.zevpaycheckout.com/v1/checkout/session/initialize",
    headers={
        "Content-Type": "application/json",
        "x-api-key": "sk_test_your_secret_key",
    },
    json={
        "amount": 500000,
        "currency": "NGN",
        "email": "customer@example.com",
        "customer_name": "John Doe",
        "callback_url": "https://yoursite.com/payment/callback",
        "reference": "order_12345",
    },
)

data = response.json()["data"]
checkout_url = data["checkout_url"]
session_id = data["session_id"]
php
$ch = curl_init('https://api.zevpaycheckout.com/v1/checkout/session/initialize');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => [
    'Content-Type: application/json',
    'x-api-key: sk_test_your_secret_key',
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'amount' => 500000,
    'currency' => 'NGN',
    'email' => 'customer@example.com',
    'customer_name' => 'John Doe',
    'callback_url' => 'https://yoursite.com/payment/callback',
    'reference' => 'order_12345',
  ]),
  CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
$checkoutUrl = $response['data']['checkout_url'];
$sessionId = $response['data']['session_id'];

The response returns the hosted page URL and the identifiers you need later.

json
{
  "session_id": "ecc48011-e36e-4741-9b99-657f4a1ee86e",
  "reference": "ZVP-CKO-S-abc123",
  "checkout_url": "https://secure.zevpaycheckout.com/ecc48011-e36e-4741-9b99-657f4a1ee86e",
  "amount": 500000,
  "currency": "NGN",
  "expires_at": "2026-01-01T12:30:00.000Z",
  "enabled_payment_methods": ["bank_transfer", "payid"]
}

Step 2: Redirect the customer

Send the customer to checkout_url.

js
window.location.href = data.checkout_url;

Or link to it directly:

html
<a href="https://secure.zevpaycheckout.com/ecc48011-e36e-4741-9b99-657f4a1ee86e">
  Complete payment
</a>

Step 3: Handle the callback

After the customer finishes or leaves, we redirect them to your callback_url with query parameters.

https://yoursite.com/payment/callback?status=success&reference=ZVP-CKO-S-abc123
ParameterValuesDescription
statussuccessPayment completed.
statuscancelledCustomer cancelled or closed the page.
statusexpiredSession expired before payment.
referencestringTransaction reference. Present on success.

Step 4: Verify the payment

Always verify

The callback query parameters are not proof of payment. Confirm every payment from your server before you fulfil an order.

js
app.get('/payment/callback', async (req, res) => {
  const { status } = req.query;

  if (status === 'success') {
    const verification = await fetch(
      `https://api.zevpaycheckout.com/v1/checkout/session/${sessionId}/verify`,
      { headers: { 'x-api-key': 'sk_test_your_secret_key' } },
    );

    const { data } = await verification.json();

    if (data.status === 'completed') {
      await fulfillOrder(data.reference, data.amount);
      return res.redirect('/order/success');
    }
    return res.redirect('/order/pending');
  }

  if (status === 'cancelled') return res.redirect('/checkout');
  if (status === 'expired') return res.redirect('/checkout?error=expired');
});

Initialize parameters

ParameterTypeRequiredDescription
amountintegerYesAmount in kobo.
emailstringYesCustomer's email address.
currencystringNo"NGN" (default) or "USD".
callback_urlstringNoWhere to redirect the customer after checkout.
referencestringNoYour unique reference. Used for idempotency, see below.
customer_namestringNoShown in the dashboard instead of "Anonymous".
metadataobjectNoCustom data attached to the session.
payment_methodsstring[]NoMethods to offer, for example ["bank_transfer", "payid"]. Defaults to ["bank_transfer", "payid"].
line_itemsarrayNoOptional line items, each { name, description?, quantity, amount } with amount in kobo. Renders an itemised summary on the page.

Authentication

Both key types can call initialize. Use your secret key from a server, which is the pattern shown here. A public key also works, in which case its allowed domains are enforced against the request origin. Never put a secret key in client-side code.

Idempotency

If you retry initialize with the same reference while a session is still active, we return the existing session rather than creating a second one. Use a stable reference per order to make retries safe.

Session lifetime

A checkout session is valid for 30 minutes. After that the hosted page shows an expired state with a link back to your site, and the callback status is expired.

Compared to Inline Checkout

AspectStandardInline
Session creationServer-side, secret keyBrowser, public key
ExperienceFull-page redirectModal on your page
Server requiredYesNo
Result deliveryCallback URLJavaScript callback
Best forServer-rendered stores, payment linksVanilla JS and single-page apps

ZevPay Checkout Developer Documentation