Paystack Amount Too Low Error
The "Amount too low" error means your transaction amount is below Paystack's minimum for that currency. For NGN the minimum is typically 10000 kobo (100 NGN). For GHS it is 100 pesewas (1 GHS). For ZAR and KES it is 100 cents (1 ZAR/KES). For USD it is 100 cents (1 USD). Remember that Paystack expects amounts in the smallest currency unit, not in the major unit.
What the Error Looks Like
When the amount you send to /transaction/initialize is below Paystack's minimum for that currency, you get:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"status": false,
"message": "Amount cannot be less than 10000"
}
The number in the message (10000) is in the smallest currency unit. For NGN, 10000 kobo is 100 Naira. The exact wording and threshold may vary depending on the currency and account type, but the pattern is the same: a 400 status with a message telling you the amount is below the floor.
Minimum Amounts by Currency
Here are the typical minimum transaction amounts Paystack enforces. These values are current as of July 2026 but can change. Always verify against the Paystack documentation for the latest figures.
| Currency | Minor unit name | Minimum (minor unit) | Minimum (major unit) |
|---|---|---|---|
| NGN | kobo | 10000 | 100 NGN |
| GHS | pesewas | 100 | 1 GHS |
| ZAR | cents | 100 | 1 ZAR |
| KES | cents | 100 | 1 KES |
| USD | cents | 100 | 1 USD |
Some account types or business categories may have different minimums. If you are running into a minimum that does not match the table above, check your Paystack dashboard or contact Paystack support for your specific account configuration.
The Kobo/Pesewa/Cents Confusion
This is the number one cause of the "amount too low" error. Paystack expects all amounts in the smallest currency unit. For Nigerian Naira, that is kobo. 1 NGN = 100 kobo. When a developer sends amount: 500 thinking they are charging 500 NGN, they are actually charging 500 kobo, which is 5 NGN.
// WRONG: sending Naira, not kobo
body: JSON.stringify({
email: 'customer@example.com',
amount: 50, // 50 kobo = 0.50 NGN - below minimum
currency: 'NGN',
})
// RIGHT: convert to kobo
const amountInNaira = 500;
body: JSON.stringify({
email: 'customer@example.com',
amount: amountInNaira * 100, // 50000 kobo = 500 NGN
currency: 'NGN',
})
The same rule applies to every currency Paystack supports:
- NGN: multiply Naira by 100 to get kobo
- GHS: multiply Cedis by 100 to get pesewas
- ZAR: multiply Rand by 100 to get cents
- KES: multiply Shillings by 100 to get cents
- USD: multiply Dollars by 100 to get cents
If you are storing prices in the major unit in your database (which is common), the conversion to the minor unit should happen at the point where you build the Paystack API request, not earlier. This keeps your business logic clean and isolates the Paystack-specific conversion to one place.
For a deeper treatment of amount conversion pitfalls including float precision issues, see Paystack Invalid Amount Error and Kobo Confusion.
Discount and Coupon Edge Cases
Discounts can push an otherwise valid amount below the minimum. If your store sells items for 200 NGN and a customer applies a 95% discount coupon, the final price is 10 NGN. That is 1000 kobo, which is below the 10000 kobo minimum for NGN.
Handle this in your pricing logic, not at the Paystack call:
const MINIMUM_AMOUNTS: Record = {
NGN: 10000, // 100 NGN in kobo
GHS: 100, // 1 GHS in pesewas
ZAR: 100, // 1 ZAR in cents
KES: 100, // 1 KES in cents
USD: 100, // 1 USD in cents
};
function calculateFinalAmount(
priceInMajorUnit: number,
discountPercent: number,
currency: string
): number {
const discounted = priceInMajorUnit * (1 - discountPercent / 100);
const amountInMinorUnit = Math.round(discounted * 100);
const minimum = MINIMUM_AMOUNTS[currency] || 100;
if (amountInMinorUnit < minimum) {
throw new Error(
`Final amount ${discounted} ${currency} is below the minimum of ${minimum / 100} ${currency}. ` +
`Adjust the discount or set a minimum order value.`
);
}
return amountInMinorUnit;
}
Some businesses solve this by setting a minimum order value that is higher than the payment gateway minimum. If your minimum order is 500 NGN, no discount can push the amount below the Paystack floor.
Server-Side Validation Before the API Call
Validate the amount on your server before calling Paystack. This gives you a chance to return a clear error message to your user instead of a cryptic API error.
const MINIMUM_AMOUNTS: Record = {
NGN: 10000,
GHS: 100,
ZAR: 100,
KES: 100,
USD: 100,
};
const CURRENCY_NAMES: Record = {
NGN: { major: 'Naira', minor: 'kobo' },
GHS: { major: 'Cedis', minor: 'pesewas' },
ZAR: { major: 'Rand', minor: 'cents' },
KES: { major: 'Shillings', minor: 'cents' },
USD: { major: 'Dollars', minor: 'cents' },
};
function validatePaystackAmount(amountInMinorUnit: number, currency: string): void {
if (!Number.isInteger(amountInMinorUnit)) {
throw new Error(
`Amount must be an integer in ${CURRENCY_NAMES[currency]?.minor || 'minor units'}. ` +
`Received: ${amountInMinorUnit}`
);
}
if (amountInMinorUnit <= 0) {
throw new Error('Amount must be a positive number.');
}
const minimum = MINIMUM_AMOUNTS[currency];
if (minimum && amountInMinorUnit < minimum) {
const majorAmount = minimum / 100;
throw new Error(
`Minimum transaction amount for ${currency} is ${majorAmount} ${CURRENCY_NAMES[currency]?.major || currency}.`
);
}
}
// Usage in your API route
app.post('/api/initialize-payment', async (req, res) => {
const { email, amountInNaira } = req.body;
const amountInKobo = Math.round(amountInNaira * 100);
const currency = 'NGN';
try {
validatePaystackAmount(amountInKobo, currency);
} catch (error) {
return res.status(400).json({ error: error.message });
}
// Proceed with Paystack API call
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, amount: amountInKobo, currency }),
});
const data = await response.json();
res.json(data);
});
This validation function catches three problems: non-integer amounts (which Paystack also rejects), negative or zero amounts, and amounts below the currency-specific minimum. Your user sees a clear message like "Minimum transaction amount for NGN is 100 Naira" instead of "Amount cannot be less than 10000".
Frontend Validation as a First Pass
Add client-side validation too. It does not replace server-side validation (never trust the client), but it gives the user instant feedback before the round trip to your server.
// React example
function PaymentForm({ currency = 'NGN' }: { currency?: string }) {
const [amount, setAmount] = useState('');
const [error, setError] = useState('');
const minimums: Record = {
NGN: 100,
GHS: 1,
ZAR: 1,
KES: 1,
USD: 1,
};
function handleAmountChange(value: string) {
setAmount(value);
const numericValue = parseFloat(value);
if (isNaN(numericValue) || numericValue <= 0) {
setError('Please enter a valid amount.');
return;
}
const minimum = minimums[currency] || 1;
if (numericValue < minimum) {
setError(`Minimum amount is ${minimum} ${currency}.`);
return;
}
setError('');
}
return (
<div>
<label>Amount ({currency})</label>
<input
type="number"
value={amount}
onChange={e => handleAmountChange(e.target.value)}
min={minimums[currency] || 1}
step="0.01"
/>
{error && <p className="text-red-500 text-sm">{error}</p>}
</div>
);
}
Notice that the frontend works in the major unit (Naira, Cedis) because that is what humans think in. The conversion to the minor unit (kobo, pesewas) happens on the server.
Testing Minimum Amount Handling
Write tests that specifically target the minimum amount boundary. Use Paystack's test mode to confirm the behavior.
// Jest / Vitest test examples
describe('Paystack amount validation', () => {
test('rejects amount below NGN minimum', () => {
expect(() => validatePaystackAmount(9999, 'NGN')).toThrow(
'Minimum transaction amount for NGN is 100 Naira'
);
});
test('accepts amount at NGN minimum', () => {
expect(() => validatePaystackAmount(10000, 'NGN')).not.toThrow();
});
test('rejects non-integer amounts', () => {
expect(() => validatePaystackAmount(100.5, 'NGN')).toThrow(
'Amount must be an integer'
);
});
test('rejects zero amount', () => {
expect(() => validatePaystackAmount(0, 'NGN')).toThrow(
'Amount must be a positive number'
);
});
test('rejects negative amount', () => {
expect(() => validatePaystackAmount(-500, 'NGN')).toThrow(
'Amount must be a positive number'
);
});
test('handles GHS minimum correctly', () => {
expect(() => validatePaystackAmount(99, 'GHS')).toThrow();
expect(() => validatePaystackAmount(100, 'GHS')).not.toThrow();
});
});
Also test your discount flow end-to-end. Apply a discount that should push the amount below the minimum and verify your system either blocks the discount or enforces a floor price.
Verification Checklist
Confirm the fix is working:
- Send a valid amount above the minimum. Confirm you get a 200 response with an
authorization_url. - Send an amount just below the minimum. Confirm your server-side validation catches it and returns a user-friendly error before calling Paystack.
- Send the exact minimum amount. Confirm Paystack accepts it. This tests that you are using the right floor value.
- Test with each currency your app supports. Each currency has a different minimum. If you accept GHS and NGN, test both.
- Test your discount/coupon flow. Apply a discount that brings the price close to the minimum. Confirm your pricing logic prevents it from going below.
- Check your frontend validation. Enter a low amount in the payment form and confirm the error message appears before form submission.
For the related error where the amount format itself is wrong (decimal instead of integer, string instead of number), see Paystack Invalid Amount Error and Kobo Confusion. For the full troubleshooting reference, see Paystack Errors and Troubleshooting: The Complete Reference.
If you want hands-on practice building payment flows that handle all these edge cases, the McTaba Full-Stack Software and AI Engineering self-paced course walks you through a production Paystack integration from first API call to deployment.
Key Takeaways
- ✓Paystack enforces minimum transaction amounts that vary by currency. If your amount is below the minimum, the API returns a 400 error with a message about the amount being too low. The minimum for NGN is 10000 kobo (100 NGN).
- ✓The most common cause is sending the amount in the major currency unit (Naira, Cedis, Rand) instead of the minor unit (kobo, pesewas, cents). Sending 50 when you meant 50 NGN actually sends 50 kobo, which is 0.50 NGN, well below the minimum.
- ✓Minimum amounts differ by currency and sometimes change. NGN: 10000 kobo (100 NGN). GHS: 100 pesewas (1 GHS). ZAR: 100 cents (1 ZAR). KES: 100 cents (1 KES). USD: 100 cents (1 USD). Always check the Paystack documentation for the latest figures.
- ✓Validate amounts server-side before calling the Paystack API. A simple check against a minimum-amounts lookup table catches the error before it reaches Paystack and lets you return a meaningful message to the user.
- ✓Be especially careful with discount and coupon flows. A 90% discount on a 100 NGN item leaves 10 NGN, which is 1000 kobo. That is below the typical NGN minimum. Your pricing logic should enforce a floor.
Frequently Asked Questions
- What is the minimum transaction amount for NGN on Paystack?
- The minimum transaction amount for NGN is typically 10000 kobo, which is 100 Nigerian Naira. This means any transaction below 100 NGN will be rejected with an "amount too low" error. This threshold can vary by account type, so check your Paystack dashboard if you see a different minimum.
- Does Paystack have a maximum transaction amount?
- Yes. Paystack enforces maximum transaction limits that depend on your account type, verification status, and currency. Newly activated accounts often have lower limits that increase as you build transaction history. Check your Paystack dashboard under Settings for your current limits, or contact Paystack support to request a limit increase.
- Why does Paystack use kobo instead of Naira?
- Using the smallest currency unit (kobo for NGN, cents for USD) avoids floating-point precision problems. Computers cannot represent 0.10 exactly as a floating-point number, which can cause rounding errors in financial calculations. By working with integers (1000 kobo instead of 10.00 NGN), Paystack eliminates these rounding issues. This is the same approach Stripe uses with cents.
- My amount is above the minimum but I still get this error. What is wrong?
- You are likely sending the amount in the major unit (Naira, Cedis) instead of the minor unit (kobo, pesewas). If you send <code>amount: 500</code> meaning 500 NGN, Paystack reads it as 500 kobo (5 NGN), which is below the 100 NGN minimum. Multiply your amount by 100 before sending it to Paystack.
- Do minimum amounts apply to test mode too?
- Yes. Paystack enforces the same minimum amounts in test mode as in live mode. This is actually helpful because it means errors you catch in testing will match what happens in production.
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