Paystack Status Page and Incident Response for Your Team
Monitor Paystack outages at status.paystack.com. Subscribe to email, SMS, or RSS alerts so your team knows the moment Paystack reports an issue. But do not rely on the status page alone. Build your own health checks because the status page is often updated manually with a delay. When an outage happens, follow your incident runbook: assign an incident lead, notify affected customers with honest messaging, queue or pause payments, and reconcile all pending transactions after recovery. The status page also has a JSON API at status.paystack.com/api/v2/status.json that you can poll programmatically.
How the Paystack Status Page Works
Paystack uses Atlassian Statuspage at status.paystack.com. It shows the current health of Paystack services broken down by component:
- API - The core transaction API (initialize, verify, charge)
- Dashboard - The merchant dashboard at dashboard.paystack.com
- Payments - Card processing, bank transfers, USSD, mobile money
- Transfers - Payouts to bank accounts
- Webhooks - Event delivery to your webhook URL
Each component shows one of four states:
- Operational - Working normally
- Degraded Performance - Working but slow or with elevated error rates
- Partial Outage - Some requests are failing
- Major Outage - Most or all requests are failing
The status page also shows scheduled maintenance windows and a history of past incidents. The incident history is useful for understanding patterns: which components fail most often, typical resolution times, and whether issues tend to happen at specific times.
Important: the status page is usually updated manually by Paystack's operations team. There is often a delay of 5-15 minutes between when an issue starts and when the status page reflects it. This is why you need your own monitoring in addition to the status page.
Subscribing to Status Alerts
Do not check the status page manually. Subscribe to alerts so you get notified automatically.
Email alerts: Visit status.paystack.com and click "Subscribe to Updates". Enter your email address. You will receive an email whenever Paystack posts an incident update or schedules maintenance.
SMS alerts: On the subscribe page, select SMS and enter your phone number. SMS alerts have lower latency than email for urgent notifications.
RSS feed: The status page has an RSS feed you can add to any RSS reader or monitoring tool. The URL is typically status.paystack.com/history.rss.
Who should subscribe:
- Your on-call engineer or DevOps team
- Customer support lead (they will get questions from customers)
- Product manager or founder (they need to make decisions about communication)
- Your monitoring channel (Slack, Teams, or whatever your team uses)
Programmatic monitoring: The status page exposes a JSON API you can poll from your monitoring system:
// Check Paystack status programmatically
function checkPaystackStatus() {
return fetch('https://status.paystack.com/api/v2/status.json')
.then(function(res) { return res.json(); })
.then(function(data) {
var status = data.status;
console.log('Paystack status: ' + status.indicator);
console.log('Description: ' + status.description);
// indicator values: "none" (operational), "minor", "major", "critical"
if (status.indicator !== 'none') {
console.warn('Paystack is reporting issues: ' + status.description);
// Trigger your internal alert
}
return status;
})
.catch(function(err) {
console.error('Could not reach Paystack status page: ' + err.message);
return null;
});
}
// Check active incidents
function checkPaystackIncidents() {
return fetch('https://status.paystack.com/api/v2/incidents/unresolved.json')
.then(function(res) { return res.json(); })
.then(function(data) {
var incidents = data.incidents;
if (incidents.length === 0) {
console.log('No active incidents.');
return [];
}
incidents.forEach(function(incident) {
console.log('Active incident: ' + incident.name);
console.log('Status: ' + incident.status);
console.log('Impact: ' + incident.impact);
console.log('Started: ' + incident.started_at);
var lastUpdate = incident.incident_updates[0];
if (lastUpdate) {
console.log('Last update: ' + lastUpdate.body);
}
});
return incidents;
});
}
// Poll every 2 minutes
setInterval(checkPaystackStatus, 120000);
Do not poll the status API more frequently than every 2 minutes. More frequent polling is unnecessary (the status page does not update that fast) and may get your IP rate-limited.
Your Internal Incident Response Runbook
When Paystack goes down, your team needs to know exactly what to do. Write this runbook before your first outage. Print it. Pin it in your Slack channel. Make sure everyone knows where to find it.
Here is a template:
==================================================
PAYMENT OUTAGE INCIDENT RESPONSE RUNBOOK
==================================================
STEP 1: CONFIRM THE OUTAGE (0-5 minutes)
-----------------------------------------
- Check status.paystack.com for active incidents
- Check your own health monitoring dashboard
- Try a test API call from your server:
curl -H "Authorization: Bearer sk_test_xxx" \
https://api.paystack.co/bank?perPage=1
- Check your error logs for spike in Paystack errors
- Confirm: is it Paystack or is it your server/network?
STEP 2: ASSIGN ROLES (5 minutes)
-----------------------------------------
- Incident Lead: [Name] coordinates all actions
- Engineering: [Name] implements technical mitigations
- Customer Support: [Name] handles inbound tickets
- Communications: [Name] drafts customer-facing messages
STEP 3: ACTIVATE DEGRADED MODE (5-10 minutes)
-----------------------------------------
- Enable the degradation flag in your config:
Set PAYSTACK_DEGRADED_MODE=true in your environment
- This should:
a) Show "Payment temporarily unavailable" on checkout
b) Queue new orders for later processing
c) Enable alternative payment methods if available
d) Stop new subscription renewals from failing silently
STEP 4: CUSTOMER COMMUNICATION (10-15 minutes)
-----------------------------------------
- Post a banner on your website/app checkout page
- If the outage affects active customers, send notification
- Template: See "Customer Communication" section below
- Do NOT promise a specific resolution time
STEP 5: MONITOR FOR RECOVERY (ongoing)
-----------------------------------------
- Watch status.paystack.com for updates
- Watch your health check for recovery signal
- When Paystack recovers, wait 5 minutes to confirm
stability before disabling degraded mode
STEP 6: POST-RECOVERY (within 1 hour of recovery)
-----------------------------------------
- Disable degraded mode
- Process all queued orders (send payment links)
- Verify all pending transactions from before the outage
- Reconcile: check for ghost charges (charged on Paystack
but not confirmed in your system)
- Send recovery notification to affected customers
- Log the incident details for your records
==================================================
The runbook is not a suggestion. It is a checklist. During an outage, stress is high and thinking is slow. A checklist removes the need to think about process so you can focus on the problem.
Customer Communication During an Outage
Customers who see a broken checkout page with no explanation will leave and may not come back. Customers who see an honest message with a clear next step will wait or try an alternative. Communication is the difference.
On your website/app:
// Checkout page banner during outage
var outageMessages = {
// Short banner at top of checkout
banner: 'We are experiencing a temporary issue with card and bank '
+ 'payments. M-Pesa payments are working normally. '
+ 'We expect to resolve this shortly.',
// Full message on checkout page if payment is blocked
checkout: 'Our payment system is temporarily unavailable. '
+ 'Your cart is saved and we will not lose your order. '
+ 'You can try again in a few minutes, pay via M-Pesa '
+ 'if you are in Kenya, or contact us at '
+ 'support@yourcompany.com for assistance.',
// Email to customers with pending orders
emailSubject: 'Update on your order',
};
function buildOutageEmail(customerName, orderId) {
return 'Hi ' + customerName + ',\n\n'
+ 'We are experiencing a temporary issue with our payment '
+ 'system that may have affected your order #' + orderId + '.\n\n'
+ 'Your order is saved and we will send you a payment link '
+ 'as soon as the issue is resolved. You do not need to '
+ 'place the order again.\n\n'
+ 'We apologize for the inconvenience and appreciate your patience.\n\n'
+ 'Best,\n[Your Company Name]';
}
Rules for outage communication:
- Be honest. "Our payment system is temporarily unavailable" is better than "We are performing scheduled maintenance" (if it is not scheduled).
- Do not blame Paystack by name. Say "our payment system" or "our payment provider". Customers do not care which third party is down.
- Tell customers what they can do, not just what went wrong.
- Do not promise a resolution time unless Paystack has given you one. "Shortly" or "within the next few hours" is honest. "In 5 minutes" may be a lie.
- Reassure customers their data is safe. "Your order is saved" matters more than technical details.
- Send a follow-up when the issue is resolved. Close the loop.
Post-Incident Reconciliation
This is the step most teams skip, and it costs them money. After Paystack recovers, you need to reconcile every transaction that was in flight during the outage.
The reconciliation checklist:
// lib/post-incident-reconciliation.js
function reconcileAfterOutage(outageStart, outageEnd) {
console.log(
'Reconciling transactions from ' + outageStart + ' to ' + outageEnd
);
// Step 1: Find all transactions initiated during the outage window
return findTransactionsDuringOutage(outageStart, outageEnd)
.then(function(transactions) {
console.log('Found ' + transactions.length + ' transactions to reconcile');
var results = {
confirmed_paid: [],
confirmed_failed: [],
ghost_charges: [],
needs_payment_link: [],
};
// Step 2: Verify each transaction with Paystack
var verifyPromises = transactions.map(function(txn) {
return fetch(
'https://api.paystack.co/transaction/verify/' + txn.reference,
{
headers: {
'Authorization': 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
},
}
)
.then(function(res) { return res.json(); })
.then(function(paystackData) {
var paystackStatus = paystackData.data
? paystackData.data.status
: 'not_found';
if (paystackStatus === 'success' && txn.localStatus === 'paid') {
// Both agree: paid. Nothing to do.
results.confirmed_paid.push(txn.reference);
} else if (paystackStatus === 'success' && txn.localStatus !== 'paid') {
// GHOST CHARGE: Paystack charged the customer but your
// system did not record it. Grant access immediately.
results.ghost_charges.push({
reference: txn.reference,
amount: paystackData.data.amount / 100,
email: paystackData.data.customer.email,
});
} else if (paystackStatus === 'failed') {
results.confirmed_failed.push(txn.reference);
} else {
// Transaction not found on Paystack or still pending
results.needs_payment_link.push(txn);
}
})
.catch(function(err) {
console.error('Verify failed for ' + txn.reference + ': ' + err.message);
});
});
return Promise.all(verifyPromises).then(function() {
return results;
});
})
.then(function(results) {
console.log('\n=== RECONCILIATION RESULTS ===');
console.log('Confirmed paid: ' + results.confirmed_paid.length);
console.log('Confirmed failed: ' + results.confirmed_failed.length);
console.log('Ghost charges (action needed): ' + results.ghost_charges.length);
console.log('Need payment link: ' + results.needs_payment_link.length);
// Step 3: Fix ghost charges
results.ghost_charges.forEach(function(ghost) {
console.log(
'GHOST CHARGE: ' + ghost.reference +
' - ' + ghost.email +
' - amount: ' + ghost.amount
);
// Grant access to the customer
// grantAccess(ghost.email, ghost.reference);
});
// Step 4: Send payment links for orders that never got charged
results.needs_payment_link.forEach(function(txn) {
console.log('Sending payment link for order: ' + txn.orderId);
// sendPaymentLink(txn.email, txn.orderId);
});
return results;
});
}
function findTransactionsDuringOutage(start, end) {
// Replace with your database query
// Find all orders with payment_status != 'paid'
// created between start and end timestamps
return Promise.resolve([]);
}
module.exports = { reconcileAfterOutage };
Ghost charges are the most critical finding. A ghost charge means the customer paid but your system does not know it. The customer will contact support, and if you cannot find their payment, they will dispute the charge with their bank. Run reconciliation within 1 hour of recovery.
Keeping an Incident Log
After every payment outage, record what happened. This log is your institutional memory. It helps you improve your response time, justify infrastructure investments, and answer management questions about reliability.
// Template for your incident log
// Store in a spreadsheet, Notion, or database
var incidentTemplate = {
date: '2026-07-20',
duration_minutes: 45,
detected_by: 'health_check',
detection_delay_minutes: 3,
paystack_components_affected: ['Payments', 'API'],
impact: 'Card payments failed. Bank transfers worked. ~120 orders affected.',
customer_communications_sent: true,
degraded_mode_activated: true,
alternative_payments_used: 'mpesa',
orders_queued: 47,
orders_processed_after: 47,
ghost_charges_found: 3,
ghost_charges_resolved: 3,
total_revenue_at_risk: 'KES 580,000',
revenue_recovered: 'KES 565,000',
lessons_learned: 'Health check detected the outage 12 minutes before '
+ 'the status page updated. M-Pesa fallback handled 23 payments '
+ 'during the outage. Need to improve reconciliation script speed.',
action_items: [
'Add automatic Slack alert when health check triggers',
'Reduce reconciliation batch size for faster processing',
'Add bank transfer as a second fallback option',
],
};
Review this log quarterly. Look for patterns: Are outages happening at the same time of day? Are specific components failing more than others? Is your detection getting faster over time? Use the data to improve your playbook.
Combining the Status Page with Your Own Monitoring
The status page is one signal. Your own health checks are another. The best incident detection uses both.
// lib/combined-monitoring.js
var healthCheck = require('./paystack-health-check');
var paystackState = {
healthCheckStatus: 'unknown',
statusPageStatus: 'unknown',
lastHealthCheck: null,
lastStatusCheck: null,
alertSent: false,
};
// Your health check (pings Paystack API directly)
healthCheck.on('down', function(info) {
paystackState.healthCheckStatus = 'down';
paystackState.lastHealthCheck = new Date();
evaluateAndAlert();
});
healthCheck.on('recovered', function() {
paystackState.healthCheckStatus = 'up';
paystackState.alertSent = false;
evaluateAndAlert();
});
// Status page check (runs every 2 minutes)
function pollStatusPage() {
fetch('https://status.paystack.com/api/v2/status.json')
.then(function(res) { return res.json(); })
.then(function(data) {
var indicator = data.status.indicator;
paystackState.statusPageStatus = indicator === 'none' ? 'up' : 'issues';
paystackState.lastStatusCheck = new Date();
evaluateAndAlert();
})
.catch(function() {
paystackState.statusPageStatus = 'unreachable';
});
}
setInterval(pollStatusPage, 120000);
function evaluateAndAlert() {
var hc = paystackState.healthCheckStatus;
if (hc === 'down' && !paystackState.alertSent) {
var sp = paystackState.statusPageStatus;
if (sp === 'issues') {
sendAlert('CONFIRMED OUTAGE: Both health check and status page '
+ 'report Paystack issues. Activating incident response.');
} else {
sendAlert('POSSIBLE OUTAGE: Health check failing but status page '
+ 'shows operational. Investigating. May be our network.');
}
paystackState.alertSent = true;
}
if (hc === 'up' && paystackState.alertSent) {
sendAlert('RECOVERED: Paystack health check passing again. '
+ 'Starting post-incident reconciliation.');
}
}
function sendAlert(message) {
console.log('[ALERT] ' + message);
// Send to Slack, email, PagerDuty, etc.
}
healthCheck.start();
pollStatusPage();
This combined approach gives you faster detection (health check finds issues in 30-90 seconds) with confirmation (status page confirms it is Paystack, not your network). The different alert messages help your team understand the confidence level and respond appropriately.
Verification: Test Your Incident Response
Run a fire drill. Simulate a Paystack outage and walk through your runbook.
Step 1: Simulate the outage.
In your staging environment, block outbound traffic to api.paystack.co (using firewall rules or a network tool). This triggers your health check without affecting production.
Step 2: Verify detection.
Confirm your health check detects the "outage" within your expected timeframe (30-90 seconds). Confirm the alert fires to your Slack channel or notification system.
Step 3: Walk through the runbook.
Assign the roles. Activate degraded mode. Draft the customer communication. Do it in real time, not hypothetically. Note how long each step takes.
Step 4: Test queuing.
Place several orders during the simulated outage. Verify they are queued correctly and the customer sees the appropriate message.
Step 5: Simulate recovery.
Unblock traffic to api.paystack.co. Verify your health check detects recovery. Run the reconciliation script. Verify queued orders are processed.
Step 6: Review and improve.
After the drill, discuss what went well and what was slow or confusing. Update the runbook based on what you learned. Schedule the next drill in 3-6 months.
The first time you run this drill, it will take longer than expected and you will find gaps in your runbook. That is the point. Better to find those gaps in a drill than during a real outage at midnight.
Key Takeaways
- ✓status.paystack.com is your first external source of truth during a suspected Paystack outage. Subscribe every team member who handles payments to email or SMS alerts.
- ✓The status page has a JSON API (status.paystack.com/api/v2/status.json) you can poll programmatically, but your own health checks will detect problems faster.
- ✓Build an incident runbook before your first outage. Deciding what to do during an outage is slower and more stressful than following a pre-written plan.
- ✓Customer communication during an outage should be honest, specific, and action-oriented. Tell customers what happened, what you are doing, and what they should do next.
- ✓Post-incident reconciliation is where most teams fail. After Paystack recovers, verify every pending transaction, process queued orders, and send payment links for orders that could not be charged.
- ✓Assign clear roles: incident lead (coordinates response), engineering (monitors and implements fixes), customer support (handles inbound questions), and communications (sends proactive updates).
- ✓Keep a log of every outage with duration, impact, and resolution steps. This log helps you improve your response and is useful for post-mortems.
Frequently Asked Questions
- Where is the Paystack status page?
- status.paystack.com. It shows current system status, active incidents, scheduled maintenance, and incident history. Subscribe to email or SMS alerts at the bottom of the page so you get notified automatically when Paystack reports an issue.
- Can I programmatically check if Paystack is down?
- Yes. The status page has a JSON API at status.paystack.com/api/v2/status.json. The response includes a status.indicator field: "none" means operational, "minor" means degraded, "major" means partial outage, and "critical" means major outage. You can also check active incidents at status.paystack.com/api/v2/incidents/unresolved.json. Poll every 2 minutes or more.
- Why does the status page say operational but my API calls are failing?
- Two possibilities. First, the status page may not be updated yet. It is often updated manually with a 5-15 minute delay. Second, the problem may be on your side: network issues, expired API keys, SSL errors, or a firewall blocking connections. Test from a different network or machine to rule out local problems.
- What should I tell customers during a Paystack outage?
- Be honest and action-oriented. "Our payment system is temporarily unavailable. Your order is saved and we will send you a payment link as soon as the issue is resolved." Do not blame Paystack by name. Do not promise a specific resolution time. Focus on what the customer can do: wait, try an alternative method, or contact support.
- How do I reconcile transactions after a Paystack outage?
- Find all transactions initiated during the outage window. Verify each one by calling GET /transaction/verify/:reference. Look for ghost charges (Paystack says paid but your system does not). Grant access for ghost charges immediately. Send payment links for orders that were never charged. Run this reconciliation within 1 hour of recovery.
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