Payment Integration
Add an M-Pesa Pay Button to Any Website (No Backend Needed to Start)
Two snippets of HTML give your website a "Pay with M-Pesa" button. The customer types their number, gets the STK prompt on their phone and enters their PIN. The money goes straight into your own Paybill or Till. Here is how to set it up, step by step, and the one check you must add before you deliver anything.
See it first: try the demo checkout
Before you read the steps, open the demo and see what your customer will see: your business name first, the product, the amount and one field for their phone number.
This is a demo. No real M-Pesa prompt is sent and nothing is stored. It only checks that the phone number is in the right format.
What you need
- A website where you can paste HTML. Plain HTML, WordPress, or a site builder that allows custom code.
- For testing: nothing else. A new KenZobe Checkout account starts in sandbox and can make a test payment straight away using KenZobe's own sandbox app.
- For real payments: your own Paybill or Till, and your own Safaricom Daraja app (consumer key, consumer secret and passkey). Our guide to getting your Daraja API keys walks through that.
One honest limit up front: KenZobe Checkout does M-Pesa only. No cards, no Airtel Money, no bank transfers.
Step 1: Sign up free (sandbox)
Create an account at app.kenzobe.com. Every account starts in test mode: payments go through Safaricom's sandbox and no real money moves. You do not need your own Daraja keys yet.
Step 2: Add a product and a price, then copy the price id
In the dashboard, go to Products, add a product (for example "Delivery fee" or "Ankara dress") and give it a price. Open the product and copy its price id. It starts with price_.
Step 3: Create a website key for your domain
Create a website key and add the domain your button will live on (for example your-shop.co.ke). Test keys start with kz_pk_test_ and live keys with kz_pk_live_.
A website key is public and safe to put in a web page, because it only works from the domains you allowed for it. If someone copies it onto their own site, it will not work there.
Step 4: Paste the two snippets
Put the script tag once on the page (or in your site's header), with your website key in data-key:
<script src="https://pay.kenzobe.com/widget.js" data-key="kz_pk_live_…" defer></script>Then add a button wherever you want people to pay, with your price id:
<button data-kenzobe-price="price_…"
data-kenzobe-success-url="https://your-shop.co.ke/thanks"
data-kenzobe-client-reference="order-1042">Pay with M-Pesa</button>What each part does:
data-kenzobe-price(required): the price id from Step 2.data-kenzobe-success-url(optional): where the customer goes after a confirmed payment. It must behttpsand on one of the key's allowed domains. KenZobe adds?kenzobe_payment=pay_…to it.data-kenzobe-client-reference(optional): your own order or customer id, up to 100 characters. It comes back with the payment so you can match it to your order.
Clicking the button opens KenZobe's hosted payment page on pay.kenzobe.com. It works on old phone browsers, and buttons you add to the page later also work.
Where to paste it
- Plain HTML: script tag before
</body>or in the<head>, button anywhere in the page. - WordPress: add a Custom HTML block and paste both snippets into it.
- Site builders: any builder that allows custom code, such as Wix custom code.
- AI-built sites: see adding M-Pesa to a website built with AI for the prompt to give your builder.
Why the button never sends an amount
Look at the button again: there is no amount in it. That is on purpose. Anything in a web page can be edited by the visitor in their browser. If the button said "amount: 2,500", someone could change it to 1 and pay one shilling.
Instead, the button sends only the price id. KenZobe looks up the amount on its own server, so a visitor cannot change what they pay.
It also means you can change a price's amount later in the dashboard without touching your website. The price id stays the same, so the button keeps working and the checkout shows the new amount. A customer who had already opened the checkout pays what they were shown (for up to an hour).
Try it on your own site in sandbox
Sign-up is free and you can make a test payment before adding any Daraja keys.
Step 5: Test in sandbox
Use your test website key (kz_pk_test_…) and click your button. Payments go through Safaricom's sandbox, so no real money moves. Check that:
- the payment page shows your business name, product and amount;
- after the test payment you land on your success URL with
?kenzobe_payment=pay_…on the end; - your server check (next section) says the payment is paid and the price matches.
Step 6: Add your Daraja keys and go live
- Turn on two-step sign-in (an authenticator app). It is required before live keys can be saved.
- Add your Daraja keys in the dashboard. For a Paybill: the paybill number. For a Till: the store number and the till number. Both need the consumer key, consumer secret and passkey. You can add sandbox keys first and live keys later.
- Choose a monthly plan and pay for it by M-Pesa. Live payments open with a paid plan.
- Add a live price to your product (test and live prices have different ids) and a live website key for your domain.
- Swap the test website key in your script tag for the live one (
kz_pk_live_…) and the test price id on each button for its live price id.
Your keys are encrypted and never shown again after you save them, and changing live keys asks for your password again.
Before you deliver anything: check the payment on your server
The safety rule
The return address (?kenzobe_payment=pay_…) and the client reference are pointers, not proof. A visitor can type any address or edit the button. Before you deliver anything, your server must ask the KenZobe API, with your secret key, whether that payment is paid, and check that the price (and client_reference) match your own order.
Here is a short example in JavaScript for a Node.js server. It runs on your server only:
// Server only. paymentId is the pay_… value from ?kenzobe_payment=
const res = await fetch('https://api.kenzobe.com/v1/payments/' + paymentId, {
headers: { Authorization: 'Bearer ' + process.env.KENZOBE_SECRET_KEY },
});
const { success, data } = await res.json();
if (success
&& data.status === 'paid'
&& data.price === order.priceId
&& data.client_reference === order.id) {
// Safe to deliver this order
}- The secret key stays on the server. It starts with
kz_sk_. Never put it in a web page, a script tag or an app. Keep it in an environment variable. - Check the status and the price, not just one. A paid payment for a cheaper price is not payment for this order.
- Then send the customer on to a clean address (without
?kenzobe_payment=), and keep third-party scripts off the return page.
"Paid" in KenZobe means Safaricom confirmed the payment with a status query, never just a callback or what a browser says. If you would rather be told than ask, KenZobe can also send signed webhooks to your server.
No server yet? That is fine for starting out. Treat the return page as a thank-you note, not proof: confirm the payment arrived in your own Paybill or Till before you hand anything over, and add the server check when you automate delivery.
What it costs
KenZobe Checkout is a monthly plan with no percentage per transaction. Prices are in KES per month:
| Plan | Price per month | Successful live payments |
|---|---|---|
| Sandbox | Free | Unlimited test payments |
| Basic | KES 2,400 | Up to 300 |
| Growth | KES 6,000 | Up to 1,500 |
| Business | KES 14,000 | Up to 6,000 |
- No cut from KenZobe. The plan is the whole KenZobe cost, and a customer's payment is never blocked because you went over your plan's volume.
- Safaricom's charges still apply as they would to any Till or Paybill payment. For a Till, at the time of writing (October 2026) the merchant pays nothing up to KES 500, 0.55% from KES 501 to 36,363, and a flat KES 200 above that, per Safaricom's tariff page. Paybill charges depend on the tariff option you agree with Safaricom. More in Is the M-Pesa API free?
Prefer to build it yourself?
You can. Safaricom's Daraja API lets you send the STK prompt from your own server, and our STK Push tutorial shows how. You then handle callbacks, status checks, retries and keeping your keys safe yourself. For the full picture of your options, see how to accept M-Pesa payments on your website. If you want a team to set it up for you, talk to us.
Frequently Asked Questions
Do I need a backend to add an M-Pesa pay button to my website?+
Not to start taking payments. The button and KenZobe Checkout handle the STK prompt and the payment page, so a plain HTML page is enough. You do need a server-side check before you deliver anything automatically: your server asks the KenZobe API, with your secret key, whether the payment is paid. Until you have that, check the payment in your KenZobe dashboard (it shows the M-Pesa receipt once Safaricom confirms it) or in your own Paybill or Till before you hand anything over.
Can a customer change the price in the button?+
No. The button only carries a price id, never an amount. KenZobe looks up the amount from that id on its own server, so editing the button in the browser cannot change what the customer pays.
Does the money go through KenZobe?+
No. Customer money goes straight into your own Paybill or Till. KenZobe never receives, holds or settles customer funds. It is software that runs the checkout, not a payment aggregator.
Does the M-Pesa button work on WordPress and Wix?+
Yes, anywhere you can paste custom HTML: a plain HTML site, a WordPress Custom HTML block, or a site builder that allows custom code, such as Wix custom code. It also works on sites built with AI tools.
How much does the KenZobe M-Pesa button cost?+
Testing in sandbox is free. Live payments need a monthly plan: Basic KES 2,400, Growth KES 6,000 or Business KES 14,000, paid by M-Pesa. KenZobe takes no percentage per transaction. Safaricom’s normal M-Pesa charges still apply.
Can I take card payments or Airtel Money with it?+
No. KenZobe Checkout does M-Pesa only. If you need cards or other mobile money, you will need a different provider for those.
Get started
Sign up free, make a test payment in sandbox, and paste the two snippets into your site. When you are ready for real money, add your Daraja keys and pick a plan.
The demo sends no real M-Pesa prompt and stores nothing.