Skip to main content
POST
Create a product

Authorizations

Authorization
string
header
required

Authenticate using a bearer token. To create a token, navigate to /settings/api-tokens and click Create API Token.

Body

application/json
name
string
required

Product name

Maximum string length: 200
category_id
integer
required

ID of the product category

sku
string
required

Internal SKU

Maximum string length: 100
category
object | null

Product category information

supplier_id
integer | null

ID of the preferred supplier

supplier
object | null

Product preferred supplier information

distribution_template_id
integer | null

ID of the distribution template (size curve) to assign to this product. Use GET /products/{productId}/distribution-template/candidates to find compatible templates for a master SKU.

grid_template_category_id
integer | null

ID of the variant distribution group (size-curve category) to assign to this product. Unlike distribution_template_id, this does not pin a single curve: the group is combined with each destination warehouse to pick the right curve per buy. Returned as distribution_template_category on the product response. Returns 422 if the group's axes don't fit the product.

image_url
string | null

URL to product image

Maximum string length: 255
sellable
boolean | null

Whether the product can be sold

lot_tracking
boolean | null

Whether to track product by lots

is_drop_ship_item
boolean | null

Flag the product as a drop-ship item. A preference marker only — it does not currently change fulfillment-order routing or purchase-order creation.

taxable
boolean | null

Whether the product is subject to sales tax. Defaults to true when omitted.

sub_category_id
integer | null

ID of the product subcategory

subcategory
object | null

Product sub-category information

default_receiving_location_id
integer | null

Default location ID for receiving this product

default_assembly_location_id
integer | null

Default location (bin) ID where assembled goods (BOM output) are credited for this product. When set, it is used as the destination when defaulting assembly/disassembly work, falling back to default_receiving_location_id and then the warehouse default.

description
string | null

Product description

wholesale_price
number<float> | null

Wholesale price

Required range: x >= 0
retail_price
number<float> | null

Retail price

Required range: x >= 0
unit_cost
number<float> | null

Cost per unit. Interpreted in the currency given by unit_cost_currency; when that is omitted, unit_cost is the tenant base-currency inventory cost.

Required range: x >= 0
unit_cost_currency
string | null

Optional ISO currency code for unit_cost. Omit (or send null) to treat unit_cost as the base-currency inventory cost (existing behavior; any stored supplier purchase price is left untouched). Send the tenant base currency to set the base cost explicitly and clear a foreign-currency purchase price on the preferred supplier. Send the preferred supplier's default currency to store unit_cost as the supplier purchase (FOB) price on that supplier's SKU; it is converted at today's exchange rate into the base-currency inventory cost. Any other currency, or a supplier currency without a preferred supplier that has a currency, returns 422 keyed on unit_cost_currency. Only applies when unit_cost is also sent.

Example:

"EUR"

manufacturing_fee
number<float> | null

Manufacturing fee per unit

Required range: x >= 0
estimated_landed_cost
number<float> | null

Planner's estimated landed cost per unit, stored on the product. Separate from the computed landed_cost. Uses the same currency as the product's other costs (there is no separate currency field). Send null to clear it.

Required range: x >= 0

Product design URL or link. Send null to clear it.

Maximum string length: 2000
product_weight
object

Product weight. Accepts a single {unit, value} object or an array of such segments (a compound weight like 4 lb + 6 oz is written as two entries and summed).

Accepted units. Imperial units are stored as-is: lb/lbs (pounds) and oz/ozs (ounces). Metric units are accepted on input and converted to ounces at storage — g/gram/grams and kg/kgs/kilogram/kilograms. Because metric is converted, the input unit is not round-tripped: a weight submitted in grams or kilograms reads back in ounces.

Rejected input (400). A bare number with no unit; a comma inside a number (2,5kg — ambiguous decimal vs. thousands separator, use 2.5kg); a negative value; mixing metric and imperial units in one weight (e.g. 1 lb (454 g)); or repeating a metric unit (e.g. 3kg / 2.8kg) — these read as the same weight written twice rather than a total.

dimensional_weight
object

Product weight. Accepts a single {unit, value} object or an array of such segments (a compound weight like 4 lb + 6 oz is written as two entries and summed).

Accepted units. Imperial units are stored as-is: lb/lbs (pounds) and oz/ozs (ounces). Metric units are accepted on input and converted to ounces at storage — g/gram/grams and kg/kgs/kilogram/kilograms. Because metric is converted, the input unit is not round-tripped: a weight submitted in grams or kilograms reads back in ounces.

Rejected input (400). A bare number with no unit; a comma inside a number (2,5kg — ambiguous decimal vs. thousands separator, use 2.5kg); a negative value; mixing metric and imperial units in one weight (e.g. 1 lb (454 g)); or repeating a metric unit (e.g. 3kg / 2.8kg) — these read as the same weight written twice rather than a total.

product_length
number<float> | null

Length of the product (in inches)

Required range: x >= 0
product_width
number<float> | null

Width of the product (in inches)

Required range: x >= 0
product_height
number<float> | null

Height of the product (in inches)

Required range: x >= 0
box_weight
object

Product weight. Accepts a single {unit, value} object or an array of such segments (a compound weight like 4 lb + 6 oz is written as two entries and summed).

Accepted units. Imperial units are stored as-is: lb/lbs (pounds) and oz/ozs (ounces). Metric units are accepted on input and converted to ounces at storage — g/gram/grams and kg/kgs/kilogram/kilograms. Because metric is converted, the input unit is not round-tripped: a weight submitted in grams or kilograms reads back in ounces.

Rejected input (400). A bare number with no unit; a comma inside a number (2,5kg — ambiguous decimal vs. thousands separator, use 2.5kg); a negative value; mixing metric and imperial units in one weight (e.g. 1 lb (454 g)); or repeating a metric unit (e.g. 3kg / 2.8kg) — these read as the same weight written twice rather than a total.

box_length
number<float> | null

Length of the box (in inches)

Required range: x >= 0
box_width
number<float> | null

Width of the box (in inches)

Required range: x >= 0
box_height
number<float> | null

Height of the box (in inches)

Required range: x >= 0
carton_weight
object

Product weight. Accepts a single {unit, value} object or an array of such segments (a compound weight like 4 lb + 6 oz is written as two entries and summed).

Accepted units. Imperial units are stored as-is: lb/lbs (pounds) and oz/ozs (ounces). Metric units are accepted on input and converted to ounces at storage — g/gram/grams and kg/kgs/kilogram/kilograms. Because metric is converted, the input unit is not round-tripped: a weight submitted in grams or kilograms reads back in ounces.

Rejected input (400). A bare number with no unit; a comma inside a number (2,5kg — ambiguous decimal vs. thousands separator, use 2.5kg); a negative value; mixing metric and imperial units in one weight (e.g. 1 lb (454 g)); or repeating a metric unit (e.g. 3kg / 2.8kg) — these read as the same weight written twice rather than a total.

carton_length
number<float> | null

Length of the carton (in inches)

Required range: x >= 0
carton_width
number<float> | null

Width of the carton (in inches)

Required range: x >= 0
carton_height
number<float> | null

Height of the carton (in inches)

Required range: x >= 0
shipping_weight
object

Product weight. Accepts a single {unit, value} object or an array of such segments (a compound weight like 4 lb + 6 oz is written as two entries and summed).

Accepted units. Imperial units are stored as-is: lb/lbs (pounds) and oz/ozs (ounces). Metric units are accepted on input and converted to ounces at storage — g/gram/grams and kg/kgs/kilogram/kilograms. Because metric is converted, the input unit is not round-tripped: a weight submitted in grams or kilograms reads back in ounces.

Rejected input (400). A bare number with no unit; a comma inside a number (2,5kg — ambiguous decimal vs. thousands separator, use 2.5kg); a negative value; mixing metric and imperial units in one weight (e.g. 1 lb (454 g)); or repeating a metric unit (e.g. 3kg / 2.8kg) — these read as the same weight written twice rather than a total.

shipping_length
number<float> | null

Shipping length (in inches)

Required range: x >= 0
shipping_width
number<float> | null

Shipping width (in inches)

Required range: x >= 0
shipping_height
number<float> | null

Shipping height (in inches)

Required range: x >= 0
pallet_weight
object

Product weight. Accepts a single {unit, value} object or an array of such segments (a compound weight like 4 lb + 6 oz is written as two entries and summed).

Accepted units. Imperial units are stored as-is: lb/lbs (pounds) and oz/ozs (ounces). Metric units are accepted on input and converted to ounces at storage — g/gram/grams and kg/kgs/kilogram/kilograms. Because metric is converted, the input unit is not round-tripped: a weight submitted in grams or kilograms reads back in ounces.

Rejected input (400). A bare number with no unit; a comma inside a number (2,5kg — ambiguous decimal vs. thousands separator, use 2.5kg); a negative value; mixing metric and imperial units in one weight (e.g. 1 lb (454 g)); or repeating a metric unit (e.g. 3kg / 2.8kg) — these read as the same weight written twice rather than a total.

pallet_length
number<float> | null

Length of the pallet (in inches)

Required range: x >= 0
pallet_width
number<float> | null

Width of the pallet (in inches)

Required range: x >= 0
pallet_height
number<float> | null

Height of the pallet (in inches)

Required range: x >= 0
units_per_carton
number<float> | null

Number of units per carton (Shipping & Packing). Setting units_per_carton or units_per_pallet also updates the product's Carton / Pallet unit conversion, as saving in the app does.

Required range: x >= 0
cartons_per_pallet
number<float> | null

Number of cartons per pallet (Shipping & Packing). Setting units_per_carton or units_per_pallet also updates the product's Carton / Pallet unit conversion, as saving in the app does.

Required range: x >= 0
units_per_pallet
number<float> | null

Number of units per pallet (Shipping & Packing). Setting units_per_carton or units_per_pallet also updates the product's Carton / Pallet unit conversion, as saving in the app does.

Required range: x >= 0
upc
string | null

UPC/Barcode

default_supply_method
enum<string> | null

Default supply mode used when planning replenishment for this product. Determines whether the system expects to purchase, drop-ship, assemble, or pull from on-hand stock when supplying demand.

Available options:
purchase,
vendor_supplied,
assemble,
on_hand,
assembly_order,
buy_and_ship,
brand_supplied
Maximum string length: 50
priority_list_id
integer | null

ID of the fulfillment priority list to assign to this product

priority_list
object | null

Priority list to assign by ID or name (alternative to priority_list_id)

custom_fields
object | null

Custom field values

tags
string[] | null

Tags to associate with the product

default_selling_unit_id
integer | null

ID of the unit of measure this product is sold in.

If omitted (along with selling_uom), Luminous defaults it to the account's base unit of measure (e.g. ea under the Quantity unit class). The request is rejected only if the account has no unit of measure configured at all.

Required range: x >= 1
default_purchase_unit_id
integer | null

ID of the unit of measure this product is purchased in.

If omitted (along with purchase_uom), Luminous defaults it to the account's base unit of measure (e.g. ea).

Required range: x >= 1
unit_class_id
integer | null

ID of the unit class this product's units belong to (e.g. Quantity).

If omitted, Luminous defaults it to the unit class of the account's base unit.

Required range: x >= 1
selling_uom
object | null

Selling unit of measure by name — an alternative to default_selling_unit_id. When default_selling_unit_id is not provided, the named UOM is resolved to its ID.

purchase_uom
object | null

Purchase unit of measure by name — an alternative to default_purchase_unit_id. When default_purchase_unit_id is not provided, the named UOM is resolved to its ID.

product_variants
object[] | null

Variant option taxonomy for the product — the axes (e.g. Size, Color) and the allowed terms on each axis.

You almost never need to set this. Tag each child SKU under variants[].product_variants with the terms it represents instead, and Luminous will derive the parent taxonomy automatically as the union of every term used by the children. Setting this directly is only useful as an escape hatch (e.g. seeding an empty option set, or pruning a term no child uses).

Returned on the response as variant_attributes (same shape).

variant_template

A variant template to expand into child SKUs, given as either the template's id (integer) or its name (string). When set on a master product create, the template's option axes are expanded into child variant SKUs — the same one-click "generate variants" step available in the SKU form, reachable from the API.

Rules:

  • Ignored when you also send an explicit variants array — being specific always wins over a preset.
  • Idempotent — skipped when the product already has child variants, so re-sending the same request does not duplicate them.
  • An unknown template name/id fails loudly with a 422 validation error rather than silently producing a master with no variants.
variants
object[] | null

Product variants

type
enum<string> | null
default:PRODUCT

Product type. PRODUCT for regular products, KIT for kit products that contain other products as components.

Available options:
PRODUCT,
KIT
kit_items
object[] | null

Array of kit items (components) for kit products. Required when type = KIT. Each kit item must specify either product_id or sku, and quantity.

boms
integer[] | null

Array of BOM IDs to attach to the product. Omit this field entirely to leave the product's existing BOM associations unchanged (upserts do not touch BOMs unless boms is provided). When the field is provided, it replaces all existing BOM associations: pass an array of IDs to set them, or null/an empty array to detach all BOMs.

BOM ID

profile_id
integer | null

Opt-in reference to a Product Builder Profile (GET /product-profiles). When provided (and the profile is active), the product is validated against the profile before any writes — SKU format, required variant preset / distribution group / custom fields — returning a 422 on any violation, and the profile's fixed selections and hidden defaults are stamped onto the product where you left them unset. Omit to create the product without profile enforcement.

profile_slug
string | null

The profile's slug, an alternative to profile_id for referencing a Product Builder Profile.

Response

Successful response

data
object