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 Metadata: Passing Custom Data Through a Transaction
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 20, 2026

Paystack Metadata: Passing Custom Data Through a Transaction

Pass a metadata object when initializing a Paystack transaction. It accepts any JSON key-value pairs. Paystack stores this data and returns it in verify responses and webhook payloads at data.metadata. Use it to link transactions to your internal records (order IDs, user IDs, product names) without needing a separate mapping table.

In this article

  1. 1. What Metadata Is For
  2. 2. Metadata Structure
  3. 3. Custom Fields for Display
  4. 4. The cancel_action URL
  5. 5. Common Metadata Use Cases
  6. 6. Limits and Restrictions
  7. 7. Reading Metadata in Webhooks
  8. 8. Stay Up to Date

What Metadata Is For

When a Paystack webhook arrives at your server with a charge.success event, you need to know what to do with the payment. Which order does it belong to? Which user paid? What product should be delivered? You can answer these questions two ways:

  1. Look up the transaction reference in your database: This works if you stored a mapping between the reference and the order before initializing the transaction.
  2. Read the metadata from the webhook payload: This works if you attached the relevant IDs to the transaction when you initialized it.

Both approaches work. Metadata makes the second approach possible and can serve as a useful backup or supplement to reference-based lookups.

// Initialize with metadata
var 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: 350000,
    currency: 'NGN',
    reference: 'order_2026_00142',
    metadata: {
      order_id: 'ORD-2026-00142',
      user_id: 'usr_8f3k2n',
      product_type: 'subscription',
      plan: 'annual_pro',
    },
  }),
});

After payment, when you verify the transaction or receive a webhook, the metadata comes back in data.metadata:

// In your webhook handler
var metadata = event.data.metadata;
console.log(metadata.order_id);      // 'ORD-2026-00142'
console.log(metadata.user_id);       // 'usr_8f3k2n'
console.log(metadata.product_type);  // 'subscription'
console.log(metadata.plan);          // 'annual_pro'

Metadata Structure

The metadata field is a JSON object. You can nest objects and arrays within it, though flat structures are easier to work with.

// Flat structure (recommended)
metadata: {
  order_id: 'ORD-2026-00142',
  user_id: 'usr_8f3k2n',
  items_count: 3,
  source: 'web_checkout',
}

// Nested structure (works but harder to query)
metadata: {
  order: {
    id: 'ORD-2026-00142',
    items_count: 3,
  },
  user: {
    id: 'usr_8f3k2n',
    tier: 'premium',
  },
}

Flat structures are easier to read in the Paystack dashboard and simpler to extract in webhook handlers. Use flat keys unless nesting truly adds clarity.

Data types

Metadata values can be strings, numbers, booleans, arrays, or nested objects. However, when metadata comes back from Paystack (in verify responses or webhooks), all values are serialized as JSON. Be prepared for numbers to arrive as strings in some cases and always validate types in your handler.

// Be defensive when reading metadata values
var orderId = String(metadata.order_id);
var itemsCount = Number(metadata.items_count);

Get weekly developer tips

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

No spam. Unsubscribe anytime.

Custom Fields for Display

The custom_fields key is a special metadata structure. It is an array of objects, each with display_name, variable_name, and value. Paystack renders these on the checkout page and in the transaction details on your dashboard.

metadata: {
  order_id: 'ORD-2026-00142',
  user_id: 'usr_8f3k2n',
  custom_fields: [
    {
      display_name: 'Order Number',
      variable_name: 'order_number',
      value: 'ORD-2026-00142',
    },
    {
      display_name: 'Customer Name',
      variable_name: 'customer_name',
      value: 'Amina Okafor',
    },
    {
      display_name: 'Delivery Address',
      variable_name: 'delivery_address',
      value: '15 Adeola Odeku, VI, Lagos',
    },
  ],
}

Custom fields serve two audiences:

  • The customer: They see the custom fields on the checkout page below the payment form, which serves as an order confirmation before they pay.
  • Your support team: When they look up a transaction on the Paystack dashboard, custom fields appear prominently, making it easy to identify what the transaction was for without querying your database.

You can have both regular metadata keys (for your backend logic) and custom_fields (for display) in the same metadata object. They do not interfere with each other. For advanced custom field patterns, see collecting extra checkout information.

The cancel_action URL

Paystack recognizes a special metadata key called cancel_action. If you set it to a URL, Paystack displays a "Cancel" button on the checkout page that redirects the customer to that URL when clicked. Without it, the cancel button closes the popup or navigates back.

metadata: {
  cancel_action: 'https://yoursite.com/cart',
  order_id: 'ORD-2026-00142',
}

This is useful when you want to redirect the customer to a specific page (like their cart or the product page) instead of just closing the checkout. It only works with redirect checkout; for inline/popup checkout, the onCancel callback handles the cancellation.

Common Metadata Use Cases

E-commerce order tracking

metadata: {
  order_id: 'ORD-2026-00142',
  cart_id: 'cart_9x8k2',
  items_count: 3,
  shipping_method: 'express',
  coupon_code: 'SAVE20',
}

SaaS subscription activation

metadata: {
  user_id: 'usr_8f3k2n',
  plan: 'pro_annual',
  workspace_id: 'ws_4m2n',
  trial_conversion: true,
}

Event ticket purchase

metadata: {
  event_id: 'evt_devfest_2026',
  ticket_type: 'vip',
  quantity: 2,
  attendee_email: 'customer@example.com',
  custom_fields: [
    {
      display_name: 'Event',
      variable_name: 'event_name',
      value: 'DevFest Lagos 2026',
    },
    {
      display_name: 'Ticket Type',
      variable_name: 'ticket_type',
      value: 'VIP (x2)',
    },
  ],
}

Marketplace or multi-vendor payment

metadata: {
  vendor_id: 'vendor_abc',
  platform_fee_percent: 10,
  buyer_id: 'buyer_xyz',
  listing_id: 'listing_789',
}

In each case, the metadata travels with the transaction. When the webhook arrives, you read the metadata to determine what to do: create tickets, activate a subscription, update an order status, or split funds between vendors.

Limits and Restrictions

Paystack does not publish an exact size limit for metadata, but the practical limit is a few kilobytes. Here are the guidelines:

  • Keep it small: Store IDs and short strings, not entire objects or large text blobs. If you need to pass a full order manifest, store it in your database and pass only the order ID in metadata.
  • No binary data: Do not base64-encode files, images, or PDFs into metadata. The request will likely fail or be rejected.
  • No sensitive data: Metadata is visible on the Paystack dashboard and in API responses. Do not store passwords, tokens, secret keys, or sensitive PII like national ID numbers.
  • String encoding: Keep values as simple strings and numbers. Special characters, emoji, and non-ASCII text generally work but add to the payload size.

A reasonable upper bound: keep the serialized metadata JSON under 5KB. Most practical use cases are well under 1KB.

// BAD: too much data in metadata
metadata: {
  full_cart: [
    { name: 'Product 1', price: 5000, description: '500 words of text...' },
    { name: 'Product 2', price: 3000, description: '500 words of text...' },
    // ... 20 more items
  ],
}

// GOOD: just the IDs, look up the rest from your database
metadata: {
  cart_id: 'cart_9x8k2',
  items_count: 22,
}

Reading Metadata in Webhooks

The webhook payload includes your metadata at data.metadata. Here is how to use it in your handler:

app.post('/webhooks/paystack', function(req, res) {
  // Return 200 immediately
  res.sendStatus(200);

  var event = req.body;

  if (event.event === 'charge.success') {
    var metadata = event.data.metadata || {};

    // Use metadata to determine what to do
    if (metadata.product_type === 'subscription') {
      activateSubscription(metadata.user_id, metadata.plan);
    } else if (metadata.product_type === 'order') {
      fulfillOrder(metadata.order_id);
    } else {
      // Fallback: look up by reference
      processGenericPayment(event.data.reference);
    }
  }
});

Always have a fallback. If metadata is missing or malformed (which can happen in edge cases), fall back to looking up the transaction by its reference. Your system should never break because metadata is empty.

For the full webhook handling guide, see the complete webhook engineering guide.

Stay Up to Date

We update these Paystack integration guides when API changes affect how metadata works or when Paystack adds new metadata features.

Sign up for the McTaba newsletter to get notified about Paystack changes that affect your integration.

Key Takeaways

  • ✓The metadata field accepts any JSON object. Whatever you put in comes back in verify responses and webhook payloads at data.metadata.
  • ✓Use metadata to store order IDs, user IDs, plan names, and anything else your fulfillment logic needs to identify what the payment was for.
  • ✓custom_fields is a special metadata structure that Paystack displays on the checkout page and dashboard. Use it for human-readable transaction labels.
  • ✓Metadata has size limits. Keep it under a few kilobytes. Do not store large blobs, base64 images, or entire cart inventories.
  • ✓Metadata is not encrypted. Do not store sensitive information like passwords, API keys, or personally identifiable information that should not appear in logs.
  • ✓You can combine regular metadata keys and custom_fields in the same metadata object. Regular keys are for your backend; custom_fields are for display.

Frequently Asked Questions

Can I update metadata after a transaction is initialized?
No. Metadata is set at initialization time and cannot be modified after. If you need to change the metadata, initialize a new transaction. To track changing data, store it in your database and link it via the transaction reference.
Is metadata included in the transaction export from the Paystack dashboard?
Yes. When you export transactions from the Paystack dashboard, metadata fields (including custom_fields) are included in the export. This makes metadata useful for reporting and reconciliation.
Can metadata keys conflict with Paystack internal fields?
Paystack reserves a few metadata keys like custom_fields and cancel_action. Other than those, you can use any key names. To be safe, prefix your keys with your app name or use a namespace like app_order_id instead of just id.
Does metadata affect transaction processing or fees?
No. Metadata is purely informational. It does not affect how Paystack processes the transaction, what fees apply, or how settlement works. It is pass-through data for your use.
Can I search transactions by metadata values in the Paystack dashboard?
The Paystack dashboard has limited search by metadata. You can search by reference, email, and amount. For metadata-based queries, use the Paystack API to list transactions and filter by metadata values on your end, or maintain a searchable index in your own database.

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

Using Paystack Custom Fields to Collect Extra Checkout Information

Paystack custom fields let you attach structured, human-readable data to a transaction that shows up on the checkout page, in your dashboard, and in webhook payloads. This guide covers display_name vs variable_name, common field patterns, and how to extract custom field data when the webhook arrives.

Read more

Paystack Customer Objects: Create, Fetch, Update, Whitelist

Paystack creates a customer object every time a new email hits your checkout. You can also create customers explicitly, update their details, fetch their transaction history, and whitelist or blacklist them for risk control. This guide covers every operation with working Node.js code.

Read more

Building a Wallet Top-Up Flow on Paystack

A step-by-step guide to building wallet top-up flows with Paystack. Initialize payment, handle webhooks, credit wallets safely, enforce minimum amounts, and prevent double-crediting in production.

Read more

Race Conditions Between Paystack Webhooks and Redirect Callbacks

The Paystack redirect callback and the webhook are two independent HTTP requests. Sometimes the redirect arrives first and the webhook has not updated the order yet. This guide explains why this happens and gives you three patterns to handle it cleanly.

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.