Modifiers

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#

  • POST/v1/modifier-groupsRequired API key scope: commerce.catalog.writeReference for POST /v1/modifier-groups

    Creates a buyer-facing prompt. Call it before adding choices or placing the group in a set. Example: POST /v1/modifier-groups with name: "Milk".

  • GET/v1/modifier-groupsRequired API key scopes: commerce.catalog.read or commerce.catalog.writeReference for GET /v1/modifier-groups

    Lists groups for authoring and reuse. Call it when building a modifier editor. Example: GET /v1/modifier-groups?page_size=20.

  • GET/v1/modifier-groups/{modifier_group_id}Required API key scopes: commerce.catalog.read or commerce.catalog.writeReference for GET /v1/modifier-groups/{modifier_group_id}

    Reads one group and its current rules. Call it before editing the group.

  • PATCH/v1/modifier-groups/{modifier_group_id}Required API key scope: commerce.catalog.writeReference for PATCH /v1/modifier-groups/{modifier_group_id}

    Updates the group prompt, selection rules, or complete modifiers array.

  • DELETE/v1/modifier-groups/{modifier_group_id}Required API key scope: commerce.catalog.writeReference for DELETE /v1/modifier-groups/{modifier_group_id}

    Archives a group that should not be used for new authoring. Call it only after removing active dependencies.

For example, a single-choice group can require exactly one selection:

JSON
{
  "name": "Milk",
  "modifier_group_type": "list",
  "min_selected": 1,
  "max_selected": 1
}

Modifier sets#

  • POST/v1/modifier-setsRequired API key scope: commerce.catalog.writeReference for POST /v1/modifier-sets

    Creates a reusable set. Include existing groups or create groups inline. Example: POST /v1/modifier-sets with name: "Engraving".

  • GET/v1/modifier-setsRequired API key scopes: commerce.catalog.read or commerce.catalog.writeReference for GET /v1/modifier-sets

    Lists sets for authoring and reuse. Call it when choosing reusable customization. Example: GET /v1/modifier-sets?page_size=20.

  • GET/v1/modifier-sets/{modifier_set_id}Required API key scopes: commerce.catalog.read or commerce.catalog.writeReference for GET /v1/modifier-sets/{modifier_set_id}

    Reads one set and its current group configuration. Call it before editing or attaching the set.

  • PATCH/v1/modifier-sets/{modifier_set_id}Required API key scope: commerce.catalog.writeReference for PATCH /v1/modifier-sets/{modifier_set_id}

    Updates the set. Including modifier_groups replaces the complete group collection and requires expected_version.

  • DELETE/v1/modifier-sets/{modifier_set_id}Required API key scope: commerce.catalog.writeReference for DELETE /v1/modifier-sets/{modifier_set_id}

    Archives a set that should not be attached again. Call it after removing it from active catalog items.

Add engraving to a product#

Create the set and its text group in one request:

JSON
{
  "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.

JSON
{
  "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:

JSON
{
  "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 send quantity when the group allows quantities.
  • For text, send text with both modifier_group_id and value. Text selections do not accept quantity.
JSON
{
  "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.

The Modifier object#

Every field on a modifier, as returned by retrieve and carried by the endpoints below.

Attributes

allow_quantitiesbooleanRequired
created_atstring

RFC3339 timestamp.

external_reference_idstring

Caller-owned identifier for this resource in an external system.

max_quantityinteger

Whole-number quantity; fractional quantities are not supported.

max_selectedinteger
max_total_quantityinteger

Whole-number quantity; fractional quantities are not supported.

merchant_idstring
metadatamap of string
min_quantityinteger

Whole-number quantity; fractional quantities are not supported.

min_selectedinteger
modifier_group_idstringRequired
modifier_group_typeenumRequired
  • list
  • text
modifiersarray of object
namestringRequired
show_on_fulfillmentbooleanRequired
show_on_receiptbooleanRequired
statusenumRequired
  • active
  • inactive
  • archived
textobject
updated_atstring

RFC3339 timestamp.

versionintegerRequired

Version of the modifier group and its modifiers.

JSON
{
  "allow_quantities": false,
  "created_at": "2026-03-17T14:30:00Z",
  "max_selected": 1,
  "merchant_id": "mer_123",
  "min_selected": 1,
  "modifier_group_id": "mg_123",
  "modifier_group_type": "list",
  "modifiers": [
    {
      "modifier_group_id": "mg_123",
      "modifier_id": "mod_123",
      "name": "Whole milk",
      "position": 0,
      "selected_by_default": true,
      "show_on_fulfillment": true,
      "show_on_receipt": true,
      "status": "active"
    },
    {
      "modifier_group_id": "mg_123",
      "modifier_id": "mod_456",
      "name": "Oat milk",
      "position": 1,
      "selected_by_default": false,
      "show_on_fulfillment": true,
      "show_on_receipt": true,
      "status": "active",
      "unit_price_delta_money": {
        "amount": 75,
        "currency": "USD"
      }
    }
  ],
  "name": "Milk",
  "show_on_fulfillment": true,
  "show_on_receipt": true,
  "status": "active",
  "updated_at": "2026-03-17T14:30:00Z",
  "version": 1
}

List modifier groups#

GET/v1/modifier-groups

Requires scope commerce.catalog.read or commerce.catalog.write

List modifier groups.

Query parameters

page_sizeinteger

Page size, default 20, max 100.

page_tokenstring

Cursor returned by the previous list response.

statusenum

Filter by modifier group status.

  • active
  • inactive
  • archived
modifier_group_typeenum

Filter by modifier group type.

  • list
  • text
external_reference_idstring

Exact-match filter on the caller-owned external reference ID.

querystring

Search across modifier group ID, external reference ID, name, and description. Text fields match any part of the value, and %, _ and \ are ordinary characters, not wildcards. IDs match from the start and need the type prefix, such as ord_01.

Response · 200

dataarray of objectRequired
metaobject
next_page_tokenstring
request_idstring
curl https://api.withflintpay.com/v1/modifier-groups \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"
JSON
{
  "data": [
    {
      "allow_quantities": false,
      "created_at": "2026-03-17T14:30:00Z",
      "max_selected": 1,
      "merchant_id": "mer_123",
      "min_selected": 1,
      "modifier_group_id": "mg_123",
      "modifier_group_type": "list",
      "modifiers": [
        {
          "modifier_group_id": "mg_123",
          "modifier_id": "mod_123",
          "name": "Whole milk",
          "position": 0,
          "selected_by_default": true,
          "show_on_fulfillment": true,
          "show_on_receipt": true,
          "status": "active"
        },
        {
          "modifier_group_id": "mg_123",
          "modifier_id": "mod_456",
          "name": "Oat milk",
          "position": 1,
          "selected_by_default": false,
          "show_on_fulfillment": true,
          "show_on_receipt": true,
          "status": "active",
          "unit_price_delta_money": {
            "amount": 75,
            "currency": "USD"
          }
        }
      ],
      "name": "Milk",
      "show_on_fulfillment": true,
      "show_on_receipt": true,
      "status": "active",
      "updated_at": "2026-03-17T14:30:00Z",
      "version": 1
    }
  ],
  "next_page_token": "example",
  "request_id": "bce56cba-0827-44aa-bb56-4f200ba15ee6"
}

Create modifier group#

POST/v1/modifier-groupsIdempotent

Requires scope commerce.catalog.write

Create modifier group.

Request body

allow_quantitiesboolean
external_reference_idstring

Caller-owned identifier for this resource in an external system.

max_quantityinteger

Whole-number quantity; fractional quantities are not supported.

max_selectedinteger
max_total_quantityinteger

Whole-number quantity; fractional quantities are not supported.

metadatamap of string
min_quantityinteger

Whole-number quantity; fractional quantities are not supported.

min_selectedinteger
modifier_group_typeenum

Inferred as text when text configuration is supplied, otherwise list.

  • list
  • text
modifiersarray of object
namestringRequired
show_on_fulfillmentboolean
show_on_receiptboolean
statusenum
  • active
  • inactive
textobject

Response · 201

dataobjectRequired
metaobject
request_idstring
curl -X POST https://api.withflintpay.com/v1/modifier-groups \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: a-unique-key" \
  -d '{}'
curl https://api.withflintpay.com/v1/modifier-groups/mg_123 \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"
JSON
{
  "data": {
    "allow_quantities": false,
    "created_at": "2026-03-17T14:30:00Z",
    "max_selected": 1,
    "merchant_id": "mer_123",
    "min_selected": 1,
    "modifier_group_id": "mg_123",
    "modifier_group_type": "list",
    "modifiers": [
      {
        "modifier_group_id": "mg_123",
        "modifier_id": "mod_123",
        "name": "Whole milk",
        "position": 0,
        "selected_by_default": true,
        "show_on_fulfillment": true,
        "show_on_receipt": true,
        "status": "active"
      },
      {
        "modifier_group_id": "mg_123",
        "modifier_id": "mod_456",
        "name": "Oat milk",
        "position": 1,
        "selected_by_default": false,
        "show_on_fulfillment": true,
        "show_on_receipt": true,
        "status": "active",
        "unit_price_delta_money": {
          "amount": 75,
          "currency": "USD"
        }
      }
    ],
    "name": "Milk",
    "show_on_fulfillment": true,
    "show_on_receipt": true,
    "status": "active",
    "updated_at": "2026-03-17T14:30:00Z",
    "version": 1
  },
  "request_id": "bce56cba-0827-44aa-bb56-4f200ba15ee6"
}

Update modifier group#

PATCH/v1/modifier-groups/{modifier_group_id}Idempotent

Requires scope commerce.catalog.write

Update modifier group.

Path parameters

modifier_group_idstringRequired

Flint modifier group ID.

Request body

Send at least one of these

allow_quantitiesboolean
expected_versioninteger

Modifier group version last read by the caller. Required when modifiers is present.

external_reference_idstring

Caller-owned identifier for this resource in an external system.

max_quantityinteger

Whole-number quantity; fractional quantities are not supported.

max_selectedinteger
max_total_quantityinteger

Whole-number quantity; fractional quantities are not supported.

metadatamap of string or null

Caller-owned metadata. Omit this field to leave metadata unchanged. Send an object to merge by key, set a key to null to remove it, or set metadata to null to clear all metadata. An empty object makes no change. Empty strings are stored. Keys starting with flint_ are reserved and cannot be written through the public API.

min_quantityinteger

Whole-number quantity; fractional quantities are not supported.

min_selectedinteger
namestring
show_on_fulfillmentboolean
show_on_receiptboolean
statusenum
  • active
  • inactive
textobject

Response · 200

Same response as Create modifier group.

curl -X PATCH https://api.withflintpay.com/v1/modifier-groups/mg_123 \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: a-unique-key" \
  -d '{}'
curl -X DELETE https://api.withflintpay.com/v1/modifier-groups/mg_123 \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"

List modifier sets#

GET/v1/modifier-sets

Requires scope commerce.catalog.read or commerce.catalog.write

List modifier sets.

Query parameters

page_sizeinteger

Page size, default 20, max 100.

page_tokenstring

Cursor returned by the previous list response.

statusenum

Filter by modifier set status.

  • active
  • inactive
  • archived
external_reference_idstring

Exact-match filter on the caller-owned external reference ID.

querystring

Search across modifier set ID, external reference ID, name, and description. Text fields match any part of the value, and %, _ and \ are ordinary characters, not wildcards. IDs match from the start and need the type prefix, such as ord_01.

Response · 200

dataarray of objectRequired
metaobject
next_page_tokenstring
request_idstring
curl https://api.withflintpay.com/v1/modifier-sets \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"
JSON
{
  "data": [],
  "next_page_token": "example",
  "request_id": "bce56cba-0827-44aa-bb56-4f200ba15ee6"
}

Create modifier set#

POST/v1/modifier-setsIdempotent

Requires scope commerce.catalog.write

Create modifier set.

Request body

external_reference_idstring

Caller-owned identifier for this resource in an external system.

metadatamap of string
modifier_groupsarray of one of
namestringRequired
statusenum
  • active
  • inactive

Response · 201

dataobjectRequired
metaobject
request_idstring
curl -X POST https://api.withflintpay.com/v1/modifier-sets \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: a-unique-key" \
  -d '{}'
curl https://api.withflintpay.com/v1/modifier-sets/{modifier_set_id} \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"
JSON
{
  "data": {},
  "request_id": "bce56cba-0827-44aa-bb56-4f200ba15ee6"
}

Update modifier set#

PATCH/v1/modifier-sets/{modifier_set_id}Idempotent

Requires scope commerce.catalog.write

Update modifier set.

Path parameters

modifier_set_idstringRequired

Flint modifier set ID.

Request body

Send at least one of these

expected_versioninteger
external_reference_idstring

Caller-owned identifier for this resource in an external system.

metadatamap of string or null

Caller-owned metadata. Omit this field to leave metadata unchanged. Send an object to merge by key, set a key to null to remove it, or set metadata to null to clear all metadata. An empty object makes no change. Empty strings are stored. Keys starting with flint_ are reserved and cannot be written through the public API.

namestring
statusenum
  • active
  • inactive

Response · 200

Same response as Create modifier set.

curl -X PATCH https://api.withflintpay.com/v1/modifier-sets/{modifier_set_id} \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: a-unique-key" \
  -d '{}'
curl -X DELETE https://api.withflintpay.com/v1/modifier-sets/{modifier_set_id} \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"

Was this helpful?