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. Paystack Test Mode Working but Live Mode Failing
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 20, 2026

Paystack Test Mode Working but Live Mode Failing

When Paystack works in test but fails in live, the cause is almost always one of these: your business account is not fully activated (Paystack requires identity verification and business documents before enabling live payments), you are still using test keys (sk_test_) instead of live keys (sk_live_), your webhook URL is not HTTPS (Paystack requires HTTPS for live webhooks), your domain is not verified in the Paystack dashboard, or your callback URL uses HTTP instead of HTTPS. Run through the checklist in this guide to find the exact issue.

In this article

  1. 1. What "Live Mode Failing" Looks Like
  2. 2. Check 1: Is Your Business Account Activated?
  3. 3. Check 2: Are You Using Live Keys?
  4. 4. Check 3: Is Your Webhook URL HTTPS?
  5. 5. Check 4: Is Your Callback URL HTTPS?
  6. 6. Check 5: Is Your Domain Verified?
  7. 7. Check 6: Are Your Environment Variables Correct on the Production Server?
  8. 8. The Complete Go-Live Checklist
  9. 9. Verification: Confirm Live Mode Works

What "Live Mode Failing" Looks Like

You have been testing your Paystack integration for days. Test cards work. Webhooks fire. Verification succeeds. You switch to live keys, and suddenly:

  • The API returns { "status": false, "message": "Invalid key" }
  • Transactions initialize but fail during payment with no clear error
  • Webhooks stop arriving at your server
  • The checkout page shows an error or loads a blank Paystack page
  • Real card payments are declined with "Transaction failed"
  • The API returns { "status": false, "message": "Account not activated" }

The fix depends on which of these symptoms you see. Walk through the checklist below from top to bottom. Each item takes under two minutes to check.

Check 1: Is Your Business Account Activated?

This is the most common cause by far. Paystack allows you to develop with test keys before your account is activated, but live keys only work after activation is complete.

To check your activation status:

  1. Log into your Paystack dashboard
  2. Look at the top of the page. If you see a banner saying "Complete your business registration" or "Activate your account", your account is not activated
  3. Go to Settings > Business Settings and check if all required fields are completed

Paystack activation requirements (for Nigerian businesses):

  • Business name and registration number (CAC number)
  • Business address
  • Director/owner identity verification (BVN or valid ID)
  • Bank account details for settlement
  • Business category and description

For other countries (Ghana, South Africa, Kenya), the requirements are similar but use local business registration and identity systems.

Activation usually takes 24 to 48 hours after submitting all documents. Some accounts activate within hours. If it has been more than 48 hours, contact Paystack support at support@paystack.com with your business name and registered email.

The fix: Complete all required fields in your business settings and wait for activation. You will receive an email when your account is activated. Until then, continue developing in test mode.

Get weekly developer tips

Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.

No spam. Unsubscribe anytime.

Check 2: Are You Using Live Keys?

This sounds obvious, but it trips up more developers than you would expect. Your code must switch from test keys to live keys in two places: the server (secret key) and the frontend (public key).

// Check which keys your server is using
const key = process.env.PAYSTACK_SECRET_KEY?.trim();
console.log('Key prefix:', key?.substring(0, 8));
// Must show "sk_live_" for live mode

// In your frontend, check the public key
// Your PaystackPop.setup or script tag should use pk_live_, not pk_test_

Common mistakes:

  • Server has live key, frontend has test key. The server initializes the transaction in live mode, but the frontend popup uses a test public key. The popup will not load or will show an error.
  • Frontend has live key, server has test key. The server initializes the transaction in test mode, generating a test authorization_url. But the customer has a real card. Test transactions with real cards still "succeed" in test mode, but no real money moves. You think it works but it does not.
  • .env file has the right key, but the deployment uses the old key. You updated your local .env file but forgot to update the environment variable on Vercel, Railway, or wherever your production server runs.

The fix: Verify keys in both places.

// Server startup check
function verifyLiveMode() {
  const secretKey = process.env.PAYSTACK_SECRET_KEY?.trim();
  const publicKey = process.env.PAYSTACK_PUBLIC_KEY?.trim();

  if (!secretKey?.startsWith('sk_live_')) {
    console.error('WARNING: Server is NOT using live Paystack keys');
    console.error(`Current prefix: ${secretKey?.substring(0, 8)}`);
  }

  if (publicKey && !publicKey.startsWith('pk_live_')) {
    console.error('WARNING: Public key is NOT a live key');
    console.error(`Current prefix: ${publicKey?.substring(0, 8)}`);
  }

  if (secretKey?.startsWith('sk_live_') && publicKey?.startsWith('pk_live_')) {
    console.log('Paystack live mode confirmed');
  }
}

verifyLiveMode();

Check 3: Is Your Webhook URL HTTPS?

Paystack accepts HTTP webhook URLs in test mode. In live mode, it requires HTTPS. If your webhook URL starts with http://, Paystack will not deliver webhooks in live mode.

To check your webhook URL:

  1. Go to your Paystack dashboard
  2. Navigate to Settings > API Keys & Webhooks
  3. Check the Webhook URL field
  4. Make sure it starts with https://
// Correct live webhook URL
https://yoursite.com/api/webhooks/paystack

// WRONG: HTTP will not work in live mode
http://yoursite.com/api/webhooks/paystack

// WRONG: localhost will not work in live mode
http://localhost:3000/api/webhooks/paystack

Your webhook URL must:

  • Use HTTPS (not HTTP)
  • Point to a publicly accessible server (not localhost)
  • Return a 200 status code within 10 seconds
  • Be a real endpoint that accepts POST requests

If you have not set up HTTPS yet, see Paystack Mixed Content and HTTPS Errors for a guide on getting a free SSL certificate.

The fix: Update your webhook URL in the Paystack dashboard to use HTTPS. Make sure the endpoint is deployed and reachable before changing the URL.

Check 4: Is Your Callback URL HTTPS?

Similar to webhook URLs, Paystack requires HTTPS for callback URLs in live mode. If your callback_url uses HTTP, the redirect after payment may fail silently.

// BROKEN in live mode: HTTP callback_url
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: 'customer@example.com',
    amount: 500000,
    callback_url: 'http://yoursite.com/payment/verify',  // HTTP won't work in live mode
  }),
});

// FIXED: HTTPS callback_url
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: 'customer@example.com',
    amount: 500000,
    callback_url: 'https://yoursite.com/payment/verify',  // HTTPS required
  }),
});

Also check the default callback URL in your Paystack dashboard under Settings > API Keys & Webhooks. If it uses HTTP, update it to HTTPS.

Check 5: Is Your Domain Verified?

Paystack may require domain verification for live transactions. This confirms that you own the domain where the checkout popup or redirect will run.

To verify your domain:

  1. Go to your Paystack dashboard
  2. Navigate to Settings > Domains
  3. Add your production domain (e.g., yoursite.com)
  4. Follow the verification steps (usually adding a DNS record or a meta tag)

Domain verification is not always required. It depends on your account type and risk profile. But if your live transactions are failing and everything else on this checklist is correct, unverified domain could be the issue. Add and verify your domain to rule it out.

If you use multiple domains (e.g., yoursite.com and app.yoursite.com), verify each one separately.

Check 6: Are Your Environment Variables Correct on the Production Server?

The most frustrating version of this problem: your code is correct, your local .env file has live keys, but your production server is still using test keys. This happens when you update your local file but forget to update the deployment platform.

Check your production environment variables:

# Vercel
vercel env ls
# Look for PAYSTACK_SECRET_KEY and PAYSTACK_PUBLIC_KEY
# Verify they start with sk_live_ and pk_live_

# Railway
railway variables
# Check the Paystack-related variables

# Render
# Check the Environment tab in your Render dashboard

# Heroku
heroku config
# Look for Paystack key values

A common trap: multiple environments. Many platforms let you set different environment variables for production, preview, and development. If you set your live key only for "production" but your deployment is tagged as "preview", it will use the test key.

# Vercel: set for production specifically
vercel env add PAYSTACK_SECRET_KEY production
# Enter: sk_live_xxxxxxxxxxxxxxxx

# Verify it is set for production
vercel env ls production

Another trap: stale deployments. If you change environment variables on your platform without redeploying, the running server still uses the old values. Most platforms require a redeploy for environment variable changes to take effect.

# Force a redeploy after changing environment variables
# Vercel: push a commit or click "Redeploy" in the dashboard
# Railway: click "Redeploy" in the dashboard
# Render: deployments redeploy automatically on env var changes

The Complete Go-Live Checklist

Before switching from test to live, run through this checklist. Each item takes under a minute.

// Go-live checklist for Paystack integration

const goLiveChecklist = [
  {
    item: 'Business account activated',
    check: 'Dashboard shows no activation banner. Live keys are available.',
  },
  {
    item: 'Server uses sk_live_ secret key',
    check: 'Log key prefix at startup. Confirm sk_live_.',
  },
  {
    item: 'Frontend uses pk_live_ public key',
    check: 'Inspect checkout popup or script tag. Confirm pk_live_.',
  },
  {
    item: 'Webhook URL is HTTPS',
    check: 'Dashboard > Settings > API Keys & Webhooks. URL starts with https://.',
  },
  {
    item: 'Webhook endpoint returns 200',
    check: 'curl -X POST your webhook URL. Should return 200.',
  },
  {
    item: 'Callback URL is HTTPS',
    check: 'callback_url in transaction/initialize starts with https://.',
  },
  {
    item: 'Domain is verified',
    check: 'Dashboard > Settings > Domains. Domain shows verified.',
  },
  {
    item: 'Production env vars are updated',
    check: 'Check deployment platform. Verify live keys are set for production.',
  },
  {
    item: 'Production server is redeployed',
    check: 'Redeploy after changing env vars.',
  },
  {
    item: 'Test transaction with real card',
    check: 'Pay 100 NGN with a real card. Verify webhook, callback, and verification all work.',
  },
  {
    item: 'Refund the test transaction',
    check: 'Refund the 100 NGN from the Paystack dashboard to confirm refunds work.',
  },
];

// Log incomplete items
goLiveChecklist.forEach(({ item, check }) => {
  console.log(`[ ] ${item}`);
  console.log(`    How: ${check}`);
});

Verification: Confirm Live Mode Works

After completing the checklist, verify live mode works end to end:

Step 1: Verify the live key is valid.

// Run from your server (not the browser)
async function verifyLiveKey() {
  const key = process.env.PAYSTACK_SECRET_KEY?.trim();

  if (!key?.startsWith('sk_live_')) {
    console.error('Not a live key:', key?.substring(0, 8));
    return;
  }

  const res = await fetch('https://api.paystack.co/transaction?perPage=1', {
    headers: { Authorization: `Bearer ${key}` },
  });

  const data = await res.json();

  if (res.status === 200 && data.status) {
    console.log('Live key is valid and working');
  } else {
    console.error('Live key rejected:', data.message);
  }
}

verifyLiveKey();

Step 2: Initialize a real transaction.

Use your production server to initialize a transaction for a small amount (100 NGN or equivalent). Confirm you get an authorization_url back. Open the URL in your browser and confirm the Paystack checkout page loads.

Step 3: Complete a real payment.

Use a real debit card to pay the small amount. Confirm:

  • The payment succeeds on the Paystack checkout page
  • You are redirected to your callback URL
  • Your webhook endpoint receives the charge.success event
  • Your verification endpoint confirms the transaction as successful
  • The transaction appears in your Paystack dashboard under live transactions

Step 4: Refund the test payment.

In the Paystack dashboard, find the test transaction and initiate a refund. This confirms refunds work and returns the money to your card.

Key Takeaways

  • ✓The number one reason live mode fails is that your Paystack business account is not fully activated. Paystack requires identity verification and business registration documents before enabling live payments.
  • ✓Test keys (sk_test_, pk_test_) and live keys (sk_live_, pk_live_) are completely separate. Your server and frontend must both switch to live keys for live mode to work.
  • ✓Paystack requires HTTPS for live webhook URLs. A webhook URL starting with http:// will be rejected in live mode even though it works in test mode.
  • ✓Your callback_url must also use HTTPS in live mode. HTTP callback URLs work in test mode but fail silently in live mode.
  • ✓Domain verification in the Paystack dashboard confirms you own the domain where your checkout will run. Without it, live transactions from that domain may be blocked.
  • ✓After switching to live mode, make a real test transaction with a small amount (like 100 NGN) using a real card to confirm everything works end to end.
  • ✓Keep your test and live environment variables separate. Use your deployment platform's environment variable management to ensure each environment gets the right keys automatically.

Frequently Asked Questions

How long does Paystack business activation take?
Typically 24 to 48 hours after you submit all required documents. Some accounts activate within hours. The most common delay is missing or incorrect documents. Make sure your CAC number, BVN, and bank account details are accurate before submitting.
Can I process real payments before my Paystack account is activated?
No. Live payment processing is only available after your business account is fully activated. You can develop and test your entire integration using test mode keys, but real money transactions require activation.
Do I need separate test and live webhook URLs?
It is recommended. In test mode, Paystack sends webhooks to the URL in your dashboard (which can be HTTP). In live mode, it sends to the same URL (which must be HTTPS). Some developers use the same URL for both, but using separate URLs for test and live prevents test webhooks from triggering live business logic. Paystack sends webhooks for both modes to the same URL unless you change it when switching modes.
My live key returns "Invalid key" even though I just copied it from the dashboard. Why?
Check for trailing whitespace. When you copy a key from the Paystack dashboard, you might accidentally select invisible whitespace characters. Trim the key with .trim() in your code. Also confirm you are looking at the live key section of the dashboard, not the test key section. See our guide on Paystack Live Keys Rejected After Business Activation for more causes.
I switched to live keys but my test transactions still show up. Is something wrong?
Test and live transactions are separate in the Paystack dashboard. If you are seeing test transactions, switch the dashboard view to "Live" mode using the toggle at the top. If you initialized a transaction with a test key, it will always be a test transaction regardless of whether the card is real.

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 Errors and Troubleshooting: The Complete Reference

Every Paystack error you will hit in production, what causes it, and how to fix it. Authentication failures, webhook signature problems, transaction errors, transfer issues, and frontend bugs. Code-first solutions for each one.

Read more

Paystack Live Keys Rejected After Business Activation

Your Paystack business is activated but live keys still return "Invalid key" or fail silently. This is usually a wrong environment variable, an incomplete activation, or a key that needs to be regenerated.

Read more

Paystack Invalid Key: Every Cause and Fix

The Paystack "Invalid key" error means the API key you sent does not match any active key on your Paystack account. This guide covers every cause and the exact fix for each one.

Read more

Paystack Callback URL Not Redirecting

Your customer pays but is not redirected back to your site. This happens when callback_url is missing, you are using popup mode instead of redirect mode, or the browser is blocking the redirect.

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.