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 Payment Requests and Invoices via API
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 20, 2026

Paystack Payment Requests and Invoices via API

To create a Paystack payment request, POST to /paymentrequest with the customer code or email, amount, and due date. Paystack generates an invoice and sends it to the customer via email with a payment link. You can track the payment status via the API or wait for the charge.success webhook when the customer pays.

In this article

  1. 1. What Payment Requests Are
  2. 2. Creating a Payment Request
  3. 3. Adding Line Items and Tax
  4. 4. Tracking Payment Status
  5. 5. Managing Payment Requests
  6. 6. Automated Invoicing Workflow
  7. 7. Payment Requests vs Initialize Transaction
  8. 8. Stay Up to Date

What Payment Requests Are

A payment request is an invoice that Paystack creates and sends on your behalf. It includes the amount, a description, your business name, and a payment link. The customer opens the email, clicks "Pay," and completes payment through the standard Paystack checkout.

Payment requests are different from Initialize Transaction in a key way: with Initialize Transaction, you control when the checkout opens. With payment requests, you send an invoice and wait for the customer to act on it. The customer decides when to pay.

This is the natural flow for service businesses, freelancers, agencies, and B2B billing: you do the work, you send an invoice, the client pays when they receive it.

Creating a Payment Request

async function createPaymentRequest(customerEmail, amountInKobo, description) {
  var response = await fetch('https://api.paystack.co/paymentrequest', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      customer: customerEmail,
      amount: amountInKobo,
      description: description,
      due_date: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
      send_notification: true,
    }),
  });

  var data = await response.json();

  if (data.status) {
    return {
      requestCode: data.data.request_code,
      id: data.data.id,
      status: data.data.status,
    };
  }

  throw new Error('Failed to create payment request: ' + data.message);
}

// Usage
var invoice = await createPaymentRequest(
  'client@company.com',
  7500000, // 75,000 NGN
  'Website development - Phase 1 milestone payment'
);
console.log('Invoice created: ' + invoice.requestCode);

Key parameters:

  • customer: The customer's email address or Paystack customer code
  • amount: Amount in the smallest currency unit (kobo for NGN)
  • description: What the invoice is for. This appears in the email and on the payment page.
  • due_date: When the payment is due. Optional but useful for tracking overdue invoices.
  • send_notification: Whether Paystack should email the invoice to the customer. Set to true for automatic delivery.
  • line_items: Optional array of line items with name, amount, and quantity for detailed invoices.
  • tax: Optional array of tax objects to add tax lines to the invoice.

Get weekly developer tips

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

No spam. Unsubscribe anytime.

Adding Line Items and Tax

For detailed invoices, break down the total into line items:

var response = await fetch('https://api.paystack.co/paymentrequest', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    customer: 'client@company.com',
    amount: 8625000, // Total including tax
    description: 'Web Development Services - July 2026',
    line_items: [
      { name: 'Frontend Development', amount: 5000000, quantity: 1 },
      { name: 'API Integration', amount: 2500000, quantity: 1 },
    ],
    tax: [
      { name: 'VAT', amount: 1125000 },
    ],
    due_date: '2026-08-01T00:00:00.000Z',
    send_notification: true,
  }),
});

Line items and tax lines appear on the invoice the customer receives, giving them a clear breakdown of what they are paying for. This is important for B2B invoicing where clients need to match invoices to purchase orders or expense reports.

Tracking Payment Status

// Fetch a specific payment request
async function getPaymentRequest(requestCode) {
  var response = await fetch(
    'https://api.paystack.co/paymentrequest/' + requestCode,
    {
      headers: {
        Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
      },
    }
  );

  var data = await response.json();
  return data.data;
}

// List all payment requests with filters
async function listPaymentRequests(status) {
  var url = 'https://api.paystack.co/paymentrequest';
  if (status) {
    url = url + '?status=' + status;
  }

  var response = await fetch(url, {
    headers: {
      Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
    },
  });

  var data = await response.json();
  return data.data;
}

// Find overdue invoices
async function findOverdueInvoices() {
  var pending = await listPaymentRequests('pending');
  var today = new Date();

  return pending.filter(function(req) {
    return req.due_date && new Date(req.due_date) < today;
  });
}

Payment request statuses:

  • pending: Invoice sent, waiting for payment
  • success: Customer has paid
  • expired: Past the due date without payment (if expiry is enabled)

You can also listen for webhooks related to payment requests. When the customer pays through the invoice link, Paystack sends a charge.success event that you can use to update your records immediately.

Managing Payment Requests

Resend a notification

If the customer did not receive or lost the invoice email, you can resend the notification:

async function resendInvoice(requestCode) {
  var response = await fetch(
    'https://api.paystack.co/paymentrequest/notify/' + requestCode,
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
      },
    }
  );

  var data = await response.json();
  return data;
}

Void a payment request

If the invoice was sent in error or the work was cancelled, void the request to deactivate the payment link:

async function voidPaymentRequest(requestCode) {
  // Archive/void the request
  var response = await fetch(
    'https://api.paystack.co/paymentrequest/archive/' + requestCode,
    {
      method: 'POST',
      headers: {
        Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
      },
    }
  );

  return response.json();
}

Once voided, the payment link no longer works. The customer cannot pay a voided invoice. Make sure to communicate this to the customer if they have already received the email.

Automated Invoicing Workflow

For recurring billing scenarios, you can automate the entire invoice lifecycle:

// Monthly invoicing job
async function generateMonthlyInvoices() {
  var clients = await db.clients.findAll({
    where: { billing_type: 'monthly', status: 'active' },
  });

  for (var i = 0; i < clients.length; i++) {
    var client = clients[i];
    var invoice = await createPaymentRequest(
      client.email,
      client.monthly_amount,
      'Monthly retainer - ' + currentMonthName() + ' ' + currentYear()
    );

    await db.invoices.create({
      client_id: client.id,
      paystack_request_code: invoice.requestCode,
      amount: client.monthly_amount,
      status: 'sent',
      month: currentMonth(),
    });
  }
}

// Overdue follow-up job (runs daily)
async function followUpOverdue() {
  var overdue = await findOverdueInvoices();

  for (var i = 0; i < overdue.length; i++) {
    var invoice = overdue[i];
    var daysPastDue = Math.floor(
      (Date.now() - new Date(invoice.due_date).getTime()) / (24 * 60 * 60 * 1000)
    );

    if (daysPastDue === 1) {
      await resendInvoice(invoice.request_code);
    } else if (daysPastDue === 7) {
      await sendCustomReminder(invoice, 'gentle');
    } else if (daysPastDue === 14) {
      await sendCustomReminder(invoice, 'urgent');
    }
  }
}

Payment Requests vs Initialize Transaction

Both result in the customer paying through Paystack checkout. The difference is who controls the timing:

AspectPayment RequestInitialize Transaction
Who triggersYou send, customer pays laterCustomer clicks pay now
DeliveryEmail with payment linkRedirect or popup on your site
Timing controlCustomer decides whenImmediate
Best forInvoicing, B2B, servicesE-commerce, SaaS checkout
Line itemsSupportedNot built-in (use metadata)
Due datesSupportedNot applicable

Use payment requests when you are billing clients after delivering a service. Use Initialize Transaction when the customer is on your site ready to buy now.

Stay Up to Date

Paystack updates their invoicing features periodically. We keep these guides current when things change.

Sign up for the McTaba newsletter to get notified about new Paystack features and guides.

Key Takeaways

  • ✓Payment requests are Paystack-generated invoices with built-in payment links. The customer receives an email and can pay with one click.
  • ✓Create a payment request by POSTing to /paymentrequest with the customer identifier, amount, description, and optional due date.
  • ✓Payment requests can be one-time or recurring. For recurring invoices, use Paystack subscriptions instead of manually creating repeated requests.
  • ✓You can archive, void, or resend payment requests via the API. Voiding a request makes the payment link inactive.
  • ✓Payment request status progresses from "pending" to "success" when paid, or stays pending if unpaid. Track via API polling or webhooks.
  • ✓Payment requests are ideal for service businesses, freelancers, and B2B billing where you send invoices to clients rather than collecting payment at checkout.

Frequently Asked Questions

Can the customer pay a payment request with any payment channel?
Yes. When the customer clicks the payment link in the invoice email, they are taken to the standard Paystack checkout page where all available payment channels are shown. They can pay by card, bank transfer, USSD, or any other channel enabled on your account.
Can I create a payment request for a customer who is not in my Paystack customer list?
Yes. You can use the customer email address directly. If the customer does not exist in your Paystack records, Paystack creates a customer record automatically.
What happens when a payment request passes its due date?
The payment link typically remains active past the due date unless you have configured it to expire. The due date is primarily informational, helping you track overdue invoices. You can void the request manually if you want to deactivate the link after the due date.
Can I edit a payment request after creating it?
Payment request update capabilities may be limited. If you need to change the amount or details, it is usually easier to void the original request and create a new one with the correct information.
Is there a limit to how many payment requests I can send?
Paystack does not publish a strict limit on payment requests, but excessive creation in a short period may trigger rate limiting. For high-volume invoicing, spread your requests over time and monitor API responses for rate limit errors.

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 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

Every Paystack Webhook Event Explained

A complete reference for every webhook event type Paystack can send to your endpoint. For each event, this guide covers what triggers it, what the payload contains, and what your handler should do with it.

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.