> For the complete documentation index, see [llms.txt](https://apidocs.akinon.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://apidocs.akinon.com/commerce-openapis/admin/products/create-a-product.md).

# Create a product

Creates a new product. The way the product is created, and which fields are required, depends on the `product_type` you provide.

**General Rules**

* The `sku` must be unique across the catalog. Creating a product with an SKU that already exists is rejected.
* Whether the product is publicly listable (`is_listable`) and whether it requires form input (`is_form_required`) are **determined automatically** by the system from the product type and the selected attribute set. Values you send for these fields do not override the computed result.
* When a product becomes listable, the system generates its storefront URL automatically.

**Conditional Field Requirements**

| Condition                         | Requirement                                                                          |
| --------------------------------- | ------------------------------------------------------------------------------------ |
| Always                            | `name`, `sku`, `product_type`, `attribute_set`, and `extra_attributes` are required. |
| `product_type` is **Offer** (`5`) | `parent` is required. The request is rejected if it is missing.                      |
| `product_type` is **Offer** (`5`) | `data_source` is required. The request is rejected if it is missing.                 |

**Behavior by Product Type**

* **Simple** (`0`)
  * Without a `parent`, the product is created as listable.
  * With a `parent`, the product is treated as a variant. It becomes the listable variant of its group only when no other listable sibling already holds that position for the same listable-attribute values. If a listable sibling already exists, the product is created as non-listable.
  * When the `LIST_SIMPLE_INSTEAD_OF_META` setting is enabled, listability is always evaluated at the individual simple-variant level rather than at the parent level.
* **Miscellaneous** (`4`) — Created as an individual product and never listable.
* **Product Meta** (`1`) — Created as the parent of a variant group. It is listable only when its attribute set defines no listable variant attributes **and** the `LIST_SIMPLE_INSTEAD_OF_META` setting is disabled.
* **Grouped** (`3`) — Always created as listable. Any `group_products` value in the request is ignored during creation.
* **Bundle** (`2`) — Always created as non-listable and always requires form input.
* **Offer** (`5`) — Always created as non-listable. The product's images are synchronized from the offer relationship after creation.

**Dynamic Setting**

| Setting Key                   | Type             | Default                              | Effect                                                                                                                                                                                                                                                                                  |
| ----------------------------- | ---------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LIST_SIMPLE_INSTEAD_OF_META` | boolean          | `false`                              | When enabled, an individual simple variant is exposed as the listable product for its group instead of the parent product meta. This changes the listability computed here for **Simple** and **Product Meta** types, and determines which product receives a generated storefront URL. |
| `LISTABLE_PRODUCT_RULES`      | array of strings | `["image_rule", "is_listable_rule"]` | The ordered rules that decide which variant is chosen as the listable product within a group. Applied here when a new variant competes for the listable position of its group.                                                                                                          |

You configure these settings in the management panel. For `LIST_SIMPLE_INSTEAD_OF_META`, when it is not set its value falls back to the corresponding server configuration value, and to `false` if that is also unset. See the **Dynamic Settings & Environment Variables** section for full definitions.

```json
{"openapi":"3.1.0","info":{"title":"Admin API","version":"1.0.0"},"tags":[{"name":"Products","description":"Administrative endpoints for **products** — the catalog records managed by internal management tools and integration systems.\n\n## Core Capabilities\n\n**1. Product Listing & Filtering**\n* Retrieve a paginated catalog of products.\n* Filter by identifier, SKU, base code, and product type, and order results by one or more fields.\n\n**2. Product Lifecycle Management**\n* Create products of every writable type (Simple, Product Meta, Bundle, Grouped, Miscellaneous, Offer).\n* Fully or partially update existing products, subject to product-type transition rules.\n* Soft-delete (deactivate) a product while preserving its record.\n\n**3. Search Indexing**\n* Re-index a single product in the search engine so recent catalog changes become searchable immediately.\n\n## Product Types\n\nProduct endpoints use the following product types. The numeric code is the value sent and returned in requests and responses.\n\n| Code | Type | Description |\n|------|------|-------------|\n| -1 | **Pre Product** | Draft product not yet finalized |\n| 0 | **Simple** | Standard product, optionally a variant of a product meta |\n| 1 | **Product Meta** | Parent product that groups variants together |\n| 2 | **Bundle** | Configurable product built from chapter-based selections |\n| 3 | **Grouped** | Collection of related products sold as a set |\n| -2 | **Pre Miscellaneous** | Draft miscellaneous product |\n| 4 | **Miscellaneous** | Special product such as a service or fee |\n| 5 | **Offer** | Seller-specific product offer in a marketplace |\n\n## Dynamic Settings & Environment Variables\n\nThe behavior of these endpoints is influenced by the following dynamic settings, configured in the management panel. Each is referenced again in the description of the operations it affects.\n\n| Key | Type | Default | Effect |\n|-----|------|---------|--------|\n| `LIST_SIMPLE_INSTEAD_OF_META` | boolean | `false` | When enabled, an individual simple variant is exposed as the listable product for its group instead of the parent product meta. Affects the listability computed on **create** and **update** for **Simple** and **Product Meta** products, and determines which product receives a generated storefront URL. When unset, its value falls back to the corresponding server configuration value, and to `false` if that is also unset. |\n| `LISTABLE_PRODUCT_RULES` | array of strings | `[\"image_rule\", \"is_listable_rule\"]` | The ordered list of rules that decide which variant becomes the listable product within a group. Affects which sibling variant is chosen as listable on **create** and **update**. Available rules are `image_rule` (has an image), `is_listable_rule` (already listable), `stock_rule` (has stock), `max_price_rule` (highest price), and `min_price_rule` (lowest price). The list cannot be empty. |\n\n**Environment variables:** No environment variables affect these endpoints. All configurable behavior is controlled through the dynamic settings above."}],"servers":[{"description":"Omnitron Remote Proxy (external access — recommended)","url":"https://{omnitron_url}/api/remote/{channel_id}","variables":{"omnitron_url":{"default":"sandbox.akinon.com","description":"Omnitron server URL (e.g., {omnitron.akinon.com})"},"channel_id":{"default":"1","description":"The channel identifier the remote request is routed through"}}},{"description":"Commerce API Server (internal / direct access only)","url":"https://{commerce_url}/api/v1","variables":{"commerce_url":{"default":"sandbox.akinon.com","description":"Internal commerce server URL, reachable only from within the Omnitron network"}}}],"security":[{"tokenAuth":[]}],"components":{"securitySchemes":{"tokenAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Token credential sent in the Authorization header, in the form: `Token <your-token>`. Requires a staff (admin) account."}},"schemas":{"ProductWriteRequest":{"type":"object","description":"The data used to create or fully update a product.","required":["name","sku","product_type","attribute_set","extra_attributes"],"properties":{"name":{"type":"string","description":"The product name."},"base_code":{"type":["string","null"],"description":"The base code shared by variants of the same product."},"sku":{"type":"string","description":"The unique stock keeping unit."},"product_type":{"$ref":"#/components/schemas/WritableProductType"},"is_active":{"type":"boolean","default":true,"description":"Whether the product is active."},"parent":{"type":["integer","null"],"description":"The identifier of the parent product. Required for offer products."},"attributes":{"type":"object","description":"The attribute values of the product, keyed by attribute name.","additionalProperties":true},"attributes_kwargs":{"type":"object","description":"Additional attribute metadata for the product.","additionalProperties":true},"extra_attributes":{"type":"object","description":"Free-form extra attribute data for the product.","additionalProperties":true},"is_seller_product":{"type":"boolean","default":false,"description":"Whether the product belongs to a seller."},"group_products":{"type":["array","null"],"description":"The identifiers of products to group under this product.","items":{"type":"integer"}},"attribute_set":{"type":"integer","description":"The identifier of the attribute set that defines the product's attributes."},"custom_attribute_set":{"type":["integer","null"],"description":"The identifier of an additional custom attribute set."},"localized_attributes":{"type":"object","description":"Attribute values provided per language. Not returned in responses.","additionalProperties":true},"localized_attributes_kwargs":{"type":"object","description":"Additional per-language attribute metadata. Not returned in responses.","additionalProperties":true},"listing_code":{"type":["string","null"],"description":"The code that identifies the listable variant grouping."},"data_source":{"type":["integer","null"],"description":"The identifier of the default data source (seller). Required for offer products."},"is_form_required":{"type":"boolean","description":"Whether the product requires form input. This value is determined automatically by the system from the attribute set and product type; any value you send is ignored."}}},"WritableProductType":{"type":"string","description":"The product type accepted when creating or updating a product. The value is the numeric code as a string.\n\nThe draft types Pre Product (`-1`) and Pre Miscellaneous (`-2`) are not accepted here; they are used only for products created through other processes.\n* `0` — Simple\n* `1` — Product Meta\n* `2` — Bundle\n* `3` — Grouped\n* `4` — Miscellaneous\n* `5` — Offer","enum":["0","1","2","3","4","5"]},"Product":{"type":"object","description":"A product in the catalog.","properties":{"pk":{"type":"integer","description":"The unique identifier of the product.","readOnly":true},"name":{"type":"string","description":"The product name."},"base_code":{"type":["string","null"],"description":"The base code shared by variants of the same product."},"sku":{"type":"string","description":"The unique stock keeping unit."},"product_type":{"$ref":"#/components/schemas/ProductType"},"is_active":{"type":"boolean","description":"Whether the product is active."},"parent":{"type":["integer","null"],"description":"The identifier of the parent product, when the product is a variant."},"attributes":{"type":"object","description":"The attribute values of the product, keyed by attribute name.","additionalProperties":true},"attributes_kwargs":{"type":"object","description":"Additional attribute metadata for the product.","additionalProperties":true},"extra_attributes":{"type":"object","description":"Free-form extra attribute data for the product.","additionalProperties":true},"is_seller_product":{"type":"boolean","description":"Whether the product belongs to a seller."},"group_products":{"type":["array","null"],"description":"The identifiers of products grouped under this product.","items":{"type":"integer"}},"productimage_set":{"type":"array","description":"The images attached to the product.","readOnly":true,"items":{"$ref":"#/components/schemas/ProductImage"}},"attribute_set":{"type":"integer","description":"The identifier of the attribute set that defines the product's attributes."},"custom_attribute_set":{"type":["integer","null"],"description":"The identifier of an additional custom attribute set."},"is_listable":{"type":"boolean","description":"Whether the product is publicly listable. Determined by the system.","readOnly":true},"listing_code":{"type":["string","null"],"description":"The code that identifies the listable variant grouping."},"data_source":{"type":["integer","null"],"description":"The identifier of the default data source (seller) for the product."},"absolute_url":{"type":["string","null"],"description":"The storefront URL of the product, when available.","readOnly":true},"is_form_required":{"type":"boolean","description":"Whether the product requires form input."}}},"ProductType":{"type":"string","description":"The product type. The value is the numeric code as a string.\n* `-1` — Pre Product\n* `0` — Simple\n* `1` — Product Meta\n* `2` — Bundle\n* `3` — Grouped\n* `-2` — Pre Miscellaneous\n* `4` — Miscellaneous\n* `5` — Offer","enum":["-1","0","1","2","3","-2","4","5"]},"ProductImage":{"type":"object","description":"An image attached to the product.","properties":{"pk":{"type":"integer","readOnly":true},"status":{"type":"string","description":"The processing status of the image.","readOnly":true},"image":{"type":"string","description":"The image file path."},"order":{"type":"integer","description":"The display order of the image."},"created_date":{"type":"string","format":"date-time","description":"The date and time the image was created.","readOnly":true},"specialimage_set":{"type":"array","description":"Special image variants associated with the image.","items":{"type":"object"}}}},"ValidationError":{"type":"object","description":"Returned when the request contains invalid or missing data. Errors are grouped by the field they apply to: each key is the name of a field from the request and its value is a list of one or more messages describing what is wrong with that field. Messages that do not belong to any single field are grouped under `non_field_errors`.","properties":{"non_field_errors":{"type":"array","description":"Error messages that apply to the request as a whole rather than to a specific field.","items":{"type":"string"}}},"additionalProperties":{"type":"array","description":"The list of error messages for the field named by the key.","items":{"type":"string"}}},"Error":{"type":"object","description":"An error response.","properties":{"detail":{"type":"string","description":"A human-readable description of the error."}},"additionalProperties":true},"ProductBusinessError":{"type":"object","description":"Returned when a request is valid in form but violates a business rule of the catalog, such as an unsupported product-type change. The message describes the rule that was violated, and a stable code identifies it.","properties":{"non_field_errors":{"type":"string","description":"A human-readable message describing the business rule that was violated."},"error_code":{"type":"string","description":"A stable code identifying the specific business rule violation."}},"additionalProperties":true}},"responses":{"ValidationError":{"description":"The request contains invalid or missing data.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"Unauthorized":{"description":"Authentication credentials were not provided or are invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The authenticated user does not have administrator privileges.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"BusinessRuleViolation":{"description":"The request is well-formed but conflicts with a business rule — for example, requesting a product-type change that is not allowed (only Simple ↔ Miscellaneous transitions are permitted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductBusinessError"}}}}}},"paths":{"/products/":{"post":{"tags":["Products"],"operationId":"createProduct","summary":"Create a product","description":"Creates a new product. The way the product is created, and which fields are required, depends on the `product_type` you provide.\n\n**General Rules**\n\n* The `sku` must be unique across the catalog. Creating a product with an SKU that already exists is rejected.\n* Whether the product is publicly listable (`is_listable`) and whether it requires form input (`is_form_required`) are **determined automatically** by the system from the product type and the selected attribute set. Values you send for these fields do not override the computed result.\n* When a product becomes listable, the system generates its storefront URL automatically.\n\n**Conditional Field Requirements**\n\n| Condition | Requirement |\n|-----------|-------------|\n| Always | `name`, `sku`, `product_type`, `attribute_set`, and `extra_attributes` are required. |\n| `product_type` is **Offer** (`5`) | `parent` is required. The request is rejected if it is missing. |\n| `product_type` is **Offer** (`5`) | `data_source` is required. The request is rejected if it is missing. |\n\n**Behavior by Product Type**\n\n* **Simple** (`0`)\n  * Without a `parent`, the product is created as listable.\n  * With a `parent`, the product is treated as a variant. It becomes the listable variant of its group only when no other listable sibling already holds that position for the same listable-attribute values. If a listable sibling already exists, the product is created as non-listable.\n  * When the `LIST_SIMPLE_INSTEAD_OF_META` setting is enabled, listability is always evaluated at the individual simple-variant level rather than at the parent level.\n* **Miscellaneous** (`4`) — Created as an individual product and never listable.\n* **Product Meta** (`1`) — Created as the parent of a variant group. It is listable only when its attribute set defines no listable variant attributes **and** the `LIST_SIMPLE_INSTEAD_OF_META` setting is disabled.\n* **Grouped** (`3`) — Always created as listable. Any `group_products` value in the request is ignored during creation.\n* **Bundle** (`2`) — Always created as non-listable and always requires form input.\n* **Offer** (`5`) — Always created as non-listable. The product's images are synchronized from the offer relationship after creation.\n\n**Dynamic Setting**\n\n| Setting Key | Type | Default | Effect |\n|-------------|------|---------|--------|\n| `LIST_SIMPLE_INSTEAD_OF_META` | boolean | `false` | When enabled, an individual simple variant is exposed as the listable product for its group instead of the parent product meta. This changes the listability computed here for **Simple** and **Product Meta** types, and determines which product receives a generated storefront URL. |\n| `LISTABLE_PRODUCT_RULES` | array of strings | `[\"image_rule\", \"is_listable_rule\"]` | The ordered rules that decide which variant is chosen as the listable product within a group. Applied here when a new variant competes for the listable position of its group. |\n\nYou configure these settings in the management panel. For `LIST_SIMPLE_INSTEAD_OF_META`, when it is not set its value falls back to the corresponding server configuration value, and to `false` if that is also unset. See the **Dynamic Settings & Environment Variables** section for full definitions.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductWriteRequest"}}}},"responses":{"201":{"description":"The product was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"406":{"$ref":"#/components/responses/BusinessRuleViolation"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://apidocs.akinon.com/commerce-openapis/admin/products/create-a-product.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
