Stripe Billing: Subscriptions & Usage-Based Credits

by Alex Johnson 52 views

In today's digital landscape, offering flexible payment options is crucial for user satisfaction and business growth. For platforms leveraging AI, implementing a robust subscription and credits system that integrates seamlessly with payment gateways like Stripe is not just beneficial – it's essential. This article delves into a comprehensive strategy for building such a system, focusing on Stripe integration, usage-based billing for AI operations, and a user-friendly experience.

🎯 Overview: Powering Your AI with Smart Billing

We're implementing a sophisticated subscription and credits system designed to manage AI operations efficiently. By integrating with Stripe, a leading payment platform, through the convenient Supabase Stripe Wrapper, we're enabling tiered subscriptions and a flexible credits system for AI usage. Users will enjoy the ability to subscribe to various plans, purchase additional credits as needed, and gain clear visibility into their AI usage costs. This approach ensures a fair and scalable model for both users and the platform.

The architecture is built upon reliable technologies: Stripe handles all payment processing and subscription management, while Supabase acts as the central hub for data synchronization and storage. The core innovation lies in the usage-based billing for AI operations, specifically tied to input and output tokens, a common metric for AI models. For managing subscriptions, we leverage Stripe's Hosted Pages, offering a seamless experience for users to handle actions like canceling or upgrading their plans without leaving the platform's familiar environment.

πŸ“‹ Requirements: Crafting a Seamless User Experience

1. User Profile Page (Customer-Facing)

The /profile or /account page is the central hub for users to manage their subscription, credits, and view their activity. It's designed for clarity and ease of use, ensuring users always have control and visibility over their account.

  • Profile Information Section: This section displays the user's name, email, and avatar. An 'Edit Profile' button allows for quick updates, and all information is synchronized with the Supabase user_profiles table, ensuring data consistency across the platform. This provides a personalized touchpoint for every user.

  • Subscription Section: Here, users can see their current plan (Free, Pro, or Enterprise), along with a clear breakdown of the features and limits associated with it. A prominent 'Manage Subscription' button directs users to the Stripe Customer Portal, where they can effortlessly upgrade, downgrade, or cancel their subscription. Information like the next billing date and amount is readily available, providing financial transparency. This section is crucial for managing recurring revenue and user retention.

  • Credits Section: The current credit balance is displayed prominently, making it easy for users to track their remaining credits. A 'Purchase Credits' button initiates the flow to Stripe Checkout, offering various credit packages such as 100 credits for $10, 500 for $40, and 1000 for $70, often with attractive bulk discounts. A low balance warning (under 10 credits) proactively prompts users to replenish, preventing service interruptions. This section is key for a usage-based billing model.

  • Billing History Tab: This tab provides a comprehensive log of all financial transactions, including credit purchases and subscription payments. Users can easily download invoices directly from Stripe, view details like date, description, amount, and status, and navigate through long histories using pagination. This transparency builds trust and simplifies record-keeping.

  • Usage History Tab: Offering granular insights into AI operations, this tab details AI activity with associated costs. Columns include Date, Operation Type, Input Tokens, Output Tokens, and Cost in credits. Users can filter by date range and operation type, and even export their usage data to CSV. A total usage summary provides a quick overview of daily, weekly, or monthly consumption. This is vital for understanding AI expenditure.

The design follows the platform's established design system, utilizing components like GlobalAdminHeader and dashboard-card. A tab-based interface organizes the different sections logically. Glass morphism is applied to stat cards for a modern aesthetic, and the entire interface is responsive, ensuring a smooth experience on mobile devices.

2. Credit Purchase System: Instant Top-Ups with Stripe Checkout

To facilitate the acquisition of credits, we're leveraging Stripe Checkout, a secure and user-friendly solution for one-time purchases. This system is designed to be quick and intuitive, allowing users to add credits to their account with minimal friction.

We define specific Stripe Products for our credit packages:

  • Starter Pack: Aimed at casual users, this package offers 100 credits for $10.
  • Pro Pack: For more engaged users, 500 credits are available for $40, representing a 20% discount compared to the starter pack.
  • Enterprise Pack: Designed for heavy users, 1000 credits are offered at $70, providing a substantial 30% discount.
  • Custom: For maximum flexibility, users can also opt for a custom amount, entering their desired credit quantity.

The credit purchase flow is streamlined:

  1. A user clicks the 'Purchase Credits' button on their profile page.
  2. A modal pops up, clearly displaying the available credit packages and their pricing.
  3. The user selects their desired package.
  4. They are then redirected to the secure Stripe Checkout page to complete the payment.
  5. Upon successful payment, a webhook is triggered. This webhook updates the user_credits table in Supabase, instantly adding the purchased credits to the user's balance.
  6. Finally, the user is redirected back to their profile page with a confirmation message, and their updated credit balance is visible.

Robust webhook handling is critical for maintaining data integrity. We listen for key Stripe events:

  • checkout.session.completed: This event signifies a successful checkout session and is the primary trigger to add credits to the user's account.
  • payment_intent.succeeded: While checkout.session.completed is primary, this event can serve as a secondary confirmation or for scenarios where checkout isn't used directly. It ensures the credit addition is finalized.
  • payment_intent.payment_failed: If a payment fails, this event allows us to notify the user and prevent any incorrect credit additions, maintaining accuracy in the system.

This system ensures that users can easily and reliably purchase credits whenever they need them, directly supporting the usage-based billing component of our AI operations.

3. Subscription Management: Flexible Tiers with Stripe

Our platform offers a tiered subscription model designed to cater to a wide range of user needs, from individuals to large enterprises. Each tier provides a different set of features and resource allowances, all managed through Stripe's robust infrastructure.

Subscription Tiers:

Feature Free Pro ($29/mo) Enterprise ($99/mo)
Monthly Credits 50 500 2000
PDF Processing 5/month Unlimited Unlimited
AI Agent Queries 20/month Unlimited Unlimited
3D Generation ❌ 10/month Unlimited
Priority Support ❌ βœ… βœ…
Custom Branding ❌ ❌ βœ…
API Access ❌ ❌ βœ…

Implementation relies heavily on Stripe Products for each tier. These are configured in Stripe as recurring subscription products.

We utilize the Stripe Customer Portal for all subscription management tasks. This provides a secure, hosted interface where users can:

  • Upgrade or downgrade their plan to a different tier.
  • Cancel their subscription at any time.
  • Update their payment method details.
  • View past invoices and billing history.
  • Manage their billing address and other relevant information.

This approach significantly reduces the development effort required for subscription management UIs and ensures compliance with payment industry standards.

Subscription synchronization between Stripe and Supabase is handled efficiently:

  • The Supabase Stripe Wrapper automatically syncs key subscription data.
  • When a subscription changes (created, updated, canceled), a webhook triggers a process to update the user_profiles.subscription_tier in Supabase.
  • Furthermore, monthly credits are granted upon subscription renewal. This is typically handled via the invoice.payment_succeeded webhook, ensuring users receive their allocated credits promptly.

Essential Webhooks for subscription management include:

  • customer.subscription.created: Records the new subscription in Supabase and assigns the tier.
  • customer.subscription.updated: Updates the user's tier if they upgrade or downgrade.
  • customer.subscription.deleted: Downgrades the user to the Free tier.
  • invoice.payment_succeeded: A crucial webhook for granting monthly credits to subscribers. It confirms successful payment for a billing period.
  • invoice.payment_failed: Notifies the user and potentially flags their account for suspension after multiple failures, adhering to Stripe's dunning process.

This robust system ensures that user subscription statuses are always accurately reflected in our application, enabling feature entitlement and credit allocation based on their plan.

4. Usage-Based Billing (AI Operations): Precision at the Token Level

The core of our AI platform's value is its operational capabilities. To ensure fairness and transparency, we've implemented a usage-based billing model for AI operations, directly tied to the consumption of input and output tokens. This allows users to pay precisely for what they use, making the AI services accessible and predictable.

AI Operation Costs are meticulously defined, reflecting the underlying model's pricing and our platform's markup. These costs are represented in both USD (for Stripe calculations) and our internal credit system:

Operation Input Cost (per 1M tokens) Output Cost (per 1M tokens) Estimated Credit Cost per Unit
PDF Processing (Claude Sonnet 4.5) $3.00 $15.00 ~0.5 credits/page
Search Agent (Claude Haiku 4.5) $0.80 $4.00 ~0.1 credits/query
Product Agent (Claude Sonnet 4.5) $3.00 $15.00 ~0.2 credits/query
3D Generation (GPT-5) $2.50 $10.00 ~1 credit/generation
Text Embeddings (OpenAI) $0.02 N/A ~0.001 credits/embedding
Image Embeddings (SigLIP) Free (self-hosted) N/A 0 credits

Credit Calculation is performed dynamically. For instance, using Claude Sonnet 4.5:

// Example: Claude Sonnet 4.5
const inputCostUSD = (inputTokens / 1_000_000) * 3; // $3 per 1M input tokens
const outputCostUSD = (outputTokens / 1_000_000) * 15; // $15 per 1M output tokens
const totalCostUSD = inputCostUSD + outputCostUSD;
const creditsToDebit = totalCostUSD * 10; // Assuming 1 credit = $0.10

This ensures that the cost reflects the actual token usage for each operation.

Implementation Details:

  • A dedicated ai_usage_logs table is created in Supabase to meticulously record every AI operation. It stores details like user_id, operation_type, model_name, token counts, calculated USD costs, and the credits_debited. Indices are set up for efficient querying by user and workspace.
CREATE TABLE ai_usage_logs (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID REFERENCES auth.users(id),
  workspace_id UUID REFERENCES workspaces(id),
  operation_type VARCHAR(50),
  model_name VARCHAR(100),
  input_tokens INT,
  output_tokens INT,
  input_cost_usd DECIMAL(10,6),
  output_cost_usd DECIMAL(10,6),
  total_cost_usd DECIMAL(10,6),
  credits_debited DECIMAL(10,2),
  metadata JSONB, -- request details, job_id, etc.
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_ai_usage_user ON ai_usage_logs(user_id, created_at DESC);
CREATE INDEX idx_ai_usage_workspace ON ai_usage_logs(workspace_id, created_at DESC);
  • A crucial service method, debitCredits(), is developed. This function first calculates the costs associated with an AI operation, checks if the user has sufficient credits, and then atomically debits the credits from the user's balance using a Supabase RPC call (e.g., debit_user_credits). Finally, it logs the usage details in the ai_usage_logs table. This transactional approach prevents inconsistencies.
async function debitCredits({
  userId, workspaceId, operationType, modelName, inputTokens, outputTokens, metadata
}) {
  const costs = calculateAICosts(modelName, inputTokens, outputTokens);
  const userCredits = await getUserCredits(userId);
  if (userCredits.balance < costs.creditsToDebit) {
    throw new Error('Insufficient credits');
  }
  
  await supabase.rpc('debit_user_credits', {
    user_id: userId,
    amount: costs.creditsToDebit,
    operation_type: operationType
  });
  
  await supabase.from('ai_usage_logs').insert({
    user_id: userId, workspace_id: workspaceId, operation_type: operationType,
    model_name: modelName, input_tokens: inputTokens, output_tokens: outputTokens,
    input_cost_usd: costs.inputCost, output_cost_usd: costs.outputCost,
    total_cost_usd: costs.totalCost, credits_debited: costs.creditsToDebit, metadata
  });
}
  • This debitCredits() function is integrated into all AI operations: the PDF processing pipeline, agent chat responses, 3D generation processes, and embedding generation. Before any operation commences, a credit check is performed. If credits are insufficient, a warning is displayed, and the operation is blocked if the balance is zero, with a prompt to purchase more credits. This proactive approach ensures a smooth user experience and prevents unexpected costs.

5. Admin Panel - AI Usage Monitoring: Insights for Optimization

For platform administrators, understanding AI usage is paramount for cost management, performance analysis, and user support. The Admin Panel's AI Usage Monitoring section provides a comprehensive suite of tools to track, analyze, and optimize AI resource consumption.

  • AI Usage Overview Dashboard: This high-level view offers critical metrics at a glance: total AI operations performed (daily, weekly, monthly), total tokens processed (both input and output), and the total cost incurred in USD and credits. Breakdowns by operation type and model used provide immediate insights into spending patterns. Interactive charts visualize usage over time and cost trends, allowing for quick identification of spikes or significant shifts.

  • Detailed Usage Table: For in-depth analysis, this table lists all AI operations with complete details. Key columns include Date, User, Operation, Model, Input Tokens, Output Tokens, Cost in USD, and Credits Debited. Powerful filtering options by date range, user, operation type, and model, along with a search function by user email or name, enable precise data retrieval. An export to CSV feature facilitates external analysis and reporting. Pagination ensures manageable loading times for large datasets.

  • User Usage Analytics: This section identifies key user behavior: top users by usage volume and top users by cost. It also highlights users with low credit balances (< 10 credits) or zero credits, enabling proactive outreach for potential churn or support needs. Calculating the average cost per user helps in understanding customer value segments.

  • Cost Optimization Insights: Moving beyond mere monitoring, this feature provides actionable intelligence. It identifies the most expensive operations, compares model efficiency, offers recommendations for cost reduction (e.g., suggesting cheaper models for certain tasks), and includes anomaly detection to flag unusual spikes in usage or cost that might indicate issues or opportunities.

The design adheres to the admin dashboard's established design system, employing glass morphism stat cards for key metrics and utilizing libraries like Chart.js or Recharts for interactive visualizations. Real-time updates are an optional enhancement to provide the most current data.

6. Supabase Stripe Wrapper Setup: Bridging Stripe and Your Database

The Supabase Stripe Wrapper is a powerful tool that simplifies the integration of Stripe data directly into your Supabase database as foreign tables. This drastically reduces the need for custom API clients and webhook handling for basic data synchronization.

Installation in Supabase is straightforward:

CREATE EXTENSION IF NOT EXISTS wrappers;

CREATE FOREIGN DATA WRAPPER stripe_wrapper
  HANDLER stripe_fdw_handler
  VALIDATOR stripe_fdw_validator;

CREATE SERVER stripe_server
  FOREIGN DATA WRAPPER stripe_wrapper
  OPTIONS (
    api_key '<stripe_secret_key>'
  );

Ensure that <stripe_secret_key> is securely stored in your Supabase project's Secrets configuration, never hardcoded.

Next, we define foreign tables that map directly to Stripe objects. This allows you to query Stripe data using standard SQL:

-- Customers
CREATE FOREIGN TABLE stripe_customers (
  id TEXT, email TEXT, name TEXT, metadata JSONB, created BIGINT
)
SERVER stripe_server
OPTIONS (object 'customers');

-- Subscriptions
CREATE FOREIGN TABLE stripe_subscriptions (
  id TEXT, customer TEXT, status TEXT, current_period_end BIGINT, items JSONB, metadata JSONB
)
SERVER stripe_server
OPTIONS (object 'subscriptions');

-- Invoices
CREATE FOREIGN TABLE stripe_invoices (
  id TEXT, customer TEXT, amount_paid BIGINT, status TEXT, created BIGINT, invoice_pdf TEXT
)
SERVER stripe_server
OPTIONS (object 'invoices');

These tables provide direct SQL access to essential Stripe data like customer details, subscription status, and invoice information.

Sync functions are crucial for propagating relevant Stripe data back into your application's core tables, such as user_profiles. For example, a function can update user profile information when a corresponding Stripe customer record is synced:

CREATE OR REPLACE FUNCTION sync_stripe_customer()
RETURNS TRIGGER AS $
BEGIN
  UPDATE user_profiles
  SET 
    subscription_tier = NEW.metadata->>'tier', -- Assuming tier is stored in metadata
    stripe_customer_id = NEW.id
  WHERE email = NEW.email;
  RETURN NEW;
END;
$ LANGUAGE plpgsql;

This function, triggered by Stripe events via the wrapper, ensures that your internal user data remains consistent with their Stripe subscription status. The wrapper facilitates setting up triggers or scheduled jobs to keep these foreign tables updated.

7. Stripe Configuration: Products, Webhooks, and API Keys

Proper configuration within the Stripe dashboard is fundamental for the entire billing system to function correctly. This involves setting up products, managing API keys, and configuring webhooks to communicate events between Stripe and our application.

Products to Create in Stripe:

  1. Subscription Products: These are recurring products that users subscribe to.
    • Free Tier: Typically, no Stripe product is needed as it’s the default state. However, if there are any base features tied to a free