With postpaid billing (the default), Monigo generates an invoice at period-end and then collects payment via your connected payment provider. With prepaid billing, the customer maintains a wallet balance and Monigo debits that wallet atomically when the invoice is generated — no separate payment step required.
Prepaid works best when:
- Customers pre-purchase credits (SaaS with top-up model, APIs with token packs)
- You need deterministic settlement at billing time with no failed-payment recovery loops
- Your customers are API-first businesses that want to fund accounts rather than maintain card-on-file
Prepaid billing is only available on collection plans. Payout plans always use postpaid flow.
How it works
Period ends
│
▼
Usage aggregated + pricing applied
│
├── Wallet balance ≥ total?
│ │
│ ▼ YES
│ Wallet debited atomically
│ Invoice created as "paid" (no draft, no separate finalize step)
│ Period advances
│ invoice.paid webhook fired
│
└── Wallet balance < total?
│
▼ NO
Draft invoice created (audit trail)
Subscription status → "paused"
subscription.prepaid_balance_insufficient webhook fired
Period does NOT advance
(customer must top up to resume)
When the customer tops up their wallet with enough funds, Monigo automatically retries billing and resumes the subscription — no manual intervention needed.
Setting up a prepaid plan
Add "billing_mode": "prepaid" when creating a collection plan:
curl -X POST https://api.monigo.co/v1/plans \
-H "Authorization: Bearer mk_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "API Starter",
"currency": "NGN",
"plan_type": "collection",
"billing_period": "monthly",
"billing_mode": "prepaid"
}'
The billing_mode field on a plan defaults to "postpaid" and is immutable once the plan has active subscribers.
Wallet auto-creation
When a customer subscribes to a prepaid plan, Monigo automatically creates a wallet in the plan’s currency if one does not already exist. No explicit wallet-creation step is needed.
You can fetch or top-up a customer’s wallet at any time:
# List wallets for a customer
curl https://api.monigo.co/v1/customers/{customer_id}/wallets \
-H "Authorization: Bearer mk_live_..."
# Credit a wallet
curl -X POST https://api.monigo.co/v1/wallets/{wallet_id}/credit \
-H "Authorization: Bearer mk_live_..." \
-H "Content-Type: application/json" \
-d '{
"amount": "10000.00",
"description": "Top-up via payment link",
"idempotency_key": "topup_<your_reference>"
}'
Always provide an idempotency_key when crediting wallets. This prevents double-credits if the request is retried.
The happy path: billing with sufficient balance
When billing runs and the wallet has enough funds, Monigo:
- Aggregates usage for the period
- Calculates the invoice total using the plan’s prices
- Debits the wallet atomically (debit is recorded in the ledger)
- Creates the invoice directly with
status: "paid" — no draft or finalize step
- Advances the subscription to the next period
- Fires an
invoice.paid webhook
The resulting invoice will have:
| Field | Value |
|---|
status | "paid" |
paid_at | Timestamp of the debit |
wallet_debit | true |
No charge is submitted to your payment provider for prepaid invoices — settlement is entirely wallet-based.
Handling insufficient balance
If the wallet balance is lower than the invoice total when billing runs:
- A draft invoice is created as an audit record (period is not advanced)
- The subscription status moves to
"paused"
- A
subscription.prepaid_balance_insufficient webhook is fired
{
"event": "subscription.prepaid_balance_insufficient",
"data": {
"subscription_id": "sub_...",
"customer_id": "cus_...",
"plan_id": "pla_...",
"wallet_balance": "450.00",
"invoice_total": "1200.00",
"currency": "NGN"
}
}
Use this webhook to notify the customer (email, WhatsApp, in-app banner) that their balance is low and prompt them to top up.
The billing job for a paused prepaid subscription is non-retryable. The subscription stays paused until the customer tops up — at which point Monigo auto-resumes (see below). Do not manually re-trigger billing; instead, credit the wallet and let Monigo handle the rest.
Auto-resume on top-up
When you credit a wallet belonging to a customer with a paused prepaid subscription, Monigo:
- Checks whether the new balance covers the outstanding invoice total
- If yes: retries billing immediately — debits the wallet, creates the invoice as
"paid", and moves the subscription back to "active"
- If still insufficient: leaves the subscription paused
This is fully automatic. The resume flow fires the same invoice.paid webhook as a normal billing cycle.
# Top up the wallet — Monigo auto-resumes the subscription if balance is now sufficient
curl -X POST https://api.monigo.co/v1/wallets/{wallet_id}/credit \
-H "Authorization: Bearer mk_live_..." \
-H "Content-Type: application/json" \
-d '{
"amount": "5000.00",
"description": "Manual top-up",
"idempotency_key": "topup_abc123"
}'
Webhook events
| Event | When fired |
|---|
invoice.paid | Wallet debit succeeded; invoice created as paid |
subscription.prepaid_balance_insufficient | Balance too low; subscription paused |
customer.wallet.topped_up | Wallet was successfully credited |
Register a webhook endpoint in the Webhooks guide to receive these events.
Customer portal
When a customer views their subscriptions in the customer portal, prepaid subscriptions display:
- A Prepaid badge next to the subscription status
- Their current wallet balance alongside the estimated period total
- A warning and Top up wallet → link when the balance is below the estimated total
This gives customers full visibility into their balance before the next billing cycle runs.
Comparing prepaid and postpaid
| Postpaid (default) | Prepaid |
|---|
billing_mode | "postpaid" | "prepaid" |
| Invoice created | As draft, then finalized | Directly as paid |
| Payment collection | Via payment provider (card/bank) | Debited from wallet |
| Failed payment | Retry logic + dunning | Subscription paused |
| Recovery | Automatic retries | Customer tops up → auto-resume |
| Best for | SaaS with card-on-file | APIs with credit/token packs |