McTaba Labs logo
Software EngineeringThe WhiteboardProjectsEventsMasterclassesWebinarsLearn
Book Call

500+ developers already in the community

Get answers, find accountability partners, and stay ahead

Join Discord →
McTaba Labs logo

Educating 1 million students in tech by 2030.

Programs

  • HighSchool Graduates Launchpad
  • AI & Business Automation
  • Corporate Training
  • McTaba Story & Mission
  • Full-Stack Curriculum
  • Course Pricing & Plans
  • Frequently Asked Questions

Resources

  • Join Discord Community
  • Tech Events in Nairobi
  • Masterclasses
  • Free Resources
  • Learn
  • Campus
  • Africa Tech Talent Report
  • Partner With Us
  • Start a Project
  • Our Work

Contact Us

  • 124 Manyani East Road, Lavington, Nairobi
  • +254727795603
  • Book a Discovery Call

Office Hours:

Mon-Fri: 9am - 2pm EAT

Sat: 10am - 12pm EAT

© 2027 McTaba Labs - A product of Edtech Industries. All rights reserved.

Privacy PolicyTerms of ServiceRefund Policy
  1. Learn
  2. Paystack for African Developers
  3. Building a WhatsApp AI Sales Agent That Takes Payment
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

Building a WhatsApp AI Sales Agent That Takes Payment

Stack: WhatsApp Business Cloud API, Claude with function calling, Paystack Payment Links API. Tools: get_product_catalog(), create_payment_link(product_id, customer_name, customer_email). Flow: 1) WhatsApp webhook delivers customer message to your server. 2) Message + conversation history sent to Claude with tools. 3) Claude identifies product intent, calls get_product_catalog to confirm price. 4) Claude asks customer to confirm before creating link. 5) Claude calls create_payment_link — tool POSTs to Paystack /paymentrequest. 6) Link sent back via WhatsApp API. 7) charge.success webhook fires when customer pays — fulfill and notify.

WhatsApp Sales Agent Architecture

// WhatsApp Business Cloud API webhook handler
app.post('/whatsapp/webhook', async (req, res) => {
  res.sendStatus(200); // acknowledge immediately

  var message = req.body.entry?.[0]?.changes?.[0]?.value?.messages?.[0];
  if (!message || message.type !== 'text') return;

  var from = message.from;      // customer WhatsApp number
  var text = message.text.body;

  // Load conversation history from DB (keyed by phone number)
  var history = await db.whatsappSessions.get(from) || [];
  history.push({ role: 'user', content: text });

  var response = await runSalesAgent(history, from);

  // Send reply via WhatsApp Cloud API
  await sendWhatsAppMessage(from, response.reply);

  // Save updated history
  history.push({ role: 'assistant', content: response.reply });
  await db.whatsappSessions.set(from, history);
});

var salesTools = [
  {
    name: 'get_product_catalog',
    description: 'Get the list of available products with prices.',
    input_schema: { type: 'object', properties: {} },
  },
  {
    name: 'create_payment_link',
    description: 'Create a Paystack payment link for a confirmed order.',
    input_schema: {
      type: 'object',
      properties: {
        product_id: { type: 'string' },
        customer_name: { type: 'string' },
        customer_email: { type: 'string' },
      },
      required: ['product_id', 'customer_name', 'customer_email'],
    },
  },
];

async function runSalesAgent(history, customerPhone) {
  var response = await anthropic.messages.create({
    model: 'claude-opus-4-6',
    max_tokens: 512,
    tools: salesTools,
    messages: history,
    system: 'You are a sales agent for McTaba. Help customers find the right product and guide them to payment. Always confirm the order before creating a payment link. Collect customer name and email before creating a link.',
  });

  for (var block of response.content) {
    if (block.type === 'tool_use') {
      if (block.name === 'get_product_catalog') {
        var catalog = await db.products.getAll(); // your product DB
        // Feed result back and continue
        return runSalesAgent([
          ...history,
          { role: 'assistant', content: response.content },
          { role: 'user', content: [{ type: 'tool_result', tool_use_id: block.id, content: JSON.stringify(catalog) }] },
        ], customerPhone);
      }

      if (block.name === 'create_payment_link') {
        var product = await db.products.getById(block.input.product_id);
        var linkRes = await fetch('https://api.paystack.co/paymentrequest', {
          method: 'POST',
          headers: { Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY, 'Content-Type': 'application/json' },
          body: JSON.stringify({
            description: product.name,
            amount: product.amount_kobo,
            currency: 'NGN',
            customer: { email: block.input.customer_email, first_name: block.input.customer_name },
          }),
        });
        var link = (await linkRes.json()).data;
        return { reply: 'Here is your payment link for ' + product.name + ': https://paystack.com/pay/' + link.offline_reference + '

It expires in 24 hours. Reply DONE once you have paid.' };
      }
    }
  }

  return { reply: response.content.find(b => b.type === 'text')?.text };
}

Learn More

See agentic safety rails if you extend this agent to handle payouts or refunds.

Sign up for the McTaba newsletter

Key Takeaways

  • ✓WhatsApp webhook delivers messages to your server; Claude orchestrates the conversation and tool calls.
  • ✓Product catalog lives on your server — Claude never invents prices or products.
  • ✓Collect customer email before creating the Paystack link — required for receipt delivery.
  • ✓Confirm the order before creating the payment link — one confirmation message prevents wrong orders.
  • ✓Charge.success webhook fires on payment — fulfill the order and send confirmation to the WhatsApp number.

Frequently Asked Questions

How do I verify the WhatsApp webhook is from Meta and not spoofed?
Meta signs WhatsApp webhook payloads with the app secret. Verify the x-hub-signature-256 header: compute HMAC-SHA256 of the raw request body using your app secret and compare to the header value. Reject requests that fail verification. This is the same pattern as Paystack HMAC webhook validation.
What happens to conversation history when the session is idle for days?
Store conversation history with a TTL. If the customer has not sent a message in 24 hours, clear the history and start fresh on their next message. WhatsApp Business API sessions expire after 24 hours of customer inactivity anyway — your conversation history should match this boundary.
How do I fulfill the order after payment?
Set up a Paystack webhook handler for charge.success. In the webhook payload, data.metadata.reference or the payment link reference tells you which order was paid. Look up the order, fulfill it (send digital product, create account, dispatch goods), and send a WhatsApp confirmation message to the phone number stored with the order.

Learn Paystack Integration

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

Not ready? Create Free Account

Keep reading

Paystack AI Agents and the MCP Server: The Complete Guide

A comprehensive guide to building AI agents that interact with Paystack through the Model Context Protocol (MCP) server. Covers connecting the MCP server to Claude Code, querying transactions with natural language, building payment support chatbots, AI-assisted reconciliation, agentic payouts with safety rails, secret key security, human-in-the-loop design, prompt injection risks, and audit trails for AI-initiated financial actions.

Read more

RAG Over Your Payment Documentation and Transaction History

RAG lets an LLM answer questions grounded in your actual Paystack docs and transaction history instead of its training data. "What does this error code mean?" retrieves from your embedded docs. "What happened to transaction X?" retrieves from your transaction store.

Read more

Agentic Payouts: Safety Rails You Must Build First

An AI agent that can trigger Paystack transfers needs guardrails that a human operator does not. Build these safety rails before you give any agent access to POST /transfer — or you will build them after the first incident.

Read more

Building a Voice Agent That Collects Payment

A customer calls your number. They say what they want to pay for. The voice agent creates a Paystack payment link and texts it to their phone. No human operator needed. Here is how to build it.

Read more

Handle Paystack Webhooks in Firebase Cloud Functions

Handle Paystack webhook events in Firebase Cloud Functions. This guide covers HMAC SHA512 signature verification using Node.js crypto, reading the raw request body, returning 200 before processing, and updating Firestore with payment results.

Read more

Explore related topics

M-Pesa & African Stack

M-Pesa Daraja API tutorials, USSD development, and WhatsApp Business API guides. The African Stack that global bootcamps do not teach.

Learn to Code in Kenya

Everything a Kenyan needs to know before writing their first line of code. Career paths, real costs, hardware requirements, and honest answers about what it takes.

Learning to Code

Roadmaps, language guides, and practical advice for learning to code and launching a programming career.

Breaking Into Tech

Practical, no-nonsense guides for anyone looking to start or change their career in tech. From choosing your first language to acing interviews.

The African Stack: Skills for This Market

The skills that make Kenyan developers hard to replace: M-Pesa, USSD, WhatsApp, fintech, and building for the African market.

Bonaventure Ogeto

Bonaventure Ogeto

Founder, McTaba Labs

Bonaventure is the founder of McTaba Labs, a coding bootcamp in Nairobi, Kenya. He has spent years building products for the African market and mentoring the next generation of developers across the continent.