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 Podcast Membership Platform
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

Build a Podcast Membership Platform

Build a podcast membership platform by creating a Paystack Plan for your paid tier, subscribing listeners via the transaction initialize endpoint with the plan code, gating member-only episode access on active subscription status in your database, and listening to subscription.create, invoice.payment_failed, and subscription.disable webhooks to grant or revoke access automatically.

In this article

  1. 1. Plan Setup and Member Access
  2. 2. Subscription Webhooks and Member Lifecycle
  3. 3. Learn More

Plan Setup and Member Access

Tables: membership_plans (name, price, paystack_plan_code, features[]), members (user_id, plan_id, paystack_subscription_code, status, current_period_end), episodes (title, audio_url, is_members_only, published_at).

var PLANS = {
  free:      { tier: 0, label: 'Free — public episodes only' },
  supporter: { tier: 1, price: 100000, label: 'Supporter — all episodes + bonus content' }, // NGN 1,000/mo
};

async function subscribeToPlan(userId, userEmail) {
  var plan = await db.membershipPlans.findByName('supporter');

  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: userEmail,
      amount: plan.price,
      plan: plan.paystack_plan_code,
      metadata: { user_id: userId, plan_id: plan.id },
    }),
  });
  return (await res.json()).data.authorization_url;
}

// Content access gate
async function canAccessEpisode(userId, episodeId) {
  var episode = await db.episodes.findById(episodeId);
  if (!episode.is_members_only) return true;

  var member = await db.members.findActiveByUser(userId);
  return !!(member && member.status === 'active');
}

async function getEpisodeAudio(userId, episodeId) {
  var canAccess = await canAccessEpisode(userId, episodeId);
  if (!canAccess) throw { status: 403, message: 'Subscribe to access this episode.' };
  var episode = await db.episodes.findById(episodeId);
  return episode.audio_url;
}

Subscription Webhooks and Member Lifecycle

if (event.event === 'subscription.create') {
  var meta = event.data.metadata;
  await db.members.upsert({
    user_id: meta.user_id,
    plan_id: meta.plan_id,
    paystack_subscription_code: event.data.subscription_code,
    status: 'active',
    current_period_end: new Date(event.data.next_payment_date),
  });
  await sendWelcomeEmail(meta.user_id);
}

if (event.event === 'invoice.create' && event.data.status === 'success') {
  var code = event.data.subscription.subscription_code;
  await db.members.update({ code }, {
    status: 'active',
    current_period_end: new Date(event.data.next_payment_date),
  });
}

if (event.event === 'invoice.payment_failed') {
  var code = event.data.subscription.subscription_code;
  await db.members.update({ code }, { status: 'grace_period' });
  await sendPaymentFailedEmail(code); // ask them to update payment method
}

if (event.event === 'subscription.disable') {
  var code = event.data.subscription_code;
  // Keep access until current_period_end; cron downgrades after
  await db.members.update({ code }, { status: 'cancelled' });
}

// Cron: revoke access when period ends for cancelled/grace members
async function revokeExpiredAccess() {
  var expired = await db.members.findExpiredBefore(new Date());
  for (var member of expired) {
    await db.members.update(member.id, { status: 'expired' });
    await sendRenewalPromptEmail(member.user_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 streaming service billing backend for the multi-tier version of this membership model applied to video content.

Sign up for the McTaba newsletter

Key Takeaways

  • ✓Use Paystack Plans for recurring billing — one plan per membership tier.
  • ✓Gate member-only episode audio URLs on active subscription status in your database.
  • ✓Handle invoice.payment_failed with a grace period before revoking access.
  • ✓Send a welcome email on subscription.create and a renewal reminder before the next billing date.
  • ✓A free tier with public episodes is your discovery funnel — do not put everything behind the paywall.

Frequently Asked Questions

Should I offer a free tier alongside the paid membership?
Yes. A free tier with your back catalogue and occasional public episodes is how new listeners discover you. The paid tier unlocks new episodes early, bonus content, ad-free listening, or a private community. The free tier is a funnel, not a charity — every free listener is a potential paying member.
How do I handle a listener who subscribes and immediately asks for a refund?
Define a 48-hour cooling-off period with full refund via the Paystack Refund API. After 48 hours, no refunds — the subscription grants immediate content access so there is no unused period to refund. State this clearly on the subscription page before checkout.
Can I sell lifetime memberships instead of monthly subscriptions?
Yes. Use a one-time Paystack charge (not a Plan) for a lifetime membership. On charge.success, set the member status to "lifetime" with a far-future current_period_end (e.g., year 2099). Lifetime memberships are harder to predict for revenue but generate a cash injection and a committed core audience.

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

Kenya Digital Service Tax and Online Payment Products

A developer-focused guide to Kenya's Digital Service Tax and how it affects products that accept online payments. Covers what DST is, who pays it, registration requirements, reporting obligations, and how it interacts with payment gateway fees on platforms like Paystack.

Read more

Escrow-Style Flows on Paystack and Their Limits

A thorough analysis of what escrow-style flows you can and cannot build on Paystack. Covers the difference between true escrow and delayed settlement, how to use manual settlement for hold-and-release patterns, the limits around hold duration and fund recovery, regulatory considerations in African markets, and when Paystack is not the right tool for escrow.

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.