Fluent Commerce Logo
Docs
Essential knowledge

Intended Audience:

Technical User

Authors:

Holger Lierse, Kirill Gaiduk

Changed on:

24 Aug 2026

Overview

This page describes how to configure a control: the structure of the control data and the values each standard control type expects. For what each type does and how the utility resolves and applies controls, see the Controls Utilities Overview and the Detailed Technical Description on the Controls Utilities page.

Key points

  • Behavior is chosen by the `type` suffix: the suffix of `type` selects the control function of `type` (`...INCLUSION``...EXCLUSION``...BUFFER``...LIMIT``...THRESHOLD`).
  • Group-level controls use the `BULK_` prefix: Control Utils loads a control as group-level (bulk) only when its `type` begins with `BULK_`, for example `BULK_BUFFER`.
  • Every control needs a `context:` the `context` value decides which positions a control applies to. A control with no `context` never applies; a `CATALOGUE` context always matches.
  • Only `ACTIVE` controls apply: the utility only loads controls whose top-level status is `ACTIVE`.
  • Order is explicit: `executionOrder` orders controls within a group in ascending order; lower runs first.

Anatomy of a Control

Each control belongs to a control group. When the utility loads a control, it has the following structure:
1{
2  "ref": "Ctrl-001",
3  "type": "BULK_BUFFER",
4  "status": "ACTIVE",
5  "name": "Buffer for Category ABC",
6  "executionOrder": 0,
7  "values": [
8    { 
9        "name": "context", 
10        "type": "CONTEXT", 
11        "value": [ ... ] 
12    }
13  ]
14}
  • `type` - selects the control function by its suffix (`...INCLUSION``...EXCLUSION``...BUFFER``...LIMIT``...THRESHOLD`). Group-level (bulk) controls are loaded when `type` begins with `BULK_`; Position, Product and Variant level controls are matched by `ref`.
  • `status` - only controls with a `status` of `ACTIVE` are loaded.
  • `executionOrder` - orders controls within a group (ascending); the lowest value is applied first. When several controls of the same type can match one position only the first is applied, so give those controls distinct orders. 
  • `values` - the configuration. Every control carries a `context` value that decides which positions it applies to, plus any type-specific values described below.

Targeting with `context`

The `context` value is an array of matcher objects. All objects in the array must match for the control to apply to a position; where an individual object's `value` is itself an array, any one of those values may match.
1{ 
2    "name": "context", 
3    "type": "CONTEXT", 
4    "value": [
5        { 
6            "type": "CATEGORY", 
7            "property": "ref", 
8            "value": "ABC" 
9        }
10    ]
11}
  • `type` - what to match against: `PRODUCT``VARIANT``LOCATION``CATEGORY``NETWORK` or `POSITION``CATALOGUE` is a special case that always matches (used for catalog-wide controls).
  • `property` - the path within that entity, for example `ref``status`, or an attribute via `attributes.byName.<attributeName>`.
  • `value` - the expected value at that path. A single value, or an array of values of which any one may match.  
The structure of a `context` matcher:

A catalog-wide control (applies to every position in the catalog):
1{ 
2    "name": "context", 
3    "type": "CONTEXT", 
4    "value": [ 
5        { 
6            "type": "CATALOGUE" 
7        } 
8    ]
9}
Multiple matchers are combined with AND. The following applies only to product `AH8050` in network `F_NSW`:
1{ 
2    "name": "context", 
3    "type": "CONTEXT", 
4    "value": [
5        { 
6            "type": "NETWORK", 
7            "property": "ref", 
8            "value": "F_NSW" 
9        },
10        { 
11            "type": "PRODUCT", 
12            "property": "ref", 
13            "value": "AH8050" 
14        }
15    ]
16} 

Control Types

Inclusion

Sets the matched position's `status` to `ACTIVE`. Carries only a `context`.
1{
2  "ref": "Ctrl-inc-1",
3  "type": "BULK_INCLUSION",
4  "status": "ACTIVE",
5  "name": "Include Category ABC",
6  "executionOrder": 0,
7  "values": [
8    { 
9        "name": "context", 
10        "type": "CONTEXT", 
11        "value": [ 
12            { 
13                "type": "CATEGORY", 
14                "property": "ref", 
15                "value": "ABC"
16            } 
17        ] 
18    }
19  ]
20}

Exclusion

1{
2  "ref": "Ctrl-ex-1",
3  "type": "BULK_EXCLUSION",
4  "status": "ACTIVE",
5  "name": "Exclude Category ABC",
6  "executionOrder": 0,
7  "values": [
8    { 
9        "name": "context", 
10        "type": "CONTEXT", 
11        "value": [ 
12            { 
13                "type": "CATEGORY", 
14                "property": "ref", 
15                "value": "ABC" 
16                
17            } 
18        ] 
19    }
20  ]
21}
Sets the matched position's `status` to `INACTIVE`. Carries only a `context`.

Buffer (Absolute)

Adjusts the position `quantity` by a fixed amount. A negative `quantity` reduces available stock; a positive one increases it.
1{
2  "ref": "Ctrl-buf-1",
3  "type": "BULK_BUFFER",
4  "status": "ACTIVE",
5  "name": "Reduce size 10 by 10",
6  "executionOrder": 0,
7  "values": [
8    { 
9        "name": "context", 
10        "type": "CONTEXT", 
11        "value": [ 
12            { 
13                "type": "VARIANT", 
14                "property": "attributes.byName.size", 
15                "value": "10" 
16            } 
17        ] 
18    },
19    { 
20        "name": "quantity", 
21        "type": "INTEGER", 
22        "value": -10 
23    }
24  ]
25}

Buffer (Percentage)

A buffer control uses one of two values: a `quantity` value (the absolute buffer shown above) or a `percentage` value. When the control has no `quantity` value, the utility calculates the buffer as the `percentage` of the position's current quantity. A positive percentage increases the quantity; a negative one reduces it.
1{
2  "ref": "Ctrl-buf-2",
3  "type": "BULK_BUFFER",
4  "status": "ACTIVE",
5  "name": "Buffer Category ABC by 50%",
6  "executionOrder": 0,
7  "values": [
8    { "name": "context", "type": "CONTEXT", "value": [ { "type": "CATEGORY", "property": "ref", "value": "ABC" } ] },
9    { "name": "percentage", "type": "INTEGER", "value": 50 }
10  ]
11}

Limit

Clamps the position `quantity` so it is never below `min` nor above `max`.
1{
2  "ref": "Ctrl-lim-1",
3  "type": "BULK_LIMIT",
4  "status": "ACTIVE",
5  "name": "Cap AH8050 in F_NSW at 80",
6  "executionOrder": 1,
7  "values": [
8    { 
9        "name": "context", 
10        "type": "CONTEXT", 
11        "value": [
12            { "type": "NETWORK", "property": "ref", "value": "F_NSW" },
13            { "type": "PRODUCT", "property": "ref", "value": "AH8050" }
14        ]
15    },
16    { 
17        "name": "min", 
18        "type": "INTEGER", 
19        "value": 80 
20    },
21    { 
22        "name": "max", 
23        "type": "INTEGER", 
24        "value": 80
25    }
26  ]
27}

Threshold

Sets the position `status` when the `quantity` is at or below `threshold`. It changes status only, never quantity.
1{
2  "ref": "Ctrl-thr-1",
3  "type": "BULK_THRESHOLD",
4  "status": "ACTIVE",
5  "name": "Mark UNISEX_SHOES at risk under 200",
6  "executionOrder": 0,
7  "values": [
8    { 
9        "name": "context", 
10        "type": "CONTEXT", 
11        "value": [ 
12            { "type": "CATEGORY", "property": "ref", "value": "UNISEX_SHOES" } 
13        ]
14    },
15    { 
16        "name": "threshold", 
17        "type": "NUMBER", 
18        "value": 200 
19    },
20    { 
21        "name": "status", 
22        "type": "STRING", 
23        "value": "AT_RISK" 
24    }
25  ]
26}

Combined Example

A control group typically holds several controls of different types. The util applies them in a fixed order - inclusion, then exclusion, then buffer, then limit, then threshold - and the effect is cumulative: each type sees the quantity and status left by the previous one. Within a single type, the utility applies the most specific matching control (position or product level before group level).The controls below belong to one group scoped to category `ABC`: an absolute buffer and a two-tier threshold.
1[
2  {
3    "ref": "Ctrl-buf",
4    "type": "BULK_BUFFER",
5    "status": "ACTIVE",
6    "name": "Hold back 10 for Category ABC",
7    "executionOrder": 0,
8    "values": [
9      {
10        "name": "context",
11        "type": "CONTEXT",
12        "value": [
13          {
14            "type": "CATEGORY",
15            "property": "ref",
16            "value": "ABC"
17          }
18        ]
19      },
20      {
21        "name": "quantity",
22        "type": "INTEGER",
23        "value": -10
24      }
25    ]
26  },
27  {
28    "ref": "Ctrl-thr-oos",
29    "type": "BULK_THRESHOLD",
30    "status": "ACTIVE",
31    "name": "Out of stock at 0",
32    "executionOrder": 0,
33    "values": [
34      {
35        "name": "context",
36        "type": "CONTEXT",
37        "value": [
38          {
39            "type": "CATEGORY",
40            "property": "ref",
41            "value": "ABC"
42          }
43        ]
44      },
45      {
46        "name": "threshold",
47        "type": "NUMBER",
48        "value": 0
49      },
50      {
51        "name": "status",
52        "type": "STRING",
53        "value": "OUT_OF_STOCK"
54      }
55    ]
56  },
57  {
58    "ref": "Ctrl-thr-risk",
59    "type": "BULK_THRESHOLD",
60    "status": "ACTIVE",
61    "name": "At risk at 10",
62    "executionOrder": 1,
63    "values": [
64      {
65        "name": "context",
66        "type": "CONTEXT",
67        "value": [
68          {
69            "type": "CATEGORY",
70            "property": "ref",
71            "value": "ABC"
72          }
73        ]
74      },
75      {
76        "name": "threshold",
77        "type": "NUMBER",
78        "value": 10
79      },
80      {
81        "name": "status",
82        "type": "STRING",
83        "value": "AT_RISK"
84      }
85    ]
86  }
87]