Paystack Product API for Simple Storefronts
Use the Paystack Product API (POST /product) to create products with a name, description, price, and currency. Each product can be linked to a payment page, giving you a shareable URL for purchasing that product. This works for simple storefronts with a few products. For inventory management, cart functionality, or complex pricing, build a custom integration.
Creating Products
async function createProduct(name, description, priceInKobo, currency) {
var response = await fetch('https://api.paystack.co/product', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: name,
description: description,
price: priceInKobo,
currency: currency,
unlimited: true, // No stock limit
}),
});
var data = await response.json();
if (data.status) {
return {
id: data.data.id,
productCode: data.data.product_code,
name: data.data.name,
price: data.data.price,
};
}
throw new Error('Failed to create product: ' + data.message);
}
// Create some products
var ebook = await createProduct(
'M-Pesa Integration Guide (PDF)',
'A 120-page PDF covering Daraja API integration for Node.js developers.',
999900, // 9,999 NGN
'NGN'
);
var course = await createProduct(
'Full-Stack AI Engineering Course',
'26-week live bootcamp with mentorship.',
12000000, // 120,000 NGN
'NGN'
);
Product fields:
name: Product name shown to customersdescription: Detailed description of the productprice: Price in smallest currency unit (kobo for NGN)currency: Currency code (NGN, GHS, ZAR, KES, USD)unlimited: Set totruefor unlimited stock, orfalsewith aquantityfor limited stockimage: Optional product image URL
Listing and Managing Products
// List all products
async function listProducts() {
var response = await fetch('https://api.paystack.co/product', {
headers: {
Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
},
});
var data = await response.json();
return data.data;
}
// Get a specific product
async function getProduct(productId) {
var response = await fetch('https://api.paystack.co/product/' + productId, {
headers: {
Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
},
});
var data = await response.json();
return data.data;
}
// Update a product (e.g., change price)
async function updateProduct(productId, updates) {
var response = await fetch('https://api.paystack.co/product/' + productId, {
method: 'PUT',
headers: {
Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify(updates),
});
var data = await response.json();
return data.data;
}
// Update price
await updateProduct(ebook.id, { price: 799900 }); // New price: 7,999 NGN
Products are also visible and editable in the Paystack dashboard. Non-technical team members can update prices, descriptions, and stock levels from the dashboard while your code handles the integration.
Connecting Products to Payment Pages
The most straightforward way to sell a product is to connect it to a payment page. The page becomes the storefront for that product.
// Create a payment page linked to a product
async function createProductPage(product) {
var response = await fetch('https://api.paystack.co/page', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: product.name,
amount: product.price,
description: product.description,
slug: product.name.toLowerCase().replace(/[^a-z0-9]+/g, '-'),
redirect_url: 'https://yoursite.com/thank-you',
metadata: {
product_code: product.productCode,
},
}),
});
var data = await response.json();
return {
pageUrl: 'https://paystack.com/pay/' + data.data.slug,
pageId: data.data.id,
};
}
var ebookPage = await createProductPage(ebook);
console.log('Buy here: ' + ebookPage.pageUrl);
// Share this URL on social media, WhatsApp, email, etc.
Now you have a URL you can share anywhere. When a customer visits that URL, they see the product details and can pay immediately. No website needed.
Building a Simple Storefront Page
If you want a page that shows multiple products, you can build a simple HTML page that lists your products with "Buy" buttons linking to their payment pages:
<!-- Simple storefront - static HTML -->
<div class="products">
<div class="product">
<h3>M-Pesa Integration Guide (PDF)</h3>
<p>120-page PDF for Node.js developers</p>
<p><strong>N9,999</strong></p>
<a href="https://paystack.com/pay/mpesa-guide">Buy Now</a>
</div>
<div class="product">
<h3>Full-Stack AI Engineering Course</h3>
<p>26-week live bootcamp with mentorship</p>
<p><strong>N120,000</strong></p>
<a href="https://paystack.com/pay/fullstack-ai">Buy Now</a>
</div>
</div>
This "storefront" is just a static HTML page with links. Each "Buy Now" button takes the customer to the corresponding Paystack payment page. You can host this HTML file on any static hosting (GitHub Pages, Netlify, Vercel, or even a Google Drive shared page).
For digital products, set up a webhook handler that delivers the product (sends a download link, grants access) when the payment succeeds. Without the webhook, you would need to check your dashboard manually for each sale.
Automated Fulfillment with Webhooks
Payment pages and the Product API do not handle fulfillment. When a customer pays, you need a separate mechanism to deliver the product. Webhooks are that mechanism.
// Webhook handler for product sales
app.post('/webhooks/paystack', function(req, res) {
res.sendStatus(200);
var event = req.body;
if (event.event === 'charge.success') {
var metadata = event.data.metadata || {};
var productCode = metadata.product_code;
var customerEmail = event.data.customer.email;
if (productCode === 'PROD_mpesaguide') {
// Send the PDF download link
sendDownloadLink(customerEmail, 'https://yoursite.com/downloads/mpesa-guide.pdf');
} else if (productCode === 'PROD_fullstackai') {
// Create a course account
createCourseAccess(customerEmail);
}
}
});
Without this webhook handler, sales happen but you deliver manually. For a few sales a week, manual delivery works. For dozens or hundreds, automate it.
When to Outgrow the Product API
The Product API and payment pages are a starting point. You will outgrow them when you need:
- A shopping cart: Customers want to buy multiple products in one checkout. Payment pages are one product per page.
- Inventory tracking: You need to show "3 left in stock" and stop selling at zero. The Product API has basic quantity support but no real-time inventory management.
- Dynamic pricing: Coupons, bulk discounts, regional pricing, or time-limited sales. Payment pages have fixed prices.
- Customer accounts: You want customers to log in, see their purchase history, and re-download purchases. Payment pages do not have user accounts.
- Shipping and logistics: Physical products need address collection, shipping calculation, and order tracking. Payment pages do not handle this.
When these needs arise, build a custom checkout using Initialize Transaction. Your backend manages products, pricing, and inventory. Paystack handles the payment collection. This is the natural evolution from "quick and simple" to "full-featured store."
For the complete guide to custom integration, see accepting payments with Paystack.
Key Takeaways
- ✓The Product API lets you create product records on Paystack with a name, description, price, currency, and optional image.
- ✓Products can be linked to payment pages, giving each product a shareable payment URL.
- ✓This is suitable for simple storefronts: a few digital products, a course, merchandise, or downloadable content.
- ✓The Product API does not handle inventory, shipping, or cart logic. Those require your own backend.
- ✓Products created via the API appear in your Paystack dashboard for easy management.
- ✓When your storefront outgrows what the Product API offers, migrate to Initialize Transaction with your own product database and checkout flow.
Frequently Asked Questions
- Can I use the Product API without payment pages?
- Yes. The Product API creates product records that you can reference in your own custom checkout flow. You do not have to use payment pages. Use the product data (name, price) in your own frontend and Initialize Transaction on your backend.
- Does the Product API support product variants (sizes, colors)?
- The Product API does not have built-in variant support. For products with variants, create separate products for each variant (e.g., "T-Shirt - Medium", "T-Shirt - Large") or use custom fields on payment pages to let the customer select options.
- Can I set a product as out of stock?
- If you created the product with unlimited set to false and a quantity, Paystack decrements the quantity with each sale. When it reaches zero, the payment page shows the product as sold out. You can also manually update the quantity via the API.
- Do products show up on a public Paystack storefront?
- Products are linked to payment pages, which have public URLs. However, there is no single "storefront" page that lists all your products. You would need to build that listing page yourself and link to each payment page.
- Can I delete a product?
- Check the Paystack API documentation for product deletion endpoints. If deletion is not supported, you can deactivate the associated payment page to stop sales. The product record remains in your account for historical reference.
Ready to build real-world apps?
Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.
Apply to the McTaba Marathon