Introduction
For SaaS businesses, setting up recurring payments is critical for predictable revenue. Yet, many developers struggle with selecting the right payment provider, integrating subscriptions properly, and managing failed payments. Without a solid billing system in place, issues like revenue loss, user churn, and compliance headaches can quickly add up.
This guide walks through setting up subscription billing with an API, covering everything from choosing a payment provider to handling upgrades, downgrades, and dunning. Whether you’re just getting started or looking to optimize an existing system, this guide will help you avoid common pitfalls while setting up scalable subscription payments.
Choosing the Right Payment API for Your SaaS
When picking a payment provider for recurring payments, there are several factors to consider:
- Ease of integration – Some APIs require extensive setup, while others provide no-code or low-code solutions.
- Global payments support – If you plan to sell internationally, look for providers that handle multiple currencies and local payment methods.
- Tax compliance – Sales tax, VAT, and GST can be a major headache. Some providers automate this.
- Subscription management – Features like upgrades, downgrades, proration, and dunning should be handled efficiently.
- Vendor lock-in concerns – Switching providers down the line can be painful if you don’t plan for flexibility.
Comparison of Popular Payment APIs
- Stripe Billing – Developer-friendly, supports complex pricing models, but requires tax compliance management.
- Paddle – A merchant of record (MoR) solution that handles tax compliance but comes with higher fees.
- Chargebee/Recurly – Subscription-first platforms that integrate with multiple payment processors and offer more granular subscription controls.
- Lemon Squeezy – Another MoR option with a more flexible feature set than Paddle.
For many SaaS businesses, Stripe is the default choice due to its robust API and wide adoption. However, for global expansion, Paddle or Lemon Squeezy may be better suited due to built-in tax handling.
Setting Up Subscription Billing with an API
Step 1: Create a Payment Gateway Account and API Keys
Sign up for Stripe, Paddle, or another provider. Retrieve your API keys and set them in your environment variables for secure authentication.
Step 2: Define Your Subscription Model
Decide whether your SaaS will use:
- Fixed monthly/yearly pricing
- Usage-based billing (charging per action, API call, or seats)
- Hybrid billing (a base subscription fee plus metered charges)
For trials, you’ll need logic to transition users into paid subscriptions and handle failed payments post-trial.
Step 3: Implement Subscription Creation via API
For Stripe, you can create a subscription using the following API call:
import stripestripe.api_key = "your_secret_key"customer = stripe.Customer.create(email="customer@example.com",payment_method="pm_card_visa",invoice_settings={"default_payment_method": "pm_card_visa"},)subscription = stripe.Subscription.create(customer=customer.id,items=[{"price": "price_12345"}],expand=["latest_invoice.payment_intent"],)
This will:
- Create a customer
- Attach a payment method
- Subscribe them to a plan
Managing Subscription Events with Webhooks
Webhooks allow your application to react to payment events like successful charges, failed payments, or cancellations.
Key webhook events to track:
- invoice.payment_succeeded – Grant user access
- invoice.payment_failed – Trigger dunning emails
- customer.subscription.deleted – Cancel user access
Example of a webhook handler:
from flask import Flask, requestimport stripeapp = Flask(__name__)stripe.api_key = "your_secret_key"@app.route("/webhook", methods=["POST"])def stripe_webhook():payload = request.get_data(as_text=True)event = Nonetry:event = stripe.Event.construct_from(json.loads(payload), stripe.api_key)except ValueError:return "Invalid payload", 400if event.type == "invoice.payment_failed":customer_id = event.data.object.customer# Update database to flag failed paymentprint(f"Payment failed for customer {customer_id}")return "OK", 200if __name__ == "__main__":app.run(port=4242)
This will flag failed payments so you can send an automated follow-up email.
Managing Subscription Changes
Upgrades and Downgrades
When users switch plans, you’ll need to handle:
- Prorated charges – If they upgrade mid-cycle, they should be charged only for the difference.
- Seamless transitions – Avoid forcing users to re-enter payment details.
Stripe automatically handles prorated adjustments when a subscription is updated:
stripe.Subscription.modify("sub_123",items=[{"id": "si_456", "price": "new_price_id"}],proration_behavior="create_prorations",)
Handling Cancellations
When a user cancels, decide if they should lose access immediately or at the end of the billing cycle.
Stripe supports immediate or scheduled cancellations:
stripe.Subscription.modify("sub_123",cancel_at_period_end=True)
Storing Subscription Data Securely
- Keep a local copy of the subscription status to avoid excessive API calls.
- Store minimal payment details—never store raw credit card numbers.
- Use JWT tokens to store user subscription status and avoid unnecessary database queries.
Handling Multi-Currency & Tax Compliance
For global SaaS businesses, dealing with taxes is non-trivial.
- Stripe Tax calculates and applies VAT, GST, and sales tax.
- Paddle and Lemon Squeezy act as merchants of record, handling tax compliance for you.
When selling in multiple countries, ensure your payment processor supports:
- Localized pricing
- Automatic currency conversion
- Country-specific tax rules
Automating Subscription Management & Scaling Payments
As your SaaS grows, automate:
- Recurring invoicing with PDF generation
- Failed payment recovery (dunning emails & retries)
- Customer portals for managing subscriptions
Stripe’s Customer Portal allows users to update payment details, change plans, and cancel subscriptions without custom code.
Common Mistakes to Avoid
- Ignoring webhooks – If you only check subscriptions at login, you’ll miss cancellations.
- Not handling payment failures properly – Dunning management should include retries and user notifications.
- Hardcoding payment logic – Always use an abstraction layer to switch providers easily.
- Skipping tax compliance – This can lead to legal issues when scaling globally.
Future-Proofing Your Subscription Billing
- Use an abstraction layer to switch payment providers if needed.
- Ensure PCI compliance when handling payment data.
- Regularly review failed payments and churn analytics to optimize revenue.
Conclusion
Setting up recurring payments with an API is a must for SaaS businesses. By choosing the right provider, implementing webhooks, and automating dunning, you can minimize revenue loss while providing a seamless payment experience.
If you're looking for an easier way to integrate authentication and payments, Update helps streamline these processes so you can focus on growing your SaaS without handling billing complexity manually.
Want to get started? Set up your first API-based recurring payment today.