Billing Cycles
Billing cycles determine when recurring donations are charged. Batchmates supports monthly, quarterly, and yearly billing frequencies.
PayMongo Invoicing & Schedule: Billing schedules and retries are managed server-side by PayMongo Subscriptions. Draft invoices are generated 24 hours prior to billing, finalized, and charged. If a payment fails, PayMongo automatically retries payment daily over a 3-day window (past_due) before suspending the subscription (unpaid). Local database fields (next_billing_date, failure_count, last_charged_at) operate strictly as read-only mirrors of PayMongo webhook events.
Supported Cycles
Monthly
Charges occur once per month on the same day. Most popular option for regular supporters.
Example: Created on January 15
- First charge: January 15
- Next charge: February 15
- Following: March 15
Quarterly
Charges occur every 3 months. Good for larger donations spread throughout the year.
Example: Created on January 15
- First charge: January 15
- Next charge: April 15
- Following: July 15
Yearly
Charges occur once per year. Ideal for significant annual contributions.
Example: Created on January 15, 2024
- First charge: January 15, 2024
- Next charge: January 15, 2025
- Following: January 15, 2026
Monthly Subscription
{
"campaign_id": 5,
"amount": 500,
"billing_cycle": "monthly",
"payment_method_id": 2
}
Quarterly Subscription
{
"campaign_id": 5,
"amount": 1500,
"billing_cycle": "quarterly",
"payment_method_id": 2
}
Yearly Subscription
{
"campaign_id": 5,
"amount": 6000,
"billing_cycle": "yearly",
"payment_method_id": 2
}
Next Billing Date
The next_billing_date field indicates when the next charge will occur:
{
"id": 1,
"billing_cycle": "monthly",
"next_billing_date": "2024-02-15",
"last_charged_at": "2024-01-15T10:00:00.000000Z"
}
Calculation Logic
After each successful payment, the system automatically calculates the next billing date:
- Monthly: Adds 1 month to current billing date
- Quarterly: Adds 3 months to current billing date
- Yearly: Adds 1 year to current billing date
Edge Cases
End of Month: If created on January 31, monthly billing adjusts to the last day of shorter months:
- January 31 → February 28/29 → March 31 → April 30
Leap Years: Yearly subscriptions created on February 29 will bill on February 28 in non-leap years.
Billing Process
Intended design — not currently executed. See the note at the top of this page.
When enabled, the automated billing process runs daily and processes subscriptions due for billing:
-
Identify Due Subscriptions
- Query subscriptions where
status = 'active' - Filter by
next_billing_date <= today
- Query subscriptions where
-
Attempt Payment
- Use saved payment method
- Create donation record with
donation_type = 'recurring' - Process through payment gateway
-
Handle Result
Success:
- Mark donation as
completed - Update campaign balance
- Reset
failure_countto 0 - Calculate next billing date
Failure:
- Mark donation as
failed - Increment
failure_count - Record
last_failure_reason - If
failure_count >= 3, set status topayment_failed
- Mark donation as
Payment Retry Logic
Intended design — no retry job is scheduled. subscriptions:retry-failed was removed from the scheduler.
When enabled, failed payments are retried on this schedule:
- Name
First Failure- Description
Retry after 3 days
- Name
Second Failure- Description
Retry after 7 days
- Name
Third Failure- Description
Status changes to
payment_failed, no more retries
After Third Failure
{
"id": 1,
"status": "payment_failed",
"failure_count": 3,
"last_failure_at": "2024-01-22T10:00:00.000000Z",
"last_failure_reason": "Insufficient funds"
}
Pausing & Resuming
Pausing
When a subscription is paused:
- No billing attempts occur
next_billing_dateremains unchanged- Status changes to
paused paused_attimestamp is recorded
Paused Subscription
{
"id": 1,
"status": "paused",
"paused_at": "2024-01-20T14:30:00.000000Z",
"next_billing_date": "2024-02-15"
}
Resuming
When resumed:
- Status returns to
active paused_atis cleared- Billing resumes on
next_billing_date - If billing date has passed, charges immediately
Changing Billing Cycles
Currently, changing billing cycles requires:
- Cancelling existing subscription
- Creating new subscription with desired cycle
Note: Future updates may support cycle changes without cancellation.
Minimum Amounts
Campaigns can set minimum recurring amounts:
Campaign Settings
{
"allow_recurring": true,
"min_recurring_amount": "100.00"
}
If user attempts to subscribe below minimum:
Error Response
{
"success": false,
"message": "Minimum recurring amount is ₱100"
}
Billing Notifications
Users receive notifications for:
- ✅ Successful recurring payment
- ⚠️ Failed payment attempt (with retry date)
- ❌ Payment failed after 3 attempts
- 📅 Upcoming billing reminder (3 days before)
Email Notifications
Subject: Recurring Donation Successful - Engineering Scholarship Fund
Thank you for your recurring donation of ₱500.00 to
Engineering Scholarship Fund.
Next billing date: February 15, 2024
View your subscription: https://app.batchmates-v2.revlv.com/subscriptions/1
Campaign End Handling
When a campaign ends while subscriptions are active:
- Existing subscriptions status →
expired - No more billing attempts
- Users notified of campaign completion
- Subscription remains in history
Expired Subscription
{
"id": 1,
"status": "expired",
"campaign": {
"id": 5,
"status": "completed",
"title": "Engineering Scholarship Fund"
}
}
Best Practices
For Users
- Ensure payment method is valid and has sufficient funds
- Keep card expiration dates updated
- Review monthly commitment vs. budget
- Monitor email for payment notifications
For Campaigns
- Set reasonable minimum amounts (₱50-100 for monthly)
- Communicate impact of recurring support
- Update donors on how funds are used
- Thank recurring supporters regularly
Subscription Lifecycle
Create → Active → (Optional Pause) → Active → Cancel
↓
Payment Failed → Update Payment → Active
Key States:
active- Currently billing on schedulepaused- Temporarily stopped by userpayment_failed- Requires payment method updatecancelled- Permanently endedexpired- Campaign ended
Statistics
Track your recurring donation impact:
Subscription Stats
{
"total_subscriptions": 5,
"active_count": 3,
"paused_count": 1,
"monthly_commitment": "1500.00",
"total_donated": "18000.00"
}
monthly_commitment - Total amount of active monthly subscriptions (quarterly and yearly converted to monthly equivalent)
total_donated - Sum of all completed donations from recurring subscriptions