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 Transaction Timeline API for Debugging Customer Complaints
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

Paystack Transaction Timeline API for Debugging Customer Complaints

The Paystack Transaction Timeline API returns a chronological list of events for a single transaction. Each event includes a timestamp, action description, and relevant data. You can see when the transaction was initialized, when the customer entered card details, when authorization was sent to the bank, whether 3DS was triggered, when the charge succeeded or failed, and when the webhook was sent.

In this article

  1. 1. The Transaction Timeline Endpoint
  2. 2. Reading Timeline Events
  3. 3. Debugging Common Customer Complaints
  4. 4. Building an Internal Support Tool
  5. 5. Using the Timeline to Debug Webhook Issues
  6. 6. Storing Timeline Data for Post-Mortem Analysis
  7. 7. Stay Up to Date

The Transaction Timeline Endpoint

The timeline endpoint gives you a step-by-step record of everything that happened during a transaction. You can query it by transaction ID or reference.

// Fetch timeline by transaction reference
const reference = 'order_142_1721472000000';

const response = await fetch(
  'https://api.paystack.co/transaction/timeline/' + reference,
  {
    headers: {
      Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
    },
  }
);

const data = await response.json();
// data.data.history is an array of timeline events
// data.data.start_time is when the transaction started

for (const event of data.data.history) {
  console.log(event.time + ' | ' + event.type + ' | ' + event.message);
}

Each event in the history array contains:

  • type: The category of event (e.g., "action", "success", "close", "error")
  • message: A human-readable description of what happened
  • time: Seconds elapsed since the transaction started

The timeline is available for all transaction types: card, bank transfer, USSD, and mobile money. The events differ by channel, but the structure is the same.

Reading Timeline Events

Here is what a typical successful card payment timeline looks like:

// Example timeline for a successful card payment
[
  { "type": "action", "message": "Attempted to charge card", "time": 0 },
  { "type": "action", "message": "Authentication Required: OTP", "time": 1 },
  { "type": "action", "message": "OTP submitted", "time": 45 },
  { "type": "success", "message": "Transaction Successful", "time": 47 },
  { "type": "action", "message": "Webhook sent to https://yoursite.com/webhooks/paystack", "time": 48 },
  { "type": "action", "message": "Webhook acknowledged (200 OK)", "time": 49 }
]

And here is a failed payment timeline:

// Example timeline for a failed card payment
[
  { "type": "action", "message": "Attempted to charge card", "time": 0 },
  { "type": "action", "message": "Authentication Required: OTP", "time": 1 },
  { "type": "action", "message": "OTP submitted", "time": 120 },
  { "type": "close", "message": "Transaction Failed: Incorrect OTP", "time": 122 }
]

From the first timeline, you can see the payment completed in about 49 seconds, the customer took 45 seconds to enter their OTP, and the webhook was delivered successfully.

From the second timeline, you can see the customer took 2 minutes to enter the OTP and entered the wrong one. The charge failed because of incorrect OTP, not insufficient funds or a card problem.

This level of detail is what separates guesswork from informed debugging.

Get weekly developer tips

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

No spam. Unsubscribe anytime.

Debugging Common Customer Complaints

Here are the most common customer complaints and how to use the timeline to investigate them.

"I was charged but did not receive my product"

Pull the timeline. Check if the transaction succeeded (look for a "Transaction Successful" event). If it did, check the webhook events. Was the webhook sent? Was it acknowledged with a 200 status? If the webhook was not acknowledged, your server did not process the payment notification. Check your webhook handler logs.

"My payment failed but I was debited"

Pull the timeline. Look at the last event. If it says "Transaction Failed" with a specific reason, the charge was declined by the bank. Some banks show a temporary debit that gets reversed within 24 to 48 hours. Explain this to the customer. If the timeline shows "Transaction Successful" but your system shows it as failed, the issue is in your verification or webhook handling.

"I was charged twice"

Check your database for multiple transactions from the same customer around the same time. Pull the timeline for each transaction reference. If both timelines show "Transaction Successful," the customer may have clicked the pay button twice and initiated two separate charges. Check whether both references were generated by your system (a double-submit bug) or if one was a retry initiated by the customer.

"The payment just hung and nothing happened"

Pull the timeline. If the last event is "Authentication Required: OTP" with no subsequent events, the customer never entered the OTP. The bank sent the OTP but the customer did not complete the step. The transaction will eventually time out and be marked as abandoned.

Building an Internal Support Tool

Instead of having support agents ask engineers to look up transaction details, build a simple internal tool that anyone on the support team can use.

// Simple Express endpoint for your internal admin panel
app.get('/admin/transaction/:reference', async (req, res) => {
  const reference = req.params.reference;

  // Fetch transaction details
  const txResponse = await fetch(
    'https://api.paystack.co/transaction/verify/' + reference,
    {
      headers: {
        Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
      },
    }
  );
  const txData = await txResponse.json();

  // Fetch timeline
  const tlResponse = await fetch(
    'https://api.paystack.co/transaction/timeline/' + reference,
    {
      headers: {
        Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
      },
    }
  );
  const tlData = await tlResponse.json();

  // Fetch order from our database
  const order = await db.query(
    'SELECT * FROM orders WHERE paystack_reference = $1',
    [reference]
  );

  res.json({
    transaction: {
      reference: txData.data.reference,
      amount: txData.data.amount / 100,
      currency: txData.data.currency,
      status: txData.data.status,
      channel: txData.data.channel,
      customer_email: txData.data.customer.email,
      gateway_response: txData.data.gateway_response,
      paid_at: txData.data.paid_at,
    },
    timeline: tlData.data.history.map(function(e) {
      return {
        time_seconds: e.time,
        type: e.type,
        message: e.message,
      };
    }),
    order: order.rows[0] || null,
  });
});

This endpoint combines three data sources into one view: the Paystack transaction details, the timeline events, and your internal order record. A support agent enters the reference, sees everything in one place, and can resolve the customer's issue without engineering help.

Add this to your admin dashboard with a search bar. The agent types a reference or customer email, and the tool displays the transaction history and timeline.

Using the Timeline to Debug Webhook Issues

Webhook problems are one of the most common integration issues. The timeline helps you pinpoint exactly what happened.

Scenario: Webhook was sent but not acknowledged

The timeline shows "Webhook sent to [your URL]" followed by "Webhook failed (timeout)" or "Webhook failed (500)." This means Paystack sent the webhook, but your server did not respond correctly. Check your server logs around the timestamp for errors.

Scenario: No webhook event in the timeline

If the transaction succeeded but the timeline does not show a webhook event, the webhook may not be configured correctly on your Paystack dashboard. Check Settings > API Keys & Webhooks in your Paystack dashboard to verify the webhook URL.

Scenario: Webhook acknowledged but order not fulfilled

The timeline shows "Webhook acknowledged (200 OK)" but the customer did not receive their product. This means Paystack delivered the webhook and your server returned 200, but your webhook handler did not fulfill the order. The bug is in your code, not in Paystack. Check your webhook handler logic: is it verifying the transaction? Is it checking the amount and status? Is it updating the order in the database?

For each webhook issue pattern, the timeline tells you whether the problem is on Paystack's side (webhook not sent), your network's side (webhook not received), or your application's side (webhook received but not processed correctly).

Storing Timeline Data for Post-Mortem Analysis

For high-volume applications, store timeline data for failed transactions automatically. This gives you a dataset for analyzing failure patterns without having to query Paystack on demand.

// In your webhook handler, store the timeline for failed transactions
async function onTransactionFailed(reference) {
  try {
    const response = await fetch(
      'https://api.paystack.co/transaction/timeline/' + reference,
      {
        headers: {
          Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
        },
      }
    );
    const data = await response.json();

    await db.query(
      'INSERT INTO transaction_timelines (reference, timeline_data, created_at) VALUES ($1, $2, $3)',
      [reference, JSON.stringify(data.data.history), new Date()]
    );
  } catch (error) {
    console.log('Failed to store timeline for ' + reference + ': ' + error.message);
  }
}

Over time, this data reveals patterns. You might discover that 40% of your failed payments fail at the OTP step (customers not receiving or entering the OTP). That insight leads you to add clearer OTP instructions in your checkout flow. Or you might find that failures spike at certain times of day, pointing to bank-side processing issues.

For the full accept payments workflow, see the complete accept payments guide. For understanding bank decline reasons, see reading gateway responses.

Stay Up to Date

Paystack adds new timeline events as they expand their API. We update these guides when new debugging features become available.

Join the McTaba newsletter for Paystack engineering updates.

Sign up for the McTaba newsletter

Key Takeaways

  • ✓The Transaction Timeline API endpoint is GET /transaction/timeline/{id_or_reference}. It returns an array of events in chronological order, each with a timestamp, action type, and message.
  • ✓Use the timeline to answer "what happened?" questions from customers and support agents. Instead of guessing, you can see the exact sequence of events for any transaction.
  • ✓Common timeline events include: transaction initialized, card details entered, authorization sent to bank, bank responded (approve/decline), 3DS triggered, OTP sent, charge completed, webhook delivered, and settlement processed.
  • ✓The timeline shows failure points clearly. If a charge failed, the timeline tells you whether it failed at the bank (insufficient funds, card blocked), at 3DS (OTP timeout), or at your webhook (delivery failed).
  • ✓Build an internal support tool that pulls the timeline for any transaction reference. Your support agents can look up a customer complaint in seconds instead of escalating to the engineering team.
  • ✓The timeline is read-only and does not affect the transaction. You can query it as many times as needed without side effects.

Frequently Asked Questions

Is the Transaction Timeline available for all Paystack transactions?
Yes. The timeline is available for all transaction types: card, bank transfer, USSD, and mobile money. The specific events differ by channel, but every transaction has a timeline. You can query it by transaction ID or by reference.
How long is timeline data available after a transaction?
Paystack retains transaction timeline data for a significant period. You can query timelines for transactions that happened weeks or months ago. For long-term analysis, store the timeline data in your own database so you do not depend on Paystack retention.
Can I use the timeline to detect fraud?
Indirectly. The timeline shows patterns like rapid failed attempts (card testing), OTP failures (potential stolen card without access to the cardholder phone), and unusual time patterns. Combined with other signals (IP address, customer history), timeline data can feed into fraud detection logic.
Does querying the timeline affect the transaction?
No. The timeline endpoint is read-only. Querying it does not modify the transaction, trigger webhooks, or have any side effects. You can query it as many times as needed for debugging.
Can support agents access the timeline directly on the Paystack dashboard?
Yes. You can view transaction details including step-by-step events on the Paystack dashboard by clicking on a transaction. However, the API is more useful when you want to integrate timeline data into your own support tools, where agents can see both the Paystack events and your internal order data side by side.

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

Accepting Payments with Paystack: Complete Guide

Everything you need to accept your first payment with Paystack: choosing between Initialize Transaction and the Charge API, handling amounts in kobo, attaching metadata, setting callback URLs, and designing transaction references that keep your system clean.

Read more

Paystack Metadata: Passing Custom Data Through a Transaction

Paystack metadata lets you attach arbitrary JSON data to a transaction that flows through the entire lifecycle: from initialization to verification to webhooks. This guide shows you what to put in metadata, how to structure it for different use cases, and the limits you need to stay within.

Read more

Paystack Product API for Simple Storefronts

The Paystack Product API lets you create products with names, prices, and descriptions, then generate payment links for each one. For simple storefronts selling a handful of products, this is faster than building a full e-commerce backend. This guide covers creating products, linking them to payment pages, and knowing when to outgrow this approach.

Read more

Reconciling Dedicated Virtual Account Deposits

Dedicated Virtual Accounts (DVAs) let each customer have a permanent bank account number linked to your Paystack integration. When a customer transfers money to their DVA, Paystack notifies you. But matching those deposits to the right customer, handling partial payments, and reconciling against your records requires careful engineering. This guide walks through the reconciliation workflow.

Read more

Paystack Webhooks on Vercel Serverless Functions

A complete guide to building a Paystack webhook endpoint on Vercel. Covers API route setup, the raw body problem in serverless, Edge vs Node.js runtime trade-offs, signature verification, and a copy-paste handler you can deploy in minutes.

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.