API Reference · Payins

Create a payin

Start a collection and get a checkout link. Klustar does not redirect the customer for you: read data.checkout_url from the response and send them there straight away, because the link is not stored and cannot be fetched again. Call this from your server, not a browser. Sign every request with HMAC-SHA256. The signed fields are amount, currency, customerEmail, customerName, gateway, narration, notifyUrl, paymentMethod, redirectUrl and reference; any other JSON field is ignored and must not be signed. If no provider verdict has arrived 10 minutes after creation, the pay-in closes as TIMED_OUT and is not checked again, even if the customer pays later.

POSThttps://payment.klustar.io/payment/api/payins

Body params

reference
stringrequired

Your reference for this attempt, echoed in webhooks. Generate a new one for every attempt, for example ORDER-<UUID>. Use only A-Za-z0-9_-, and 5 to 50 characters: Korapay refuses anything else without naming the field, and that uses the reference up. It must not start with KLU-. A reference you have used before in the same environment is refused with 409 DUPLICATE_REFERENCE: failed attempts count, and references differing only in case count as the same. Do not reuse one between test and live or copy one from a sample: Korapay also refuses a reference any other Klustar merchant has used, and a shared reference can stop a result being applied.

amount
stringrequired

Amount in major units (naira, not kobo), sent as a JSON string of plain digits with at most 2 decimal places and no leading zeros, such as "2000" or "2000.50". It is signed as that exact text, so "2000.50" and "2000.5" sign differently, though "02000" signs as 2000 and fails. A JSON number also binds, but your language may format it differently from what you signed. In test mode Korapay refuses card amounts outside NGN 100 to 1,000,000: below NGN 100 with 409, and above it, at 0 or below 0 with 422.

currency
stringrequired

ISO currency code. Currently NGN.

customerName
stringrequired

Customer full name, as a string. Send it on every pay-in: Korapay, which handles every sandbox pay-in, refuses a pay-in without one.

customerEmail
stringrequired

Customer email address. Send it on every pay-in: Korapay, which handles every sandbox pay-in, refuses a pay-in without one.

redirectUrl
stringrequired

Where the customer returns after payment. Must be https, at most 1000 characters, with a host and no credentials in the URL. Send it on every pay-in: a live bank transfer through Hydrogen is refused without it.

notifyUrl
stringoptional

Leave this out. It does not set your webhook: Klustar sends webhooks only to the URL saved in Profile & Settings → API Keys. If you do send it, it must be signed, and a live provider may treat it as the customer return address.

gateway
stringoptional

Leave this out unless told otherwise. Pins the provider: KORAPAY, PALMPAY or HYDROGENPAY. It overrides paymentMethod routing and removes failover. Under test, PALMPAY and HYDROGENPAY are refused with HTTP 200 and PALMPAY_SANDBOX_DISABLED or HYDROGEN_SANDBOX_DISABLED, and the pay-in closes FAILED.

paymentMethod
stringoptional

CARD or BANK_TRANSFER, case-sensitive. Send it on every pay-in, and include it in the signed canonical body. Under test, every pay-in without a gateway goes to Korapay, showing that method at checkout. Under live, CARD goes to Korapay and BANK_TRANSFER to Hydrogen or PalmPay with failover, unless your business has a saved bank-transfer provider (Profile & Settings → Settlement), which pins that provider and removes failover even with no gateway. Without paymentMethod the provider is chosen by a legacy rotation with no failover.

narration
stringoptional

Short description shown on the payment flow, at most 255 bytes. Korapay refuses =, % and +, and that uses the reference up. Use letters, digits, spaces and simple punctuation.

Request body

application/json
{
  "reference": "ORDER-<new UUID for every attempt>",
  "amount": "2000",
  "currency": "NGN",
  "customerName": "Jane Doe",
  "customerEmail": "jane@example.com",
  "redirectUrl": "https://merchant.example/return",
  "paymentMethod": "CARD",
  "narration": "Order #1042"
}

Responses

Send the customer to data.checkout_url. This is Korapay, which handles every card pay-in and every sandbox pay-in. The response is the provider's own, so under live a BANK_TRANSFER pay-in differs: PalmPay answers success and checkoutUrl, and Hydrogen answers data.url with virtual account details.

Response body
{
  "status": true,
  "message": "Charge created successfully",
  "data": {
    "reference": "ORDER-8f14e45f-ceea-467d-a5b3-0c1f7b2d9e11",
    "checkout_url": "https://test-checkout.korapay.com/KPY-PI-.../pay"
  }
}