AI
How to Accept M-Pesa on an AI-Built Website (Base44, Lovable, Bolt and Others)
AI builders can give you a working shop front in an afternoon. Taking M-Pesa safely is the part they tend to get wrong. Here is why, a prompt you can paste into your builder, and the one check your thank-you page must do before it delivers anything.
Why “just ask the AI to add M-Pesa” usually goes wrong
Tools like Base44, Lovable and Bolt are very good at front ends: pages, buttons, forms, layouts. M-Pesa needs two things a front end cannot provide on its own:
- Secrets. To start an M-Pesa payment through Safaricom's Daraja API you need a consumer key, a consumer secret and a passkey. These must never sit in browser code. Anything in the page can be read by anyone who opens the page source. Read more in our guide to Daraja API keys.
- A server that hears Safaricom's answer. Safaricom reports the result of a payment to a server address (a callback URL), not to the customer's browser. Something on a server has to receive it and confirm it.
So when you type “add M-Pesa payments” into an AI builder, the result is often unsafe (Daraja keys pasted into front-end code) or broken (no server to receive the answer, or an order marked paid because the browser said so).
How KenZobe Checkout splits the work
KenZobe Checkout is our own M-Pesa checkout, and it is one way to solve this. It is built so the AI-made front end only needs public information:
- The page holds a website key (
kz_pk_test_…orkz_pk_live_…). It is public, and it only works from the domains you allow. - Each Buy button carries a price id. The button never sends an amount: KenZobe decides the amount from the price id, so a visitor cannot change what they pay.
- Clicking opens KenZobe's hosted checkout on pay.kenzobe.com: your business name first, the product, the amount and one field for the phone number. The customer gets the M-Pesa prompt and enters their PIN.
- Your Daraja keys go into the KenZobe dashboard, where they are encrypted and never shown again. They never touch your AI builder.
- Customer money goes straight into your own Paybill or Till. KenZobe never receives or holds it.
The only server-side part left for you is small: a final “was this paid?” check before you deliver. More on that below.
Honest limits: KenZobe Checkout does M-Pesa only (no cards, no Airtel Money), and for live payments you need your own Paybill or Till and your own Daraja app. If you would rather build the whole thing yourself, our STK Push tutorial and the M-Pesa website integration guide cover that path. You will need a real server for it.
What we found testing Base44 (October 2026)
When we tested in October 2026, the pay button and the payment itself worked on Base44's Starter plan. But backend functions, which you need for the server-side check, were not available on that plan. That meant the thank-you page could not confirm the payment safely. Backend functions came with a higher plan (Builder). Plans change, so check Base44's current plans before you decide.
For Lovable, Bolt and other builders, use whatever server-side function your builder supports (for example a Supabase Edge Function). The check is a single request, so any server-side function will do.
Step-by-step: set up KenZobe Checkout
- Sign up free. Create an account at app.kenzobe.com. You start in test mode (sandbox): no real money moves. You can try a test payment straight away on KenZobe's own sandbox app, before adding your own Daraja keys.
- Add a product and a price. In the dashboard, go to Products, add your product and give it a price. Copy the price id (it starts with
price_). If you change the amount later, the id stays the same, so you will not need to edit your site. - Create a website key and allow your domains. Add every domain your app runs on. AI builders often publish on their own subdomain first, before you connect your own domain, so add that builder subdomain as well as your own domain. A key used from a domain you did not add will not work.
- Keep the secret key for the server only. Your server-side check uses a secret key (
kz_sk_…). Store it in your builder's server secrets, never in the page. - Paste the prompt below into your AI builder, replacing the placeholders with your website key, price ids and domain.
- Test in sandbox, including a visit to your thank-you page with a made-up
kenzobe_paymentvalue. It should refuse to confirm. - Go live when ready. Add your Daraja live keys in the dashboard (two-step sign-in is required first), choose a monthly plan, add a live price to each product, and swap the test website key, secret key and price ids for the live ones.
Want to see the customer side first? Try the demo checkout (no real prompt is sent), or try it free in sandbox.
Prompt to paste into your AI builder
Copy this, replace the placeholders, and paste it into Base44, Lovable, Bolt or any other AI builder. It tells the AI exactly what to build and what never to do.
Add M-Pesa payments to this app using KenZobe Checkout.
1. Add this script tag once, in the page <head> or just before </body>:
<script src="https://pay.kenzobe.com/widget.js" data-key="kz_pk_test_REPLACE_ME" defer></script>
This is a public website key. It is safe in front-end code.
2. Turn each Buy button into a plain HTML button like this (one per product):
<button data-kenzobe-price="price_REPLACE_ME"
data-kenzobe-success-url="https://<your-domain>/thanks"
data-kenzobe-client-reference="<order id>">Pay with M-Pesa</button>
Do not add a click handler, an amount or a phone field. The script handles it.
Never send an amount anywhere. The price id decides the amount.
3. Never put a secret key (kz_sk_...) or any Safaricom Daraja keys
(consumer key, consumer secret, passkey) in front-end code, in
browser-visible environment variables, or in the code repository.
Do not call the Daraja API directly.
4. Create a /thanks page. It reads kenzobe_payment from the URL
(it looks like pay_...). It must NOT show a confirmation or a download
just because that value is there. Instead it calls a server-side
function with the kenzobe_payment value and the order id.
The server function:
- reads the secret key from server secrets (KENZOBE_SECRET_KEY);
- sends GET https://api.kenzobe.com/v1/payments/<kenzobe_payment value>
with the header: Authorization: Bearer <KENZOBE_SECRET_KEY>;
- returns OK only if the payment status is "paid" AND its price
matches the price id for this order AND its client_reference
matches the order id.
Only then show the confirmation or download. Otherwise show
"We could not confirm your payment yet" and how to contact us.
5. After a successful check, change the browser address to a clean
/thanks without the kenzobe_payment value, and do not load analytics
or other third-party scripts on /thanks.If your app has no order ids, use a customer id, or leave out the data-kenzobe-client-reference line and the client reference check. It accepts up to 100 characters. The success address must be https and on one of the domains you allowed for your website key.
Check what the AI produced. Search the code for kz_sk_ and for “consumer” or “passkey”. None of them should appear in any front-end file.
The safety rule you must not skip
After a confirmed payment, the customer comes back to your success address with ?kenzobe_payment=pay_… added. That value, and the client reference, are pointers, not proof. A visitor can type any address into the browser, or edit the button.
Before you deliver anything, your server asks the KenZobe API, using your secret key, whether that payment is paid:
GET https://api.kenzobe.com/v1/payments/pay_…
Authorization: Bearer kz_sk_live_…It then checks that the price (and client_reference) in the answer match its own order. Only then does it deliver. After that, send the customer on to a clean address, and keep third-party scripts off the return page.
In KenZobe, “paid” means Safaricom confirmed the payment with a status query, never just a callback or what a browser says. Your server check is how your app relies on that confirmation instead of on the address bar.
If your plan has no server functions
If your builder plan cannot run server-side code, do not fake the check in the browser. You have a few honest options:
- Deliver by hand. Let the button take the payment, then check the payment in your KenZobe dashboard and send the product or confirmation yourself. This works well while orders are few.
- Use a payment link instead. A payment link is a fixed amount behind a short pay.kenzobe.com address. Put it behind a button or share it on WhatsApp, then confirm in the dashboard before delivering.
- Upgrade or plug in a small backend. Move to a plan with server functions, or run the single check on a small server-side function elsewhere (for example a Supabase Edge Function) that your app calls.
If you want someone to wire it up for you, our team can help. Get in touch.
Frequently Asked Questions
Is the website key safe to put in the page?+
Yes. The website key (kz_pk_test_… or kz_pk_live_…) is public by design and is meant to sit in your page code. It only works from the domains you allowed for it, and it cannot set an amount: KenZobe takes the amount from the price id. What must never go in the page is the secret key (kz_sk_…) or your Daraja consumer key, consumer secret and passkey.
Why not just trust the thank-you page?+
Because anyone can type an address. The ?kenzobe_payment=pay_… part of the return address is a pointer, not proof, and a visitor can also edit the button in their browser. Before you deliver anything, your server asks the KenZobe API with your secret key whether that payment is paid and checks that the price and client reference match your order. In KenZobe, paid means Safaricom confirmed the payment with a status query, not just what a browser says.
Does this work on Wix or WordPress too?+
Yes. The same pay button works on any site that lets you add custom code, including WordPress and Wix custom code. Our pay button guide walks through it. The same rule applies there: check the payment on a server before you deliver.
Can I test without real money?+
Yes. A new KenZobe Checkout account starts in test mode (sandbox). Payments go through Safaricom's sandbox and no real money moves. You can try a test payment straight away using KenZobe's own sandbox app, before you add your own Daraja keys.
Do I need my own Paybill or Till?+
For live payments, yes. KenZobe Checkout uses your own Safaricom Daraja app and your own Paybill or Till, and customer money goes straight into it. KenZobe never receives or holds customer funds. Live payments also need a paid monthly plan; testing in sandbox is free.
For Wix, WordPress and plain HTML sites, see how to add an M-Pesa pay button to any website.
Get started
Build your front end with AI, keep the secrets on a server, and check every payment before you deliver. Try it free in sandbox, or try the demo checkout to see what your customers will see.