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 Car Hire Booking System with Preauthorization
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

Build a Car Hire Booking System with Preauthorization

Build a car hire booking system using Paystack's two-step charge: first, authorize a card to hold the damage deposit (the customer sees a pending amount but is not yet charged); on return, capture the exact amount due. Use the Paystack Charge endpoint with authorization_code for returning customers, or a one-time card authorization flow for new customers.

In this article

  1. 1. Card Authorization and Deposit Hold
  2. 2. Return Processing and Damage Charges
  3. 3. Learn More

Card Authorization and Deposit Hold

Tables: vehicles (make, model, plate, daily_rate, deposit_amount, status), rentals (vehicle_id, customer_id, pickup_date, return_date, rental_fee, deposit_held, actual_charge, status, paystack_ref, authorization_code).

Paystack card tokenization: when the customer completes their first payment, Paystack returns an authorization.authorization_code in the charge.success webhook. Save this code — it lets you charge the same card again without the customer re-entering their details.

// Step 1: Initial booking — collect rental fee + authorize deposit
async function initiateBooking(customerId, customerEmail, vehicleId, pickupDate, returnDate) {
  var vehicle = await db.vehicles.findById(vehicleId);
  var days = Math.ceil((new Date(returnDate) - new Date(pickupDate)) / 86400000);
  var rentalFee = vehicle.daily_rate * days;

  // Charge rental fee now, note the authorization for deposit later
  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: rentalFee,
      currency: 'NGN',
      metadata: { customer_id: customerId, vehicle_id: vehicleId, pickup_date: pickupDate, return_date: returnDate, purpose: 'rental_fee' },
    }),
  });
  return (await res.json()).data.authorization_url;
}

// Webhook: save authorization_code for future charges
if (event.event === 'charge.success' && event.data.metadata.purpose === 'rental_fee') {
  var authCode = event.data.authorization.authorization_code;
  var meta = event.data.metadata;

  await db.rentals.create({
    customer_id: meta.customer_id, vehicle_id: meta.vehicle_id,
    pickup_date: meta.pickup_date, return_date: meta.return_date,
    rental_fee: event.data.amount, status: 'confirmed',
    authorization_code: authCode, // save this
  });
}

Return Processing and Damage Charges

// On vehicle return — charge damage deposit or excess fees using saved auth code
async function processReturn(rentalId, damageAssessment) {
  var rental = await db.rentals.findById(rentalId);
  var depositAmount = rental.deposit_amount;

  if (damageAssessment.total > 0) {
    // Charge damage using saved authorization code (no card re-entry needed)
    var chargeAmount = Math.min(damageAssessment.total, depositAmount);

    var res = await fetch('https://api.paystack.co/charge/authorization', {
      method: 'POST',
      headers: { Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY, 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email: rental.customer_email,
        amount: chargeAmount,
        authorization_code: rental.authorization_code,
        metadata: { rental_id: rentalId, purpose: 'damage_charge', description: damageAssessment.notes },
      }),
    });

    var data = await res.json();
    await db.rentals.update(rentalId, {
      status: 'returned_with_damage',
      damage_charge: chargeAmount,
      paystack_damage_ref: data.data.reference,
    });
  } else {
    // No damage — just close the rental
    await db.rentals.update(rentalId, { status: 'returned_clean' });
  }

  await db.vehicles.update(rental.vehicle_id, { status: 'available' });
}

The charge/authorization endpoint charges the card without the customer needing to re-enter their details. This is what makes car hire feasible on Paystack — you charge the rental up front and charge damages on return without a second checkout flow.

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 hotel booking and deposit system for the deposit-and-balance pattern in accommodation bookings.

Sign up for the McTaba newsletter

Key Takeaways

  • ✓Use Paystack charge authorization to hold a damage deposit without actually charging the card until return.
  • ✓Tokenize the customer's card on the first transaction to enable follow-up charges for damages.
  • ✓Collect rental fees at pickup and damage/excess fees on return using the saved authorization_code.
  • ✓Store the authorization_code securely — it is a reusable token tied to the customer's card.
  • ✓Handle no-shows by capturing the deposit; handle early returns by calculating the actual rental period.

Frequently Asked Questions

Does Paystack support pre-authorization holds (block funds without charging)?
Paystack does not natively support pre-authorization holds (where funds are reserved but not yet captured) the way Stripe does with payment_intent. The practical pattern for car hire on Paystack is to charge the rental fee up front and use the saved authorization_code to charge damages on return. Communicate clearly to customers that the deposit will only be charged if damages are found.
What if the customer's card is declined when charging for damages?
A declined damage charge is a business risk. Have a policy: if the charge fails, contact the customer for an alternative payment method. Maintain a record of the damage assessment and the failed charge. If the customer refuses to pay, this becomes a collections or small claims matter. Your terms and conditions should make this liability explicit at booking time.
Can I verify vehicle damage with photos?
Yes. Build a vehicle condition checklist that the staff completes at pickup and return, with photo uploads at each stage. Store photos in cloud storage and link them to the rental record. These photos are your evidence in case of a damage charge dispute. A timestamped photo of the vehicle before and after rental resolves most disputes quickly.

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 a Chama Contribution Tracker with Payments

A complete build guide for a chama (investment group) contribution tracker with integrated M-Pesa payments through Paystack. Covers member registration, monthly contribution collection, tracking who has paid, automatic reminders, merry-go-round payout rotation, treasury balance management, and financial reporting.

Read more

Building a Freelance Marketplace on Paystack

A freelance marketplace holds client funds until the work is approved, then releases to the freelancer. This guide covers implementing that hold-and-release pattern using Paystack delayed settlement, collecting platform commission via splits, and handling disputes and refunds.

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.