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”graph TD A[Customer Enrolls in Plan] --> B[1. Pre-Dunning Notice<br/>SMS / Webhook 24h prior] B --> C[2. Renewal Date: STK Push Dispatched<br/>Prompt appears on customer phone]
C -->|Customer Authorizes PIN| D[✅ Cycle Renewed<br/>next_billing_at = +30d] C -->|Fail: Offline / Low Balance| E[⚠️ Smart Dunning Retry Engine]
E --> F[Retry 1: +12h Evening Prompt] F -->|Success| D F -->|Fail| G[Retry 2: +24h Morning Prompt] G -->|Success| D G -->|Fail| H[Retry 3: Payday Window] H -->|Success| D H -->|Exhausted > 3 Retries| I[🛑 Transition to 'past_due'<br/>Trigger subscription.past_due webhook]
style A fill:#047857,stroke:#10b981,color:#fff style D fill:#047857,stroke:#10b981,color:#fff style E fill:#d97706,stroke:#f59e0b,color:#fff style I fill:#b91c1c,stroke:#ef4444,color:#fff🔁 Dunning Sequence & Timeline
Section titled “🔁 Dunning Sequence & Timeline”sequenceDiagram autonumber actor Customer participant App as Merchant Backend participant Zirzir as Zirzir Rust Engine participant Telco as Mobile Money (Telebirr/M-Pesa)
Note over Customer,Zirzir: Day 0: Initial Subscription Customer->>App: Click 'Subscribe to Pro' (500 ETB/mo) App->>Zirzir: POST /api/v1/subscriptions Zirzir->>Telco: STK Push (500 ETB) Telco->>Customer: Phone PIN Prompt Customer->>Telco: Confirms with PIN Telco-->>Zirzir: Webhook (Status: Completed) Zirzir-->>App: Event 'subscription.created'
Note over Customer,Zirzir: Day 30: Automated Renewal & Smart Dunning Zirzir->>Zirzir: Background Worker detects due cycle Zirzir->>Telco: Dispatch Renewal STK Push Telco-->>Zirzir: Failed (Insufficient Balance) Zirzir->>Zirzir: Schedule Retry 1 in 12h Note over Customer,Zirzir: Day 31: Retry 1 Zirzir->>Telco: Re-dispatch STK Push Customer->>Telco: Confirms with PIN Telco-->>Zirzir: Webhook (Status: Completed) Zirzir->>Zirzir: Advance cycle to Day 60 Zirzir-->>App: Event 'subscription.renewed'🛠️ 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), and schedulesnext_billing_at.
⚡ 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. - Triggers webhook events (
subscription.renewed,subscription.past_due).