Modifiers let buyers customize a line item at purchase time: size, toppings, add-ons, or free-text input like an engraving message. The model has three layers:
- A modifier group is a single buyer-facing prompt (a choose-from-a-list group or a text input) with selection rules like min/max selected and per-choice quantities.
- Each choice within a group is a modifier, with its own optional price adjustment and tax settings.
- A modifier set collects groups into an ordered bundle, with per-set overrides for display, defaults, pricing, and availability.
Set modifier_set_id on a product, variant, or bundle to offer those modifiers. Send null to remove the set. When a buyer makes a selection, the order line item stores a priced snapshot for receipts and fulfillment.
Modifier groups and choices#
For example, a single-choice group can require exactly one selection:
{
"name": "Milk",
"modifier_group_type": "list",
"min_selected": 1,
"max_selected": 1
}
Modifier sets#
Add engraving to a product#
Create the set and its text group in one request:
{
"name": "Engraving",
"modifier_groups": [
{
"source": "inline",
"modifier_group": {
"name": "Engraving message",
"modifier_group_type": "text",
"allow_quantities": false,
"text": {
"required": true,
"max_length": 40,
"multiline": false
}
}
}
]
}
An inline group belongs to its modifier set. The response includes the generated modifier_set_group_id and a complete nested modifier_group, including its modifier_group_id and modifier IDs. To edit it, send the same inline shape back through the modifier set. Include IDs for the group and any modifiers you want to retain. Omitting a modifier archives it.
{
"expected_version": 1,
"modifier_groups": [
{
"source": "inline",
"modifier_set_group_id": "msg_01J00000000000000000000000",
"modifier_group": {
"modifier_group_id": "mg_01J00000000000000000000000",
"name": "Engraving message",
"modifier_group_type": "text",
"allow_quantities": false,
"text": {
"required": true,
"max_length": 60,
"multiline": true
}
}
}
]
}
Send this body to PATCH /v1/modifier-sets/{modifier_set_id}. Inline groups are not available through /v1/modifier-groups. Use source: "existing" when the group should remain an independent, reusable resource.
Then attach the returned set to the product:
{
"modifier_set_id": "ms_01J00000000000000000000000"
}
Send the second body to PATCH /v1/products/{product_id}. Read the product with expand=modifier_set to include its groups and overrides.
Replace a line item's selections#
Read the order, then send the line item's current version as expected_version to PATCH /v1/orders/{order_id}/line-items/{order_line_item_id}. The modifiers array replaces all selections on that line item. Keep a selection by including its order_line_item_modifier_id, remove it by omitting it from the array, or send an empty array to clear every selection.
Each array item must contain exactly one selection source:
- For a list choice, send
modifier_id. You may also sendquantitywhen the group allows quantities. - For text, send
textwith bothmodifier_group_idandvalue. Text selections do not acceptquantity.
{
"expected_version": 3,
"modifiers": [
{
"order_line_item_modifier_id": "olim_01J00000000000000000000000",
"modifier_id": "mod_01J00000000000000000000000",
"quantity": 1
},
{
"text": {
"modifier_group_id": "mg_01J00000000000000000000000",
"value": "Happy birthday"
}
}
]
}
An order_line_item_modifier_id can only retain the same list choice or text group from the current line item. Omit the ID to create a replacement selection. If another request changes the line item first, Flint returns 409 ORDER_LINE_ITEM_VERSION_CONFLICT. Read the order again and retry with the new line-item version.
Send the group's last-read version as expected_version when PATCH includes modifiers. Include modifier_id to retain a choice, omit the ID to create one, and omit a previous choice to archive it. Omission leaves the collection unchanged; null is invalid. An empty array is allowed only when the resulting group permits no choices. Choices referenced by a non-archived modifier set cannot be removed. A stale version returns MODIFIER_GROUP_CHANGED; retrieve the group before retrying.
