Products

Products are the core of Flint's catalog: physical goods, services, fees, digital items, and gift cards. The product is the parent record; its variants are the sellable units that carry price and SKU. A simple product has a single default variant, while an optioned product defines options (like size or color) whose combinations map to distinct variants.

When an order line item references a variant_id, Flint resolves price, display name, SKU, image, and tax settings from the catalog; callers cannot override catalog-owned fields on those rows. Products carry a status of active or inactive (reversible), or archived (permanent).

Variants of product_type: gift_card require USD and are non-taxable, untracked, and exempt from delivery. They cannot include modifiers or belong to bundles or subscriptions. Ordinary cart discounts exclude gift card purchase lines. Existing gift card value can pay for other goods in the same order, but cannot pay for a new gift card purchase. A product cannot change to or from gift_card; create a separate product instead.

gift_card_configuration keeps the issued face_value_money separate from the variant's unit_price_money. Omission on creation uses a fixed denomination at face value. An explicit configuration requires price_mode: "face_value" or price_mode: "discounted"; discounted pricing must collect less than the face value. Values and custom amount bounds use USD and cannot exceed 200000 cents per card.

Provide custom_amount_bounds with minimum_money and maximum_money to define a custom amount offer. The bounds must include the reference face value. Custom amounts use the reference price-to-face-value ratio, rounded to the nearest cent with ties up. Variant updates replace the whole configuration when provided and preserve it when omitted. The kept configuration must still fit the new price, so to change the price of a face_value variant, send gift_card_configuration with the new face_value_money. gift_card_configuration: null is not accepted. Send expected_version to reject a concurrent change.

A variant does not hold a stock count. Provide inventory_item_id or an inline inventory_item to have Flint track its stock through an inventory item, which then lives on inventory levels per Location rather than on the variant. Tracking is never inferred from a product being physical: an untracked variant sells without a stock check. Send inventory_item_id: null on a variant update to stop tracking it. Quantities change through the inventory endpoints with an audited reason, not through product updates.

Products can belong to more than one category. Product writes accept category display names and create a category when its normalized handle does not exist. Product reads return each category as {category_id, handle, name} so you can use its stable handle in promotion and return targeting. To change membership, send the complete categories array in a product update with the product's current version as expected_version. Send an empty array to clear every category.

Create product options and their values with the product, or replace the complete options array in a product update with expected_version. Include returned option and value IDs when keeping existing members. Omitting a member retires it.

Filter products with category_handle. Handles do not change when a category is renamed.

Use the exact sku filter on the product list to find a product by one of its variant SKUs. Use the same filter on the bundle list when you need to search bundles.

Related catalog resources: categories for reusable grouping and targeting, modifiers for per-line-item choices, and bundles for selling variants together.

The Product object#

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

Attributes

active_variant_countinteger
available_for_saleboolean
categoriesarray of object
created_atstring

RFC3339 timestamp.

default_variantobject
default_variant_idstring
delivery_configuration_statusenumRequired
  • configured
  • action_required
  • not_applicable
descriptionstring
external_reference_idstring

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

imagesarray of objectRequired
matched_variantobject
merchant_idstring
metadatamap of string
modifier_setobject or null
modifier_set_idstring or nullRequired

Attached modifier set. Send null on update to remove it.

namestringRequired
option_countinteger
optionsarray of objectRequired
price_rangeobject
product_idstringRequired
product_typeenumRequired
  • physical
  • service
  • fee
  • digital
  • gift_card
statusenumRequired
  • active
  • inactive
  • archived
updated_atstring

RFC3339 timestamp.

variant_countinteger
versionintegerRequired
JSON
{
  "active_variant_count": 1,
  "available_for_sale": true,
  "categories": [
    {
      "category_id": "ctg_tickets",
      "handle": "tickets",
      "name": "Tickets"
    },
    {
      "category_id": "ctg_events",
      "handle": "events",
      "name": "Events"
    }
  ],
  "created_at": "2026-03-17T14:30:00Z",
  "default_variant_id": "var_123",
  "delivery_configuration_status": "configured",
  "images": [],
  "merchant_id": "mer_123",
  "metadata": {
    "event_id": "evt_123"
  },
  "modifier_set_id": null,
  "name": "General Admission",
  "option_count": 0,
  "options": [],
  "price_range": {
    "max_unit_price_money": {
      "amount": 2500,
      "currency": "USD"
    },
    "min_unit_price_money": {
      "amount": 2500,
      "currency": "USD"
    }
  },
  "product_id": "prod_123",
  "product_type": "physical",
  "status": "active",
  "updated_at": "2026-03-17T14:30:00Z",
  "variant_count": 1,
  "version": 1
}

List products#

GET/v1/products

Requires scope commerce.products.read or commerce.products.write

Returns a paginated list of products for the authenticated merchant.

Query parameters

page_sizeinteger

Page size, default 20, max 100.

page_tokenstring

Cursor returned by the previous list response.

product_typeenum

Filter by product type.

  • physical
  • service
  • fee
  • digital
  • gift_card
statusenum

Filter by product status.

  • active
  • inactive
  • archived
category_handlestring

Filter by category handle.

external_reference_idstring

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

skustring

Filter by exact variant SKU.

querystring

Search across product ID, external reference ID, name, description, and SKU. 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.

delivery_profile_idstring

Filter products with at least one non-deleted variant assigned to this delivery profile.

delivery_configuration_statusenum

Filter by aggregated delivery readiness across non-deleted variants.

  • configured
  • action_required
  • not_applicable
sort_byenum

Sort field.

  • name
  • created_at
  • updated_at
sort_directionenum

Sort direction.

  • asc
  • desc
created_afterstring

RFC3339 lower bound for created_at.

created_beforestring

RFC3339 upper bound for created_at.

updated_afterstring

RFC3339 lower bound for updated_at.

updated_beforestring

RFC3339 upper bound for updated_at.

Response · 200

dataarray of objectRequired
metaobject
next_page_tokenstring
request_idstring
curl https://api.withflintpay.com/v1/products \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"
JSON
{
  "data": [
    {
      "active_variant_count": 1,
      "available_for_sale": true,
      "categories": [
        {
          "category_id": "ctg_tickets",
          "handle": "tickets",
          "name": "Tickets"
        },
        {
          "category_id": "ctg_events",
          "handle": "events",
          "name": "Events"
        }
      ],
      "created_at": "2026-03-17T14:30:00Z",
      "default_variant_id": "var_123",
      "delivery_configuration_status": "configured",
      "images": [],
      "merchant_id": "mer_123",
      "metadata": {
        "event_id": "evt_123"
      },
      "modifier_set_id": null,
      "name": "General Admission",
      "option_count": 0,
      "options": [],
      "price_range": {
        "max_unit_price_money": {
          "amount": 2500,
          "currency": "USD"
        },
        "min_unit_price_money": {
          "amount": 2500,
          "currency": "USD"
        }
      },
      "product_id": "prod_123",
      "product_type": "physical",
      "status": "active",
      "updated_at": "2026-03-17T14:30:00Z",
      "variant_count": 1,
      "version": 1
    }
  ],
  "next_page_token": "Zm9yd2FyZC1vbmx5LW9wYXF1ZS1jdXJzb3I",
  "request_id": "bce56cba-0827-44aa-bb56-4f200ba15ee6"
}

Create product#

POST/v1/productsIdempotent

Requires scope commerce.products.write

Creates a product for the authenticated merchant.

Request body

Send exactly one of these

categoriesarray of string
default_variantobjectRequired
descriptionstring
external_reference_idstring

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

imagesarray of object

The complete desired gallery in display order. The first image is primary. Send [] to clear the gallery.

metadatamap of string
modifier_set_idstring or null

Attached modifier set. Send null on update to remove it.

namestringRequired
product_typeenumRequired
  • physical
  • service
  • fee
  • digital
  • gift_card
statusenum
  • active
  • inactive

Response · 201

dataobjectRequired
metaobject
request_idstring
curl -X POST https://api.withflintpay.com/v1/products \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: a-unique-key" \
  -d '{
    "categories": [
      "tickets",
      "events"
    ],
    "default_variant": {
      "sku": "ga-001",
      "unit_price_money": {
        "amount": 2500,
        "currency": "USD"
      }
    },
    "metadata": {
      "event_id": "evt_123"
    },
    "name": "General Admission",
    "product_type": "physical"
  }'

Get product#

GET/v1/products/{product_id}

Requires scope commerce.products.read or commerce.products.write

Returns a single product by ID.

Path parameters

product_idstringRequired

Flint product ID.

Query parameters

expandarray of enum

Supported expansions: modifier_set. Expand the attached modifier set. Limits: at most 10 unique expand paths per request; path depth at most 2. Repeat expand, for example expand=modifier_set&expand=modifier_set, or pass one comma-separated value.

  • modifier_set

Response · 200

dataobjectRequired
metaobject
request_idstring
curl https://api.withflintpay.com/v1/products/prod_123 \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"
JSON
{
  "data": {
    "active_variant_count": 1,
    "available_for_sale": true,
    "categories": [
      {
        "category_id": "ctg_tickets",
        "handle": "tickets",
        "name": "Tickets"
      },
      {
        "category_id": "ctg_events",
        "handle": "events",
        "name": "Events"
      }
    ],
    "created_at": "2026-03-17T14:30:00Z",
    "default_variant_id": "var_123",
    "delivery_configuration_status": "configured",
    "images": [],
    "merchant_id": "mer_123",
    "metadata": {
      "event_id": "evt_123"
    },
    "modifier_set_id": null,
    "name": "General Admission",
    "option_count": 0,
    "options": [],
    "price_range": {
      "max_unit_price_money": {
        "amount": 2500,
        "currency": "USD"
      },
      "min_unit_price_money": {
        "amount": 2500,
        "currency": "USD"
      }
    },
    "product_id": "prod_123",
    "product_type": "physical",
    "status": "active",
    "updated_at": "2026-03-17T14:30:00Z",
    "variant_count": 1,
    "version": 1
  },
  "request_id": "bce56cba-0827-44aa-bb56-4f200ba15ee6"
}

Update product#

PATCH/v1/products/{product_id}Idempotent

Requires scope commerce.products.write

Applies a sparse update to product-parent fields. When categories is present, it replaces the full category list; send an empty array to clear categories. Sellable price, SKU, and inventory live on variants.

Path parameters

product_idstringRequired

Flint product ID.

Request body

categoriesarray of string
default_variant_idstring
descriptionstring
expected_versioninteger

Resource version last read by the caller. Required when replacing an owned collection.

external_reference_idstring

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

imagesarray of object

The complete desired gallery in display order. The first image is primary. Send [] to clear the gallery.

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.

modifier_set_idstring or null

Attached modifier set. Send null on update to remove it.

namestring
optionsarray of object

Replaces all product options and values atomically. Include existing option_id and option_value_id values to retain members. Omitted members are archived. Null is not accepted.

product_typeenum
  • physical
  • service
  • fee
  • digital
  • gift_card
statusenum
  • active
  • inactive

Response · 200

dataobjectRequired
metaobject
request_idstring
curl -X PATCH https://api.withflintpay.com/v1/products/prod_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 '{
    "categories": [
      "vip",
      "events"
    ],
    "expected_version": 1,
    "name": "VIP Admission",
    "status": "inactive"
  }'

Retire product#

DELETE/v1/products/{product_id}Idempotent

Requires scope commerce.products.write

Archives a product and returns its final state.

Path parameters

product_idstringRequired

Flint product ID.

Query parameters

expected_versioninteger

Optional product version last read by the caller.

Response · 200

dataobjectRequired
metaobject
request_idstring
curl -X DELETE https://api.withflintpay.com/v1/products/prod_123 \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"

List product options#

GET/v1/products/{product_id}/options

Requires scope commerce.products.read or commerce.products.write

List product options.

Path parameters

product_idstringRequired

Flint product ID.

Query parameters

page_sizeinteger

Page size, default 20, max 100.

page_tokenstring

Cursor returned by the previous list response.

statusenum

Filter by option status.

  • active
  • inactive
  • archived

Response · 200

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

Get product option#

GET/v1/products/{product_id}/options/{option_id}

Requires scope commerce.products.read or commerce.products.write

Get product option.

Path parameters

product_idstringRequired

Flint product ID.

option_idstringRequired

Flint product option ID.

Response · 200

dataobjectRequired
metaobject
request_idstring
curl https://api.withflintpay.com/v1/products/prod_123/options/opt_123 \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"
JSON
{
  "data": {
    "created_at": "2026-03-17T14:30:00Z",
    "name": "Seat",
    "option_id": "opt_123",
    "position": 0,
    "product_id": "prod_123",
    "status": "active",
    "updated_at": "2026-03-17T14:30:00Z",
    "values": [
      {
        "created_at": "2026-03-17T14:30:00Z",
        "option_value_id": "optval_123",
        "position": 0,
        "status": "active",
        "updated_at": "2026-03-17T14:30:00Z",
        "value": "Balcony"
      }
    ]
  },
  "request_id": "bce56cba-0827-44aa-bb56-4f200ba15ee6"
}

List product variants#

GET/v1/products/{product_id}/variants

Requires scope commerce.products.read or commerce.products.write

List product variants.

Path parameters

product_idstringRequired

Flint product ID.

Query parameters

page_sizeinteger

Page size, default 20, max 100.

page_tokenstring

Cursor returned by the previous list response.

statusenum

Filter by variant status.

  • active
  • inactive
  • archived
external_reference_idstring

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

querystring

Search across variant ID, external reference ID, name, SKU, and barcode. 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.

sort_byenum

Sort field.

  • position
  • created_at
  • updated_at
  • unit_price
sort_directionenum

Sort direction.

  • asc
  • desc
delivery_profile_idstring

Filter by assigned delivery profile ID.

delivery_configuration_statusenum

Filter by delivery readiness.

  • configured
  • action_required
  • not_applicable

Response · 200

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

Create product variant#

POST/v1/products/{product_id}/variantsIdempotent

Requires scope commerce.products.write

Create product variant.

Path parameters

product_idstringRequired

Flint product ID.

Request body

variantobjectRequired

Response · 201

dataobjectRequired
metaobject
request_idstring
curl -X POST https://api.withflintpay.com/v1/products/prod_123/variants \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: a-unique-key" \
  -d '{
    "variant": {
      "sku": "ga-balcony-001",
      "unit_price_money": {
        "amount": 2500,
        "currency": "USD"
      }
    }
  }'

Get product variant#

GET/v1/products/{product_id}/variants/{variant_id}

Requires scope commerce.products.read or commerce.products.write

Get product variant.

Path parameters

product_idstringRequired

Flint product ID.

variant_idstringRequired

Flint product variant ID.

Query parameters

expandarray of enum

Supported expansions: modifier_set. Expand the attached modifier set. Limits: at most 10 unique expand paths per request; path depth at most 2. Repeat expand, for example expand=modifier_set&expand=modifier_set, or pass one comma-separated value.

  • modifier_set

Response · 200

dataobjectRequired
metaobject
request_idstring
curl https://api.withflintpay.com/v1/products/prod_123/variants/var_123 \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"
JSON
{
  "data": {
    "available_for_sale": true,
    "created_at": "2026-03-17T14:30:00Z",
    "delivery_configuration_status": "configured",
    "effective_images": [],
    "images": [],
    "images_inherited": true,
    "inventory_tracking": "not_tracked",
    "merchant_id": "mer_123",
    "modifier_set_id": null,
    "position": 0,
    "product_id": "prod_123",
    "status": "active",
    "unit_price_money": {
      "amount": 2500,
      "currency": "USD"
    },
    "updated_at": "2026-03-17T14:30:00Z",
    "variant_id": "var_123",
    "version": 1
  },
  "request_id": "bce56cba-0827-44aa-bb56-4f200ba15ee6"
}

Update product variant#

PATCH/v1/products/{product_id}/variants/{variant_id}Idempotent

Requires scope commerce.products.write

Update product variant.

Path parameters

product_idstringRequired

Flint product ID.

variant_idstringRequired

Flint product variant ID.

Request body

barcodestring
delivery_profile_idstring
expected_versioninteger

Resource version last read by the caller. Required when replacing an owned collection.

gift_card_configurationobject

Replaces the complete gift card configuration. Omission preserves it. Null is not accepted. Include expected_version to reject a concurrent variant change.

imagesarray of object

Replaces the authored variant gallery atomically. Send [] to clear it and resume product-image inheritance.

inventory_itemobject
inventory_item_idstring or null

Inventory item tracked by this variant. Send null to stop tracking inventory.

line_item_tax_categoryenum

Flint line-item tax category.

  • general
  • physical_goods
  • digital_goods
  • software
  • saas
  • services
  • professional_services
  • food
  • prepared_food
  • clothing
  • medical_goods
  • admission
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.

modifier_set_idstring or null

Attached modifier set. Send null on update to remove it.

namestring
positioninteger
skustring
statusenum
  • active
  • inactive
taxableboolean
unit_price_moneyobject

Monetary amount represented as integer minor units plus an ISO 4217 currency code.

Response · 200

dataobjectRequired
metaobject
request_idstring
curl -X PATCH https://api.withflintpay.com/v1/products/prod_123/variants/var_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 '{
    "expected_version": 1,
    "name": "Balcony admission"
  }'

Retire product variant#

DELETE/v1/products/{product_id}/variants/{variant_id}Idempotent

Requires scope commerce.products.write

Retire product variant.

Path parameters

product_idstringRequired

Flint product ID.

variant_idstringRequired

Flint product variant ID.

Query parameters

expected_versioninteger

Optional product variant version last read by the caller.

Response · 200

dataobjectRequired
metaobject
request_idstring
curl -X DELETE https://api.withflintpay.com/v1/products/prod_123/variants/var_123 \
  -H "Flint-Version: 2026-09-07" \
  -H "Authorization: Bearer YOUR_API_KEY"

Was this helpful?