Scan a product barcode to look up price and SKU from your inventory API. Build an order object with line items. Call POST /terminal/:terminal_id/event to send a purchase event to the Paystack Terminal. The terminal displays the amount and waits for card tap or PIN. When payment completes, Paystack fires a terminalaction.process.completed event — handle it to mark the sale as complete and print a receipt.
The retail checkout flow with Paystack Terminal:
Your POS app (web or React Native) talks to your backend, which talks to Paystack. The terminal never talks to your app directly.
// POST /api/checkout — your POS backend endpoint
app.post('/api/checkout', async (req, res) => {
var { terminalId, items } = req.body;
// items: [{ name, sku, quantity, unit_price }]
var total = items.reduce((sum, item) => sum + item.quantity * item.unit_price, 0);
// Push payment to terminal
var response = await fetch(
'https://api.paystack.co/terminal/' + terminalId + '/event',
{
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'purchase',
action: {
amount: Math.round(total * 100), // kobo
currency: 'NGN',
reference: 'pos_' + Date.now(),
description: items.map(i => i.name).join(', '),
}
}),
}
);
var data = await response.json();
if (!data.status) {
return res.status(400).json({ error: data.message });
}
// Store the sale in DB with status: 'awaiting_payment'
var sale = await db.sales.create({
reference: data.data.reference || ('pos_' + Date.now()),
terminal_id: terminalId,
items,
total,
status: 'awaiting_payment',
});
res.json({ sale_id: sale.id, total });
});
Get weekly developer tips
Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.
No spam. Unsubscribe anytime.
// Handle terminal payment completion
if (event.event === 'terminalaction.process.completed') {
var action = event.data;
if (action.status === 'success') {
await db.sales.update(
{
status: 'paid',
paid_at: new Date().toISOString(),
terminal_reference: action.reference,
},
{ where: { reference: action.reference } }
);
// Update inventory
var sale = await db.sales.findByReference(action.reference);
for (var item of sale.items) {
await db.inventory.decrement({ sku: item.sku, by: item.quantity });
}
// Trigger receipt print via your receipt printer API
await printReceipt(sale);
}
}
This guide is part of the Paystack Terminal guide series.
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