-
Notifications
You must be signed in to change notification settings - Fork 1
Subscription Plans
Flexible subscription tiers with Stripe integration
Multi-tier subscription system offering:
- Free Tier - Basic access with limited credits
- Starter - $20/month with 2000 credits
- Pro - $50/month with 5000 credits
- Enterprise - Custom pricing and features
Payment Provider: Stripe
Database Tables: subscription_products, users
# Add to .env
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key
STRIPE_PUBLISHABLE_KEY=pk_test_your_publishable_key
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret-
Log in to Stripe Dashboard
-
Navigate to Products
-
Create subscription products:
- Starter: $20/month
- Pro: $50/month
- Enterprise: Custom
-
Copy Price IDs and add to database
INSERT INTO subscription_products (
stripe_price_id,
name,
price,
credits,
billing_cycle
) VALUES
('price_starter_monthly', 'Starter', 20.00, 2000, 'monthly'),
('price_pro_monthly', 'Pro', 50.00, 5000, 'monthly'),
('price_enterprise_monthly', 'Enterprise', 200.00, 25000, 'monthly');Price: $0/month
Features:
- $10 free trial credits
- Basic API access
- Community support
- 1000 requests per month
- Standard rate limits
Best For: Testing and small projects
Price: $20/month
Features:
- 2000 credits per month ($20 value)
- All AI models
- Email support
- 10,000 requests per month
- Higher rate limits
Best For: Individual developers and small teams
Price: $50/month
Features:
- 5000 credits per month ($50 value)
- Priority support
- Advanced analytics
- 50,000 requests per month
- Highest rate limits
- Custom rate limits
Best For: Production applications and growing teams
Price: Custom
Features:
- Custom credit allocation
- Dedicated support
- SLA guarantees
- Custom integrations
- Unlimited requests
- White-label options
- Custom contracts
Best For: Large organizations with specific needs
GET /plans
Response:
{
"plans": [
{
"id": 1,
"name": "Starter",
"price": 20.00,
"credits": 2000,
"billing_cycle": "monthly",
"features": [
"2000 credits per month",
"All AI models",
"Email support"
]
},
{
"id": 2,
"name": "Pro",
"price": 50.00,
"credits": 5000,
"billing_cycle": "monthly",
"features": [
"5000 credits per month",
"Priority support",
"Advanced analytics"
]
}
]
}POST /subscribe
Request:
{
"plan_id": 1,
"billing_cycle": "monthly"
}Response:
{
"checkout_url": "https://checkout.stripe.com/session_abc123",
"session_id": "cs_test_abc123"
}GET /user/subscription
Response:
{
"plan": "Pro",
"status": "active",
"credits_remaining": 3500,
"credits_total": 5000,
"renews_at": "2025-01-15T00:00:00Z",
"billing_cycle": "monthly"
}POST /user/subscription/cancel
Response:
{
"status": "canceled",
"canceled_at": "2024-12-15T10:30:00Z",
"effective_until": "2025-01-15T00:00:00Z"
}import requests
url = "https://api.gatewayz.com/subscribe"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {
"plan_id": 1, # Starter plan
"billing_cycle": "monthly"
}
response = requests.post(url, headers=headers, json=payload)
checkout_url = response.json()["checkout_url"]
# Redirect user to checkout_url
print(f"Complete payment at: {checkout_url}")url = "https://api.gatewayz.com/user/subscription"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
response = requests.get(url, headers=headers)
subscription = response.json()
print(f"Plan: {subscription['plan']}")
print(f"Credits remaining: {subscription['credits_remaining']}")CREATE TABLE subscription_products (
id SERIAL PRIMARY KEY,
stripe_price_id TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
price DECIMAL(10,2) NOT NULL,
credits INTEGER NOT NULL,
billing_cycle TEXT NOT NULL, -- monthly, yearly
features JSONB,
active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);-- Subscription-related fields in users table
subscription_status TEXT, -- trial, active, canceled, expired
subscription_plan_id INTEGER REFERENCES subscription_products(id),
subscription_started_at TIMESTAMP,
subscription_renews_at TIMESTAMP,
stripe_customer_id TEXT,
stripe_subscription_id TEXTimport stripe
stripe.api_key = os.getenv("STRIPE_SECRET_KEY")
session = stripe.checkout.Session.create(
customer=stripe_customer_id,
payment_method_types=["card"],
line_items=[{
"price": stripe_price_id,
"quantity": 1
}],
mode="subscription",
success_url="https://yourapp.com/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url="https://yourapp.com/canceled",
metadata={
"user_id": user.id,
"plan_id": plan.id
}
)@app.post("/webhooks/stripe")
async def stripe_webhook(request: Request):
payload = await request.body()
sig_header = request.headers.get("stripe-signature")
event = stripe.Webhook.construct_event(
payload, sig_header, webhook_secret
)
if event.type == "checkout.session.completed":
session = event.data.object
await handle_subscription_created(session)
elif event.type == "invoice.payment_succeeded":
invoice = event.data.object
await handle_subscription_renewed(invoice)
elif event.type == "customer.subscription.deleted":
subscription = event.data.object
await handle_subscription_canceled(subscription)
return {"status": "success"}- User signs up
- Automatically gets free tier
- $10 trial credits added
- 3-day trial period
- User subscribes to paid plan
- Trial status changes to "active"
- Credits allocated based on plan
- Billing cycle starts
- Stripe charges card automatically
- Credits reset to plan allocation
- Usage resets
- Subscription extends for another month
- User cancels subscription
- Access continues until end of billing period
- No automatic renewal
- Status changes to "canceled"
- Billing period ends
- Credits set to 0
- Status changes to "expired"
- User moves to free tier
def allocate_credits(user_id, plan_id):
plan = db.table("subscription_products").select("credits").eq("id", plan_id).single()
db.table("users").update({"credits": plan["credits"]}).eq("id", user_id).execute()def reset_monthly_credits(user_id):
user = get_user(user_id)
plan = get_plan(user.subscription_plan_id)
db.table("users").update({
"credits": plan.credits,
"subscription_renews_at": next_month()
}).eq("id", user_id).execute()def handle_credit_overage(user_id):
user = get_user(user_id)
if user.credits < 0:
# Option 1: Block API access
block_api_access(user_id)
# Option 2: Allow overage with notification
send_overage_notification(user_id, abs(user.credits))| Feature | Free | Starter | Pro | Enterprise |
|---|---|---|---|---|
| Price | $0 | $20/mo | $50/mo | Custom |
| Credits | $10 trial | 2000 | 5000 | Custom |
| Requests/mo | 1,000 | 10,000 | 50,000 | Unlimited |
| Support | Community | Priority | Dedicated | |
| Analytics | Basic | Standard | Advanced | Custom |
| Rate Limits | Standard | Higher | Highest | Custom |
| SLA | None | None | 99.9% | Custom |
def upgrade_subscription(user_id, new_plan_id):
# Calculate prorated amount
prorated_amount = calculate_proration(user_id, new_plan_id)
# Update Stripe subscription
stripe.Subscription.modify(
subscription_id,
items=[{"price": new_price_id}],
proration_behavior="always_invoice"
)
# Update database
db.table("users").update({
"subscription_plan_id": new_plan_id,
"credits": new_plan.credits # Immediate credit boost
}).eq("id", user_id).execute()def downgrade_subscription(user_id, new_plan_id):
# Schedule downgrade at period end
stripe.Subscription.modify(
subscription_id,
items=[{"price": new_price_id}],
proration_behavior="none",
prorate=False
)
# Database updated on next renewal- Clear Pricing - Make pricing transparent and easy to understand
- Flexible Billing - Offer monthly and yearly options
- Easy Upgrades - Allow seamless plan changes
- Grace Period - Give users time after payment failure
- Usage Tracking - Help users monitor credit usage
- Notifications - Alert before subscription renewal
- Cancellation - Make it easy to cancel (build trust)
Symptom: Subscription payment fails
Solution:
- Send notification to user
- Retry payment (Stripe automatic retry)
- Provide grace period (7 days)
- Downgrade to free tier if unresolved
Symptom: User subscribed but no credits
Solution:
- Check webhook delivery in Stripe dashboard
- Verify webhook handler processed event
- Manually allocate credits if needed
- Review logs for errors
Symptom: User has multiple active subscriptions
Solution:
- Cancel older subscriptions in Stripe
- Consolidate to single active subscription
- Refund if necessary
- Update database to reflect single subscription
- Stripe Integration - Payment processing
- Free Trial System - Trial management
- Pricing System - Credit pricing
Last Updated: December 2024 Status: Production Ready
- Stripe-Integration — Payment processing and webhooks
- Free-Trial-System — Trial before subscription
- Coupon-System — Discounts on plans
- Delta Report — P0-7: Trial configuration discrepancy, P1-6: Overage strategy
Reading Path (start here, in order)
- Conceptual Model
- Stability Definition
- Conceptual Model Features
- Features
- Delta Report
- Features-Acceptance-Criteria
Testing
Security & Access
Billing
Monitoring
Features
Providers
Operations
Data References