SaaS Billing Setup with Stripe
Configure Stripe Checkout, Customer Portal, and webhooks for DataXPipe SaaS plans including Free, Team, and Business tiers with org-scoped entitlements.
- stripe
- billing
- saas
DataXPipe SaaS uses Stripe for subscription billing across Free, Team, and Business plans. The FastAPI backend handles Checkout sessions, Customer Portal access, and webhook-driven plan synchronization. This guide covers end-to-end Stripe setup for production.
Plan structure
| Plan | Price | Pipelines | Connections | Support |
|---|---|---|---|---|
| Free | $0 | 3 | 2 | Community |
| Team | $49/mo | 25 | 10 | |
| Business | $199/mo | Unlimited | Unlimited | Priority |
Plan limits enforce at the API layer when organizations register pipelines or connections beyond their tier.
Stripe Dashboard setup
1. Create products and prices
In Stripe Dashboard → Products:
- Create DataXPipe Team — recurring monthly price (e.g.
$49/month) - Create DataXPipe Business — recurring monthly price (e.g.
$199/month)
Copy price IDs (price_...) for environment configuration.
2. Configure environment variables
On the API deployment (DigitalOcean App Platform or DOKS):
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PRICE_TEAM=price_xxxxxxxx
STRIPE_PRICE_BUSINESS=price_yyyyyyyy
On Vercel frontends (marketing/ and product-ui/):
NEXT_PUBLIC_STRIPE_PRICE_TEAM=price_xxxxxxxx
NEXT_PUBLIC_STRIPE_PRICE_BUSINESS=price_yyyyyyyy
Frontend price IDs power upgrade buttons; backend price IDs validate Checkout session creation.
3. Register webhook endpoint
Stripe Dashboard → Webhooks → Add endpoint:
https://api.dataxpipe.com/webhooks/stripe
Subscribe to events:
checkout.session.completedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deleted
Copy the signing secret to STRIPE_WEBHOOK_SECRET.
API billing endpoints
Authenticated org members call:
# Create Checkout session for upgrade
curl -X POST https://api.dataxpipe.com/api/v1/billing/checkout `
-H "Authorization: Bearer <jwt>" `
-H "Content-Type: application/json" `
-d '{"price_id":"price_xxxxxxxx"}'
# Open Customer Portal for payment management
curl -X POST https://api.dataxpipe.com/api/v1/billing/portal `
-H "Authorization: Bearer <jwt>"
Checkout redirects users to Stripe-hosted payment pages. On success, webhooks update the organization’s plan in Postgres.
Webhook processing flow
Stripe event → POST /webhooks/stripe
→ verify signature (STRIPE_WEBHOOK_SECRET)
→ map stripe_customer_id → organization
→ update plan, stripe_subscription_id, stripe_price_id
Key handler logic in app/billing/stripe_service.py:
- Subscription created/updated — set org plan to
teamorbusinessbased on price ID - Subscription deleted — downgrade org to
free - Checkout completed — link Stripe customer ID to organization
Webhook failures return non-2xx so Stripe retries delivery. Monitor webhook logs in Stripe Dashboard.
Database schema
Migration 0002_saas adds billing columns to organizations:
| Column | Purpose |
|---|---|
stripe_customer_id | Links org to Stripe customer |
stripe_subscription_id | Active subscription reference |
stripe_price_id | Current price tier |
plan | free, team, or business |
Plan changes from webhooks update plan atomically—API handlers read this column for limit enforcement.
Testing in development
Use Stripe test mode keys (sk_test_...) locally:
$env:STRIPE_SECRET_KEY = "sk_test_..."
$env:STRIPE_WEBHOOK_SECRET = "whsec_test_..."
Forward webhooks to localhost with Stripe CLI:
stripe listen --forward-to localhost:8000/webhooks/stripe
stripe trigger checkout.session.completed
Unit tests in tests/test_billing_unit.py mock Stripe SDK calls.
Security
- Never expose
STRIPE_SECRET_KEYto frontends - Verify webhook signatures on every request—reject unsigned payloads
- Use HTTPS only for webhook endpoints
- Restrict billing API endpoints to authenticated org admins via OIDC roles
For multi-tenant isolation details, see multi-tenant pipeline catalogs. For full SaaS deployment, see Deploy DataXPipe on DigitalOcean.