Build any Discount Model

Introduction

One of the core principles our system is built upon is having flexible data structures. This schema is the means by which we can support any meter-type, price-machine, rewards algorithm, or discount you may want to apply.

This document is focused on the promotions model. We will discuss:

  1. The discount data structure.
  2. The generic discount - advanced, very flexible data structures.
  3. The discount templates - the more simplistic, but also more easily configurable data structures.

The discount structure

Generally speaking a promotion is made up of the following parts:

  1. Granularity
  2. Condition
  3. Discount-Model
  4. Measure

We will explain these notions in the next sections. For the moment let's start by introducing a high level diagram for the promotion structure:

832

Granularity

In a usage-based pricing world, an invoice contains many prices:

  1. Total invoice price (before discounts)
    1.1. The total usage price --is the sum of all of the item prices--> Total Price for a specific invoiced item individually --is the sum of all of the variant prices--> Prices for each specific item variant usage individually (invoice for an item with specific dimension values)
    1.2. Total fixed fee prices -- is the sum of all the fixed fees applied--> Price for each individual fee.

Granularity is an object to let us specify the target of the discount. Currently we support the following granularities:

  1. Product (or plan) - both discount the total invoice price.
  2. Item - discount the total price for a specific invoiced item (ie. a specific Product Item).

Down the line we may include additional granularities - for example, a discount for the total usage price, or a discount on a specific fixed fee. The important thing to remember, is that each part of the invoice can be a subject to a discount.


Condition

This part answers the following questions:

  1. Can we apply a discount? - can we apply a discount to the customer or can we keep the current discount from the previous cycle.
  2. Can we use the discount at this time? - even if we can apply a discount to a customer, it's still possible that we can't use it to discount the current invoice.

Below is a diagram describing the existing discount conditions:

778

Time-Limited Condition

This condition limits a discount for a certain amount of billing-cycles, months or the min of both.

If neither 'cycles' or 'months' are provided, or if the 'promotionTimeLimit' is not provided than there is no time limit to the discount.

Schema:

---
type: "object"
properties:
  requiredHistory:
    type: "object"
    properties:
      cycles:
        type: "integer"
        description: "max amount of billing cycles this promotion can be applied (optional)"
      months:
        type: "integer"
        description: "max amount of months this promotion can be applied (optional)"
  type:
    type: "string"

Same-Plan Condition

A condition for keeping a discount as long as the customer is on same plan as the plan used when applying the discount.

schema:

---
type: "object"
properties:
  type:
    type: "string"
		description: "must be same_plan"

After-Product Price-Threshold Condition

This condition simply tells our system to start applying the discount to an account after the customer has met a certain predefined "product-level bill threshold". This "threshold" is an accumulating sum of the total price of the current and previous invoice as specified in the 'requiredHistory' of the condition.

For example, this condition would allow for a discount which may be applied after the customer spends their first $1,000, regardless of how many billing cycles it takes to reach this threshold.

Schema:

---
type: "object"
properties:
  minThreshold:
    type: "number"
  requiredHistory:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  type:
    type: "string"
    description: "must be after_product_price_threshold"

After-Item Price-Threshold Condition

This condition is very similar to the Product-level Price-Threshold condition. This condition looks at the total price of a specific product item, as opposed to the total price of the entire product usage.

Schema:

---
type: "object"
properties:
  minThreshold:
    type: "number"
  itemId:
  	type: "string"
  requiredHistory:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  type:
    type: "string"
    description: "must be after_item_price_threshold"

Next Billing Cycle

This discount condition doesn't impose any condition for applying the discount.
Instead, it tells our system to start using a discount on the next month from the moment it was assigned.

---
type: "object"
properties:
  type:
    type: "string"

No Condition

This special "condition" is just to serve as a placeholder for condition in cases where we don't wish to specify any.

Schema:

---
type: "object"
properties:
  type:
    type: "string"

And Condition

The "and condition" is just a simple way to combine multiple conditions using an 'and' clause.

Schema:

---
type: "object"
properties:
  conditions:
    type: "array"
    items:
      type: "object"
      description: "an array of condition objects"
  type:
    type: "string"
    description: "must be and_condition"

Discount Model

This is the actual discount model we apply on the current invoice.

We currently support the following models:

674

Model with Max

This isn't a concrete model but rather a parent class of all of our existing models.

A "Model with Max" discount model comes with an optional total max discount (since the discount was applied) an optional billing cycle max discount.

Absolute

A constant discount for the entire bill (can be the product item or the entire product bill depending on the granularity).

Schema:

---
type: "object"
properties:
  cycleMaxDiscount:
    type: "number"
  discount:
    type: "number"
  measure:
    type: "object"
  requiredHistory:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"
		description: "must be and_condition"

Relative

The discount is a constant ratio of the total price (can be for a product item or the entire product bill depending on the granularity).

Schema:

---
type: "object"
properties:
  cycleMaxDiscount:
    type: "number"
  discountRatio:
    type: "number"
  measure:
    type: "object"
  requiredHistory:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"

Tiered absolute

This discount is similar to the absolute case, only in this case the discount amount is determined according to the total invoice price using some predefined discounting tiers.

Schema:

---
type: "object"
properties:
  cycleMaxDiscount:
    type: "number"
  discountValueMap:
    type: "object"
    additionalProperties:
      type: "number"
  measure:
    type: "object"
  requiredHistory:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"
		description: "must be price_tiered_absolute"

Example:

{
    "discountValueMap": {
        "50": 1
        "100": 10
    },
    "type": "price_tiered_absolute",
    "measure": {
        "type": "total_price"
    },
    "requiredHistory": {
        "cycles": 0,
        "months": 0
    },
    "totalMaxDiscount": null,
    "cycleMaxDiscount": null
}

The configuration above represents a tiered absolute discount of:

  1. $1 for any total price between $50 to $100.
  2. $10 for any total price of $100 or higher.

Tiered Relative

The tiered relative discount is more of a flexible case, and can actually contain the following two discounting algorithms:

  1. CHOOSE_SINGLE_TIER - the discount amount is determined according to the total invoice price using some predefined tiers and applied to the entire discountable price.
  2. STEP_FUNCTION- this option can be thought of in the same way income tax amounts are calculated. We split the total discountable price value into intervals (ranging from 0 to inf) where each interval starting point is marked as 'Ai' and identify the interval. Then the total discount is:
    total discount = sum over all Ai-s of Max(0, Min(Ai+1 - Ai, price-value - Ai)) * Discount-Ai

Schema:

---
type: "object"
properties:
  cycleMaxDiscount:
    type: "number"
  discountCalculationStrategy:
    type: "string"
    description: "STEP_FUNCTION, CHOOSE_SINGLE_TIER"
  discountRatioMap:
    type: "object"
    additionalProperties:
      type: "number"
  measure:
    type: "object"
  requiredHistory:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"
    description: "must be price_tiered_relative"

For example, let's assume the following tiers:

From PriceTo PriceDiscount
01000%
10010005%
1000inf6%

Now, for a price of $1050.

With 'CHOOSE_SINGLE_TIER' we will calculate a discount of:
1050 * 0.06 = $63 discount

With 'STEP_FUNCTION' we will calculate a discount of:
100 0.00 + (1000 - 100) 0.05 + (1050 - 1000) * 0.06 = 0 + 45 + 3 = $48 discount


Measure

Before moving forward to the different discount object types, let's cover one last (advanced object).

The discount model itself can work on the price, but can also work on:

  1. The usage using the average item price for each invoiced unit.
  2. A batch of usage using the item p

Why do we need the measure

Imagine that you want to give an absolute discount for an item-invoice.

An item invoice contains the:

  1. The total amount of usage for the item.
  2. The total price of the item usage.

Now, here are the options for giving an absolute discount for an invoiced item:

  1. TotalPrice- A discount of $X for the entire bill (bill can be product item-level or product-level depending on the granularity).
  2. PerUnit - A discount of $Y for each invoiced unit of usage invoiced.
  3. PerUnitBatch - A discount of $Z for each batch of N units of usage invoiced.

For example, you can give a $100 discount for the entire item-bill, but you can also give, let's say $0.01 for each invoiced unit of usage.

Schemas:

Total Price Schema:

---
type: "object"
properties:
  type:
    type: "string"
		description: "must be total_price"

Per Unit Schema:

---
type: "object"
properties:
  type:
    type: "string"
	  description: "must be per_unit"

Per Unit Batch Schema:

---
type: "object"
properties:
  batchSize:
    type: "integer"
  type:
    type: "string"
    description: "must be per_batch"

Generic Discounts

Generic models are the most advanced data structure we have. They are only available on the API and they allow you to create a specific discount if this isn't captured by any of the templates (mentioned below). As a rule of thumb, because generic discounts are more difficult to configure, we suggest you to first see if there is a template that fits your needs, and only if not consider using a generic promotions.

We currently support two types of generic models:

GenericProductPromotion

Schema:

---
type: "object"
properties:
  condition:
    type: "object"
  description:
    type: "string"
  id:
    type: "string"
  lockingStatus:
    type: "string"
    description: "OPEN, CLOSE_TO_DELETIONS, CLOSE_TO_CHANGES, DEPRECATED"
  promotionModel:
    type: "object"
  promotionName:
    type: "string"
  promotionType:
    type: "string"
    description: "only 'DISCOUNT' is currently supported"
    default: "DISCOUNT"
  targetProductId:
    type: "string"
  type:
    type: "string"
    description: "must be generic_product_promotion"

Example 1:

Below is an example for a product (granularity), time-limited (condition), relative (discount model) discount. Please compare it with the example for "Time Limited Relative Product Discount" below.

{
    "targetProductId": "ed7a3d38-bdd0-4db2-b047-2bc5d7b67336",
    "promotionType": "discount",
    "condition": {
        "type": "time_limited",
        "requiredHistory": {
            "cycles": 0,
            "months": 1
        }
    },
    "promotionModel": {
        "discountRatio": 0.1,
        "type": "relative",
        "measure": {
            "type": "total_price"
        },
        "requiredHistory": {
            "cycles": 0,
            "months": 1
        },
        "totalMaxDiscount": 100,
        "cycleMaxDiscount": 20
    },
    "id": "6aa33aa2-daf5-47b1-80c0-394127f383e7",
    "type": "generic_product_promotion",
    "promotionName": "55ed6c54-a201-4bfe-aaba-d9bd1b759d7c",
    "lockingStatus": "open"
}

Example 2:
A relative product-level discount with the following conditions:

  1. A total accumulating product price of $10 over the last 6 month (including current).
  2. A time limit of 18 months since the discount was first applied.

(Naturally you are less likely to configure such a discount, what we wanted to convey with this example is the flexibility of this schema.)

{
    "targetProductId": "392d5b67-f49d-43c9-979b-89b296063f79",
    "promotionType": "discount",
    "condition": {
        "type": "and_condition",
        "conditions": [
            {
                "type": "after_product_price_threshold",
                "requiredHistory": {
                    "cycles": 0,
                    "months": 6
                },
                "minThreshold": 10
            },
            {
                "type": "time_limited",
                "requiredHistory": {
                    "cycles": 0,
                    "months": 18
                }
            }
        ]
    },
    "promotionModel": {
        "discountRatio": 0.1,
        "type": "relative",
        "measure": {
            "type": "total_price"
        },
        "requiredHistory": {
            "cycles": 0,
            "months": 1
        },
        "totalMaxDiscount": 100,
        "cycleMaxDiscount": 20
    },
    "id": "36577499-d2d2-478d-974a-1f34bc7464e9",
    "type": "generic_product_promotion",
    "promotionName": "0a81c207-6232-4d08-88a1-e877a87c6d53",
    "description": null,
    "lockingStatus": "open",
    "lastUpdateTimeInMillis": 0
}

GenericItemPromotion

Schema:

---
type: "object"
properties:
  condition:
    type: "object"
  description:
    type: "string"
  dimensionConstraintMap:
    type: "object"
    description: "A map of dimension key to value (string to string) indicating that this promotion can only be applied against usage that includes the given dimension values."
    additionalProperties:
      type: "string"
  id:
    type: "string"
  lockingStatus:
    type: "string"
    description: "OPEN, CLOSE_TO_DELETIONS, CLOSE_TO_CHANGES, DEPRECATED"
  promotionModel:
    type: "object"
  promotionName:
    type: "string"
  promotionType:
    type: "string"
    description: "only 'DISCOUNT' is currently supported"
    default: "DISCOUNT"
  targetItemId:
    type: "string"
  type:
    type: "string"
    description: "must be generic_item_promotion"

Example 1:

Below is an example for an item (granularity), time-limited (condition), relative (discount model) discount. Please compare it with the example for "Time Limited Relative Product Discount" below.

{
    "targetItemId": "58e0a665-5244-4d01-8e1e-c0a7a72f169a",
    "promotionType": "discount",
    "condition": {
        "type": "time_limited",
        "requiredHistory": {
            "cycles": 0,
            "months": 1
        }
    },
    "promotionModel": {
        "discountRatio": 0.1,
        "type": "relative",
        "measure": {
            "type": "total_price"
        },
        "requiredHistory": {
            "cycles": 0,
            "months": 1
        },
        "totalMaxDiscount": 100,
        "cycleMaxDiscount": 20
    },
    "id": "50aa986b-d384-4dc4-8a9e-eee1f29f46f5",
    "type": "generic_item_promotion",
    "promotionName": "1675182e-5837-48e7-8df2-41a81aa9815f",
    "lockingStatus": "open",
    "lastUpdateTimeInMillis": 0
}

Example 2:

Below is an example for an item (granularity), time-limited (condition), relative (discount model) discount - exactly as in example-1. But we also added a constraint to it, that the discount can only be applied towards usage with the following dimension's values:

  1. cloudProvider = AWS
  2. region = us-west-2
{
    "targetItemId": "58e0a665-5244-4d01-8e1e-c0a7a72f169a",
    "promotionType": "discount",
    "condition": {
        "type": "time_limited",
        "requiredHistory": {
            "cycles": 0,
            "months": 1
        }
    },
    "dimensionConstraintMap": {
        "region": "us-west-2",
        "cloudProvider": "AWS"
    },
    "promotionModel": {
        "discountRatio": 0.1,
        "type": "relative",
        "measure": {
            "type": "total_price"
        },
        "requiredHistory": {
            "cycles": 0,
            "months": 1
        },
        "totalMaxDiscount": 100,
        "cycleMaxDiscount": 20
    },
    "id": "50aa986b-d384-4dc4-8a9e-eee1f29f46f5",
    "type": "generic_item_promotion",
    "promotionName": "1675182e-5837-48e7-8df2-41a81aa9815f",
    "lockingStatus": "open",
    "lastUpdateTimeInMillis": 0
}

Example 3:
A relative item discount with the following conditions:

  1. A total accumulating item price of $10 over the last 5 invoices (including current).
  2. A total accumulating product price of $500 over the last 5 invoices (including current).
  3. The plan wasn't changed since the discount has started.
  4. A time limit of 12 months since the discount was first applied.

(Naturally you are less likely to configure such a discount, what we wanted to convey with this example is the flexibility of the schema.)

{
    "targetItemId": "ca288a7c-9944-41d4-a7e2-d47eabce1496",
    "promotionType": "discount",
    "condition": {
        "type": "and_condition",
        "conditions": [
            {
                "type": "after_item_price_threshold",
                "itemId": null,
                "requiredHistory": {
                    "cycles": 5,
                    "months": 0
                },
                "minThreshold": 10
            },
            {
                "type": "after_product_price_threshold",
                "requiredHistory": {
                    "cycles": 5,
                    "months": 0
                },
                "minThreshold": 500
            },
            {
                "type": "same_plan"
            },
            {
                "type": "time_limited",
                "requiredHistory": {
                    "cycles": 0,
                    "months": 12
                }
            }
        ]
    },
    "promotionModel": {
        "discountRatio": 0.1,
        "type": "relative",
        "measure": {
            "type": "total_price"
        },
        "requiredHistory": {
            "cycles": 10,
            "months": null
        },
        "totalMaxDiscount": 100,
        "cycleMaxDiscount": 20
    },
    "id": "f2aac76a-840a-4608-b268-bae52615e637",
    "type": "generic_item_promotion",
    "promotionName": "d6a2eb2a-91f5-407d-bde9-2bfa2f1d6e7d",
    "description": null,
    "lockingStatus": "open",
    "lastUpdateTimeInMillis": 0
}

Templates

Template are the most common forms of discounts we see; because they represent patterns of discounts that repeats themselves, we wrapped them in an easy-to-use configuration.

Below is a list of the currently available templates:

Time-Limited Absolute Product Discount

Granularity: Product
Condition: Time-Limited
Discount Model: Absolute

Schema:

---
type: "object"
properties:
  description:
    type: "string"
  discount:
    type: "number"
  id:
    type: "string"
  lockingStatus:
    type: "string"
    description: "OPEN, CLOSE_TO_DELETIONS, CLOSE_TO_CHANGES, DEPRECATED"
  promotionName:
    type: "string"
  promotionTimeLimit:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  targetProductId:
    type: "string"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"
    description: "must be time_limited_absolute_product_discount"

Example:
In the example below we create a new discount which is limited to 12 months since the moment it is applied to a customer. The discount itself targets the entire invoice bill, and it can give a discount of up to $25 per invoice, or up to $100 for all consecutive invoices since the discount was applied.

{
    "targetProductId": "4d228d9e-0683-4636-b21f-81c4127298dc",
    "promotionTimeLimit": {
        "cycles": 0,
        "months": 12
    },
    "discount": 25,
    "totalMaxDiscount": 100,
    "id": "10de0900-7751-43f7-a415-fec4fa835009",
    "type": "time_limited_absolute_product_discount",
    "promotionName": "my promo",
    "lockingStatus": "open"
}

Time-Limited Absolute Item Discount

Granularity: Item
Condition: Time-Limited
Discount Model: Absolute

Schema:

---
type: "object"
properties:
  description:
    type: "string"
  dimensionConstraintMap:
    type: "object"
    additionalProperties:
      type: "string"
  discount:
    type: "number"
  id:
    type: "string"
  lockingStatus:
    type: "string"
    description: "OPEN, CLOSE_TO_DELETIONS, CLOSE_TO_CHANGES, DEPRECATED"
  promotionName:
    type: "string"
  promotionTimeLimit:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  targetProductItemId:
    type: "string"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"
    description: "must be time_limited_absolute_item_discount"

Example:
In the example below we create a new discount which is limited to 12 months since the moment it is applied to a customer. The discount itself targets the entire invoice of a single item usage ("552a8bf2-864e-4f89-87b0-0962aaec5cdf"), and it can give a discount of up to $10 per invoice, or up to $50 for all consecutive invoices since the discount was applied.

{
    "targetProductItemId": "552a8bf2-864e-4f89-87b0-0962aaec5cdf",
    "promotionTimeLimit": {
        "cycles": 0,
        "months": 12
    },
    "discount": 10,
    "totalMaxDiscount": 500,
    "id": "9d6cb505-bc9a-4ada-8f27-5b39a39428aa",
    "type": "time_limited_absolute_item_discount",
    "promotionName": "my promo",
    "lockingStatus": "open"
}

Time-Limited Relative Product Discount

Granularity: Product
Condition: Time-Limited
Discount Model: Relative

Schema:

---
type: "object"
properties:
  cycleMaxDiscount:
    type: "number"
  description:
    type: "string"
  discountRatio:
    type: "number"
  id:
    type: "string"
  lockingStatus:
    type: "string"
    description: "OPEN, CLOSE_TO_DELETIONS, CLOSE_TO_CHANGES, DEPRECATED"
  promotionName:
    type: "string"
  promotionTimeLimit:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  targetProductId:
    type: "string"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"
    description: "must be time_limited_relative_product_discount"

Example:
In the example below we create a new discount which is limited to 18 billing cycles since the moment it is applied to a customer. The discount itself gives a 10% discount on the top of the entire bill (up to $100 for all consecutive invoices since the discount was applied).

{
    "targetProductId": "feb90ba8-58a5-4c93-862a-8befc88c31c7",
    "promotionTimeLimit": {
        "cycles": 18,
        "months": 0
    },
    "discountRatio": 0.1,
    "totalMaxDiscount": 100,
    "cycleMaxDiscount": null,
    "id": "db859149-56e5-4b35-8946-96efdff0c7f9",
    "type": "time_limited_relative_product_discount",
    "promotionName": "my promo",
    "lockingStatus": "open"
}

Time-Limited Relative Item Discount

Granularity: Item
Condition: Time-Limited
Discount Model: Relative

Schema:

---
type: "object"
properties:
  cycleMaxDiscount:
    type: "number"
  description:
    type: "string"
  dimensionConstraintMap:
    type: "object"
    description: "A map of dimension key to value (string to string) indicating that this promotion can only be applied against usage that includes the given dimension values."
    additionalProperties:
      type: "string"
  discountRatio:
    type: "number"
  id:
    type: "string"
  lockingStatus:
    type: "string"
    description: "OPEN, CLOSE_TO_DELETIONS, CLOSE_TO_CHANGES, DEPRECATED"
  promotionName:
    type: "string"
  promotionTimeLimit:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  targetProductItemId:
    type: "string"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"
    description: "must be time_limited_relative_item_discount"

Example:
In the example below we create a new discount which is limited to 18 billing cycles since the moment it is applied to a customer. The discount itself gives a 10% discount on the top of the usage cost of item "acde888f-7720-4138-918d-f9442febc96e" (and up to $100 for all consecutive invoices since the discount was applied).

{
    "targetProductItemId": "acde888f-7720-4138-918d-f9442febc96e",
    "promotionTimeLimit": {
        "cycles": 18,
        "months": 0
    },
    "discountRatio": 0.1,
    "totalMaxDiscount": 100,
    "cycleMaxDiscount": null,
    "id": "768dbdb4-932b-430b-be8c-aae3a9a2c1ca",
    "type": "time_limited_relative_item_discount",
    "promotionName": "my promo",
    "lockingStatus": "open"
}

Time-Limited Tiered Absolute Product Discount

Granularity: Product
Condition: Time-Limited
Discount Model: Tiered-Absolute

Schema:

---
type: "object"
properties:
  acrossBillingPeriods:
    type: "boolean"
    description: "if true then the tier level discount will be detemined using the sum of all invoices since the promotion was applied."
  description:
    type: "string"
  discountMap:
    type: "object"
		additionalProperties:
    	type: "number"
  id:
    type: "string"
  lockingStatus:
    type: "string"
    description: "OPEN, CLOSE_TO_DELETIONS, CLOSE_TO_CHANGES, DEPRECATED"
  measure:
    type: "object"
  promotionName:
    type: "string"
  promotionTimeLimit:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  targetProductId:
    type: "string"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"
		description: "must be time_limited_tiered_absolute_product_discount"

Example:
In the example below we create a new discount which is not limited in time. The discount itself works on the entire bill, and it gives a $1 discount for the first $1 spent, and $2 discount if the invoice is $10.

{
    "targetProductId": "1",
    "promotionTimeLimit": {
        "cycles": 0,
        "months": 0
    },
    "discountMap": {
        "1": 1,
        "10": 2
    },
    "totalMaxDiscount": null,
    "id": "c58986fc-ee9f-427c-8163-3695c9dba0e1",
    "type": "time_limited_tiered_absolute_product_discount",
    "promotionName": "my promo",
    "lockingStatus": "open"
}

Example:
In the example below we create a new discount which is limited to 3 months. The discount itself works on the entire bill, and it gives a $1 discount for the first $1 spent per invoice, and $2 discount if the total amount of all of the invoices that occurred since the discount was applied is $10 or more.

{
    "targetProductId": "1",
    "acrossBillingPeriods": true,
    "promotionTimeLimit": {
        "cycles": 0,
        "months": 0
    },
    "discountMap": {
        "1": 1,
        "10": 2
    },
    "totalMaxDiscount": null,
    "id": "c58986fc-ee9f-427c-8163-3695c9dba0e1",
    "type": "time_limited_tiered_absolute_product_discount",
    "promotionName": "my promo",
    "lockingStatus": "open"
}

Time-Limited Tiered Absolute Item Discount

Granularity: Item
Condition: Time-Limited
Discount Model: Tiered-Absolute

Schema:

---
type: "object"
properties:
  acrossBillingPeriods:
    type: "boolean"
    description: "if true then the tier level discount will be detemined using the sum of all invoices since the promotion was applied."
  description:
    type: "string"
  dimensionConstraintMap:
    type: "object"
    description: "A map of dimension key to value (string to string) indicating that this promotion can only be applied against usage that includes the given dimension values."
    additionalProperties:
      type: "string"
  discountMap:
    type: "object"
		additionalProperties:
    	type: "number"
  id:
    type: "string"
  lockingStatus:
    type: "string"
    description: "OPEN, CLOSE_TO_DELETIONS, CLOSE_TO_CHANGES, DEPRECATED"
  measure:
    type: "object"
  promotionName:
    type: "string"
  promotionTimeLimit:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  targetProductItemId:
    type: "string"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"
    description: "must be time_limited_tiered_absolute_item_discount"

Example:
In the example below we create a new discount which is not limited in time. The discount itself works on the usage bill of item "2d59a1d5-31d7-409d-9d78-843f31eb3e08", and it gives a $1 discount for the first $1 spent, and $2 discount if the invoice is $10.

{
    "targetProductItemId": "2d59a1d5-31d7-409d-9d78-843f31eb3e08",
    "promotionTimeLimit": {
        "cycles": 0,
        "months": 0
    },
    "discountMap": {
        "1": 1,
        "10": 2
    },
    "totalMaxDiscount": null,
    "id": "4f7c999d-213f-4472-87c1-1b26da690338",
    "type": "time_limited_tiered_absolute_item_discount",
    "promotionName": "my promo",
    "lockingStatus": "open"
}

Time-Limited Tiered Relative Product Discount

Granularity: Product
Condition: Time-Limited
Discount Model: Tiered-Absolute

Schema:

---
type: "object"
properties:
  acrossBillingPeriods:
    type: "boolean"
    description: "if true then the tier level discount will be detemined using the sum of all invoices since the promotion was applied."
  cycleMaxDiscount:
    type: "number"
  description:
    type: "string"
  discountCalculationStrategy:
    type: "string"
    description: "STEP_FUNCTION, CHOOSE_SINGLE_TIER"
  id:
    type: "string"
  lockingStatus:
    type: "string"
    description: "OPEN, CLOSE_TO_DELETIONS, CLOSE_TO_CHANGES, DEPRECATED"
  priceToDiscountMap:
    type: "object"
		additionalProperties:
    	type: "number"
  promotionName:
    type: "string"
  promotionTimeLimit:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  targetProductId:
    type: "string"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"
    description: "must be time_limited_tiered_relative_product_discount"

Example:
In the example below we create a new discount which is limited to 18 billing cycles. The discount itself works on the entire invoice, and it gives a 10% discount for the first $10 spent, and 20% discount for any larger amount. There is a max of $19 per cycle and $100 for the entire life time of the discount. The discount itself is calculated using the "step_function" method mentioned above.

{
    "targetProductId": "1",
    "promotionTimeLimit": {
        "cycles": 18,
        "months": 0
    },
    "priceToDiscountMap": {
        "0": 0.1,
        "10": 0.2
    },
    "discountCalculationStrategy": "step_function",
    "totalMaxDiscount": 100,
    "cycleMaxDiscount": 19,
    "id": "67a63178-cdd4-48f6-a305-2038033abd9a",
    "type": "time_limited_tiered_relative_product_discount",
    "promotionName": "my promo",
    "lockingStatus": "open"
}

Time-Limited Tiered Relative Item Discount

Granularity: Item
Condition: Time-Limited
Discount Model: Tiered-Absolute

Schema:

---
type: "object"
properties:
  acrossBillingPeriods:
    type: "boolean"
    description: "if true then the tier level discount will be detemined using the sum of all invoices since the promotion was applied."
  cycleMaxDiscount:
    type: "number"
  description:
    type: "string"
  dimensionConstraintMap:
    type: "object"
    description: "A map of dimension key to value (string to string) indicating that this promotion can only be applied against usage that includes the given dimension values."
    additionalProperties:
      type: "string"
  discountCalculationStrategy:
    type: "string"
    description: "STEP_FUNCTION, CHOOSE_SINGLE_TIER"
  id:
    type: "string"
  lastUpdateTimeInMillis:
    type: "integer"
  lockingStatus:
    type: "string"
    description: "OPEN, CLOSE_TO_DELETIONS, CLOSE_TO_CHANGES, DEPRECATED"
  priceToDiscountMap:
    type: "object"
		additionalProperties:
    	type: "number"
  promotionName:
    type: "string"
  promotionTimeLimit:
    type: "object"
    properties:
      cycles:
        type: "integer"
      months:
        type: "integer"
  targetProductItemId:
    type: "string"
  totalMaxDiscount:
    type: "number"
  type:
    type: "string"
    description: "must be time_limited_tiered_relative_item_discount"

Example:
In the example below we create a new discount which is limited to 18 billing cycles. The discount itself works on the usage cost of item "806fdb8e-5bce-4b24-b6ce-ab37ef857e89", and it gives a 10% discount for the first $10 spent, and 20% discount for any larger amount. There is a max of $25 per cycle and $100 for the entire life time of the discount. The discount itself is calculated using the "step_function" method mentioned above.

{
    "targetProductItemId": "806fdb8e-5bce-4b24-b6ce-ab37ef857e89",
    "promotionTimeLimit": {
        "cycles": 18,
        "months": 0
    },
    "priceToDiscountMap": {
        "0": 0.1,
        "10": 0.2
    },
    "discountCalculationStrategy": "step_function",
    "totalMaxDiscount": 100,
    "cycleMaxDiscount": 25,
    "id": "4ba106b9-2ef5-48b5-bc13-24dcf6cd635d",
    "type": "time_limited_tiered_relative_item_discount",
    "promotionName": "my promo",
    "lockingStatus": "open"
}