Recurring Subscriptions & Smart Dunning
In Africa, credit card penetration is under 5%. Traditional subscriptions relying on silent card autopay tokenization fail because 90%+ of African payments run on mobile money wallets (Telebirr, CBE Birr, Safaricom M-Pesa).
Zirzir provides a purpose-built Smart Dunning & Recurring Billing Engine engineered specifically for mobile money prompt flows.
🔄 Mobile Money Dunning Architecture
Section titled “🔄 Mobile Money Dunning Architecture”🛠️ Step 1: Create a Billing Plan
Section titled “🛠️ Step 1: Create a Billing Plan”Create recurring plans via CLI, Dashboard, or REST API:
zirzir sub plan create --name "Pro Monthly" --amount 500.0 --currency ETB --interval monthTypeScript SDK
Section titled “TypeScript SDK”import { Zirzir } from '@zirzir/sdk';
const zirzir = new Zirzir({ baseUrl: 'http://localhost:8080', apiKey: process.env.ZIRZIR_API_KEY!,});
// Create recurring planconst response = await fetch('http://localhost:8080/api/v1/plans', { method: 'POST', headers: { 'X-API-Key': process.env.ZIRZIR_API_KEY!, 'Content-Type': 'application/json', }, body: JSON.stringify({ name: 'Pro Tier Monthly', amount: 500.0, currency: 'ETB', interval: 'month', interval_count: 1, }),});📱 Step 2: Enroll a Subscriber
Section titled “📱 Step 2: Enroll a Subscriber”When a user signs up on your website:
curl -X POST http://localhost:8080/api/v1/subscriptions \ -H "X-API-Key: zz_test_..." \ -H "Content-Type: application/json" \ -d '{ "plan_id": "plan_9f81a2b", "provider": "telebirr", "customer_phone": "0911223344" }'- Immediate Action: Dispatches an initial mobile money STK push prompt to the customer’s phone.
- Ledger State: Sets
current_period_start, computescurrent_period_end(+30 days), schedulesnext_billing_at, and records anopeninvoice for the first charge.
⚡ Step 3: Automated Background Dunning
Section titled “⚡ Step 3: Automated Background Dunning”The Zirzir server runs a built-in background dunning cron worker:
- Automatically detects when
next_billing_at <= NOW(). - Dispatches recurring STK prompts to user wallets.
- Increments
retry_countand reschedules failed charges with intelligent backoff windows. - Each charge creates an invoice with status
open. The invoice becomespaidwhen its payment completes (orfailedif it fails), and the billing period advances only on successful settlement. - Your backend receives the standard
payment.completed/payment.failed/payment.cancelledevents for these charges (see Webhooks). There are no separatesubscription.*events.
Telebirr and CBE Birr payments are not settled automatically (no status API). Subscriptions on those rails stay
openuntil the payment is reconciled in the dashboard.