You can sell on WhatsApp and collect payment through Paystack by generating a payment link via the Paystack API, then sending that link in a WhatsApp message. The customer taps the link, pays with M-Pesa or card on the Paystack checkout page, and you receive a webhook confirming the payment. No custom checkout page required.
WhatsApp is the most used messaging app in Kenya. It is where people coordinate, negotiate, and make buying decisions. Millions of small businesses already sell through WhatsApp by posting product photos in status updates and group chats, then negotiating in DMs.
The problem has always been payment. The conversation happens on WhatsApp, but collecting money requires jumping to another channel. "Send to till 123456." "Pay to paybill 789." "I'll send you M-Pesa, give me your number." Each jump introduces friction. Friction kills conversions.
Paystack payment links solve this by putting a clickable payment URL directly inside the WhatsApp conversation. The customer taps it, lands on a Paystack-hosted checkout page, pays with M-Pesa or card, and comes back to the chat. No new app to install. No till number to remember. No amount to type manually.
This is not a new payment method. It is an existing payment method (Paystack checkout) delivered through the channel where Kenyan customers already spend their time.
A Paystack payment link is a URL that opens a hosted checkout page. The page shows the amount, accepts payment, and redirects the customer afterward. Think of it as a mini checkout with no website required.
There are two ways to create payment links:
When we talk about WhatsApp commerce, the API approach is what matters. You want to generate a link for each order, with the correct amount, and send it in the chat. Doing this manually through the dashboard works for the first five orders. After that, you need automation.
The link itself looks something like https://paystack.com/pay/some-reference for dashboard-created links, or you can use the authorization_url returned by the Transaction Initialize endpoint. Both lead to the same Paystack checkout experience.
Get weekly developer tips
Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.
No spam. Unsubscribe anytime.
The Transaction Initialize endpoint is the foundation. You call it with the customer's email, the amount, and any metadata you want to attach. Paystack returns an authorization_url, which is the payment link you send to the customer.
// Generate a Paystack payment link for a WhatsApp order
async function createPaymentLink(order) {
const response = await fetch('https://api.paystack.co/transaction/initialize', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: order.customerEmail,
amount: order.totalCents, // KES 1,500 = 150000
currency: 'KES',
reference: `wa-${order.id}-${Date.now()}`,
callback_url: 'https://yoursite.co.ke/payment-complete',
metadata: {
order_id: order.id,
customer_phone: order.phone,
channel: 'whatsapp',
custom_fields: [
{
display_name: 'Order',
variable_name: 'order_id',
value: order.id,
},
],
},
}),
});
const data = await response.json();
if (!data.status) {
throw new Error(`Paystack error: ${data.message}`);
}
return {
paymentUrl: data.data.authorization_url,
reference: data.data.reference,
accessCode: data.data.access_code,
};
}
A few details worth noting:
wa- lets you filter WhatsApp orders in your Paystack dashboard and reconciliation reports. When you have orders coming from your website, your app, and WhatsApp, this prefix saves hours.150000. This trips people up on the first integration. Double-check your amounts.The authorization_url in the response is the link you send on WhatsApp. It is a one-time-use URL tied to that specific transaction.
After you send the link, you need to know when the customer pays. This is where Paystack webhooks come in.
When the customer completes payment, Paystack sends a charge.success event to your webhook URL. The payload includes the reference you set when creating the link, the amount paid, and the metadata you attached.
// Webhook handler for WhatsApp payment confirmations
app.post('/webhooks/paystack', express.json(), async (req, res) => {
// Always return 200 immediately
res.status(200).send('OK');
const hash = crypto
.createHmac('sha512', process.env.PAYSTACK_SECRET_KEY)
.update(JSON.stringify(req.body))
.digest('hex');
if (hash !== req.headers['x-paystack-signature']) {
console.error('Invalid Paystack signature');
return;
}
const event = req.body;
if (event.event === 'charge.success') {
const { reference, amount, currency, metadata } = event.data;
// Check if this is a WhatsApp order
if (reference.startsWith('wa-')) {
const orderId = metadata.order_id;
const customerPhone = metadata.customer_phone;
// Update order status in your database
await updateOrderStatus(orderId, 'paid', {
paystackRef: reference,
amountPaid: amount,
currency,
});
// Send confirmation back to the customer on WhatsApp
await sendWhatsAppMessage(
customerPhone,
`Payment received for order ${orderId}. We are preparing your order now.`
);
}
}
});
The key pattern here is the loop: the customer pays on Paystack, your webhook picks it up, and you send a confirmation back to WhatsApp. The entire transaction starts and ends in the chat, even though the actual payment happened on Paystack's checkout page.
Always verify the webhook signature. Always confirm the amount matches what you expected for that order. These are not optional steps. Without them, someone could forge a webhook and your system would mark an order as paid without receiving money.
WhatsApp Business lets you create a product catalog inside the app. Customers can browse your products, see prices and descriptions, and tap to inquire. The catalog is free and built into WhatsApp Business.
The limitation: WhatsApp catalogs in Kenya do not have built-in payment. The customer can browse and add items to a cart, but there is no checkout button that processes payment. That is where Paystack payment links fill the gap.
The workflow looks like this:
For businesses using WhatsApp Business (the app, not the API), steps 2 through 4 happen manually. You read the message, calculate the total, go to your backend or a simple tool to generate the link, and paste it back.
For businesses using the WhatsApp Business API, you can automate the entire flow. The customer sends a catalog order, your bot parses the items, calculates the total, calls the Paystack API to generate a link, and sends it back. All within seconds.
A few catalog-specific tips:
Once payment is confirmed, you still need to fulfill the order. WhatsApp becomes your order management channel, and the Paystack reference ties everything together.
A basic order lifecycle on WhatsApp looks like this:
For tracking, store each order in your database with the WhatsApp phone number, the Paystack reference, the items, and the current status. When the customer asks "Where is my order?" you look up their phone number and give them a status update.
If you need to issue a refund, use the Paystack Refunds API with the original transaction reference. Let the customer know in the chat that the refund has been initiated and when to expect it.
One thing to be careful about: WhatsApp has a 24-hour messaging window for Business API users. After 24 hours without a customer message, you can only send pre-approved template messages. This means your post-payment updates need to go out promptly, or you need approved templates for order status messages.
Manual link generation works when you have a few orders per day. Beyond that, you need a system.
The simplest automation is a lightweight backend service that takes an order (items, amounts, customer details) and returns a payment link. Here is a minimal Express endpoint:
// POST /api/whatsapp-order
// Body: { items: [...], customerPhone: '0712345678', customerEmail: 'j@example.com' }
app.post('/api/whatsapp-order', async (req, res) => {
const { items, customerPhone, customerEmail } = req.body;
// Calculate total
const totalKES = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
const totalCents = totalKES * 100;
// Build order summary for the WhatsApp message
const summary = items
.map((item) => `${item.quantity}x ${item.name} (KES ${item.price.toLocaleString()})`)
.join(', ');
// Generate order ID
const orderId = `WA-${Date.now()}`;
// Save order to database
await saveOrder({
id: orderId,
items,
totalKES,
customerPhone,
customerEmail,
status: 'pending_payment',
});
// Create Paystack payment link
const paystackRes = await fetch('https://api.paystack.co/transaction/initialize', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PAYSTACK_SECRET_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: customerEmail,
amount: totalCents,
currency: 'KES',
reference: orderId,
metadata: {
order_id: orderId,
customer_phone: customerPhone,
channel: 'whatsapp',
items: items.map((i) => `${i.quantity}x ${i.name}`),
},
}),
});
const paystackData = await paystackRes.json();
if (!paystackData.status) {
return res.status(500).json({ error: paystackData.message });
}
res.json({
orderId,
paymentUrl: paystackData.data.authorization_url,
message: `Your order: ${summary}. Total: KES ${totalKES.toLocaleString()}.\n\nPay here: ${paystackData.data.authorization_url}`,
});
});
This endpoint does three things: calculates the total, saves the order, and generates the payment link. The response includes a ready-to-send WhatsApp message with the link. If you are using the WhatsApp Business API, your bot calls this endpoint and sends the message automatically. If you are running a manual operation, a staff member hits this endpoint from a simple internal tool and pastes the message into WhatsApp.
For businesses processing dozens of WhatsApp orders daily, this small backend is the difference between spending an hour on payment logistics and spending five minutes.
WhatsApp commerce is messy. Customers change their mind, lose connection, pay partial amounts by accident, or send payment for the wrong order. Here is how to handle the common problems.
Payment links on WhatsApp are the starting point. They work today with zero custom development if you are willing to generate links from the Paystack dashboard manually. With a small backend, they scale to hundreds of daily orders.
If you want to go further, the WhatsApp Bot That Collects Payment via Paystack guide covers building a full conversational bot that handles product browsing, cart management, and payment all within WhatsApp.
For the broader picture of Paystack in Kenya, including M-Pesa, Pesalink, settlement, and regulatory requirements, start with Paystack in Kenya: M-Pesa, Pesalink, and the Daraja Question.
If you are building payment integrations professionally, the McTaba 26-week bootcamp covers payment systems as part of a full-stack engineering curriculum. You ship real products that accept real money from Kenyan customers.
KES 2,999
The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.
Start Paystack Course