Prices describe how much your products cost.
Once you have created a product
, next you will need to create a price
.
The price points to a specific product and will set how much that product costs, as well as important details like whether that product is paid for on a one-time or recurring (subscription) basis, and if pricing is tiered.
The price object
Let's take a look at a full price
object:
{
"id": "price_d2e4fba4b9b44f39ada98f48ac6fab97",
"active": false,
"billingScheme": "tiered",
"created": "2021-01-01T00:00:00.000Z",
"currency": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"description": "This price encodes your billing scheme and can be attached to products.",
"lookupKey": "123e4567-e89b-12d3-a456-426614174000",
"meta": {
"uuid": "<your_uuid>"
},
"name": "Example Price",
"network": "sol",
"product": "product_94373caad0004e3e96c9e3b23d0c96c0",
"recurring": {
"type": "delegated",
"defaultLength": 5,
"interval": "month",
"intervalCount": 1,
"usageAggregation": "latest",
"usageType": "metered"
},
"taxBehavior": "inclusive",
"tiers": [
{
"flatAmount": "100",
"flatAmountDecimal": 10,
"unitAmount": "10",
"unitAmountDecimal": 1,
"upTo": 100
},
{
"flatAmount": "0",
"flatAmountDecimal": 20,
"unitAmount": "20",
"unitAmountDecimal": 2,
"upTo": "inf"
}
],
"tierType": "volume",
"type": "oneTime",
"unitAmountDecimal": 10,
"updated": "2021-01-01T00:00:00.000Z"
}
id
: string
Unique identifier for the object. Auto-generated by Sphere upon creation.
active
: boolean
Denotes whether your price is usable in new payment methods.
- Inactive
price
objects passed as alineItem
to a payment method will return an API error. - Pre-existing payment methods with a newly inactive price will continue to function. Recommended to update the payment method directly to make it inactive or remove specific line items.
billingScheme
: enum
Critical because it defines how the total cost of the price will be calculated.
-
perUnit
: means that the cost of the price is defined by theunitAmountDecimals
field.- For example,
"unitAmountDecimals" : 5
means that the cost of this price is 5.
- For example,
-
tiered
: means that the cost of the price is defined by the tranches within thetier
field.- See the
tier
field below for an example.
- See the
created
: string
datetime for when the price was created.
currency
: string
Defines the underlying token or money for the price.
- For crypto, it is the public key for the mint address (Solana) or token contract address (EVM).
- For fiat, it is one of
usd
,euro
, andgbp
.
description
: string
Describes your price. Hidden from users. Max length (500).
lookupKey
: string
Used to retrieve prices quickly from a list of products. Useful if your products have many different prices. Unique. Max length (200).
meta
: object
Set of key-value pairs (JSON) for arbitrary usage. Used to save structured information about the object to reference elsewhere. Think of it as general purpose storage space.
name
: string
The name of your price. Hidden from users. Max length (500).
network
: enum
The underlying network of your subscription. Either a blockchain abbreviation or fiat
.
- For cross-chain payments, this identifies the destination chain that your
price
will live on. - Other than cross-chain, it is useful if your
currency
is an Ethereum token contract address and you would like to specify which EVM-compatible or equivalent blockchain it is native to.
product
: string
The id
of the product that this price points to.
- This field is critical because it is what connects your price with a product.
- It is strongly recommended that you use this field upon creation of a price, although it is technically optional and you can always go back and update it.
recurring
object
Relevant if the type
of your price is recurring (e.g., a subscription).
type
:enum
Critical. Defines whether the customer pays for the subscription by pre-funding an escrow account (escrowed), or approving automatic withdrawals from their wallet (delegated).escrowed
:string
Customers lock up funds dedicated to the subscription in an escrow account. Each billing period, funds will be withdrawn from that account.- Customers can withdraw at anytime through the subscription management portal. You can also use the withdraw escrow funds endpoint to serve the transaction on your own frontend.
- Similarly, customers may top-off their escrow account either through the subscription management portal or your own frontend via the add escrow funds endpoint.
- We suggest listening for the
subscription.escrowed.low_balance
andsubscription.escrowed.insufficient
events to appropriately notify your customers.
delegated
:string
Customers approve to have funds automatically drawn from their wallet at the end of each billing period. If there are insufficient funds, the subscription is voided.- Customers may revoke delegation in the subscription management portal. You can also use the revoke delegation endpoint to serve the transaction on your own frontend.
- Similarly, customers may approve for additional tokens to be delegated either through the subscription management portal or your own frontend via the extend delegation endpoint.
- We suggest listening for the
subscription.delegated.insufficient
andsubscription.delegated.redelegated
events to appropriately notify your customers.
defaultLength
:number
Defines the default number of billing periods to approve token transfers for. Relevant if your subscription's billing scheme is escrowless (e.g.,delegated
).- E.g., with
"defaultLength": 3
and"interval": month
, the customer will be prompted to approve the delegation of tokens equal to the amount of 3 months of billing upon subscribing.
- E.g., with
interval
:number
Defines the frequency of each billing period, fromblock
(for real-time streamed payments, coming soon),min
,hr
,day
,week
,month
toyear
.intervalCount
:number
Defines the number of intervals between billing periods.- E.g., with
"interval": "day"
andintervalCount: 2
, the customer is billed every 2 days. - The maximum total amount of time between billing periods is 5 years.
- E.g., with
usageType
:enum
Defines whether your billing islicensed
ormetered
.licensed
means that your customers will be charged based upon the quantity they specify upon checkout, irrespective of usage. Oppositely,metered
means that your customer will get charged based upon their total usage.licensed
can get a little complicated, so let's break it down.- As we will explain in further detail in
paymentLink
andinvoice
, payment methods requirelineItems
.lineItems
are the connection between products and their payment methods. - A
lineItem
has three fields:- (1) The
id
of theprice
object, and therefore theproduct
object that it points to, that will be included as an item for sale in the checkout. - (2)
quantity
, anumber
defining the default amount of a givenproduct
being bought. - (3)
quantityMutable
, aboolean
for if customers can adjust the defaultquantity
.
- (1) The
- If
licensed
is selected, then customers will be charged forprice
xquantity
.- If
quantityMutable
is true, thenquantity
is whatever the customer chooses.
- If
- As we will explain in further detail in
metered
means that your customer will be billed based on their usage.- This is calculated on your backend and passed to Sphere through the
usageRecords
object, with the exact details for pricing, such as the underlying pricing model, being defined by fields such asusageAggregation
andtier
inside theprice
object. - Check out Usage Records for more details. You will need to create
usageRecord
objects for each subscription customer periodically so we can appropriately bill them for their usage.
- This is calculated on your backend and passed to Sphere through the
usageAggregation
:enum
Defines how usage for metered billing is calculated.sum
: The customer will be billed for the sum of their usage over the current billing period.latest
: The customer will be billed for the latest reported usage, irrespective of billing period.max
: The customer will be billed for the maximum of their usage over the current billing period.
taxBehavior
: enum
Identifies whether the price is inclusive or exclusive of taxes.
inclusive
: Your price includes taxes.- E.g., a tax inclusive price of $10 could mean the "true" value of the product is $9, with a tax of $1.
exclusive
: Your price does not include taxes.- E.g., a tax exclusive price of $10 means that the "true" value of the product is $10.
- Note: this field is primarily intended for your own accounting purposes. Sphere's billing engine will apply whatever
taxRate
is defined to tax exclusive products during payment.
tier
: object
Defines details in your pricing model and makes it convenient to tier pricing.
- Note: this parameter requires
billingScheme
to be set totiered
, otherwise it'll produce an error.
(Note: we suggest creating separate products if you want to offer a standard 3-tier product e.g., Bronze, Silver, Gold. Although it is technically possible to create this tiering through a single product using the tier
field, it typically results in object overload and unexpected behavior, so is not recommended.)
Tiering can get complicated, so let's start with the basic example from above.
"tiers": [
{
"flatAmount": "100",
"flatAmountDecimal": 10,
"unitAmount": "10",
"unitAmountDecimal": 1,
"upTo": 100
},
{
"flatAmount": "0",
"flatAmountDecimal": 20,
"unitAmount": "20",
"unitAmountDecimal": 2,
"upTo": "inf",
},
],
In this example, we've defined two tiers. We can ignore the non-decimal sub-fields, as they contain the same information as the decimal sub-fields, but just presented as the raw default integer value of a token.
The algorithm for total billing will depend on the tier type.
tierType
: enum
Defines how usage costs are calculated across different tiers.
- Graduated billing sums up the cost of usage as you go up tiers.
- Whereas volume based billing will assume the most recent tier that was reached.
Let's suppose the customer is being billed for 110 units.
- If we're using
graduated
pricing, then the total will be: 10 + 1(100) + 2(10) = 130. - If we're using
volume
based pricing, then the total will be: 0 + 2(110) = 220.
Let's break this calculation down.
The first tier defines a flatAmountDecimal
of 10, while the second tier defines a flatAmountDecimal
of 0.
flatAmountDecimal
: number
The flat cost for usage in a given tier. Formatted to base-10.
- This means that usage within the first tier will trigger a flat cost of 10 tokens.
graduated
calculates progressively by each tier. Hence, the first 100 units of usage triggers the 10 token cost set by tier 1. The next 10 units of usage triggers the 0 token cost set by tier 2. +10volume
calculates by most recent tier. Hence, it ignores the flat cost of 10 set by tier 1 because 110 units of usage gets us into tier 2, where the flat token cost is 0. +0
unitAmountDecimal
: number
The per-unit cost for each unit of usage in a given tier. Formatted to base-10.
The first tier also sets a unitAmountDecimal
of 1, while the second tier sets a unitAmountDecimal
of 2.
- This means each unit of usage in tier 1 costs 1 token, while each unit of usage in tier 2 costs 2 tokens.
graduated
calculates progressively by each tier. So the first 100 units of usage costs 1 token each, whereas the last 10 units of usage cost 2 tokens each. 1(100) + 2(10) = +120.volume
calculates by most recent tier. So we ignore the cost of usage in tier 1, since 110 units of usage means that we're in tier 2. With each unit of usage costing 2 tokens each, 2(110) = +220.
You'll notice that for the last defined tier, upTo
is set to inf
.
upTo
: number
Defines the number of units of usage that the given tier goes up to.
- This is critical. Because your last defined tier covers the pricing for all potential usage indefinitely, if you don't set
upTo
toinf
in that final tier, the API will throw an error.
If you're still confused, check out the tier guide.
type
: enum
Critical because it defines whether the product you attach this price to is paid for on a one-time or on a recurring basis (subscription). Defaults to oneTime
, but if set to recurring
you will be able to define key variables such as the billing period (in the recurring
field) and pricing model (in tier
).
unitAmountDecimal
: number
Defines the default cost of your price, automatically converting the amount of raw token units for a given currency into base-10 (decimals).
- For example, SOL has a default unit amount of 10^e-9 and ETH is 10^e-18. Instead of passing in "1,000,000,000" to represent a cost of 1 SOL, you can just pass in "1".
updated
: string
datetime for when the price was last updated.