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. Build a Job Board with Paid Listings
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

Build a Job Board with Paid Listings

Build a paid job board by creating listings in "draft" state, initializing a Paystack payment for the listing fee, and publishing the listing only when the charge.success webhook fires. Support listing tiers (standard, featured, urgent) and optional employer subscription bundles for frequent posters.

In this article

  1. 1. Listing Tiers and Payment Flow
  2. 2. Employer Subscription Bundles and Listing Expiry
  3. 3. Learn More

Listing Tiers and Payment Flow

Tables: employers (name, email, company, subscription_credits), listings (employer_id, title, description, location, type, salary, tier, status, paystack_ref, published_at, expires_at), listing_tiers (name, price, duration_days, features).

var LISTING_TIERS = {
  standard: { price: 1500000, duration: 30, label: 'Standard 30-day listing' }, // NGN 15,000
  featured:  { price: 3000000, duration: 30, label: 'Featured listing — top placement' }, // NGN 30,000
  urgent:    { price: 2000000, duration: 14, label: 'Urgent — highlighted for 14 days' }, // NGN 20,000
};

async function createListing(employerEmail, employerId, listingData, tier) {
  var tierConfig = LISTING_TIERS[tier];
  if (!tierConfig) throw new Error('Invalid listing tier');

  // Check if employer has subscription credits
  var employer = await db.employers.findById(employerId);
  if (employer.subscription_credits > 0) {
    await db.employers.decrement(employerId, 'subscription_credits', 1);
    return await publishListing(employerId, listingData, tier, null); // no payment needed
  }

  // Create listing in draft
  var reference = 'LISTING-' + Date.now();
  var listing = await db.listings.create({
    employer_id: employerId, ...listingData,
    tier, status: 'draft', paystack_ref: reference,
  });

  // Initialize payment
  var res = 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: employerEmail, amount: tierConfig.price, currency: 'NGN', reference,
      metadata: { listing_id: listing.id, tier, duration_days: tierConfig.duration },
      label: tierConfig.label,
    }),
  });
  return { listing, authorizationUrl: (await res.json()).data.authorization_url };
}

// Webhook: publish listing on payment
if (event.event === 'charge.success') {
  var meta = event.data.metadata;
  var publishedAt = new Date();
  var expiresAt = new Date();
  expiresAt.setDate(expiresAt.getDate() + meta.duration_days);

  await db.listings.update(meta.listing_id, { status: 'published', published_at: publishedAt, expires_at: expiresAt });
  await scheduleExpiryReminder(meta.listing_id, expiresAt);
}

Employer Subscription Bundles and Listing Expiry

// Employer buys a posting bundle — e.g., 5 posts for the price of 4
async function purchasePostingBundle(employerEmail, employerId, bundleSize) {
  var BUNDLES = { 5: 6000000, 10: 10000000 }; // NGN 60k for 5, NGN 100k for 10
  var price = BUNDLES[bundleSize];
  if (!price) throw new Error('Invalid bundle size');

  var reference = 'BUNDLE-' + Date.now();
  var res = 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: employerEmail, amount: price, currency: 'NGN', reference,
      metadata: { employer_id: employerId, bundle_credits: bundleSize, purpose: 'bundle_purchase' },
    }),
  });
  return (await res.json()).data.authorization_url;
}

// Webhook: credit bundle
if (event.event === 'charge.success' && event.data.metadata.purpose === 'bundle_purchase') {
  await db.employers.increment(event.data.metadata.employer_id, 'subscription_credits', event.data.metadata.bundle_credits);
}

// Cron: expire listings and send renewal reminders
async function processExpiredListings() {
  var today = new Date();
  await db.listings.updateWhere({ status: 'published', expires_at_lt: today }, { status: 'expired' });

  var expiringSoon = await db.listings.findExpiringSoon(addDays(today, 5));
  for (var listing of expiringSoon) {
    await sendRenewalReminder(listing.employer_id, listing.id);
  }
}

Get weekly developer tips

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

No spam. Unsubscribe anytime.

Learn More

See build a classifieds site with featured listing payments for the same paid listing model applied to a broader classifieds platform.

Sign up for the McTaba newsletter

Key Takeaways

  • ✓Create listings in draft state; publish only after the Paystack webhook confirms payment.
  • ✓Support multiple listing tiers: standard (30 days), featured (top placement), urgent (highlighted).
  • ✓Auto-expire listings after their duration and send renewal reminders 5 days before expiry.
  • ✓Employer subscription bundles (NGN 50,000/month for 5 postings) reduce per-post friction for heavy users.
  • ✓Track which listings converted (received applications) to improve pricing and feature value.

Frequently Asked Questions

Should job seekers pay or only employers?
Employer-pays is the dominant model for job boards (LinkedIn, Jobberman, Careers24). Free for job seekers maximizes the candidate pool, which is the core value you sell to employers. Premium job seeker features (CV builder, application boosting, skills assessments) can generate additional revenue, but the core board should be free for candidates.
How do I handle listings from employers who request a refund after publishing?
Define a no-refund policy for published listings (the listing has already received visibility). Refunds are reasonable for listings that were never published due to a technical issue. If you unpublish a listing at the employer's request before it expires, offer a credit for future listings rather than a cash refund — this retains the revenue while giving the employer flexibility.
How do I prevent duplicate or fraudulent job listings?
Require employer email verification before allowing listing creation. Moderate new employers' first listing before publishing (auto-publish after the first listing is approved). Flag listings with vague descriptions, requests for personal financial information, or suspicious salary ranges. A simple admin review queue catches most fraud before it goes live.

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

Things You Can Build with Paystack: Project Guides

A complete map of real-world projects you can build using the Paystack API. From online store checkouts and subscription platforms to savings apps and solar pay-as-you-go systems, each category links to step-by-step build guides with working code.

Read more

Build a Parking Payment App

A build guide for a parking payment app where drivers scan a QR code on entry, pay for their session via Paystack (card or M-Pesa), and the system validates payment before the barrier lifts for exit. Covers time-based pricing, session management, and overstay handling.

Read more

Build a Referral Payout System

A build guide for a referral payout system where users share referral links, earn commissions when referrals convert, and withdraw their balance via Paystack Transfers to their bank account or M-Pesa wallet.

Read more

Build a Farmers Market Ordering Platform

A build guide for a farmers market ordering platform where customers order fresh produce from multiple farmers in one cart, the platform collects the combined payment via Paystack, and each farmer receives their share via Paystack Split Payments or Transfers. Covers inventory management, order routing to individual farmers, and delivery coordination.

Read more

WhatsApp Commerce Plus Paystack Payment Links

A practical guide to selling on WhatsApp using Paystack payment links in Kenya. Covers creating payment links via the API, sharing them in conversations, tracking completed payments, integrating with WhatsApp Business catalogs, and automating link generation for orders.

Read more

Building a Two-Sided Marketplace on Paystack

An end-to-end architecture guide for building a two-sided marketplace on Paystack. Covers seller onboarding with subaccount creation, initializing split transactions at checkout, handling webhooks to confirm splits, managing refunds on split transactions, database schema design, and the operational edge cases that trip up most marketplace builders.

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.