# Plugins

In the Commerce system, plugins are used to load additional data on the product listing page. Currently, there is only one type of plugin available. New plugin definitions are requested and developed by the Commerce team based on requirements.

**Available Plugin:**

* `products.listable_product_variants`

The only plugin currently available in the system allows additional data, defined for the plugin, to be added to the existing product data on the listing page. **Once a plugin is defined, existing products must be reindexed to reflect its effects.**

The next section details how to list and create plugins using the Commerce API.

### <mark style="color:$primary;">**Listable Product Variants Plugin**</mark>

The `products.listable_product_variants` plugin is used to add extra data to the `extra_data` field within a product on the listing page.

**Default `extra_data` Field Without Plugin:**

If the plugin is not available or is inactive, the `extra_data` field of a product on the listing page appears as follows:

```java
"extra_data": {
   "variants": []
}
```

**Modified `extra_data` Field with Plugin:**

When the plugin is configured with the following settings:

```
"config": {
   "attribute_keys": [
       "size",
       "color"
   ],
   "product_field_names": [
       "pk",
       "price",
       "absolute_url",
       "productimage_set",
       "attributes"
   ],
   "attribute_set_attributes": {}
}
```

The `extra_data` field on the listing page is modified as follows:

```
"extra_data": {
   "variants": [
       {
           "options": [{
               "label": "XS",
               "product": {
                   "pk": 114768,
                   "sku": "5797434",
                   "price": "1599",
                   "attributes": {},
                   "absolute_url": "/product/114768/",
                   "productimage_set": []
               },
               "in_stock": true,
               "is_selectable": true
           }],
           "attribute_key": "color"
       },
       {
           "options": [
               {},
               {},
               {},
               {}
           ],
           "attribute_key": "size"
       }
   ]
}
```

The modified structure results from defining `attribute_keys` with values like `color` and `size`. This allows variants of the product based on these attribute values to be listed within `extra_data`.

Additionally, the `product_field_names` setting defines which fields of the variant products should be included in the response. In the example above, the fields `pk`, `price`, `absolute_url`, `productimage_set`, and `attributes` are specified, ensuring that these details are included when displaying variant products.

**Note:** The attributes specified in `attribute_keys` must be **variant attributes**. That is, they should correspond to attributes that define different variations of a product (e.g., `color`, `size`) rather than general product attributes.

#### **Config settings**

The plugin is configured via three keys in `config`:

<table><thead><tr><th width="223.19140625">Setting</th><th>Description</th></tr></thead><tbody><tr><td><code>product_field_names</code></td><td>List of product field names to include in each variant option’s <code>product</code> object. Only the fields in the allowed list (see below) can be used. <strong><code>attributes</code> must always be included.</strong></td></tr><tr><td><code>attribute_keys</code></td><td>List of attribute keys that define which variant dimensions are shown and which product attributes are returned. Keys are brand-specific (e.g. size, color, beden). These must be variant attributes for the product’s attribute set.</td></tr><tr><td><code>attribute_set_attributes</code></td><td>Optional. Map of attribute set ID (string) to a list of attribute keys. When set, overrides <code>attribute_keys</code> per attribute set so different product types can expose different variant attributes (see <a href="#variant-attributes-per-attribute-set">Variant attributes per attribute set</a> below).</td></tr></tbody></table>

#### **Allowed product fields (product\_field\_names)**

Values for `product_field_names` are product-level fields derived from the Product model and its related data. You may use only the following names:

<table><thead><tr><th width="218.01953125">Field</th><th>Description</th></tr></thead><tbody><tr><td><code>pk</code></td><td>Product ID.</td></tr><tr><td><code>name</code></td><td>Product name.</td></tr><tr><td><code>sku</code></td><td>Stock keeping unit. <em>(Always included by the plugin even if omitted from <code>product_field_names</code>.)</em></td></tr><tr><td><code>base_code</code></td><td>Base product code.</td></tr><tr><td><code>attributes</code></td><td>Product attributes (key–value). <strong>Required in <code>product_field_names</code>.</strong> Which keys appear is controlled by <code>attribute_keys</code> (and <code>attribute_set_attributes</code> when used).</td></tr><tr><td><code>attribute_set</code></td><td>Attribute set ID.</td></tr><tr><td><code>attributes_kwargs</code></td><td>Attribute key–value with language/label info.</td></tr><tr><td><code>extra_attributes</code></td><td>Extra attributes (JSON).</td></tr><tr><td><code>productimage_set</code></td><td>Product images.</td></tr><tr><td><code>price</code></td><td>Price.</td></tr><tr><td><code>in_stock</code></td><td>Whether the product is in stock.</td></tr><tr><td><code>currency_type</code></td><td>Currency.</td></tr><tr><td><code>retail_price</code></td><td>Retail price.</td></tr><tr><td><code>unit_type</code></td><td>Stock unit type.</td></tr><tr><td><code>tax_rate</code></td><td>Tax rate.</td></tr><tr><td><code>absolute_url</code></td><td>Product URL.</td></tr><tr><td><code>productvideo_set</code></td><td>Product videos.</td></tr><tr><td><code>product_type</code></td><td>Product type.</td></tr><tr><td><code>price_type</code></td><td>Price type.</td></tr><tr><td><code>form_schema</code></td><td>Form schema for attributes.</td></tr><tr><td><code>is_ready_to_basket</code></td><td>Whether the product can be added to basket.</td></tr><tr><td><code>stock</code></td><td>Stock quantity.</td></tr><tr><td><code>data_source</code></td><td>Data source.</td></tr><tr><td><code>basket_offers</code></td><td>Basket/offer data.</td></tr><tr><td><code>is_listable</code></td><td>Whether the product is listable.</td></tr><tr><td><code>listing_code</code></td><td>Listing code.</td></tr></tbody></table>

#### **How to add product attributes to the data?**

To have product attributes in each variant’s `product` object in the listing response:

1. **Include `attributes` in `product_field_names`**\
   The API requires `attributes` in `product_field_names`; otherwise the plugin config is invalid.
2. **Set `attribute_keys`**\
   Add the attribute keys you want to expose (e.g. size, color, beden). These keys:
   * Define which variant dimensions appear in `extra_data.variants`.
   * Define which keys are present in each variant option’s `product.attributes`. Only these keys are returned; other product attributes are omitted.

So the variant product’s `attributes` object in the response will contain only the keys you list in `attribute_keys` (or in `attribute_set_attributes` for that product’s attribute set). Attribute keys are brand- or tenant-specific; use the keys defined in your attribute set(s) for variant attributes.

#### **Variant attributes per attribute set (attribute\_set\_attributes)**

By default, `attribute_keys` applies to all products. If you have multiple attribute sets (e.g. different product types or brands) and want different variant attributes per set, use `attribute_set_attributes`.

* **Key:** attribute set ID as a **string** (e.g. `"5"`, `"12"`).
* **Value:** list of attribute keys to use for that attribute set (same meaning as `attribute_keys`).

Example: products with attribute set `5` expose `size` and `color`; products with attribute set `12` expose `beden`:

```
"attribute_set_attributes": {
   "5": ["size", "color"],
   "12": ["beden"]
}
```

For a product whose `attribute_set_id` is in this map, the plugin uses the list for that ID instead of `attribute_keys`. Products whose attribute set is not in the map still use `attribute_keys`.

***

**Audience:** The plugin API can be used by third-party integrators or internally. After creating or changing a plugin’s config, **reindex the affected products** so listing responses reflect the new settings.

### <mark style="color:$primary;">**Plugin API Endpoints**</mark>

#### **`GET` List Plugins**

This endpoint retrieves the plugin settings stored in the database.

**Path:** `/api/v1/plugins/`

**Example Request**

```
curl --location '{commerce_url}/api/v1/plugins/'
```

**Example Response**

```java
{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "pk": 2,
            "key": "products.listable_product_variants",
            "name": "Listable Product Variants",
            "description": "...",
            "is_active": false,
            "config": {
                "attribute_keys": [],
                "product_field_names": ["attributes"],
                "attribute_set_attributes": {}
            },
            "default_config": {
                "attribute_keys": [],
                "product_field_names": ["attributes", "pk", "..."],
                "attribute_set_attributes": {}
            }
        }
    ]
}
```

**Response Parameters**

| Key              | Description                                                   |
| ---------------- | ------------------------------------------------------------- |
| `pk`             | Contains the ID of the plugin.                                |
| `key`            | Stores the `KEY` attribute value of the plugin class.         |
| `name`           | Stores the `NAME` attribute value of the plugin class.        |
| `description`    | Stores the `DESCRIPTION` attribute value of the plugin class. |
| `config`         | Contains the `CONFIG` attribute value of the plugin.          |
| `default_config` | Contains the `DEFAULT CONFIG` attribute value of the plugin.  |
| `is_active`      | Indicates whether the plugin is active.                       |

#### **`GET` List All Available Plugins**

This endpoint retrieves all plugin classes registered in the Plugin Registry.

**Path:** `/api/v1/plugins/all/`

**Example Request**

```
curl --location '{commerce_url}/api/v1/plugins/all/'
```

**Example Response**

```
[
    {
        "key": "products.listable_product_variants",
        "name": "Listable Product Variants",
        "description": "...",
        "config": {
            "attribute_keys": [],
            "product_field_names": [
                "pk",
                "price",
                "absolute_url",
                "productimage_set",
                "attributes"
            ],
            "attribute_set_attributes": {}
        },
        "is_active": false
    }
]
```

**Response Parameters**

| Key           | Description                                                   |
| ------------- | ------------------------------------------------------------- |
| `key`         | Stores the `KEY` attribute value of the plugin class.         |
| `name`        | Stores the `NAME` attribute value of the plugin class.        |
| `description` | Stores the `DESCRIPTION` attribute value of the plugin class. |
| `config`      | Contains the `CONFIG` attribute value of the plugin.          |
| `is_active`   | Indicates whether the plugin is active.                       |

#### **`POST` Create a Plugin**

This endpoint is used to add settings and activate a plugin. Only one record can be created for each plugin key, and duplicate records are not allowed. If the provided `key` does not exist in the Plugin Registry, the API returns an error: `Plugin with this key does not exist.`

The `config` key in the request body must contain a dictionary formatted according to the `config_serializer` defined in the plugin class.

**Path:** `/api/v1/plugins/`

**Request Body Parameters**

| Key         | Description                                                     |
| ----------- | --------------------------------------------------------------- |
| `key`       | Must contain the `KEY` attribute value of the plugin class.     |
| `config`    | Must contain a valid configuration according to the serializer. |
| `is_active` | Indicates whether the plugin is active.                         |

**Example Request**

```
curl --location '{commerce_url}/api/v1/plugins/' \
--header 'Content-Type: application/json' \
--data '{
    "key": "products.listable_product_variants",
    "config": {
        "product_field_names": [
            "pk",
            "price",
            "retail_product",
            "attributes"
        ],
        "attribute_keys": [],
        "attribute_set_attributes": {}
    },
    "is_active": false
}'
```

**Example Response**

```
{
    "pk": 2,
    "key": "products.listable_product_variants",
    "name": "Listable Product Variants",
    "description": "...",
    "is_active": false,
    "config": {
        "attribute_keys": [],
        "product_field_names": [
            "pk",
            "price",
            "retail_product",
            "attributes"
        ],
        "attribute_set_attributes": {}
    },
    "default_config": {
        "attribute_keys": [],
        "product_field_names": [
            "attributes", "pk", "..."
        ],
        "attribute_set_attributes": {}
    }
}
```

**Response Parameters**

<table><thead><tr><th width="180.046875">Key</th><th>Description</th></tr></thead><tbody><tr><td><code>pk</code></td><td>Contains the ID of the plugin.</td></tr><tr><td><code>key</code></td><td>Stores the <code>KEY</code> attribute value of the plugin class.</td></tr><tr><td><code>name</code></td><td>Stores the <code>NAME</code> attribute value of the plugin class.</td></tr><tr><td><code>description</code></td><td>Stores the <code>DESCRIPTION</code> attribute value of the plugin class.</td></tr><tr><td><code>config</code></td><td>Contains the <code>CONFIG</code> attribute value of the plugin.</td></tr><tr><td><code>default_config</code></td><td>Contains the <code>DEFAULT CONFIG</code> attribute value of the plugin.</td></tr><tr><td><code>is_active</code></td><td>Indicates whether the plugin is active.</td></tr></tbody></table>

#### **`PUT` Update a Plugin**

This endpoint updates the settings and activation status of an existing plugin. If a plugin has not been added previously, it must be created first.

The `config` key in the request body must contain a dictionary formatted according to the `config_serializer` defined in the plugin class.

**Path:** `/api/v1/plugins/`

**Request Body Parameters**

<table><thead><tr><th width="148.12109375">Key</th><th>Description</th></tr></thead><tbody><tr><td><code>key</code></td><td>Must contain the <code>KEY</code> attribute value of the plugin class.</td></tr><tr><td><code>config</code></td><td>Must contain a valid configuration according to the serializer.</td></tr><tr><td><code>is_active</code></td><td>Indicates whether the plugin is active.</td></tr></tbody></table>

**Example Request**

```
curl --location --request PUT '{commerce_url}/api/v1/plugins/3/' \
--data '{
    "key": "products.listable_product_variants",
    "config": {
        "product_field_names": ["pk", "attributes"],
        "attribute_keys": [],
        "attribute_set_attributes": {}
    },
    "is_active": false // Deactivating the plugin
}'
```

**Example Response**

```
{
    "pk": 3,
    "key": "products.listable_product_variants",
    "name": "Listable Product Variants",
    "description": "...",
    "is_active": false,
    "config": {
        "attribute_keys": [],
        "product_field_names": [
            "pk","attributes"
        ],
        "attribute_set_attributes": {}
    },
    "default_config": {
        "attribute_keys": [],
        "product_field_names": [
            "pk",
            "price",
            "retail_product",
            "absolute_url",
            "productimage_set",
            "attributes"
        ],
        "attribute_set_attributes": {}
    }
}
```

**Response Parameters**

<table><thead><tr><th width="193.87890625">Key</th><th>Description</th></tr></thead><tbody><tr><td><code>pk</code></td><td>Contains the ID of the plugin.</td></tr><tr><td><code>key</code></td><td>Stores the <code>KEY</code> attribute value of the plugin class.</td></tr><tr><td><code>name</code></td><td>Stores the <code>NAME</code> attribute value of the plugin class.</td></tr><tr><td><code>description</code></td><td>Stores the <code>DESCRIPTION</code> attribute value of the plugin class.</td></tr><tr><td><code>config</code></td><td>Contains the <code>CONFIG</code> attribute value of the plugin.</td></tr><tr><td><code>default_config</code></td><td>Contains the <code>DEFAULT CONFIG</code> attribute value of the plugin.</td></tr><tr><td><code>is_active</code></td><td>Indicates whether the plugin is active.</td></tr></tbody></table>


---

# Agent Instructions: 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:

```
GET https://docs.akinon.com/technical-guides/commerce/plugins.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
