Software Engineer
Nairobi, Kenya (GMT+3)
Open to new roles · remote, across time zones
01About Me
The first time the internet did anything for me, it wasn't even mine. It was my elder brother's Nokia flip phone, and I had to ask for it.
Class six. I'd punch a song title into Tubidy and wait while that little phone reached across some invisible network and dragged the whole thing back — a track, a Java game, mine now, living in a handset that fit in my palm. Felt like magic. But it cost money. Every download was airtime my brother was counting, megabytes you could feel draining, a small negotiation each time over a thing that was never free and never would be. That's the part that lodged in me before I had words for it: the internet never floated free above the world for me. It showed up already attached to shillings.
By high school I had my own laptop, and the whole relationship flipped. I'd spent years taking things off the internet — music, games, cracked copies of everything. Now I wanted to know how the box worked. Formatted it more times than it deserved, broke it, fixed it, fixed other people's when theirs died. Somewhere in there I stopped being someone the machine performed for and became someone who could make it perform.
What I actually fell for, looking back, was the reaching across — the thing where a phone in your hand asks a question and something far away answers. So I went and studied exactly that. Networks. A CCNA. A telecoms degree. The pipes, the protocols, how the question travels and the answer comes home.
Then it clicked that the most important reaching-across in this whole country wasn't carrying songs anymore. It was carrying money. M-Pesa — a boda guy refreshing his balance twenty times a shift, school fees crossing a network in seconds, a mama mboga's entire day of float riding inside one STK push. Same magic as the Nokia. Except now, there's actual stakes on the line.
I couldn't leave that alone. So I went to live in that layer.
That's me. I build the rails money moves on — the M-Pesa libraries, the eTIMS middleware, the unglamorous plumbing nobody thanks you for until the day it saves them. I measure the things everyone else just assumes are fine. And when I'm not in the code I'm writing — usually about money, or about the distance between the story everyone repeats and the one that's actually true. Which, it turns out, is the same itch I've had since the borrowed Nokia: don't take the magic at face value. Go find out how it really works. Then say so.
02Selected Work
Full-stack short-stay rental platform — Paystack payments, AI guest chat, OTA sync for Airbnb and Booking.com, and a yield engine that auto-prices gaps. Live.
Full-stack short-stay rental platform built for a Nairobi property host — real bookings, Paystack payments (M-Pesa + card), a yield engine that auto-prices vacancy gaps, AI-powered guest chat with WhatsApp integration, and an OTA sync pipeline for Airbnb, Booking.com, and VRBO. Admin dashboard with revenue tracking and guest CRM. PWA with offline support and push notifications. Built on Next.js + FastAPI, deployed on Vercel and Railway. Live and in use.
Telegram bot for Nairobi commuters — tells you when to leave based on live traffic vs. your personal commute history.
Nairobi traffic isn't bad every day — it's bad on specific routes, at specific hours,
in ways Google Maps won't tell you because it doesn't know your commute.
Wayward is a Telegram bot that tells you whether to leave now or wait, based on
live traffic compared against your own historical baseline for that
route, day, and hour. It learns from every trip. Below three data points it stays
quiet. Once it has enough signal, it alerts you the moment congestion actually drops —
not just when it's theoretically clear. The depart command checks current
conditions, forecasts two hours ahead, and sets a watch automatically.
scenic scores alternate routes against Overpass data if you'd rather take
the long way. NLP handled by Gemini so you can just type where you're going.
Python SDK for KRA's eTIMS API — OAuth, VAT arithmetic across five tax bands, idempotency for in-flight failures, and full async support.
KRA's eTIMS API has no official Python SDK. Every developer integrating it rebuilds the same things: OAuth token refresh, VAT arithmetic across five tax bands, idempotency for in-flight network failures — the Schrödinger's Invoice problem where a timeout mid-POST leaves the invoice state unknown. This SDK handles all of that, plus async support with full API parity and a supplier onboarding gateway for informal sector compliance under Finance Act 2023 §16(1)(c). The tax calculator works offline with no credentials. It's the SDK that powers TaxID, the compliance layer I build for the informal economy.
Flutter package managing the full M-Pesa STK Push lifecycle — from initiation through killed-app recovery, without a proxy server.
Daraja handles STK Push initiation. It doesn't handle what happens when the user locks their phone mid-payment, switches apps, or closes yours entirely before the callback arrives. This Flutter package manages the full payment lifecycle: direct Safaricom API calls without a proxy server, WebSocket delivery of payment status via Appwrite Realtime, automatic state recovery when the app returns from background, and killed-app recovery on next launch via SharedPreferences. Accepts any Kenyan number format — 0712345678, +254712345678, or raw 9-digit — with automatic normalization.
Searchable reference for every Daraja API error code — causes and fixes the official documentation doesn't provide.
Safaricom's Daraja documentation doesn't document its own error codes comprehensively. Developers hit cryptic failures and have nowhere to look. A searchable reference for every error the Daraja API returns — causes, fixes, and context the official docs don't provide. Includes an llms.txt so AI tools can read it correctly. Community-contributed: open a PR to add an error code you've hit.
TypeScript library for idempotent M-Pesa STK Push — atomic callback deduplication, polling fallback, and a webhook relay that survives server restarts.
An npm package. Daraja gives you STK Push initiation. It doesn't handle what happens when the callback never arrives, when Safaricom sends the same callback three times under load, when a client retries and gets double-charged, or when your database says SUCCESS and Safaricom has no record of it. This TypeScript library handles all of that: idempotent initiation, atomic callback deduplication, polling fallback, and a reconciliation pass for payments that fall through every other safety net. v0.2.0 adds a webhook relay server — point your Safaricom CallbackURL at the relay and it guarantees delivery to your app with exponential-backoff retries, even if your server restarts mid-payment window.
03Writing
04Now
Building TaxID — compliance infrastructure for Kenya's informal economy, live and bootstrapped in the open. Thinking about what it means to build software for systems that were never designed to be programmed against.
Most of the interesting engineering problems in East Africa aren't algorithmic. They're about trust, reliability, and what happens when the network drops.
Based in Nairobi, Kenya (GMT +3). ronnyabuto@gmail.com.