This guide shows you how to implement subscription billing using Simiz recurring payments.
Scenario: SaaS monthly subscription
You’re building a SaaS product and want to charge customers 10,000 XAF/month via Mobile Money.
Step 1: Create the subscription
curl -X POST /api/v1/projects/{projectId}/recurring \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 10000,
"currency": "XAF",
"interval": "MONTHLY",
"intervalCount": 1,
"paymentMethod": "ORANGE_MONEY",
"payerPhone": "237690000001",
"payerName": "Jane Doe",
"startDate": "2026-04-01T00:00:00Z",
"description": "Pro Plan - Monthly",
"metadata": {
"plan": "pro",
"customerId": "cust_456"
}
}'
Step 2: Handle webhook events
Set up webhook listeners for recurring payment events:
app.post('/webhooks/simiz', (req, res) => {
const event = req.body;
switch (event.type) {
case 'recurring.executed':
// Payment successful — extend subscription
extendSubscription(event.data.metadata.customerId);
break;
case 'recurring.failed':
// Payment failed — notify customer
notifyCustomer(event.data.metadata.customerId, {
reason: event.data.failureReason,
});
break;
case 'recurring.paused':
// Auto-paused after too many failures
notifyCustomer(event.data.metadata.customerId, {
message: 'Subscription paused due to payment failures',
});
break;
case 'recurring.cancelled':
// Subscription cancelled — downgrade access
downgradeAccess(event.data.metadata.customerId);
break;
}
res.sendStatus(200);
});
Step 3: Handle payment failures
When a customer’s Mobile Money balance is insufficient:
- Receive
recurring.failed webhook
- Send the customer a notification (SMS, email, or in-app)
- Optionally pause the subscription:
curl -X POST /api/v1/projects/{projectId}/recurring/{recurringId}/pause \
-H "Authorization: Bearer sk_live_xxx"
- When the customer tops up, resume:
curl -X POST /api/v1/projects/{projectId}/recurring/{recurringId}/resume \
-H "Authorization: Bearer sk_live_xxx"
Common patterns
Grace period
Give customers a few days after a failed payment before revoking access:
case 'recurring.failed':
const GRACE_DAYS = 3;
setGracePeriod(customerId, GRACE_DAYS);
notifyCustomer(customerId, `Payment failed. You have ${GRACE_DAYS} days to top up.`);
break;
Plan upgrades
To upgrade a customer from a 10,000 XAF plan to 25,000 XAF:
- Cancel the current recurring payment
- Create a new one with the higher amount
- Update your internal records
Store the recurring payment id in your database alongside the customer record so you can easily manage upgrades and cancellations.
Installment plans
For selling high-value items in installments (e.g., a 120,000 XAF laptop in 12 payments):
curl -X POST /api/v1/projects/{projectId}/recurring \
-H "Authorization: Bearer sk_live_xxx" \
-d '{
"amount": 10000,
"currency": "XAF",
"interval": "MONTHLY",
"paymentMethod": "MTN_MOMO",
"payerPhone": "237670000001",
"payerName": "Paul K.",
"startDate": "2026-04-01T00:00:00Z",
"description": "Laptop installment 1/12",
"maxCycles": 12
}'
The recurring payment will automatically stop after 12 cycles.