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 Subscription Box Business Backend
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

Build a Subscription Box Business Backend

Build a subscription box backend using Paystack Plans for monthly billing. Subscribers sign up via the transaction initialize endpoint with a plan attached. Your backend receives subscription events, manages box assignments for each cycle, handles skips and pauses, and triggers shipping when a cycle payment succeeds.

In this article

  1. 1. Plans and Subscriber Sign-Up
  2. 2. Billing Cycles and Box Shipping
  3. 3. Learn More

Plans and Subscriber Sign-Up

Tables: plans (name, description, price, paystack_plan_code), subscribers (name, email, phone, address, plan_id, paystack_subscription_code, status, joined_at), box_cycles (month, year, cutoff_date), shipments (subscriber_id, cycle_id, box_contents, shipping_address, status, tracking_number).

// Create plans once (run during setup)
async function createSubscriptionPlan(name, priceInKobo, description) {
  var res = await fetch('https://api.paystack.co/plan', {
    method: 'POST',
    headers: { Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({ name, amount: priceInKobo, interval: 'monthly', currency: 'NGN', description }),
  });
  return (await res.json()).data.plan_code;
}

// Subscriber sign-up
async function subscribeCustomer(customerEmail, planId) {
  var plan = await db.plans.findById(planId);
  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: customerEmail, amount: plan.price,
      plan: plan.paystack_plan_code,
      metadata: { plan_id: planId, purpose: 'subscription_signup' },
    }),
  });
  return (await res.json()).data.authorization_url;
}

// Webhook: subscription created
if (event.event === 'subscription.create') {
  var meta = event.data.metadata;
  await db.subscribers.update({ email: event.data.customer.email }, {
    paystack_subscription_code: event.data.subscription_code,
    status: 'active',
  });
}

Billing Cycles and Box Shipping

// Each month's renewal triggers box preparation
if (event.event === 'invoice.create' && event.data.status === 'success') {
  var subscriptionCode = event.data.subscription.subscription_code;
  var subscriber = await db.subscribers.findByCode(subscriptionCode);
  var currentCycle = await db.boxCycles.findCurrentMonth();

  // Only prepare box if subscriber joined before cutoff
  if (subscriber.joined_at <= currentCycle.cutoff_date) {
    await db.shipments.create({
      subscriber_id: subscriber.id,
      cycle_id: currentCycle.id,
      shipping_address: subscriber.address,
      status: 'preparing',
    });
    await notifyWarehouse(subscriber.id, currentCycle.id);
  }
}

// Handle failed payment — grace period
if (event.event === 'invoice.payment_failed') {
  var code = event.data.subscription.subscription_code;
  await db.subscribers.update({ subscription_code: code }, { status: 'payment_failed' });
  await sendRetryPaymentEmail(code); // remind to update payment method
}

// Skip a month — subscriber requests via your website
async function skipMonth(subscriberId, skipReason) {
  var subscriber = await db.subscribers.findById(subscriberId);
  // Disable next renewal
  await fetch('https://api.paystack.co/subscription/disable', {
    method: 'POST',
    headers: { Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({ code: subscriber.paystack_subscription_code, token: subscriber.email_token }),
  });
  await db.subscribers.update(subscriberId, { next_action: 'skip', skip_reason: skipReason });
}

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 water delivery subscription service for a recurring delivery model with similar billing architecture.

Sign up for the McTaba newsletter

Key Takeaways

  • ✓Use Paystack Plans for recurring monthly billing — one plan per box tier.
  • ✓Each successful billing cycle (invoice.success) triggers box preparation and shipping.
  • ✓Allow subscribers to skip a month: disable renewal for that cycle via Paystack API.
  • ✓Handle invoice.payment_failed with a grace period before suspending the subscription.
  • ✓Cutoff dates matter: decide by which day of the month subscriptions need to activate to receive that month's box.

Frequently Asked Questions

What is the cutoff date and why does it matter?
The cutoff date is the last day a customer can subscribe and still receive that month's box. If you ship on the 15th of each month, your cutoff might be the 5th. Subscribers who join after the 5th get their first box next month. Communicate this clearly during signup so customers know when to expect their first delivery.
How do I manage box contents for each subscriber?
Create a box curation system for each monthly cycle. You define the box contents (products, quantities) in a cycle plan. When a shipment is created for a subscriber, it inherits the current cycle's box contents. Customization options (dietary preferences, size preferences) can filter or swap items from the base box.
How do I let subscribers cancel their subscription?
POST to the Paystack disable/cancel subscription endpoint with the subscriber's subscription code. Update your subscriber record to status "cancelled". Give the subscriber until the end of the current billing period before access/shipping stops — they have paid for the current month, do not cut them off mid-cycle.

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 an Affiliate Commission Engine

A build guide for an affiliate commission engine where affiliates share tracking links, earn commissions when their referrals convert (pay via Paystack), and withdraw their balance via bank transfer. Covers click tracking, last-click attribution, commission ledger, and Paystack Transfers payout.

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

Building an Agrovet or Farm Input Payment System

A practical guide to building a payment system for Kenyan agrovets and farm input suppliers. Covers M-Pesa-first design for rural users, product catalogs, farmer registration, credit and loan integration, group purchasing, SMS confirmations, delivery tracking, seasonal ordering, and supplier payouts via Paystack Transfers.

Read more

Splitting Payments for SACCOs and Chamas

SACCOs and chamas collect contributions from members and pool them for loans, welfare, and investments. This guide covers using Paystack to collect member contributions, split across welfare and savings subaccounts, and execute bulk dividend payouts to members.

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.