Skip to main content
Your autumn.config.ts file is the source of truth for your pricing. It exports features and plans using helper functions from the atmn package.
autumn.config.ts
import { feature, item, plan } from 'atmn';

export const messages = feature({ ... });
export const pro = plan({ ... });
Push changes with atmn push, or pull existing config with atmn pull.

Features

Features define what can be gated, metered, or billed in your app.

feature(config)

id
string
required
Unique identifier used in API calls (check, track, etc).
name
string
required
Display name shown in the dashboard and billing UI.
type
enum
required
"boolean" | "metered" | "credit_system"
consumable
boolean
Required for metered features.
  • true — usage is consumed (messages, API calls, credits)
  • false — usage is ongoing (seats, storage, workspaces)
creditSchema
array
Required for credit_system features. Maps metered features to credit costs.Each entry: { meteredFeatureId: string, creditCost: number }

Feature types

Boolean — simple on/off flag:
export const sso = feature({
  id: 'sso',
  name: 'SSO Authentication',
  type: 'boolean',
});
Metered, consumable — used up and replenished (messages, API calls):
export const messages = feature({
  id: 'messages',
  name: 'Messages',
  type: 'metered',
  consumable: true,
});
Metered, non-consumable — ongoing usage (seats, storage):
export const seats = feature({
  id: 'seats',
  name: 'Seats',
  type: 'metered',
  consumable: false,
});
Credit system — maps multiple metered features to credit costs:
export const basicModel = feature({
  id: 'basic_model',
  name: 'Basic Model',
  type: 'metered',
  consumable: true,
});

export const premiumModel = feature({
  id: 'premium_model',
  name: 'Premium Model',
  type: 'metered',
  consumable: true,
});

export const credits = feature({
  id: 'credits',
  name: 'AI Credits',
  type: 'credit_system',
  creditSchema: [
    { meteredFeatureId: basicModel.id, creditCost: 1 },
    { meteredFeatureId: premiumModel.id, creditCost: 5 },
  ],
});
If you set the price per credit to 1 cent, credits become monetary credits (eg, 5 credits = $0.05 per premium message).

Plans

Plans combine features with pricing to create your subscription tiers, add-ons, and top-ups.

plan(config)

id
string
required
Unique identifier used in checkout and subscription APIs.
name
string
required
Display name shown in pricing tables and billing.
price
object
Base subscription price:
  • amount: number — price amount (eg, 20 for $20)
  • interval: string"month" | "quarter" | "semi_annual" | "year" | "one_off"
items
array
Array of item() objects defining what’s included.
autoEnable
boolean
default:"false"
Automatically assign this plan to new customers. Typically used for free plans.
addOn
boolean
default:"false"
Allow this plan to be purchased alongside other plans (instead of replacing them).
freeTrial
object
Free trial before billing starts:
  • durationLength: number — eg, 14
  • durationType: string"day" | "month" | "year"
  • cardRequired: boolean — whether a card is needed to start the trial
group
string
Group related plans together. Plans in the same group replace each other on upgrade/downgrade.

Plan items

Plan items define what each plan includes — usage limits, pricing, and billing behavior.

item(config)

featureId
string
required
The id of the feature to include.
included
number
Amount included for free. Omit for boolean features.
unlimited
boolean
Grant unlimited usage of this feature.
reset
object
How often the included amount resets:
  • interval: string"hour" | "day" | "week" | "month" | "quarter" | "semi_annual" | "year"
  • intervalCount: number — defaults to 1
price
object
Pricing for usage beyond the included amount. See pricing patterns below.
proration
object
How to handle mid-cycle quantity changes:
  • onIncrease: "prorate" | "charge_immediately"
  • onDecrease: "prorate" | "refund_immediately" | "no_action"
rollover
object
Carry unused balance forward:
  • max: number — maximum rollover amount
  • expiryDurationType: "month" | "forever"
  • expiryDurationLength: number — ignored if type is "forever"

Pricing patterns

The price object on a plan item supports different billing models: Usage-based — charge based on actual usage:
item({
  featureId: seats.id,
  included: 5,
  price: {
    amount: 10,
    interval: 'month',
    billingMethod: 'usage_based',
    billingUnits: 1,
  },
})
Prepaid — customer buys a fixed quantity upfront:
item({
  featureId: credits.id,
  price: {
    amount: 5,
    billingUnits: 100,
    billingMethod: 'prepaid',
  },
})
Tiered — price changes based on usage volume:
item({
  featureId: apiCalls.id,
  price: {
    tiers: [
      { to: 1000, amount: 0.01 },
      { to: 10000, amount: 0.008 },
      { to: 'inf', amount: 0.005 },
    ],
    billingMethod: 'usage_based',
    interval: 'month',
  },
})

Price fields

amount
number
Price per billingUnits. Mutually exclusive with tiers.
tiers
array
Tiered pricing. Each entry: { to: number | "inf", amount: number }. Mutually exclusive with amount.
billingMethod
enum
required
"usage_based" | "prepaid"
interval
enum
"week" | "month" | "quarter" | "semi_annual" | "year". Omit for one-time charges. Not needed if the plan item has a top-level reset.
billingUnits
number
default:"1"
Units per price. Eg, $5 per 100 credits = amount: 5, billingUnits: 100.
maxPurchase
number
Maximum quantity that can be purchased.

Full example

A complete config with a free plan, a paid plan with a trial, and a credits top-up add-on:
autumn.config.ts
import { feature, item, plan } from 'atmn';

// Features
export const messages = feature({
  id: 'messages',
  name: 'Messages',
  type: 'metered',
  consumable: true,
});

export const seats = feature({
  id: 'seats',
  name: 'Seats',
  type: 'metered',
  consumable: false,
});

export const sso = feature({
  id: 'sso',
  name: 'SSO',
  type: 'boolean',
});

// Plans
export const free = plan({
  id: 'free',
  name: 'Free',
  autoEnable: true,
  items: [
    item({
      featureId: messages.id,
      included: 5,
      reset: { interval: 'month' },
    }),
    item({
      featureId: seats.id,
      included: 1,
    }),
  ],
});

export const pro = plan({
  id: 'pro',
  name: 'Pro',
  price: { amount: 20, interval: 'month' },
  freeTrial: {
    durationLength: 14,
    durationType: 'day',
    cardRequired: true,
  },
  items: [
    item({
      featureId: messages.id,
      included: 1000,
      reset: { interval: 'month' },
    }),
    item({
      featureId: seats.id,
      included: 5,
      price: {
        amount: 10,
        interval: 'month',
        billingMethod: 'usage_based',
        billingUnits: 1,
      },
    }),
    item({
      featureId: sso.id,
    }),
  ],
});

export const topUp = plan({
  id: 'top_up',
  name: 'Message Top-Up',
  addOn: true,
  items: [
    item({
      featureId: messages.id,
      price: {
        amount: 5,
        billingUnits: 100,
        billingMethod: 'prepaid',
      },
    }),
  ],
});