Skip to content
KonetPay

Developers

Four steps to your first payment.

Initialise, redirect, receive a signed webhook, verify. This guide follows the public KonetPay documentation, which remains the authoritative reference; keys shown are placeholders.

Base URL
https://core-api.konetpay.com/api/
Format
JSON
Currency
NGN, amounts in kobo
Mode
Decided by the key

Keys and modes

Test and live never share data.

Every business has two isolated worlds. The key you send decides which one a request touches; you never send a mode flag. A key containing _test_ is a test request, and one containing _live_ moves real money.

  • Secret key (sk_…): server side only. Full capability.
  • Public key (pk_…): checkout pages and status polling. No money movement.
  • Keys and webhook endpoints are managed in your KonetPay dashboard, not through the API.
  • Test keys are issued immediately; live keys follow a compliance review.
AuthenticationHTTP
Authorization: Bearer sk_test_XXXXXXXXXXXXXXXX

// A missing or invalid key returns 401.
// A public key on a secret-key endpoint returns 403.

Step 1 and 2

Initialise, then redirect.

Create the payment on your server. You get back a reference, an access code and an authorization_url. Redirect the customer’s browser to it.

  • amount: integer in kobo. Minimum 5000 (₦50).
  • reference: your unique value, up to 30 characters. Strongly recommended.
  • fee_bearer: merchant (default) or customer.
  • channels: only bank_transfer is live.
  • Initialising is limited to 60 requests per minute.
RequestHTTP
POST /api/transactions/initialize/
Authorization: Bearer sk_test_XXXX

{
  "amount": 500000,
  "email": "customer@example.com",
  "currency": "NGN",
  "reference": "your-unique-ref-001",
  "callback_url": "https://yourapp.com/payment/return",
  "fee_bearer": "merchant",
  "metadata": { "order_id": "1234" }
}
ResponseJSON
{
  "status": "success",
  "data": {
    "reference": "KP…",
    "access_code": "…",
    "authorization_url": "https://checkout.konetpay.com/<access_code>"
  }
}

Step 3

Receive and verify the webhook.

Every webhook carries an X-Konetpay-Signature header: an HMAC-SHA512 of the raw request body, keyed with your secret key for that mode, hex encoded. Compute it over the bytes exactly as received, compare in constant time, and reject on mismatch.

  • Events: payment.initiated, payment.successful, payment.failed.
  • Success means any 2xx. Otherwise KonetPay retries up to two more times, five minutes apart.
  • Delivery is at least once. Deduplicate on data.reference.
  • Register up to two HTTPS endpoints, without a query string, in your dashboard.
  • Reply fast, then process in the background.
Verify the signature (Node.js, Express)JavaScript
const crypto = require("crypto");

app.use(express.json({
  verify: (req, _res, buf) => { req.rawBody = buf; }
}));

app.post("/webhooks/konetpay", (req, res) => {
  const expected = crypto
    .createHmac("sha512", process.env.KONETPAY_SECRET_KEY)
    .update(req.rawBody).digest("hex");
  const received = req.headers["x-konetpay-signature"] || "";
  const valid = expected.length === received.length &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));
  if (!valid) return res.sendStatus(401);
  res.sendStatus(200);
  // enqueue req.body, dedupe on req.body.data.reference
});

Step 4

Verify before you fulfil.

As a second check, or if you prefer not to rely on the webhook alone, read the transaction straight from KonetPay. Give value only when the status is successful and the amount and currency match your order. Never credit an order because the browser landed on your callback address.

For a checkout page that must not hold a secret key, the lighter status endpoint accepts a public key.

Verify by referenceHTTP
GET /api/transactions/verify/<reference>/
Authorization: Bearer sk_test_XXXX
Webhook / verify payload (abridged)JSON
{
  "event_type": "payment.successful",
  "data": {
    "reference": "KP…",
    "business_reference": "your-unique-ref-001",
    "status": "successful",
    "amount_minor": 500000,
    "fee_minor": 5000,
    "net_amount_minor": 495000,
    "currency": "NGN",
    "channel": "bank_transfer"
  }
}

Reference

The documented endpoints.

Documented KonetPay endpoints
PurposeMethodPathAuth
Initialise a transactionPOST/api/transactions/initialize/Secret key
Verify by referenceGET/api/transactions/verify/<reference>/Secret key
Check status (lightweight)GET/api/transactions/status/<reference>/Public key
Verify by access code (used by hosted checkout)GET/api/transactions/verify-access-code/<access_code>/No key
Issue a static virtual accountPOST/api/external/virtual-accounts/Secret key
List banks for virtual accountsGET/api/external/virtual-accounts/processors/Secret key
List or retrieve virtual accountsGET/api/external/virtual-accounts/[<id>/]Secret key
Block a virtual accountPOST/api/external/virtual-accounts/<id>/block/Secret key

Errors

One envelope: status, message, code and, for validation, errors.

Error codes
HTTPCodeMeaning
400bad_requestMalformed request.
401unauthorizedMissing, invalid or revoked API key.
403forbiddenWrong key capability, for example a public key where a secret key is required.
404not_foundThe resource, such as a transaction reference, does not exist.
422validation_errorValidation failed. Field-level details are in errors.
429rate_limitedToo many requests. A Retry-After header is included.

Limits and idempotency

  • Initialise: 60 requests per minute. Other authenticated requests: 120. Unauthenticated: 60.
  • Always send your own unique reference. It ties the payment to your order across the webhook and the verify call.
  • Because webhooks are delivered at least once, make fulfilment idempotent: a repeat for a reference you already fulfilled is a no-op.
  • Only NGN is supported, and only bank_transfer is live.

Before you go live

The go-live checklist.

Work through this list before you swap test keys for live keys.

  • The integration works end to end with test keys.
  • Your webhook endpoint is registered, uses HTTPS and returns 200 quickly.
  • You verify the signature header on every webhook.
  • Fulfilment is idempotent, deduplicated on the reference.
  • You confirm status, amount and currency before giving value.
  • Your business is approved and you have swapped to live keys.
  • Secret keys live only on your server, never client side or in version control.

Need something this guide does not cover?

The official documentation is the authoritative reference. Include your business name and the transaction reference when you contact support.