Developers

A payment API that ships in an afternoon.

Typed, sandbox-first, three integration shapes - call it inline, redirect to a hosted page, or share a billable URL. Webhooks signed with HMAC-SHA256. Same key works across all three.

checkout.htmlInline
<script src="https://js.zevpaycheckout.com/v1/inline.js"></script>

<script>
  const zp = new ZevPay.ZevPayCheckout();

  document.getElementById("pay").onclick = () =>
    zp.checkout({
      apiKey: "pk_live_…",
      email:  "ada@acme.ng",
      amount: 250000, // ₦2,500 in kobo
      onSuccess: (ref) => fetch("/api/confirm/" + ref),
    });
</script>

Quickstart

Pick an integration. Copy the snippet.

All three use the same key, the same webhook shape, and settle into the same ledger. Pick what fits your stack.

01 · Inline

Inline

Open a modal over your page. SPAs, custom checkout UX, marketplaces.

Full Inline guide →
checkout.htmlHTML + JS
<script src="https://js.zevpaycheckout.com/v1/inline.js"></script>

<script>
  const zp = new ZevPay.ZevPayCheckout();

  document.getElementById("pay").onclick = () =>
    zp.checkout({
      apiKey: "pk_live_…",
      email:  "ada@acme.ng",
      amount: 250000, // ₦2,500 in kobo
      onSuccess: (ref) => fetch("/api/confirm/" + ref),
    });
</script>

02 · Standard

Standard

Redirect to a hosted page. WordPress, Shopify, no-JS sites.

Full Standard guide →
init-transaction.shcURL
curl -X POST https://api.zevpaycheckout.com/v1/checkout/session/initialize \
  -H "x-api-key: sk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "amount":       250000,
    "currency":     "NGN",
    "email":        "ada@acme.ng",
    "reference":    "ORDER-12345",
    "callback_url": "https://acme.ng/return"
  }'

# →  { "success": true, "data": { "checkout_url": "https://secure.zevpaycheckout.com/…" } }
# Redirect, customer pays, returns. Confirm on your server by your own reference:

curl https://api.zevpaycheckout.com/v1/checkout/session/ORDER-12345/verify \
  -H "x-api-key: sk_live_…"

03 · Invoice

Invoice

Generate a billable URL. Freelancers, B2B, sales teams.

Full Invoice guide →
create-invoice.shcURL
curl -X POST https://api.zevpaycheckout.com/v1/checkout/invoice \
  -H "x-api-key: sk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_name":  "Adaeze Okonkwo",
    "customer_email": "ada@acme.ng",
    "due_date":       "2026-07-14T00:00:00Z",
    "line_items": [
      { "description": "Custom embroidery", "quantity": 2, "unit_price": 1250000 },
      { "description": "Express delivery",  "quantity": 1, "unit_price":  350000 }
    ]
  }'

# →  { "success": true, "data": { "payment_url": "https://invoice.zevpaycheckout.com/…" } }
# Share the URL by WhatsApp, email or SMS. A signed webhook fires when it's paid.

Webhooks

Verify before you trust.

Every webhook carries an x-zevpay-signature header - HMAC-SHA256 of the raw body using your webhook secret. Compare with timingSafeEqual; never with ===.

Webhook event reference
verify-webhook.ts
import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(req) {
  const sig = req.headers["x-zevpay-signature"];
  const mac = createHmac("sha256", process.env.ZP_WEBHOOK_SECRET);
  mac.update(req.rawBody);

  const expected = mac.digest();
  return timingSafeEqual(Buffer.from(sig, "hex"), expected);
}

End to end

How a payment flows.

01

Customer

Pays in your checkout

Bank transfer, ZevPay ID, PalmPay, mobile money or stablecoins, in their own currency.

02

ZevPay

Confirms and signs

We confirm the money arrived, then send charge.success signed with HMAC-SHA256.

03

Your API

Receives the webhook

Verify the signature, mark the order paid once, fulfil. Retried if your server is down.

Reference

Guarantees, at a glance.

Auth
x-api-key header: sk_ keys on your server, pk_ keys in the browser
Retries
Same reference + amount returns the same session, so a retried call can't double-charge
Webhook sig
HMAC-SHA256 of the raw body, hex, in the x-zevpay-signature header
Webhook retry
Up to 5 retries over about an hour and a half, then resend from the dashboard
Rate limits
100 requests a minute per key; 30 session creations a minute; 429 on burst
Versioning
Versioned in the path: /v1
Spec
OpenAPI 3 spec and a Postman collection; typed Node SDK
Test mode
sk_test_ / pk_test_ keys before approval, simulated payments, signed test webhooks

Built for builders

Test it right now. Real money optional.

Sandbox keys appear in your dashboard the moment you sign up. Switch to live with a config swap.