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

# Pricing Models

> Choose the right pricing model for your app

# App Pricing Models

LaunchMyStore supports multiple pricing models for your app. Choose the model that best fits your value proposition and customer expectations.

## Available Models

<CardGroup cols={2}>
  <Card title="Free" icon="gift">
    No charge. Good for lead generation or basic utility apps.
  </Card>

  <Card title="One-Time" icon="credit-card">
    Single payment for lifetime access. Good for tools and templates.
  </Card>

  <Card title="Recurring" icon="repeat">
    Monthly or annual subscription. Most common for feature-rich apps.
  </Card>

  <Card title="Usage-Based" icon="chart-line">
    Pay per use (API calls, orders, etc.). Good for volume-dependent apps.
  </Card>
</CardGroup>

<Warning>
  **The `pricing` object is a flat bag, and prices are in MAJOR currency
  units (dollars), not cents.** There is no `plans[]` array, no per-plan
  `price`/`interval`/`features`, and no nested `trial{}` object — those are
  not read by the platform, and an app that ships them installs as **free**
  (no price resolves → no Stripe charge). The only fields the platform reads
  are:

  | Field          | Type   | Meaning                                                                                      |
  | -------------- | ------ | -------------------------------------------------------------------------------------------- |
  | `model`        | string | One of `free`, `one_time`, `subscription` (aliases `paid`/`recurring` accepted), `freemium`. |
  | `currency`     | string | ISO-4217, e.g. `USD`.                                                                        |
  | `monthlyPrice` | number | Monthly amount in dollars (e.g. `9` = \$9.00).                                               |
  | `yearlyPrice`  | number | Yearly amount in dollars.                                                                    |
  | `oneTimePrice` | number | One-time amount in dollars (e.g. `19.99`).                                                   |
  | `trialDays`    | number | Free-trial length in days (subscription models only).                                        |
  | `usage`        | object | `{ unitName, unitAmount, cappedAmount }` — metered rider (see Usage-Based below).            |

  The `create_app` MCP tool and the Developer Portal form both write this
  flat shape. Set the price field matching your `model` (`monthlyPrice`
  and/or `yearlyPrice` for `subscription`, `oneTimePrice` for `one_time`).
</Warning>

## Free Apps

Free apps don't charge merchants but can still generate value:

```json theme={null}
{
  "pricing": {
    "model": "free"
  }
}
```

**Use cases:**

* Lead generation for your other products
* Simple utilities that build goodwill
* Apps funded by other revenue (affiliate, data)
* Open source projects

<Info>
  Free apps are great for building reputation in the marketplace. Many developers start free and add paid tiers later.
</Info>

## One-Time Purchase

Single payment for permanent access:

```json theme={null}
{
  "pricing": {
    "model": "one_time",
    "oneTimePrice": 49.00,
    "currency": "USD"
  }
}
```

**Use cases:**

* Theme modifications
* One-time setup tools
* Templates and presets
* Migration utilities

**Considerations:**

* No recurring revenue
* Customer expects lifetime updates
* Lower total revenue per customer
* No ongoing relationship

## Recurring Subscription

Monthly and/or annual billing, the most common model. A single app has one
subscription price (there are no built-in multi-tier plans — model your
tiers as feature gates inside the app, or as separate apps):

```json theme={null}
{
  "pricing": {
    "model": "subscription",
    "monthlyPrice": 29.99,
    "currency": "USD"
  }
}
```

### Annual Billing

Offer an annual price alongside (or instead of) the monthly one. When both
are present, the merchant picks the interval at install:

```json theme={null}
{
  "pricing": {
    "model": "subscription",
    "monthlyPrice": 29.99,
    "yearlyPrice": 299.90,
    "currency": "USD"
  }
}
```

### Free Trial

Add `trialDays` to a subscription. During the trial the install is fully
functional; the first charge lands when the trial ends:

```json theme={null}
{
  "pricing": {
    "model": "subscription",
    "monthlyPrice": 29.99,
    "trialDays": 14,
    "currency": "USD"
  }
}
```

<Note>
  `trialDays` is the only trial control — there is no `requirePaymentMethod`
  option. The install row is created immediately in `trial` state and the
  merchant uses the app during the trial; the subscription's first
  `invoice.paid` flips it to `active`. If the merchant never completes the
  Stripe checkout that creates the subscription, the trial simply lapses with
  no charge.
</Note>

## Usage-Based Pricing

Charge per real-world event — per SMS sent, per AI generation, per
shipping label printed. Declared as a `usage` block on a `recurring`
plan (LaunchMyStore does not have a standalone `usage_based` model —
metered always rides on top of a Stripe subscription, even if the flat
monthly price is `0`):

```json theme={null}
{
  "pricing": {
    "model": "recurring",
    "monthlyPrice": 0,
    "currency": "usd",
    "trialDays": 0,
    "usage": {
      "unitName": "SMS",
      "unitAmount": 0.05,
      "cappedAmount": 50,
      "terms": "$0.05 per SMS sent, billed monthly"
    }
  }
}
```

Cap enforcement (`cappedAmount` = \$50 default monthly limit), idempotent
event reporting, and end-of-period invoice handling are wired into the
platform.

See [Usage-Based Billing](/billing/usage-billing) for the full event →
invoice flow and [Usage Records API](/api-reference/app-billing/usage-records)
for endpoint references.

## Hybrid Models

Combine models for flexibility:

### Freemium

The `freemium` model installs free (no charge, no Stripe checkout at
install), and your app gates premium features itself. There are no
platform-managed plan tiers — enforce the free-vs-paid limits in your own
backend, and drive an upgrade through a separate paid subscription or the
[usage/billing APIs](/api-reference/app-billing/subscriptions):

```json theme={null}
{
  "pricing": {
    "model": "freemium",
    "currency": "USD"
  }
}
```

### Base + Usage

Flat monthly subscription plus a per-event metered component — this is
the most common shape. Both items appear on one Stripe subscription;
the merchant sees a combined invoice each period.

```json theme={null}
{
  "pricing": {
    "model": "recurring",
    "monthlyPrice": 9.99,
    "currency": "usd",
    "trialDays": 14,
    "usage": {
      "unitName": "SMS",
      "unitAmount": 0.02,
      "cappedAmount": 50
    }
  }
}
```

Each `POST /api/v1/billing/usage` call adds one `UsageRecord` to the
Stripe metered item; at period end Stripe sums the records, multiplies
by `unitAmount`, and bills `monthlyPrice + total_usage`.

## Pricing Best Practices

<AccordionGroup>
  <Accordion title="Anchor with a higher tier">
    Show a premium tier even if most customers choose the middle option. It makes the mid-tier feel like a good value.
  </Accordion>

  <Accordion title="Limit the free tier">
    If offering freemium, make sure the free tier has meaningful limits that encourage upgrades as the merchant grows.
  </Accordion>

  <Accordion title="Offer annual discounts">
    15-20% annual discount reduces churn and improves cash flow. Frame it as "2 months free."
  </Accordion>

  <Accordion title="Avoid too many tiers">
    2-3 tiers is ideal. More than 4 creates decision paralysis.
  </Accordion>

  <Accordion title="Price based on value">
    Price based on the value you create, not your costs. A $50/month app that saves $500/month is a good deal.
  </Accordion>

  <Accordion title="Test pricing">
    A/B test pricing pages. Small changes can significantly impact conversion.
  </Accordion>
</AccordionGroup>

## Displaying Pricing

You don't build a pricing table. The marketplace listing and the install
consent screen render your price automatically from the `pricing` object
you set in the Developer Portal (or via `create_app`) — merchants see the
monthly/yearly/one-time amount and any trial before they install. Keep the
`pricing` fields accurate and the platform handles the display.

## Failed Payments & Grace Period

For platform-billed subscriptions (recurring/usage pricing via LaunchMyStore),
the platform manages the dunning lifecycle for you:

1. **Payment fails** → the installation's `billingStatus` becomes
   `past_due`, but your app **keeps working** — a 7-day grace window opens.
   You receive an `app_subscriptions/update` webhook with `graceEndsAt`.
2. **Payment recovers inside the window** (Stripe retries, or the merchant
   fixes their card) → `billingStatus` returns to `active` automatically;
   another `app_subscriptions/update` confirms it.
3. **Grace expires** → the installation is **disabled**: API access tokens,
   session-token minting and all extensions stop working. Webhook fires
   with `reason: "billing_grace_expired"`.
4. **Merchant cancels** → service continues until the end of the paid
   period (`reason: "cancel_scheduled"`), then the installation is
   disabled when Stripe finalizes the cancellation.
5. **Any later successful payment re-enables the installation** — treat
   disable as a pause, not an uninstall. Do **not** delete merchant data
   on disable; `shop/redact` after uninstall is the data-deletion signal.

See [`app_subscriptions/update`](/api-reference/webhooks/topics#app-lifecycle)
for payload details.

## Price Changes

When changing prices for existing customers:

1. **Grandfather existing customers** - Keep them on old pricing
2. **Give notice** - 30 days minimum for price increases
3. **Explain value** - Communicate what's improved

```javascript theme={null}
// Check if customer is on legacy pricing
async function getEffectivePrice(shopId) {
  const subscription = await getSubscription(shopId);
  
  if (subscription.legacyPlan) {
    return subscription.legacyPlan.price;
  }
  
  return currentPricing[subscription.planId].price;
}
```

## Currency Support

Each app declares a **single** billing currency via the `currency` field
(ISO-4217). All merchants are charged in that currency — there is no
per-currency price map and no `defaultCurrency` field:

```json theme={null}
{
  "pricing": {
    "model": "subscription",
    "monthlyPrice": 29.99,
    "currency": "USD"
  }
}
```

## Revenue Share

LaunchMyStore takes a percentage of app revenue:

| App Type         | Revenue Share |
| ---------------- | ------------- |
| Public apps      | 6%            |
| First-party apps | 0%            |
| Private apps     | 0%            |

Revenue share is calculated on gross revenue before refunds.

## See Also

* [Stripe Integration](/billing/stripe-integration) - Set up payments
* [Usage-Based Billing](/billing/usage-billing) - Implement usage metering
