Odoo Subscriptions (the sale_subscription module) automates recurring revenue: invoice generation on schedule, MRR/ARR reporting, and churn tracking. The module works for annual contracts invoiced monthly, monthly SaaS plans, and maintenance agreements. Getting the payment provider integration right - especially for online self-service portals - is where most implementations stall.
Installing the subscriptions module#
Install via Apps: search "Subscriptions" → install sale_subscription.
This adds:
- Subscription products (products with a recurring billing policy).
- Subscription templates (recurring billing intervals).
- MRR/ARR reporting.
- Customer portal subscription management.
Subscription product configuration#
Products that appear on subscriptions must be configured with the correct billing type.
Product → Sales tab:
- Create Recurring Invoices: enabled.
- Subscription Template: select the default billing interval (monthly, quarterly, annual).
Product → Invoice Policy: "Ordered Quantities" for subscription services (bill on subscription creation, not on delivery).
Subscription templates#
Subscriptions → Configuration → Recurring Plans → New:
| Field | Example value |
|---|---|
| Name | Monthly Plan |
| Billing Period | 1 Month |
| Duration | 12 Months (for annual commitments billed monthly) |
| Payment Mode | Payment Provider / Manual |
| Auto-close Overdue | After 15 days |
| Closing Reason | Non-payment |
Billing Period determines the invoice frequency. Duration caps the total contract length. Leave Duration empty for indefinite subscriptions.
Creating a subscription#
Subscriptions → New:
- Select customer.
- Select Recurring Plan (billing interval).
- Add subscription lines (products from catalog).
- Start Date → sets first billing date.
- Confirm (or set to In Progress).
On confirmation, Odoo schedules the first invoice generation based on the billing period.
Automatic invoice generation#
A cron job (sale.subscription.cron.invoice) runs daily. It checks all active subscriptions whose next invoice date has passed and generates invoices.
Invoice generation flow:
- Cron finds subscriptions where
next_invoice_date <= today. - Creates a draft invoice for each subscription.
- Posts the invoice (auto-confirm = True on the plan).
- Sends the invoice to the customer by email (if email send = True on the plan).
- Advances
next_invoice_dateby one billing period.
For auto-collected plans (Stripe/Adyen), the cron also triggers payment collection via the stored payment token.
Stripe integration for recurring payments#
Step 1: Install payment provider
Apps → install payment_stripe.
Step 2: Configure Stripe
Accounting → Configuration → Payment Providers → Stripe:
- Set Stripe Secret Key and Publishable Key.
- Set State to "Enabled."
- Enable "Save Credit Cards" (required for recurring collection).
- Set Capture Mode to "Automatic."
Step 3: Configure the subscription template
Recurring Plan → Payment Mode: "Payment Provider."
Select Stripe as the payment provider.
Step 4: Customer onboarding flow
When a customer subscribes via the portal:
- They see the subscription summary.
- They click "Pay" → Stripe Checkout or inline card form (depending on configuration).
- They enter card details. Odoo tokenizes the card via Stripe's payment intent API.
- The token stores in
payment.tokenlinked to the customer.
For subsequent billing periods, the cron charges the stored token automatically via Stripe's payment_intents or charges API (depending on your Stripe configuration - SCA-compliant flow uses payment intents).
Step 5: Handle failed payments
When Stripe declines a charge:
- Odoo marks the invoice as "In Payment Attempt Failed."
- The subscription moves to "Past Due" state after the configured grace period.
- The customer receives an email with a payment link.
- If unpaid after the auto-close period, the subscription closes.
Configure dunning email templates in: Subscriptions → Configuration → Settings → Overdue Invoices → Email Template.
MRR and ARR tracking#
Odoo calculates MRR (Monthly Recurring Revenue) from active subscriptions:
MRR = sum of (monthly equivalent of all active subscription line amounts)
For annual plans: MRR = annual amount / 12.
View in Subscriptions → Reporting → MRR Analysis.
Key metrics tracked:
- MRR: Current monthly recurring revenue.
- Net New MRR: MRR added minus MRR lost (churn + downgrades).
- Churn Rate: % of MRR lost per month.
- Customer Lifetime Value (CLV): Average revenue per customer over their subscription lifetime.
Churn tracking#
When a subscription closes (cancelled or expired), Odoo records the close reason and the MRR lost. The churn cohort report shows which signup month has the highest churn rate - useful for identifying onboarding problems.
Close reasons are configured in: Subscriptions → Configuration → Close Reasons. Common reasons: Non-payment, Competitor, Feature Gap, End of Contract. Add custom reasons and assign them when closing subscriptions to get actionable churn data.
Trial periods#
Some plans offer a free trial before billing starts. Configure on the subscription:
- Set a trial end date.
- Generate the first invoice only after the trial end date.
- During the trial, subscription status shows "Trial."
Implement by setting next_invoice_date to the trial end date when the subscription is created. The cron will not generate an invoice until that date arrives.
Portal self-service#
Customers can manage subscriptions from the portal (portal.customer.com/my/subscriptions):
- View active subscriptions.
- Download invoices.
- Update payment method.
- Cancel (if self-cancellation is permitted on the plan).
Enable self-cancellation: Recurring Plan → Customer Can Close = True.
Disable self-upgrades if pricing changes require approval: Customer Can Upgrade = False.

