Consuming Modem Pay Webhooks with TypeScript & Express
I build stuff, fix stuff, and make sure payments actually work. Mostly coding, sometimes dealing with servers, and occasionally pretending to be a business guy.
Search for a command to run...
I build stuff, fix stuff, and make sure payments actually work. Mostly coding, sometimes dealing with servers, and occasionally pretending to be a business guy.
No comments yet. Be the first to comment.
Can you use Stripe, Paystack, or Flutterwave in The Gambia? A developer's accurate, up-to-date look at what global payment processors support in The Gambia in 2026, and what to use instead.
Walk into most shops in Gambia and try to pay digitally. What happens next is almost always the same. You pay. The staff looks at you. Then they look at their phone. Then they ask: “Have you received
You’ve got a clean WooCommerce store, products looking sharp, shipping ready… but your customers want to pay with mobile money, and you’re still stuck in the card world. That’s where Modem Pay comes in, the gateway that actually understands how peopl...
In today’s digital age, businesses in The Gambia are rapidly moving online. Whether you’re a small merchant or a growing enterprise, offering seamless payment options is no longer optional; it’s essential. One of the most reliable methods for handlin...
TalaBuy, which describes itself as “The Gambia’s new way to shop online,” is changing e-commerce in the country. It connects Gambian shoppers to thousands of products; fashion, electronics, household essentials, beauty items, baby goods and with reli...

Webhooks let your server react to events in real time: when a customer signs up, a payment succeeds, or a charge is updated, Modem Pay sends an HTTP request to your endpoint. Rather than polling the API, you receive notifications instantly, enabling you to automate order processing, update user records, or trigger emails the moment something happens.
Node.js (>=14) and npm or yarn
TypeScript is configured in your project
Express web framework
modem-pay SDK installed:
npm install modem-pay express body-parser
# or
yarn add modem-pay express body-parser
A webhook secret generated in the Modem Pay dashboard (Developers → Webhooks) and set as an environment variable:
export MODEM_WEBHOOK_SECRET="whXXXXXXXXXXXXXXXXXXXX"
Create a dedicated route to receive POST requests from Modem Pay. In Express + TypeScript:
// src/webhook.ts
import express, { Request, Response } from 'express';
import bodyParser from 'body-parser';
import ModemPay from 'modem-pay';
const app = express();
// Parse JSON body for access to raw payload
app.use(bodyParser.json());
const modempay = new ModemPay();
const WEBHOOK_SECRET = process.env.MODEM_WEBHOOK_SECRET!;
app.post('/webhook', async (req: Request, res: Response) => {
const payload = req.body;
const signature = req.headers['x-modem-signature'] as string;
try {
// Validate and parse the event
const event = modempay.webhooks.composeEventDetails(
payload,
signature,
WEBHOOK_SECRET
);
// Delegate to specific handlers
await handleEvent(event.event, event.payload);
// Acknowledge receipt quickly
res.status(200).send('Received');
} catch (err) {
console.error('⚠️ Webhook signature verification failed:', err);
res.status(400).send('Invalid signature');
}
});
export default app;
Then wire up and start your server:
// src/index.ts
import app from './webhook';
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`🚀 Webhook listener running on port ${PORT}`);
});
Modem Pay signs each webhook with a header x-modem-signature. The SDK’s composeEventDetails method:
Verifies the signature against your secret.
Parses and returns an Event object:
interface Event<T = any> {
event: string; // e.g. "charge.succeeded"
payload: T; // event-specific data
}
Always wrap this call in a try/catch to reject invalid requests.
Below is a sample handleEvent function illustrating common use cases in an e-commerce context.
// src/handlers.ts
import { Event, EventType } from 'modem-pay';
export async function handleEvent(
eventType: EventType,
payload: any
): Promise<void> {
switch (eventType) {
case 'customer.created':
await onCustomerCreated(payload);
break;
case 'payment_intent.created':
await onPaymentIntentCreated(payload);
break;
case 'charge.succeeded':
await onChargeSucceeded(payload);
break;
default:
console.log(`🔔 Unhandled event type: ${eventType}`);
}
}
// Real‐world: Add new customer to your database
async function onCustomerCreated(customer: any) {
// e.g., save to MongoDB
await db.collection('customers').insertOne({
id: customer.id,
email: customer.email,
createdAt: new Date(customer.createdAt),
});
console.log(`✅ Customer ${customer.id} saved.`);
}
// Real‐world: Update order status when payment is captured
async function onChargeSucceeded(charge: any) {
const orderId = charge.metadata.order_id;
// e.g., update order in SQL db
await sql.query(
'UPDATE orders SET status = ? WHERE id = ?',
['paid', orderId]
);
console.log(`✅ Order ${orderId} marked as paid.`);
// Optionally, send notification email
await emailService.sendReceipt(charge.receipt_email, orderId);
}
You can extend this with additional handlers for inventory adjustments, CRM updates, SMS notifications, or accounting entries.
First, install the official CLI package:
# Install the Modem Pay CLI globally
npm install -g modempay-cli
# or with yarn
yarn global add modempay-cli
Then, authenticate in test mode and start forwarding webhooks to your local server:
# Log in (you’ll be prompted for your email and password)
modempay login
# Forward all incoming webhooks to your local endpoint
modempay listen --forward-url=http://localhost:3000/webhook
# → You’ll see a public test URL and a test secret printed
Once listening, you can simulate events to verify your handlers:
# Trigger a successful charge event
modempay trigger charge.succeeded
Check your server logs, your /webhook endpoint should receive and process the test payload exactly as in production.
Following this guide, you can securely receive and react to Modem Pay webhook events in TypeScript and Express. You’ll validate each payload’s signature, dispatch events to dedicated handlers, and integrate real-world business logic, whether updating orders, onboarding customers, or notifying users. Local testing with the CLI ensures your integration is rock-solid before going live.