Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.kulmipay.com/llms.txt

Use this file to discover all available pages before exploring further.

KulmiPay Checkout lets you accept payments without building your own payment form. You create a checkout session with your publishable key, then send the customer to a hosted KulmiPay checkout page or render it with the kulmipay browser SDK. The checkout flow supports M-Pesa and PesaLink payments through the same session. Your account payment settings can control the final method order, layout, and checkout styling.

Create a checkout session

Send a POST request to /api/v1/checkout/ with your public key and payment details. The response includes a hosted url, a checkout id, and a signature.
curl -X POST https://app.kulmipay.com/api/v1/checkout/ \
  -H "Content-Type: application/json" \
  -d '{
    "public_key": "ISPubKey_live_xxxxxxxxxxxxxxxx",
    "amount": 1500.00,
    "currency": "KES",
    "email": "customer@example.com",
    "phone_number": "254712345678",
    "first_name": "Jane",
    "last_name": "Doe",
    "api_ref": "ORDER-1001",
    "redirect_url": "https://merchant.example/thank-you",
    "mobile_tarrif": "BUSINESS-PAYS",
    "bank_tarrif": "BUSINESS-PAYS",
    "unique_api_ref": true
  }'

Request fields

FieldTypeRequiredDescription
public_keystringYes*Your publishable API key. You can pass it in the body or as X-KULMI-PUBLIC-API-KEY.
amountnumberYesAmount to collect.
currencystringNoCurrency code. Defaults to your payment settings when omitted. Common values are KES, USD, EUR, and GBP.
emailstringNoCustomer email. Used to pre-fill checkout details.
phone_numberstringNoCustomer phone number in international format.
first_namestringNoCustomer first name.
last_namestringNoCustomer last name.
api_refstringRecommendedYour order or transaction reference.
redirect_urlstringRecommendedURL where the customer should return after payment.
callback_urlstringNoCompatibility field sent by the browser SDK. Use redirect_url for customer redirects.
hoststringNoMerchant website origin. The browser SDK sets this automatically.
methodstringNoRestrict checkout to a payment method when supported by your account settings.
mobile_tarrifstringNoBUSINESS-PAYS or CUSTOMER-PAYS.
bank_tarrifstringNoBUSINESS-PAYS or CUSTOMER-PAYS.
wallet_idstringNoWallet to fund directly, when your account supports wallet funding.
unique_api_refbooleanNoWhen true, KulmiPay returns an existing checkout for the same api_ref instead of creating a duplicate.
* Required unless passed as X-KULMI-PUBLIC-API-KEY.

Success response

{
  "id": "d9f3a821-5b2c-4e8a-a1d4-3c7f9e2b0a14",
  "url": "https://app.kulmipay.com/checkout/d9f3a821-5b2c-4e8a-a1d4-3c7f9e2b0a14/express/",
  "signature": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "tracking_id": "",
  "amount": "1500.00",
  "currency": "KES",
  "email": "customer@example.com",
  "api_ref": "ORDER-1001",
  "paid": false,
  "mobile_tarrif": "BUSINESS-PAYS",
  "bank_tarrif": "BUSINESS-PAYS",
  "methods": ["mpesa", "pesalink"],
  "layout": "tabs",
  "styles": {},
  "merchant_name": "Your Business",
  "merchant_origin": "merchant.example"
}

Use the browser SDK

Install the browser SDK from npm or load it from a CDN.
npm install kulmipay
<button
  class="kulmiPayButton"
  data-amount="1500"
  data-currency="KES"
  data-email="customer@example.com"
  data-phone_number="254712345678"
  data-first_name="Jane"
  data-last_name="Doe"
  data-api_ref="ORDER-1001">
  Pay now
</button>

<script src="https://unpkg.com/kulmipay"></script>
<script>
  new KulmiPay({
    publicAPIKey: "ISPubKey_test_xxxxxxxxxxxxxxxx",
    redirectURL: "https://merchant.example/thank-you",
    live: false
  })
    .on("COMPLETE", function (response) {
      console.log("Payment complete", response);
    })
    .on("FAILED", function (response) {
      console.log("Payment failed", response);
    })
    .on("IN-PROGRESS", function (response) {
      console.log("Payment in progress", response);
    });
</script>

Inline checkout

<div id="checkoutElement" style="width: 100%; max-width: 420px; height: 720px;"></div>

<script src="https://unpkg.com/kulmipay"></script>
<script>
  const checkout = new KulmiPay({
    publicAPIKey: "ISPubKey_test_xxxxxxxxxxxxxxxx",
    redirectURL: "https://merchant.example/thank-you",
    live: false,
    mode: "inline",
    inlineContainer: "checkoutElement"
  });

  checkout.run({
    amount: 1500,
    currency: "KES",
    email: "customer@example.com",
    phone_number: "254712345678",
    api_ref: "ORDER-1001"
  });
</script>

Hosted redirect

If you do not need the SDK, redirect the customer to the url returned by the checkout API.
const checkout = await response.json();
window.location.href = checkout.url;

Idempotency with unique_api_ref

Use unique_api_ref: true with a stable api_ref when retries or page refreshes could create duplicate checkout sessions. If a checkout already exists for that reference, KulmiPay returns the existing session.
{
  "public_key": "ISPubKey_live_xxxxxxxxxxxxxxxx",
  "amount": 1500,
  "currency": "KES",
  "api_ref": "ORDER-1001",
  "unique_api_ref": true
}

Sandbox and live endpoints

EnvironmentCheckout APICheckout page
Sandboxhttps://sandbox.kulmipay.com/api/v1/checkout/https://checkout-sandbox.kulmipay.com
Livehttps://app.kulmipay.com/api/v1/checkout/https://checkout.kulmipay.com
Use sandbox public keys with sandbox.kulmipay.com and live public keys with app.kulmipay.com. Environment mismatches are rejected.