# Business Rule

> For the complete machine-readable documentation index, see [llms.txt](https://apidocs.chargebee.com/llms.txt).


A business rule pairs a condition with the actions to take when that condition is met. You supply the context to evaluate, and Chargebee returns the actions configured in `actions_on_success` when the condition evaluates to `true`.

The condition is defined in `structured_expression`, a JSON representation of the rule logic that visual editors and dynamic rule builders can both read and write. Chargebee validates and compiles the expression when the rule is created or updated, and evaluates the compiled form when you call [Apply business rules](/docs/api/business_rules/apply-business-rules).

The `field` of every condition is resolved against the context supplied at evaluation time, so the fields you reference must match the keys of the context the rule is evaluated against. A condition whose `field` is absent from the context never evaluates to `true`, which means the rule never matches.

Business rules are versioned. Creating a rule releases its first version, so `latest_version` is `1` and `released_at` is set from the outset. Editing a rule leaves that released version untouched: the first edit creates a draft, and every later edit updates the same draft. [Releasing](/docs/api/business_rules/release-a-business-rule) the draft promotes it to the next version number, and that version becomes the latest released version and the one Chargebee evaluates. Until you release it, the previously released version stays in effect, so a rule can keep serving traffic while its next version is being prepared.

The `active` attribute is an independent switch that controls whether Chargebee evaluates the rule at all. A rule is created inactive, so it has to be [activated](/docs/api/business_rules/activate-a-business-rule) before it takes effect.

Related rules can be grouped into a [business ruleset](/docs/api/business_rulesets), which evaluates its member rules in priority order using the strategy configured in the ruleset's `execute_mode`.

For a walkthrough that creates, activates, and applies a rule in three calls, take a look at the [Business Rules quickstart](https://www.chargebee.com/tutorials/business-rules-quickstart/).

**Note:** Business rules are not enabled by default. Contact [Chargebee Support](https://www.chargebee.com/support/) to enable them for your site. Until they are enabled, these endpoints return an error.

## Expressions[](#expressions)

The `structured_expression` of a rule is a tree of nodes that evaluates to a single `true` or `false`. Every node carries a `type`, which determines the rest of the fields the node takes.

The following expression matches a quote from a customer whose language contains `en` and whose shipping country is India or the United States:

Every condition is compiled so that it first tests whether the field is present in the context. A condition on a field that the context doesn't carry evaluates to `false` instead of failing, so the rule that holds it never matches and no `error_message` is returned for it.

### GROUP node[](#group-node)

Combines the nodes in `children` into a single result. Use a `GROUP` as the root of any expression that has more than one condition, and nest groups to control precedence.

-   `operation`: **Required.** `AND` to match only if every child matches, or `OR` to match if any child matches.
-   `children`: **Required.** An array holding at least one node. Each entry is itself a `GROUP`, `CONDITION`, or `COLLECTION` node.

### CONDITION node[](#condition-node)

Compares one field of the context against a value.

-   `field`: **Required.** The path of the field through the context, such as `customer.language`. See [Context](/docs/api/business_rules#context) for the paths available.
-   `operator`: **Required.** How the comparison is made. See [Operators](/docs/api/business_rules#operators) for the operators available and the field types each one compares.
-   `value`: The single value to compare against. Required for the single-value operators.
-   `values`: The array of values to compare against. Required for `BETWEEN`, `ANY_OF`, and `NONE_OF`.

### COLLECTION node[](#collection-node)

Tests the entries of an array in the context, such as the line items of a quote. All four fields are required.

-   `field`: **Required.** The array to iterate over, such as `items`.
-   `variable`: **Required.** The name each entry is bound to while the predicate is evaluated.
-   `mode`: **Required.** `ANY` to match if at least one entry satisfies the predicate, or `NONE` to match only if no entry does.
-   `predicate`: **Required.** The expression each entry is tested against, usually a `GROUP` node.

Inside the predicate, address the fields of an entry through the bound `variable`. The following node matches a quote that has at least one item discounted by more than 20:

### Operators[](#operators)

The following operators are available. The field type is the type the operator can compare, and the value column shows whether the condition takes `value` or `values`.

Operator

Field type

Value

`EQUALS`, `NOT_EQUALS`

String, number, boolean

`value`

`GREATER_THAN`, `GREATER_THAN_OR_EQUALS`, `LESS_THAN`, `LESS_THAN_OR_EQUALS`

Number

`value`

`BETWEEN`

Number

`values`, holding exactly two entries, read as the inclusive lower and upper bounds

`CONTAINS`, `NOT_CONTAINS`

String

`value`

`STARTS_WITH`

String

`value`

`ANY_OF`, `NONE_OF`

String, number, boolean

`values`, holding at least one entry

An operator used on a field of another type isn't rejected when the rule is saved, so the mismatch surfaces only when the rule is evaluated.

## Context[](#context)

The `context` you pass to [Apply business rules](/docs/api/business_rules/apply-business-rules) isn't a free-form object. Its `type` selects the schema that the rest of the context is read as, and `CPQ` is the only type available, so a condition can reference only the fields of that schema. A key that falls outside the schema is dropped as the context is read, so a condition on it never evaluates to `true`. A misspelled or unsupported key therefore surfaces as an unmet condition rather than as an error.

A `CPQ` context carries `items`, `quote`, `customer`, `user`, `site`, and `quote_subscription`, each of them optional. Pass only the parts the rules you're evaluating need:

A condition addresses a field by its path through the context, so `customer.language` reads the `language` of the `customer`. A `COLLECTION` node on `items` iterates over the entries of that array.

Each `custom_fields` object holds your own fields keyed by name, and every value must be a string, a number, or a boolean. A condition reads one through its key, as in `quote.custom_fields.region`.

The response returns the context back with `rule_ids` filled in on the quote and on each item, so you can see which rules applied where.

### quote[](#quote)

-   `type` and `contract_type`: strings.
-   `contract_duration` and `payment_terms`: numbers.
-   `billing_address_country` and `shipping_address_country`: strings.
-   `billing_frequency` and `billing_currency`: strings.
-   `creator_email` and `creator_role`: strings.
-   `custom_fields`: object.
-   `rule_ids`: array of strings. Returned in the response rather than passed, recording the rules that applied to the quote.

### customer[](#customer)

-   `billing_address_city`, `billing_address_state`, and `billing_address_country`: strings.
-   `language`: string.
-   `payment_terms`: number.
-   `custom_fields`: object.

### items[](#items)

An array, with each entry holding the following.

-   `reference_id`: string, identifying the entry within the context.
-   `type`, `item_name`, and `product_family_name`: strings.
-   `billing_frequency` and `currency`: strings.
-   `billing_cycle`, `amount`, `quantity`, and `discount`: numbers.
-   `start_date` and `end_date`: timestamps.
-   `rule_ids`: array of strings. Returned in the response rather than passed, recording the rules that applied to that entry.

### user[](#user)

-   `name`, `email`, and `phone`: strings.

### site[](#site)

-   `name`, `domain`, and `currency`: strings.
-   `sandbox`: boolean.

### quote\_subscription[](#quotesubscription)

-   `custom_fields`: object.

## Actions[](#actions)

Every entry in `actions_on_success` is built from an **action template**, a built-in definition that fixes the kind of change an action makes and the parameters it accepts. An action names its template in `action_template_id` and passes that template's parameters in `input`:

The `type` of an action is derived from its template, so it's returned with the action but you don't have to pass it. A parameter that the template doesn't define is rejected. The values of enumerated parameters are matched without regard to case, and are returned in the `input` of the action exactly as you passed them.

An action can also carry a `structured_expression` of its own, written in the same format as the expression of the rule. The rule decides whether the action runs at all, and the action's own expression then narrows it to the items of the context that satisfy that expression. One rule can therefore discount some of the items it matched rather than all of them. Only the apply discount, limit discount, and limit quantity templates accept an action-level expression.

### Apply discount[](#apply-discount)

Applies a discount to the invoice amount or to specific item prices. Built from `action_template_id` `action-apply-discount` and returned with `type` `APPLY_DISCOUNT`.

-   `apply_on`: **Required.** `INVOICE_AMOUNT` to discount the invoice total, or `SPECIFIC_ITEM_PRICE` to discount the item prices the action applies to.
-   `discount`: **Required.** The discount to apply, such as `12.0`.
-   `discount_type`: **Required.** `PERCENTAGE`, `FLAT_FEE`, or `OFFER_QUANTITY`, which fixes how `discount` is read.
-   `duration_type`: **Required.** How long the discount applies, as `ONE_TIME`, `FOREVER`, or `LIMITED_PERIOD`.
-   `period_unit`: `DAY`, `WEEK`, `MONTH`, or `YEAR`. Required if `duration_type` is `LIMITED_PERIOD`.
-   `period`: The number of `period_unit`s the discount applies for. Required if `period_unit` is passed.

### Apply coupon[](#apply-coupon)

Applies existing [coupons](/docs/api/coupons). Built from `action_template_id` `action-apply-coupon` and returned with `type` `APPLY_COUPON`.

-   `apply_on`: **Required.** `INVOICE_AMOUNT` or `SPECIFIC_ITEM_PRICE`.
-   `coupon_ids`: **Required.** The coupons to apply, as an array of coupon identifiers. It must hold at least one identifier.

### Limit discount[](#limit-discount)

Caps the discount that can be given. Use this template to enforce a discount ceiling without an approval step.

Built from `action_template_id` `action-limit-discount` and returned with `type` `LIMIT_DISCOUNT`.

-   `apply_on`: **Required.** `INVOICE_AMOUNT` or `SPECIFIC_ITEM_PRICE`.
-   `maximum_discount`: **Required.** The largest discount allowed, such as `20.0`.
-   `discount_type`: **Required.** `PERCENTAGE`, `FLAT_FEE`, or `OFFER_QUANTITY`, which fixes how `maximum_discount` is read.
-   `disable_price_override`: Pass `true` to disallow overriding the price outright.

### Limit quantity[](#limit-quantity)

Constrains the quantities that can be selected. Built from `action_template_id` `action-limit-quantity` and returned with `type` `LIMIT_QUANTITY`. Every parameter is optional, so pass the ones you want to enforce.

-   `minimum_quantity`: The smallest quantity allowed.
-   `maximum_quantity`: The largest quantity allowed.
-   `quantity_step_count`: The increment the quantity can be changed in, so `5` allows 5, 10, 15, and so on.

### Error[](#error)

Returns an error message instead of a change. Use this template to block an operation when the rule matches.

Built from `action_template_id` `action-error` and returned with `type` `ERROR`.

-   `error_message`: **Required.** The message returned with the action.

## Evaluation results[](#evaluation-results)

[Apply business rules](/docs/api/business_rules/apply-business-rules) returns an `apply_rule` object that echoes back the `context` you passed and carries one entry in `rules` for each rule it evaluated:

Read the result of each rule from `evaluation_result`, and read what the rule produced from `actions`. Two things about the shape are worth knowing before you write code against it.

-   `actions` is absent, rather than empty, for a rule whose `evaluation_result` is `false`. The second entry above shows a rule that didn't match.
-   An entry for an ad hoc `structured_expression` carries only `evaluation_result`, because there's no stored rule to report an `id`, `name`, or `actions` for.

A rule that couldn't be evaluated is returned with `error_message` set instead, but only if you passed `skip_failed_rules` as `true`. Otherwise the request fails. For the full list of fields, see the response of [Apply business rules](/docs/api/business_rules/apply-business-rules).

## Sample Business rule

```json
{
  "id": "custom-uuid-1",
  "name": "Apply 12 percentage discount at invoice level",
  "description": "Apply 12 percentage discount at invoice level",
  "latest_version": 1,
  "active": false,
  "released_at": 1788510782,
  "released_by": "full_access_key_v1",
  "updated_at": 1788510782,
  "updated_by": "full_access_key_v1",
  "created_by": "full_access_key_v1",
  "created_at": 1788510782,
  "tags": [
    "CPQ",
    {..}
  ],
  "structured_expression": {
    "type": "GROUP",
    "operation": "AND",
    "children": [
      {
        "type": "CONDITION",
        "field": "customer.language",
        "operator": "CONTAINS",
        "value": "en"
      },
      {..}
    ]
  },
  "actions_on_success": [
    {
      "input": {
        "apply_on": "invoice_amount",
        "duration_type": "one_time",
        "discount": 12,
        "discount_type": "percentage"
      },
      "action_template_id": "action-apply-discount",
      "type": "APPLY_DISCOUNT"
    },
    {..}
  ],
  "resource_version": 1788510782918,
  "object": "business_rule"
}
```

## Business Rule attributes

## Input Parameters

- `id` (required, string, max chars=100)
  Unique identifier of the business rule.

- `name` (required, string, max chars=500)
  Display name of the business rule.

- `description` (optional, string, max chars=1000)
  Description of what the business rule does.

- `latest_version` (optional, integer)
  Version number of the released version that is currently in effect. It is `1` for a newly created rule, and is incremented every time a draft is released.

- `active` (required, boolean)
  Whether Chargebee evaluates the rule. A rule is created inactive. Use [Activate a business rule](/docs/api/business_rules/activate-a-business-rule) and [Deactivate a business rule](/docs/api/business_rules/deactivate-a-business-rule) to change this value.

- `released_at` (optional, timestamp(UTC) in seconds)
  Timestamp at which the version in `latest_version` was released. It is set when the rule is created and updated on every subsequent release.

- `released_by` (optional, string, max chars=100)
  User or API key that released the version in `latest_version`.

- `updated_at` (required, timestamp(UTC) in seconds)
  Timestamp at which the rule was last modified.

- `updated_by` (optional, string, max chars=100)
  User or API key that last modified the rule.

- `created_by` (required, string, max chars=100)
  User or API key that created the rule.

- `created_at` (required, timestamp(UTC) in seconds)
  Timestamp at which the rule was created.

- `structured_expression` (optional, jsonobject)
  A structured JSON representation of the rule logic, used for programmatic interpretation and for rendering the rule in visual editors and dynamic builders.
  
  See [Expressions](/docs/api/business_rules#expressions) for the node types and the operators each field type supports, and [Context](/docs/api/business_rules#context) for the fields a condition can reference.

- `actions_on_success` (optional)
  The actions returned by Chargebee when the rule expression evaluates to `true`. Each action carries its `type`, the `action_template_id` of the template it is built from, and the parameters of that template in `input`.
  
  See [Actions](/docs/api/business_rules#actions) for the templates available, the parameters each one takes, and the optional action-level `structured_expression`.

- `resource_version` (optional, long)
  Version number of this resource. Each update of the resource increments the `resource_version`. Concurrent updates can be detected by comparing this value across requests.

