---
updatedAt: 2026-09-07T08:15:07.000Z
agentTools:
  projectIndex: https://docs.makaira.io/llms.txt
---

# Tutorials

# Postman & Makaira-API

***

tl;dr: [Download Postman Collection](https://testndjson.s3.eu-central-1.amazonaws.com/Makaira%20Connect.postman_collection.json)

***

## Creating signed requests with Postman

**Task:** Check communication between Makaira API and store.

**Solution**\
With [Postman](https://www.postman.com/) it is possible to check HMAC-signed requests between the store and Makaira. The signing key is an **API key** (historically called Shared Secret). Use the legacy key or a new key with the Importer preset.\
This is done by sending a POST request to the endpoint provided by the store, e.g. `<shopurl>?cl=makaira_connect_endpoint` in the Oxid Shop.\
It is recommended to create an environment configuration with the following variables.

```json
nonce:123456
secret:<API key>
requestHash:someValueThatWillBeOverridden
```

The following headers are required:

```json
Content-Type:application/json
X-Makaira-Nonce:{{nonce}}
X-Makaira-Hash:{{requestHash}}
```

With a pre-request script, the hash is generated based on the current request body.

```json
const nonce = ((Math.random() + 1) * 10000000).toString(36);
const secret = pm.environment.get('secret');

let body = '';
try {
    body = request.data;
} catch (e) {
    console.error(e);
}

body = pm.environment.replaceIn(body);

const hashString = nonce + ':' + body;
const hash = CryptoJS.HmacSHA256(hashString, secret);

pm.request.headers.add({key: "X-Makaira-Nonce", value: nonce});
pm.request.headers.add({key: "X-Makaira-Hash", value: CryptoJS.enc.Hex.stringify(hash)});

```

Example: Body for checking the update data

```json
POST <shopurl>?cl=makaira_connect_endpoint
{"action":"getUpdates","since":0,"count":10,"language":"de"}
```

***

## Signing of API requests in the store

**Task:** Send requests directly to the Makaira API without using the Connect module.

**Solution**\
Communication with the Makaira API is secured via signed requests. The signature is an HMAC over the request body and a random nonce using an **API key**. Send `X-Makaira-Nonce` and `X-Makaira-Hash`. See [Authentication](https://docs.makaira.io/reference/authentication) and [API Keys](https://docs.makaira.io/docs/api-keys).

PHP example for generating the headers:

```php
<?php

/**
 * Execute a HTTP request to the remote server
 *
 * @param mixed  $body         request body
 * @param string $apiKey     API key from Administration → API Keys
 *
 * @return array
 */
public function generateSignatureHeaders($body = null, $apiKey)
{
    $nonce = bin2hex(random_bytes(16));
    $hash = hash_hmac('sha256', $nonce . ':' . $body, $apiKey);
    $headers[] = 'X-Makaira-Nonce: ' . $nonce;
    $headers[] = 'X-Makaira-Hash: ' . $hash;

    return $headers;
}
```

***

## Control of ES indices via the Makaira API

**Task:** Change or delete ElasticSearch indexes via the Makaira API.

**Solution**\
Makaira allows manipulating ElasticSearch indexes via the provided API.

The `<makaira-url>/indices` route is provided as the endpoint.

The requests to interact with the API require a Basic-Auth header from the login credentials for the Makaira instance for verification.

To identify the relevant index, its alias - found in Makaira under "Index Configuration" - can be used, e.g. `stage_passive_en`

* Delete an index\
  Note: When deleting, only passive indexes should be deleted. The importer ensures that these are automatically created again.

```json
curl -X DELETE \
  https://<CUSTOMER>.makaira.io/indices/stage_passive_de \
  -H 'Authorization: Basic <BASIC-AUTH> \
  -H 'Content-Type: application/json'
```

* Activate a passive index\
  Note: Activating a passive index always switches the currently active index of the selected language to inactive.

```json
curl -X PUT \
  https://<CUSTOMER>.makaira.io/indices/stage_passive_de/active \
  -H 'Authorization: Basic <BASIC-AUTH> \
  -H 'Content-Type: application/json'
```

* Status (revision) of an index\
  The request to query the index status has basically the same structure as the previous examples. However, since each instance can have multiple active and passive indexes, an additional header must be sent to specify the desired instance. In the response, the openChanges field indicates the revisions are still to be processed. If this value is 0, the respective index is up to date.

```json
curl -X PUT \
  https://<CUSTOMER>.makaira.io/importer/status \
  -H 'Authorization: Basic <BASIC-AUTH> \
  -H 'Content-Type: application/json' \
  -H 'X-Makaira-Instance: <INSTANCE>'
```

***

# Customize API request

***

## Set additional product filters

**Task:** You want to manipulate the item list with additional filters.

**Solution**\
With the help of an OXID eShop module you can extend the API request:

First, create a module directory (here specified with `<module_root>`) and a metadata.php that looks like this:

```php
<?php
/* <module_root>/metadata.php */

$sMetadataVersion = '1.1';

$aModule = array(
    'id'     => 'makaira/extension',
    'title'  => 'Makaira :: Extension',
    'extend' => array(
        'makaira_connect_request_handler' => '<module_root>/makaira_extension_request_handler'
    ),
    'files'    => array(),
    'blocks'   => array(),
    'settings' => array(),
);
```

Next comes the override of the makaira\_connect\_request\_handler::modifyRequest() method. This allows easy manipulation of the API request and setting additional filters.

```php
<?php
/* <module_root>/makaira_extension_request_handler.php */

class makaira_extension_request_handler extends makaira_extension_request_handler_parent
{
    protected function modifyRequest(Query $query)
    {
        /*
        $query->customFilter = [
            "product" => [
                "and" => [
                    [
                        "field"    => "OXSTOCK",
                        "operator" => "gt",
                        "value"    => 2
                    ],
                    [
                        "attribute" => "d2eb444e35c0a71f0a85df8194acb5b6",
                        "operator"  => "eq",
                        "value"     => ["blau", "schwarz"]
                    ],
                    [
                        "attribute" => "9438ac75bac3e344628b14bf7ed82c15",
                        "dataType"  => "integer",
                        "operator"  => "gte",
                        "value"     => 10
                    ],
                ],
                "or"  => [],
                "not" => []
            ]
        ];
        */

        return parent::modifyRequest($query);
    }
}
```

**Information**\
The customFilter property accepts filters for product fields and attributes that are linked using and, or, or not. These can also be nested within each other. As of Makaira-Connect version 2018.11.0, attributes can be imported specifically as numeric attributes. If such an attribute is to be accessed via the customFilter, dataType must be set (integer or float).

The customFilter can be applied only to product attributes, only to variant attributes, or both. So instead of product, makaira-product (variants only) or makaira-productgroup (products only) can be used:

`makaira-product` filters only by variant attributes

`makaira-productgroup` filters only by product attributes

`product` filters on both levels simultaneously: by product and variant attributes

If multiple customFilters with different types are used, they are linked with and.

***

## Provide additional data for autosuggest

**Task:** You want to display additional fields in Autosuggest, for example, the manufacturer of an item.

**Solution**\
The returned fields of the autosuggest are provided by the following function:

```php
<?php

protected function getFieldsForResults()
{
    $fields = ['OXID', 'OXTITLE', 'OXVARSELECT'];

    return $fields;
}
```

The function can be found in the Connect module at `src/oxid/core/makaira_connect_autosuggester.php.`

By extending the class makaira\_connect\_autosuggester the function can be overridden and more fields can be added.

```text
<?php

class makaira_project_autosuggester extends makaira_project_autosuggester_parent
{
    /**
     * Getter method for resulting fields
     *
     * @return array
     */
    protected function getFieldsForResults()
    {
        $fields   = parent::getFieldsForResults();
        $fields[] = 'MANUFACTURERTITLE';

        return $fields;
    }

    /**
     * data preparation hook
     *
     * @param object $doc
     * @param \oxArticle $product
     *
     * @return array
     */
    protected function prepareProductItem(&$doc, &$product)
    {
        $aItem = parent::prepareProductItem($doc, $product);
        // add additional field
        $aItem['manufacturer'] = $doc->fields['manufacturertitle']

        return $aItem;
    }
}
```

**Information**\
Calling the parent method ensures that the default autosuggest fields will continue to be used.

When preparing the data for autosuggest, an instance of the item is created. To avoid the associated database request, the loadProductItem method can be overridden instead of the prepareProductItem method.

```php
<?php

class makaira_project_autosuggester extends makaira_project_autosuggester_parent
{
    /**
     * Prepare the data
     *
     * @param object $doc
     *
     * @return array
     */
    protected function loadProductItem($doc)
    {
        if (empty($doc->fields['oxtitle'])) {
            return [];
        }

        $title = $doc->fields['oxtitle'];
        if (!empty($doc->fields['oxvarselect'])) {
            $title .= ' | ' . $doc->fields['oxvarselect'];
        }

        $aItem = [];
        $aItem['label'] = $title;
        $aItem['value'] = $title;
        $aItem['link']  = $doc->fields['url']
        $aItem['type']  = 'product';

        return $aItem;
    }
}
```

***

# Improve search results with synonym, antonym, and association

Creating synonyms, antonyms and mapping is generally not the best solution to improve search in a store, because unexpected behavior can occur quickly and features like fuzzy search do not work with synonyms. For example, if I have 10 similar products in my store, but they are all named differently, it is possible to create a temporary solution with 10 synonyms, but it would be better to edit the description of the articles or at least to store the most important terms in the Searchkeys field uniformly for each product. Furthermore, it does not make sense to import all synonyms for a term across the board from a synonym dictionary, as this quickly leads to a very fuzzy search. In general, it can be said that concentrating on a few frequently used words is better than trying to cover all conceivable cases.

A good starting point is the evaluation of the search queries (monitoring). If it becomes apparent here that certain search terms frequently do not deliver any results or are linked to a poor conversion rate, these cases should first be checked manually. If it now appears that only a few or no relevant results can be found under this search term, it must be checked whether another search term delivers better results. If the new search really fits better to the customer's intention, synonyms, antonym,s and mapping can be used to improve the search.

**Task**\
Create synonyms and still maintain the search accuracy. The whole thing will be demonstrated on the basis of various cases.

* In the store about half of the products have `black` as color description and the other half ` black` .
* Customers often search for `snapsack` but all items in my store that match are called `backpack` or `satchel`.
* Customers often search for `roomy backpack`, they are available in the store, but the word roomy does not appear in any description.

**Solution**\
Under Search->How to search->the following synonyms are created:\
`black, schwarz`\
`schnappsack=> rucksack, ranzen`\
`geraumiger rucksack=> rucksack`

## See  and edit the A/B Experiment group in the webbrowser

**Task:** Find out in which group you are and switch to the other group.

**Solution**\
The information in which group you are is stored in the cookie. This makes shure that a user does not randomly change between the groups. You can find the entry under the name

```text
Name: mak_experiments
```

The value of the cookie includes two informations which are url-encoded. You will find the id and the current group that you are in(compare this to the configuration in Makaira). For an example we use id 84. The group name will be either `original`  or the title of the experiment that you choose. In this example it is called `Personalisierung`. The possible cases are

```text
Value variant A: %5B%7B%22experiment%22%3A84%2C%22variation%22%3A%22original%22%7D%5D
Value variant B: %5B%7B%22experiment%22%3A84%2C%22variation%22%3A%22Personalisierung%22%7D%5D
```

To change the groups you simply have to edit the value and interchange `original` and `Personalisierung`.