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 a lineItem 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 the unitAmountDecimals field.

    • For example, "unitAmountDecimals" : 5 means that the cost of this price is 5.
  • tiered: means that the cost of the price is defined by the tranches within the tier field.

    • See the tier field below for an example.

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, and gbp .

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 and subscription.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 and subscription.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.
  • interval: number Defines the frequency of each billing period, from block (for real-time streamed payments, coming soon), min, hr, day, week, month to year.
  • intervalCount: number Defines the number of intervals between billing periods.
    • E.g., with "interval": "day" and intervalCount: 2, the customer is billed every 2 days.
    • The maximum total amount of time between billing periods is 5 years.
  • usageType: enum Defines whether your billing is licensed or metered. 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 and invoice, payment methods require lineItems. lineItems are the connection between products and their payment methods.
      • A lineItem has three fields:
        • (1) The id of the price object, and therefore the product object that it points to, that will be included as an item for sale in the checkout.
        • (2) quantity, a number defining the default amount of a given product being bought.
        • (3) quantityMutable, a boolean for if customers can adjust the default quantity.
      • If licensed is selected, then customers will be charged for price x quantity.
        • If quantityMutable is true, then quantity is whatever the customer chooses.
    • 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 as usageAggregation and tier inside the price 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.
  • 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 to tiered, 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. +10
  • volume 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 to inf 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.