Pricing JSON
Pricing models are expressed as a single JSON object.
This document describes the structure of a pricing.json
file, and the behavior that each option implies. It is intended to be a comprehensive reference.
If you're getting started, or just want to see some examples, please check out the to see examples of pricing.json
files reflecting common SaaS pricing models or visit the to create a pricing model.
JSON Schema
A JSON schema for pricing.json
can be found at Pricing Schema.
Plans
The root object in a pricing.json
contains a plans
object.
Each key in the plans
object is a versioned plan name starting with plan:
. The values are plan
definitions.
For example:
{
"plans": {
"plan:basic@0": {
"title": "Just a basic plan",
"features": {
"feature:foo": {
"tiers": []
}
}
}
}
}
Note that we must put at least one feature
in the plan, or else tier will not accept it.
Once pushed, a plan may not be modified or deleted. A new version of the plan may be added, however:
{
"plans": {
"plan:basic@0": {
"title": "Just a basic plan",
"features": {
"feature:message": {}
}
},
"plan:basic@1": {
"title": "A new version of the plan"
"features": {
"feature:message": {}
}
}
}
}
Plan Objects
Each of the values in the plans
collection are plan
objects.
title
A plan
may contain a title
field, which must be a string if provided. This serves as a human-readable description of the plan for invoices and other content. If no title
is provided, then the plan ID is used instead.
interval
This is a string specifying the billing interval for the feature. It must be one of the following values:
"@daily"
- feature bills each day"@monthly"
- (default) feature bills each month"@yearly"
- The feature bills each year"@quarterly"
- The feature bills each quarter
currency
This is a string specifying the currency that features are priced in. Default is "usd"
.
features
The features
field is an object containing all of the features enabled by this plan. The keys in the features
field are feature names starting with feature:
. The values are feature
objects.
{
"plans": {
"plan:basic@2": {
"title": "Now with features!",
"features": {
"feature:message": {
"tiers": [{ "upto": 10, "price": 0 }]
}
}
}
}
}
Feature Objects
A feature object describes the pricing of a feature within the context of a plan.
A feature
object may contain the following fields:
title
A feature
may contain a title
field, which must be a string if provided. This serves as a human-readable description of the feature for invoices and other content.
mode
This is a string specifying how to determine a bill for a feature using "tiers"
.
"graduated"
- (default) price is set for each unit of usage according to the tier in which that usage occurs."volume"
- price is set for all units based on the total usage.
For example:
{
"plans": {
"plan:mode-example@123": {
"feature:volume": {
"mode": "volume",
"tiers": [{ "upto": 10, "price": 2 }, { "price": 1 }]
},
"feature:graduated": {
"mode": "graduated",
"tiers": [{ "upto": 10, "price": 2 }, { "price": 1 }]
}
}
}
}
If a customer on this plan consumed 10 units of either the feature:graduated
or feature:volume
feature, the price would be the same, because all usage falls within the first tier.
However, if the customer consumed 15 units of both, then the price for feature:graduated
would be:
v--- first tier usage and price
(10 * 2) + (5 * 1) = 25 <-- total
^--- second tier usage and price
However, their price for 15 units of the feature:volume
feature would be:
v--- total usage
15 * 1 = 15 <-- total
^-- price of final tier reached
aggregate
This string specifies the function used to determine the usage multiplier for calculating the total price at billing time. It may only be set on features that include tiers
.
This maps directly to Stripe's aggregate_usage
field.
sum
- (Default) Multiply total usage by the sum of all values reported during the periodmax
- Multiply total usage by the largest value reported during the periodlast
- Multiply total usage by the last value seen during the current period. If no usage was reported during the period, then0
is used.perpetual
- Multiply total usage by the last value seen, across all periods.
divide.by`, `divide.rounding
The divide.by
and divide.rounding
fields specify a transformation to apply to metered + per-unit priced features (e.g. one tier with a base price of 0
). The transformation is applied to the reported quantity before multiplying by the price when calculating the amount owed.
Valid divide.by
values are any positive integer.
Valid divide.rounding
values are "up"
and "down"
. The default is "down"
.
Example using divide.by
for reporting bytes, but charge $1.00per KB
, per period, rounding up to the nearest KB.
{
"plans": {
"plan:free@0": {
"features": {
"feature:storage": {
"divide": {
"by": 1024,
"rounding": "up"
},
"tiers": [
{
"price": 100
}
]
}
}
}
}
}
base
The base
field is a positive integer specifying the base price for features without tiers. It is an error to specify both the base
field and tiers.
tiers
An optional array of tier
objects to specify usage-based price tiers. If the feature has a top-level base
field, then this is not allowed.
{
"plans": {
"plan:basic@3": {
"title": "Now with *enabled* features!",
"features": {
"feature:message": {
"tiers": [{ "price": 1 }]
}
}
}
}
}
An empty tiers
array means that users on this plan are not entitled to any feature usage.
Tier Objects
Each tier may include the following fields:
upto
This is a positive integer specifying the maximum usage amount for this tier.
If not specified, the default is an unbounded tier (that is, infinite).
price
This is an integer specifying the per-unit price for any usage that occurs within this tier.
If not specified, the default is 0
.
base
This is an integer specifying flat price for any usage that occurs within this tier.
If not specified, the default is 0
.
Example
{
"plans": {
"plan:free@0": {
"title": "Todo (Free)",
"features": {
"feature:todo:lists": {
"tiers": [
{
"upto": 5
}
]
}
}
},
"plan:pro@0": {
"title": "Todo (Pro)",
"features": {
"feature:support:email": {
"base": 9900
},
"feature:todo:lists": {
"tiers": [
{
"upto": 100
}
]
}
}
}
}
}
Why Each Plan Must Have At Least One Feature
Due to the way that Stripe defines Products and Prices, and the fact that Tier endeavors to make everything as safely immutable as possible, every plan in your pricing.json
must have at least one feature defined.
Without this restriction, it would be significantly more expensive to fetch your pricing model from Stripe's data.
We aren't aware of any use cases where you'd want to have customers subscribed to plans that don't grant them access to any features (since that would be equivalent to not being subscribed to any plan at all!), but if you need this for your application, definitely let us know!