> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Lovable Billing Model

> Deconstruct Lovable's message-credit subscription with daily bonus drip, team-wide sharing, and separate cloud metering, then build the same model using Dodo Payments.

Lovable (lovable.dev) is an AI web app builder that charges in credits instead of tokens. Users spend credits by sending messages to the AI builder. A monthly credit pool supports bursts of work, and a daily bonus drip rewards users who come back every day.

## Lovable's Billing Model

Lovable's pricing combines message credits with separate metering for cloud hosting and AI features.

| Plan | Price | Monthly Credits | Daily Bonus | Key Features |
| :- | :- | :- | :- | :- |
| Free | \$0/month | 0 | 5/day (up to 30/month) | Public projects only |
| Pro | \$25/month | 100 | 5/day | On-demand top-ups, usage-based Cloud + AI, custom domains |
| Business | \$50/month | 100 | 5/day | SSO, team workspace, design templates, security center |
| Enterprise | Custom | Custom | Custom | SCIM, dedicated support, audit logs |

Lovable's pricing FAQ describes these rules ([lovable.dev/pricing](https://lovable.dev/pricing)):

* **Credit-based subscription**: Messages to the AI spend credits. In Plan Mode, 1 credit = 1 message. In Default Mode, the cost varies with task complexity.
* **Credits are shared across unlimited users**: Every member of a workspace draws from one pool. Plans are priced by credits, not per seat.
* **Monthly credits refresh on renewal**: Each renewal adds the plan's credits. Unused monthly credits expire two months after they're issued.
* **On-demand credit top-ups**: Users can buy more credits if they run out. Top-up credits last 12 months.
* **Separate usage-based Cloud + AI billing**: Hosting and AI features in user apps have their own monthly grant, then draw from the credit balance.
* **Daily bonus credits reset each day**: A use-it-or-lose-it daily drip of 5 credits that doesn't roll over.

## What Makes It Unique

* **Message-based simplicity**: Users think in messages, not tokens or model weights. This deconstruction models the simplest form, 1 credit = 1 message.
* **Daily drip + monthly pool hybrid**: The 5 daily bonus credits reward daily use, and the 100 monthly credits cover bursts of work.
* **Team-wide shared pool**: Credits are shared across unlimited users for a flat team price, not per seat.
* **Two-layer billing**: Credits pay for AI interactions, and cloud infrastructure is metered separately.

## Build This with Dodo Payments

You can build Lovable's hybrid model with Dodo Payments credit entitlements and usage-based meters.

<Steps>
  <Step title="Create a Custom Unit Credit Entitlement">
    In your Dodo Payments dashboard, go to **Products → Credits** and create the message credit. This credit holds the monthly pool.

    * **Credit Type**: Custom Unit
    * **Unit Name**: "Messages"
    * **Precision**: 0
    * **Credit Expiry**: 60 days (matches Lovable's two-month expiry for monthly credits)
    * **Allow Overage**: Disabled

    Dodo Payments doesn't block usage when a balance reaches zero. To enforce a hard cap, check the balance in your application before you accept a message.
  </Step>

  <Step title="Create Subscription Products">
    Create your plans and attach the credit to the paid ones. Your application handles the Free plan's daily bonus.

    * **Free**: \$0/mo, 0 credits (daily bonus handled by app logic)
    * **Pro**: \$25/mo, 100 credits/cycle, attach credit entitlement
    * **Business**: \$50/mo, 100 credits/cycle, attach credit entitlement

    ```typescript theme={null}
    import DodoPayments from 'dodopayments';

    const client = new DodoPayments({
      bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    });

    const session = await client.checkoutSessions.create({
      product_cart: [
        { product_id: 'pdt_lovable_pro', quantity: 1 }
      ],
      customer: { email: 'user@example.com' },
      return_url: 'https://yourapp.com/dashboard'
    });
    ```
  </Step>

  <Step title="Create a Usage Meter for Cloud + AI">
    Lovable bills cloud infrastructure separately from messages. Create a meter to track it.

    * **Event name**: `cloud.compute_seconds`
    * **Aggregation**: Sum, with `compute_seconds` as the **Over Property**

    Add this meter to your subscription products with a price per unit. Dodo Payments calculates the charge from the usage you send. This snippet reuses the `client` from the previous step.

    ```typescript theme={null}
    await client.usageEvents.ingest({
      events: [{
        event_id: `compute_${Date.now()}`,
        customer_id: 'cus_abc123',
        event_name: 'cloud.compute_seconds',
        timestamp: new Date().toISOString(),
        metadata: {
          compute_seconds: 3600,
          project_id: 'proj_abc'
        }
      }]
    });
    ```
  </Step>

  <Step title="Implement Daily Bonus Credits (Application Logic)">
    Your application handles the daily bonus drip. Reset a daily counter with a scheduled job, and spend bonus credits before the Dodo Payments balance.

    Bonus messages use a separate event name, `ai.message.bonus`, that no credit-linked meter uses. They're recorded for analytics without deducting from the monthly pool.

    ```typescript theme={null}
    // Example cron job logic (pseudo-code)
    // Every day at midnight UTC:
    // 1. Reset 'daily_bonus_used' to 0 for all users in your DB

    // db is your application's database client. The user's dodo_customer_id is the
    // Dodo Payments customer ID (cus_...) you stored when they subscribed.
    async function handleMessage(userId: string) {
      const user = await db.users.findUnique({ where: { id: userId } });
      
      if (user.daily_bonus_used < 5) {
        // Use daily bonus
        await db.users.update({
          where: { id: userId },
          data: { daily_bonus_used: { increment: 1 } }
        });
        // Track for analytics but don't deduct from Dodo credits yet
        await client.usageEvents.ingest({
          events: [{
            event_id: `msg_bonus_${Date.now()}`,
            customer_id: user.dodo_customer_id,
            event_name: 'ai.message.bonus',
            timestamp: new Date().toISOString(),
            metadata: { type: 'daily_bonus' }
          }]
        });
      } else {
        // Deduct from Dodo credit entitlement
        await client.usageEvents.ingest({
          events: [{
            event_id: `msg_${Date.now()}`,
            customer_id: user.dodo_customer_id,
            event_name: 'ai.message',
            timestamp: new Date().toISOString(),
            metadata: { type: 'subscription_credit' }
          }]
        });
      }
    }
    ```
  </Step>

  <Step title="Send Usage Events for Messages">
    Track each AI message as a usage event. Create a **Count** meter for the `ai.message` event, toggle **Bill usage in Credits** on it, select the "Messages" credit, and set **Meter units per credit** to 1.

    ```typescript theme={null}
    await client.usageEvents.ingest({
      events: [{
        event_id: `msg_${Date.now()}`,
        customer_id: 'cus_abc123',
        event_name: 'ai.message',
        timestamp: new Date().toISOString(),
        metadata: {
          content_length: 450,
          project_id: 'proj_abc',
          feature_type: 'editor'
        }
      }]
    });
    ```
  </Step>

  <Step title="Handle Webhooks for Low Balance">
    Notify users when their credits run low so they can top up or upgrade.

    ```typescript theme={null}
    import DodoPayments from 'dodopayments';
    import express from 'express';

    const app = express();
    app.use(express.raw({ type: 'application/json' }));

    const client = new DodoPayments({
      bearerToken: process.env.DODO_PAYMENTS_API_KEY,
      webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY,
    });

    // notifyUser is your application's own function.
    app.post('/webhooks/dodo', async (req, res) => {
      try {
        const event = client.webhooks.unwrap(req.body.toString(), {
          headers: {
            'webhook-id': req.headers['webhook-id'] as string,
            'webhook-signature': req.headers['webhook-signature'] as string,
            'webhook-timestamp': req.headers['webhook-timestamp'] as string,
          },
        });

        if (event.type === 'credit.balance_low') {
          const { customer_id, available_balance } = event.data;
          await notifyUser(customer_id, `Your balance is low: ${available_balance} messages left.`);
        }

        res.json({ received: true });
      } catch (error) {
        res.status(401).json({ error: 'Invalid signature' });
      }
    });
    ```
  </Step>
</Steps>

## Accelerate with the LLM Ingestion Blueprint

The [LLM Ingestion Blueprint](/developer-resources/ingestion-blueprints/llm) wraps your AI client and sends a usage event for every call.

```typescript theme={null}
import { createLLMTracker } from '@dodopayments/ingestion-blueprints';
import OpenAI from 'openai';

const tracker = createLLMTracker({
  apiKey: process.env.DODO_PAYMENTS_API_KEY,
  environment: 'live_mode',
  eventName: 'ai.message',
});

const trackedClient = tracker.wrap({
  client: new OpenAI(),
  customerId: 'cus_abc123',
});

// Sends one ai.message event; the Count meter above deducts 1 credit per event
await trackedClient.chat.completions.create({
  model: 'gpt-4o',
  messages: [{ role: 'user', content: 'Build a landing page' }],
});
```

<Tip>
  Each event also carries `inputTokens`, `outputTokens`, `totalTokens`, and `model` in its metadata. See the [full blueprint documentation](/developer-resources/ingestion-blueprints/llm) for more details on automatic tracking.
</Tip>

## Architecture Overview

The sequence below shows one message: the app spends the daily bonus first, then the Dodo Payments credit balance, and meters cloud usage separately.

```mermaid theme={null}
sequenceDiagram
    participant U as User
    participant A as Your App
    participant D as Dodo Payments
    participant L as LLM Provider
    participant C as Cloud Infrastructure

    U->>A: Send Message
    A->>A: Check Daily Bonus Pool
    alt Daily Bonus Available
        A->>A: Deduct Daily Bonus
    else No Daily Bonus
        A->>D: Check Credit Balance
        D-->>A: Balance Available
        A->>D: Ingest Message Event
    end
    A->>L: Call LLM
    L-->>A: AI Response
    A->>C: Execute Compute/Hosting
    A->>D: Ingest Cloud Usage Event
    A-->>U: Return Response
```

## Key Dodo Features Used

These Dodo Payments features power the implementation:

<CardGroup cols={2}>
  <Card title="Credit-Based Billing" icon="coins" href="/features/credit-based-billing">
    Manage message credits and shared team pools.
  </Card>

  <Card title="Subscriptions" icon="calendar" href="/features/subscription">
    Set up recurring plans for Pro and Business tiers.
  </Card>

  <Card title="Usage-Based Billing" icon="chart-line" href="/features/usage-based-billing/introduction">
    Meter cloud infrastructure usage separately from AI credits.
  </Card>

  <Card title="Event Ingestion" icon="bolt" href="/features/usage-based-billing/event-ingestion">
    Send high-volume message and compute events to Dodo Payments.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/developer-resources/webhooks/intents/credit">
    Automate notifications for low credit balances.
  </Card>

  <Card title="LLM Ingestion Blueprint" icon="brain-circuit" href="/developer-resources/ingestion-blueprints/llm">
    Simplify AI usage tracking with pre-built integrations.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.