Docs / plans

Configuring Plans

Plans are the core of your billing configuration. Each plan represents a pricing tier that customers can subscribe to.

Basic Plan Structure

yaml
plans:  - id: pro    name: Pro    headline: For growing teams    prices:      monthly: { amount: 2900 }      yearly: { amount: 29000 }    limits:      projects: 25      api_calls: 50000    features:      - Up to 25 projects      - Priority support

Plan Properties

PropertyTypeRequiredDescription
idstringYesUnique identifier (^[a-z][a-z0-9_]*$)
namestringYesDisplay name
headlinestringNoShort tagline for pricing page
descriptionstringNoLonger description
typeenumNopersonal, team, or enterprise
publicbooleanNoShow on pricing page (default: true)
defaultbooleanNoMark as default plan
trial_daysintegerNoTrial period in days
pricesobjectYesPricing configuration
limitsobjectNoEntitlement values
featuresarrayNoMarketing bullet points
upgrades_toarrayNoValid upgrade paths
metadataobjectNoCustom key-value data

Plan ID Guidelines

The id field must be: - Lowercase letters and numbers only - Start with a letter - No spaces (use underscores) - Unique across all plans - Stable (don't change after launch)

yaml
# Goodid: proid: enterprise_plusid: team_starter# Badid: Pro          # uppercaseid: "Pro Plan"   # spacesid: 1st_plan     # starts with number

Pricing Models

Flat Rate

Simple fixed price per billing period. Amounts are in cents.

yaml
prices:  monthly: { amount: 2900 }   # $29/month  yearly: { amount: 29000 }   # $290/year

Free Tier

yaml
prices:  monthly: { amount: 0 }

Per-Unit (Seats)

Price multiplied by quantity:

yaml
prices:  monthly:    per_unit: 1200      # $12 per seat    unit: seat    min: 1              # Minimum 1 seat    max: 100            # Maximum 100 seats    included: 1         # First seat free

Tiered Pricing

Progressive pricing with volume discounts:

yaml
prices:  monthly:    tiers:      - up_to: 10        amount: 2000      # $20/seat for 1-10      - up_to: 50        amount: 1500      # $15/seat for 11-50      - up_to: unlimited        amount: 1000      # $10/seat for 51+    mode: graduated       # or: volume

Modes: - graduated — each tier's price applies only to units within that tier - volume — the final tier's price applies to ALL units

Trial Periods

Offer free trials:

yaml
plans:  - id: pro    name: Pro    trial_days: 14    prices:      monthly: { amount: 2900 }

You can also set a default trial period in settings:

yaml
settings:  trial_days: 14plans:  - id: pro    # Inherits 14-day trial from settings

Billing Periods

Plans can have any combination of billing periods:

yaml
prices:  monthly: { amount: 2900 }  quarterly: { amount: 7900 }  yearly: { amount: 29000 }

One-Time Payments (Lifetime Plans)

For lifetime access or one-time purchases, use billing_model: one_time:

yaml
plans:  - id: pro_lifetime    name: Pro Lifetime    headline: Pay once, use forever    billing_model: one_time    prices:      one_time: { amount: 7900 }   # $79 once    limits:      projects: unlimited    features:      - Lifetime access      - All future updates

Key differences from subscriptions: - Uses billing_model: one_time instead of default subscription - Price key is one_time instead of monthly/yearly - No trial period (doesn't make sense for one-time) - Creates a Stripe Payment Intent, not a Subscription

This is useful for: - Lifetime deals - One-time setup fees - Digital products - Early-bird offers

Feature Lists

Marketing-friendly feature lists for pricing pages:

yaml
plans:  - id: pro    features:      - Up to 25 projects      - Advanced analytics      - Priority email support      - Custom domains      - API access

These are purely for display — actual access control uses limits.

Plan Limits

Define what the plan includes using entitlements:

yaml
# First, define entitlementsentitlements:  projects:    type: int    unit: project  api_requests:    type: rate    unit: request  sso:    type: bool# Then use them in plansplans:  - id: pro    limits:      projects: 25      api_requests: { limit: 1000, per: minute }      sso: false

Special values: - unlimited — no limit - Integer — fixed limit - Boolean — feature on/off - Rate object — { limit: N, per: period }

Plan Types

Categorize plans for filtering:

yaml
plans:  - id: starter    type: personal  - id: pro    type: team  - id: enterprise    type: enterprise

Upgrade Paths

Define valid upgrade destinations:

yaml
plans:  - id: starter    upgrades_to:      - pro      - enterprise  - id: pro    upgrades_to:      - enterprise

Plan Metadata

Store custom data:

yaml
plans:  - id: enterprise    metadata:      contact_sales: true      custom_contract: true      sla_tier: premium

Plan Versioning

When you change pricing for an existing plan, you may want to keep old subscribers on their current price (grandfathering). Use the version field to manage this:

yaml
plans:  - id: pro    version: 2    prices:      monthly: { amount: 2900 }  - id: pro_v1    version: 1    public: false    prices:      monthly: { amount: 1900 }
  • version — integer identifying the plan version. New subscribers get the latest version.
  • public: false — hides the old version from your pricing page. Existing subscribers stay on it until they upgrade.

Plan Ordering

Plans are displayed in the order they appear in the config:

yaml
plans:  - id: starter    # Left  - id: pro        # Center (recommended)  - id: enterprise # Right

Complete Example

yaml
plans:  - id: free    name: Free    headline: Get started for free    type: personal    public: true    default: true    prices:      monthly: { amount: 0 }    limits:      projects: 3      team_members: 1      api_requests: { limit: 100, per: minute }      sso: false    features:      - Up to 3 projects      - Basic analytics      - Community support  - id: pro    name: Pro    headline: For growing teams    type: team    trial_days: 14    prices:      monthly:        per_unit: 1900        unit: seat        min: 1        included: 1      yearly:        per_unit: 15900        unit: seat        min: 1        included: 1    limits:      projects: 25      team_members: 25      api_requests: { limit: 1000, per: minute }      sso: false    features:      - Up to 25 projects      - Advanced analytics      - Priority email support    upgrades_to:      - enterprise  - id: enterprise    name: Enterprise    headline: Custom solutions    type: enterprise    prices:      monthly: { amount: 0 }    limits:      projects: unlimited      team_members: unlimited      api_requests: { limit: 50000, per: minute }      sso: true    features:      - Unlimited everything      - Dedicated success manager      - SLA guarantee    metadata:      contact_sales: true

Best Practices

  1. Start simple — begin with 2-3 plans, add more as needed
  2. Clear differentiation — each plan should have obvious value over the previous
  3. Stable IDs — never change plan IDs after customers subscribe
  4. Descriptive features — write features from the customer's perspective