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.
