> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mercurjs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# createProductAttributesWorkflow

> Create catalog attributes with values, mirror options, and category links.

Creates product attributes and their values. Variant-axis `multi_select` attributes also get a shared mirror `ProductOption` created, with each value bound to its option value. Optional `category_ids` create category links per attribute. Triggered by `POST /admin/product-attributes`. Emits `product-attribute.created`.

## Usage

```ts theme={null}
import { createProductAttributesWorkflow } from "@mercurjs/core/workflows"

const { result } = await createProductAttributesWorkflow(container).run({
  input: {
    attributes: [
      {
        name: "Color",
        type: "multi_select",
        is_variant_axis: true,
        values: [{ name: "Red" }, { name: "Blue" }],
        category_ids: ["pcat_apparel"],
      },
    ],
  },
})
```

## Input

<ParamField body="attributes" type="(CreateProductAttributeDTO & { category_ids?: string[] })[]" required>
  Attributes to create.

  <Expandable title="properties">
    <ParamField body="name" type="string" required>Display name of the attribute.</ParamField>
    <ParamField body="type" type="AttributeType" required>One of `single_select`, `multi_select`, `unit`, `toggle`, `text`.</ParamField>
    <ParamField body="handle" type="string">URL-safe handle; auto-generated when omitted.</ParamField>
    <ParamField body="description" type="string | null">Description of the attribute.</ParamField>
    <ParamField body="is_required" type="boolean">Whether products must carry this attribute.</ParamField>
    <ParamField body="is_filterable" type="boolean">Whether the attribute is exposed as a storefront filter.</ParamField>
    <ParamField body="is_variant_axis" type="boolean">Mirror the attribute as a shared `ProductOption` (with `type: multi_select`).</ParamField>
    <ParamField body="rank" type="number">Sort rank.</ParamField>
    <ParamField body="is_active" type="boolean">Whether the attribute is active.</ParamField>
    <ParamField body="values" type="CreateProductAttributeValueDTO[]">Values to create (`{ name, handle?, rank?, is_active?, metadata? }`).</ParamField>
    <ParamField body="category_ids" type="string[]">Category ids to link the attribute to.</ParamField>
    <ParamField body="metadata" type="object | null">Custom key-value data.</ParamField>
  </Expandable>
</ParamField>

<ParamField body="additional_data" type="object">Custom data passed through to the hooks.</ParamField>

## Result

<ResponseField name="result" type="ProductAttributeDTO[]">The created attributes.</ResponseField>

## Hooks

* `validate` — runs before creation with `{ input }`.
* `productAttributesCreated` — runs after creation with `{ attributes, additional_data }`.
