<?php

// Code generated by OpenAPI Generator (https://openapi-generator.tech), manual changes will be lost - read more on https://github.com/algolia/api-clients-automation. DO NOT EDIT.

namespace Algolia\AlgoliaSearch\Api;

use Algolia\AlgoliaSearch\Algolia;
use Algolia\AlgoliaSearch\Configuration\IngestionConfig;
use Algolia\AlgoliaSearch\Configuration\SearchConfig;
use Algolia\AlgoliaSearch\Configuration\TransformationOptions;
use Algolia\AlgoliaSearch\Exceptions\ExceededRetriesException;
use Algolia\AlgoliaSearch\Exceptions\NotFoundException;
use Algolia\AlgoliaSearch\Exceptions\ValidUntilNotFoundException;
use Algolia\AlgoliaSearch\Iterators\ObjectIterator;
use Algolia\AlgoliaSearch\Iterators\RuleIterator;
use Algolia\AlgoliaSearch\Iterators\SynonymIterator;
use Algolia\AlgoliaSearch\Model\Search\AddApiKeyResponse;
use Algolia\AlgoliaSearch\Model\Search\ApiKey;
use Algolia\AlgoliaSearch\Model\Search\AssignUserIdParams;
use Algolia\AlgoliaSearch\Model\Search\BatchAssignUserIdsParams;
use Algolia\AlgoliaSearch\Model\Search\BatchDictionaryEntriesParams;
use Algolia\AlgoliaSearch\Model\Search\BatchParams;
use Algolia\AlgoliaSearch\Model\Search\BatchResponse;
use Algolia\AlgoliaSearch\Model\Search\BatchWriteParams;
use Algolia\AlgoliaSearch\Model\Search\BrowseParams;
use Algolia\AlgoliaSearch\Model\Search\BrowseResponse;
use Algolia\AlgoliaSearch\Model\Search\CreatedAtResponse;
use Algolia\AlgoliaSearch\Model\Search\DeleteApiKeyResponse;
use Algolia\AlgoliaSearch\Model\Search\DeleteByParams;
use Algolia\AlgoliaSearch\Model\Search\DeletedAtResponse;
use Algolia\AlgoliaSearch\Model\Search\DeleteSourceResponse;
use Algolia\AlgoliaSearch\Model\Search\DictionarySettingsParams;
use Algolia\AlgoliaSearch\Model\Search\GetApiKeyResponse;
use Algolia\AlgoliaSearch\Model\Search\GetDictionarySettingsResponse;
use Algolia\AlgoliaSearch\Model\Search\GetLogsResponse;
use Algolia\AlgoliaSearch\Model\Search\GetObjectsParams;
use Algolia\AlgoliaSearch\Model\Search\GetObjectsResponse;
use Algolia\AlgoliaSearch\Model\Search\GetTaskResponse;
use Algolia\AlgoliaSearch\Model\Search\GetTopUserIdsResponse;
use Algolia\AlgoliaSearch\Model\Search\HasPendingMappingsResponse;
use Algolia\AlgoliaSearch\Model\Search\IndexSettings;
use Algolia\AlgoliaSearch\Model\Search\Languages;
use Algolia\AlgoliaSearch\Model\Search\ListApiKeysResponse;
use Algolia\AlgoliaSearch\Model\Search\ListClustersResponse;
use Algolia\AlgoliaSearch\Model\Search\ListIndicesResponse;
use Algolia\AlgoliaSearch\Model\Search\ListUserIdsResponse;
use Algolia\AlgoliaSearch\Model\Search\MultipleBatchResponse;
use Algolia\AlgoliaSearch\Model\Search\OperationIndexParams;
use Algolia\AlgoliaSearch\Model\Search\RemoveUserIdResponse;
use Algolia\AlgoliaSearch\Model\Search\ReplaceSourceResponse;
use Algolia\AlgoliaSearch\Model\Search\Rule;
use Algolia\AlgoliaSearch\Model\Search\SaveObjectResponse;
use Algolia\AlgoliaSearch\Model\Search\SaveSynonymResponse;
use Algolia\AlgoliaSearch\Model\Search\SearchDictionaryEntriesParams;
use Algolia\AlgoliaSearch\Model\Search\SearchDictionaryEntriesResponse;
use Algolia\AlgoliaSearch\Model\Search\SearchForFacetValuesRequest;
use Algolia\AlgoliaSearch\Model\Search\SearchForFacetValuesResponse;
use Algolia\AlgoliaSearch\Model\Search\SearchMethodParams;
use Algolia\AlgoliaSearch\Model\Search\SearchParams;
use Algolia\AlgoliaSearch\Model\Search\SearchResponse;
use Algolia\AlgoliaSearch\Model\Search\SearchResponses;
use Algolia\AlgoliaSearch\Model\Search\SearchRulesParams;
use Algolia\AlgoliaSearch\Model\Search\SearchRulesResponse;
use Algolia\AlgoliaSearch\Model\Search\SearchSynonymsParams;
use Algolia\AlgoliaSearch\Model\Search\SearchSynonymsResponse;
use Algolia\AlgoliaSearch\Model\Search\SearchUserIdsParams;
use Algolia\AlgoliaSearch\Model\Search\SearchUserIdsResponse;
use Algolia\AlgoliaSearch\Model\Search\SettingsResponse;
use Algolia\AlgoliaSearch\Model\Search\Source;
use Algolia\AlgoliaSearch\Model\Search\SynonymHit;
use Algolia\AlgoliaSearch\Model\Search\UpdateApiKeyResponse;
use Algolia\AlgoliaSearch\Model\Search\UpdatedAtResponse;
use Algolia\AlgoliaSearch\Model\Search\UpdatedAtWithObjectIdResponse;
use Algolia\AlgoliaSearch\Model\Search\UserId;
use Algolia\AlgoliaSearch\ObjectSerializer;
use Algolia\AlgoliaSearch\RetryStrategy\AlgoliaResponse;
use Algolia\AlgoliaSearch\RetryStrategy\ApiWrapper;
use Algolia\AlgoliaSearch\RetryStrategy\ApiWrapperInterface;
use Algolia\AlgoliaSearch\RetryStrategy\ClusterHosts;
use Algolia\AlgoliaSearch\Support\ChunkedHelperOptions;
use Algolia\AlgoliaSearch\Support\Helpers;
use GuzzleHttp\Psr7\Query;

/**
 * SearchClient Class Doc Comment.
 *
 * @category Class
 */
class SearchClient
{
    public const VERSION = '4.46.2';

    /**
     * @var ApiWrapperInterface
     */
    protected $api;

    /**
     * @var IngestionClient
     */
    protected $ingestionTransporter;

    /**
     * @var SearchConfig
     */
    protected $config;

    public function __construct(ApiWrapperInterface $apiWrapper, SearchConfig $config)
    {
        $this->config = $config;
        $this->api = $apiWrapper;
    }

    /**
     * Instantiate the client with basic credentials.
     *
     * @param string $appId  Application ID
     * @param string $apiKey Algolia API Key
     */
    public static function create($appId = null, $apiKey = null)
    {
        return static::createWithConfig(SearchConfig::create($appId, $apiKey));
    }

    /**
     * Instantiate the client with configuration.
     *
     * @param SearchConfig $config Configuration
     */
    public static function createWithConfig(SearchConfig $config)
    {
        $config = clone $config;

        $apiWrapper = new ApiWrapper(
            Algolia::getHttpClient(),
            $config,
            self::getClusterHosts($config)
        );

        $client = new static($apiWrapper, $config);

        if (null !== $config->getTransformationOptions()) {
            $client->ingestionTransporter = self::buildIngestionTransporter($config, $config->getTransformationOptions());
        }

        $logger = Algolia::getLogger();
        $logger->info('Algolia API client: Algolia SearchClient initialized (appId: '.$config->getAppId().')');
        Algolia::logDebugWarningOnce();

        return $client;
    }

    /**
     * Gets the cluster hosts depending on the config.
     *
     * @return ClusterHosts
     */
    public static function getClusterHosts(SearchConfig $config)
    {
        $cacheKey = sprintf('%s-clusterHosts-%s', __CLASS__, $config->getAppId());

        if ($hosts = $config->getHosts()) {
            // If a list of hosts was passed, we ignore the cache
            $clusterHosts = ClusterHosts::create($hosts);
        } elseif (false === ($clusterHosts = ClusterHosts::createFromCache($cacheKey))) {
            // We'll try to restore the ClusterHost from cache, if we cannot
            // we create a new instance and set the cache key
            $clusterHosts = ClusterHosts::createFromAppId($config->getAppId())
                ->setCacheKey($cacheKey)
            ;
        }

        return $clusterHosts;
    }

    /**
     * @return SearchConfig
     */
    public function getClientConfig()
    {
        return $this->config;
    }

    /**
     * Stub method setting a new API key to authenticate requests.
     *
     * @param string $apiKey
     */
    public function setClientApiKey($apiKey)
    {
        $this->config->setClientApiKey($apiKey);
    }

    /**
     * Sets (or replaces) the ingestion transporter used by the `*WithTransformation` helpers.
     * The transporter is built from the Ingestion API defaults (25s timeouts, region-derived
     * hosts); only the fields set on `$transformationOptions` override those defaults — the
     * parent `SearchConfig` is never forwarded.
     *
     * @see https://www.algolia.com/doc/libraries/sdk/methods/ingestion/
     */
    public function setTransformationOptions(TransformationOptions $transformationOptions)
    {
        $this->config->setTransformationOptions($transformationOptions);
        $this->ingestionTransporter = self::buildIngestionTransporter($this->config, $transformationOptions);
    }

    /**
     * Creates a new API key with specific permissions and restrictions.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param ApiKey|array $apiKey apiKey (required)
     *                             - $apiKey['acl'] => (array) Permissions that determine the type of API requests this key can make. The required ACL is listed in each endpoint's reference. For more information, see [access control list](https://www.algolia.com/doc/guides/security/api-keys/#access-control-list-acl). (required)
     *                             - $apiKey['description'] => (string) Description of an API key to help you identify this API key.
     *                             - $apiKey['indexes'] => (array) Index names or patterns that this API key can access. By default, an API key can access all indices in the same application.  You can use leading and trailing wildcard characters (`*`):  - `dev_*` matches all indices starting with \"dev_\" - `*_dev` matches all indices ending with \"_dev\" - `*_products_*` matches all indices containing \"_products_\".
     *                             - $apiKey['maxHitsPerQuery'] => (int) Maximum number of results this API key can retrieve in one query. By default, there's no limit.
     *                             - $apiKey['maxQueriesPerIPPerHour'] => (int) Maximum number of API requests allowed per IP address or [user token](https://www.algolia.com/doc/guides/sending-events/concepts/usertoken) per hour.  If this limit is reached, the API returns an error with status code `429`. By default, there's no limit.
     *                             - $apiKey['queryParameters'] => (string) Query parameters to add when making API requests with this API key.  To restrict this API key to specific IP addresses, add the `restrictSources` parameter. You can only add a single source, but you can provide a range of IP addresses.  Creating an API key fails if the request is made from an IP address outside the restricted range.
     *                             - $apiKey['referers'] => (array) Allowed HTTP referrers for this API key.  By default, all referrers are allowed. You can use leading and trailing wildcard characters (`*`):  - `https://algolia.com/_*` allows all referrers starting with \"https://algolia.com/\" - `*.algolia.com` allows all referrers ending with \".algolia.com\" - `*algolia.com*` allows all referrers in the domain \"algolia.com\".  Like all HTTP headers, referrers can be spoofed. Don't rely on them to secure your data. For more information, see [HTTP referrer restrictions](https://www.algolia.com/doc/guides/security/security-best-practices/#http-referrers-restrictions).
     *                             - $apiKey['validity'] => (int) Duration (in seconds) after which the API key expires. By default, API keys don't expire.
     *
     * @see ApiKey
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return AddApiKeyResponse|array<string, mixed>
     */
    public function addApiKey($apiKey, $requestOptions = [])
    {
        $response = $this->addApiKeyWithHttpInfo($apiKey, $requestOptions);

        return $response->getData();
    }

    /**
     * If a record with the specified object ID exists, the existing record is replaced. Otherwise, a new record is added to the index.  If you want to use auto-generated object IDs, use the [`saveObject` operation](https://www.algolia.com/doc/rest-api/search/save-object). To update _some_ attributes of an existing record, use the [`partial` operation](https://www.algolia.com/doc/rest-api/search/partial-update-object) instead. To add, update, or replace multiple records, use the [`batch` operation](https://www.algolia.com/doc/rest-api/search/batch).
     *
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param string $objectID       Unique record identifier. (required)
     * @param array  $body           The record. A schemaless object with attributes that are useful in the context of search and discovery. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtWithObjectIdResponse
     */
    public function addOrUpdateObject($indexName, $objectID, $body, $requestOptions = [])
    {
        $response = $this->addOrUpdateObjectWithHttpInfo($indexName, $objectID, $body, $requestOptions);

        return $response->getData();
    }

    /**
     * Adds a source to the list of allowed sources.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param array|Source $source Source to add. (required)
     *                             - $source['source'] => (string) IP address range of the source. (required)
     *                             - $source['description'] => (string) Source description.
     *
     * @see Source
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|CreatedAtResponse
     */
    public function appendSource($source, $requestOptions = [])
    {
        $response = $this->appendSourceWithHttpInfo($source, $requestOptions);

        return $response->getData();
    }

    /**
     * Assigns or moves a user ID to a cluster.  The time it takes to move a user is proportional to the amount of data linked to the user ID.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param string                   $xAlgoliaUserID     Unique identifier of the user who makes the search request. (required)
     * @param array|AssignUserIdParams $assignUserIdParams assignUserIdParams (required)
     *                                                     - $assignUserIdParams['cluster'] => (string) Cluster name. (required)
     *
     * @see AssignUserIdParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|CreatedAtResponse
     *
     * @deprecated
     */
    public function assignUserId($xAlgoliaUserID, $assignUserIdParams, $requestOptions = [])
    {
        $response = $this->assignUserIdWithHttpInfo($xAlgoliaUserID, $assignUserIdParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Adds, updates, or deletes records in one index with a single API request.  Batching index updates reduces latency and increases data integrity.  - Actions are applied in the order they're specified. - Actions are equivalent to the individual API requests of the same name.  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     *
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string                 $indexName        Name of the index on which to perform the operation. (required)
     * @param array|BatchWriteParams $batchWriteParams batchWriteParams (required)
     *                                                 - $batchWriteParams['requests'] => (array)  (required)
     *
     * @see BatchWriteParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|BatchResponse
     */
    public function batch($indexName, $batchWriteParams, $requestOptions = [])
    {
        $response = $this->batchWithHttpInfo($indexName, $batchWriteParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Assigns multiple user IDs to a cluster.  **You can't move users with this operation**.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param string                         $xAlgoliaUserID           Unique identifier of the user who makes the search request. (required)
     * @param array|BatchAssignUserIdsParams $batchAssignUserIdsParams batchAssignUserIdsParams (required)
     *                                                                 - $batchAssignUserIdsParams['cluster'] => (string) Cluster name. (required)
     *                                                                 - $batchAssignUserIdsParams['users'] => (array) User IDs to assign. (required)
     *
     * @see BatchAssignUserIdsParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|CreatedAtResponse
     *
     * @deprecated
     */
    public function batchAssignUserIds($xAlgoliaUserID, $batchAssignUserIdsParams, $requestOptions = [])
    {
        $response = $this->batchAssignUserIdsWithHttpInfo($xAlgoliaUserID, $batchAssignUserIdsParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Adds or deletes multiple entries from your plurals, segmentation, or stop word dictionaries.
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param array                              $dictionaryName               Dictionary type in which to search. (required)
     * @param array|BatchDictionaryEntriesParams $batchDictionaryEntriesParams batchDictionaryEntriesParams (required)
     *                                                                         - $batchDictionaryEntriesParams['clearExistingDictionaryEntries'] => (bool) Whether to replace all custom entries in the dictionary with the ones sent with this request.
     *                                                                         - $batchDictionaryEntriesParams['requests'] => (array) List of additions and deletions to your dictionaries. (required)
     *
     * @see BatchDictionaryEntriesParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function batchDictionaryEntries($dictionaryName, $batchDictionaryEntriesParams, $requestOptions = [])
    {
        $response = $this->batchDictionaryEntriesWithHttpInfo($dictionaryName, $batchDictionaryEntriesParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Retrieves records from an index, up to 1,000 per request.  Searching returns _hits_ (records augmented with highlighting and ranking details). Browsing returns matching records only. Use browse to export your indices.  - The Analytics API doesn't collect data when using `browse`. - Records are ranked by attributes and custom ranking. - There's no ranking for typo tolerance, number of matched words, proximity, or geo distance.  Browse requests automatically apply these settings:  - `advancedSyntax`: `false` - `attributesToHighlight`: `[]` - `attributesToSnippet`: `[]` - `distinct`: `false` - `enablePersonalization`: `false` - `enableRules`: `false` - `facets`: `[]` - `getRankingInfo`: `false` - `ignorePlurals`: `false` - `optionalFilters`: `[]` - `typoTolerance`: `true` or `false` (`min` and `strict` evaluate to `true`)  If you send these parameters with your browse requests, they're ignored.
     *
     * Required API Key ACLs:
     *  - browse
     *
     * @param string             $indexName    Name of the index on which to perform the operation. (required)
     * @param array|BrowseParams $browseParams browseParams (optional)
     *
     * @see BrowseParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|BrowseResponse
     */
    public function browse($indexName, $browseParams = null, $requestOptions = [])
    {
        $response = $this->browseWithHttpInfo($indexName, $browseParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Deletes only the records from an index while keeping settings, synonyms, and rules. This operation is resource-intensive and subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     *
     * Required API Key ACLs:
     *  - deleteIndex
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function clearObjects($indexName, $requestOptions = [])
    {
        $response = $this->clearObjectsWithHttpInfo($indexName, $requestOptions);

        return $response->getData();
    }

    /**
     * Deletes all rules from the index.
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName         Name of the index on which to perform the operation. (required)
     * @param bool   $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array  $requestOptions    the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function clearRules($indexName, $forwardToReplicas = null, $requestOptions = [])
    {
        $response = $this->clearRulesWithHttpInfo($indexName, $forwardToReplicas, $requestOptions);

        return $response->getData();
    }

    /**
     * Deletes all synonyms from the index.
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName         Name of the index on which to perform the operation. (required)
     * @param bool   $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array  $requestOptions    the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function clearSynonyms($indexName, $forwardToReplicas = null, $requestOptions = [])
    {
        $response = $this->clearSynonymsWithHttpInfo($indexName, $forwardToReplicas, $requestOptions);

        return $response->getData();
    }

    /**
     * This method lets you send requests to the Algolia REST API.
     *
     * @param string $path           Path of the endpoint, for example `1/newFeature`. (required)
     * @param array  $parameters     Query parameters to apply to the current query. (optional)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|object
     */
    public function customDelete($path, $parameters = null, $requestOptions = [])
    {
        $response = $this->customDeleteWithHttpInfo($path, $parameters, $requestOptions);

        return $response->getData();
    }

    /**
     * This method lets you send requests to the Algolia REST API.
     *
     * @param string $path           Path of the endpoint, for example `1/newFeature`. (required)
     * @param array  $parameters     Query parameters to apply to the current query. (optional)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|object
     */
    public function customGet($path, $parameters = null, $requestOptions = [])
    {
        $response = $this->customGetWithHttpInfo($path, $parameters, $requestOptions);

        return $response->getData();
    }

    /**
     * This method lets you send requests to the Algolia REST API.
     *
     * @param string $path           Path of the endpoint, for example `1/newFeature`. (required)
     * @param array  $parameters     Query parameters to apply to the current query. (optional)
     * @param array  $body           Parameters to send with the custom request. (optional)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|object
     */
    public function customPost($path, $parameters = null, $body = null, $requestOptions = [])
    {
        $response = $this->customPostWithHttpInfo($path, $parameters, $body, $requestOptions);

        return $response->getData();
    }

    /**
     * This method lets you send requests to the Algolia REST API.
     *
     * @param string $path           Path of the endpoint, for example `1/newFeature`. (required)
     * @param array  $parameters     Query parameters to apply to the current query. (optional)
     * @param array  $body           Parameters to send with the custom request. (optional)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|object
     */
    public function customPut($path, $parameters = null, $body = null, $requestOptions = [])
    {
        $response = $this->customPutWithHttpInfo($path, $parameters, $body, $requestOptions);

        return $response->getData();
    }

    /**
     * Deletes the API key.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param string $key            API key. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|DeleteApiKeyResponse
     */
    public function deleteApiKey($key, $requestOptions = [])
    {
        $response = $this->deleteApiKeyWithHttpInfo($key, $requestOptions);

        return $response->getData();
    }

    /**
     * This operation doesn't accept empty filters.  This operation is resource-intensive. Use it only if you can't get the object IDs of the records you want to delete. It's more efficient to get a list of object IDs with the [`browse` operation](https://www.algolia.com/doc/rest-api/search/browse), and then delete the records using the [`batch` operation](https://www.algolia.com/doc/rest-api/search/batch).  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     *
     * Required API Key ACLs:
     *  - deleteIndex
     *
     * @param string               $indexName      Name of the index on which to perform the operation. (required)
     * @param array|DeleteByParams $deleteByParams deleteByParams (required)
     *                                             - $deleteByParams['facetFilters'] => (array)
     *                                             - $deleteByParams['filters'] => (string) Filter expression to only include items that match the filter criteria in the response.  You can use these filter expressions:  - **Numeric filters.** `<facet> <op> <number>`, where `<op>` is one of `<`, `<=`, `=`, `!=`, `>`, `>=`. - **Ranges.** `<facet>:<lower> TO <upper>`, where `<lower>` and `<upper>` are the lower and upper limits of the range (inclusive). - **Facet filters.** `<facet>:<value>`, where `<facet>` is a facet attribute (case-sensitive) and `<value>` a facet value. - **Tag filters.** `_tags:<value>` or just `<value>` (case-sensitive). - **Boolean filters.** `<facet>: true | false`.  You can combine filters with `AND`, `OR`, and `NOT` operators with the following restrictions:  - You can only combine filters of the same type with `OR`.   **Not supported:** `facet:value OR num > 3`. - You can't use `NOT` with combinations of filters.   **Not supported:** `NOT(facet:value OR facet:value)` - You can't combine conjunctions (`AND`) with `OR`.   **Not supported:** `facet:value OR (facet:value AND facet:value)`  Use quotes if the facet attribute name or facet value contains spaces, keywords (`OR`, `AND`, `NOT`), or quotes. If a facet attribute is an array, the filter matches if it matches at least one element of the array.  For more information, see [Filters](https://www.algolia.com/doc/guides/managing-results/refine-results/filtering).
     *                                             - $deleteByParams['numericFilters'] => (array)
     *                                             - $deleteByParams['tagFilters'] => (array)
     *                                             - $deleteByParams['aroundLatLng'] => (string) Coordinates for the center of a circle, expressed as a comma-separated string of latitude and longitude.  Only records included within a circle around this central location are included in the results. The radius of the circle is determined by the `aroundRadius` and `minimumAroundRadius` settings. This parameter is ignored if you also specify `insidePolygon` or `insideBoundingBox`.
     *                                             - $deleteByParams['aroundRadius'] => (array)
     *                                             - $deleteByParams['insideBoundingBox'] => (array)
     *                                             - $deleteByParams['insidePolygon'] => (array) Coordinates of a polygon in which to search.  Polygons are defined by 3 to 10,000 points. Each point is represented by its latitude and longitude. Provide multiple polygons as nested arrays. For more information, see [filtering inside polygons](https://www.algolia.com/doc/guides/managing-results/refine-results/geolocation/#filtering-inside-rectangular-or-polygonal-areas). This parameter is ignored if you also specify `insideBoundingBox`.
     *
     * @see DeleteByParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function deleteBy($indexName, $deleteByParams, $requestOptions = [])
    {
        $response = $this->deleteByWithHttpInfo($indexName, $deleteByParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Deletes an index and all its settings.  - Deleting an index doesn't delete its analytics data. - If you try to delete a non-existing index, the operation is ignored without warning. - If the index you want to delete has replica indices, the replicas become independent indices. - If the index you want to delete is a replica index, you must first unlink it from its primary index before you can delete it.   For more information, see [Delete replica indices](https://www.algolia.com/doc/guides/managing-results/refine-results/sorting/how-to/deleting-replicas).
     *
     * Required API Key ACLs:
     *  - deleteIndex
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|DeletedAtResponse
     */
    public function deleteIndex($indexName, $requestOptions = [])
    {
        $response = $this->deleteIndexWithHttpInfo($indexName, $requestOptions);

        return $response->getData();
    }

    /**
     * Deletes a record by its object ID.  To delete more than one record, use the [`batch` operation](https://www.algolia.com/doc/rest-api/search/batch). To delete records matching a query, use the [`deleteBy` operation](https://www.algolia.com/doc/rest-api/search/delete-by).
     *
     * Required API Key ACLs:
     *  - deleteObject
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param string $objectID       Unique record identifier. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|DeletedAtResponse
     */
    public function deleteObject($indexName, $objectID, $requestOptions = [])
    {
        $response = $this->deleteObjectWithHttpInfo($indexName, $objectID, $requestOptions);

        return $response->getData();
    }

    /**
     * Deletes a rule by its ID. To find the object ID for rules, use the [`search` operation](https://www.algolia.com/doc/rest-api/search/search-rules).
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName         Name of the index on which to perform the operation. (required)
     * @param string $objectID          Unique identifier of a rule object. (required)
     * @param bool   $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array  $requestOptions    the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function deleteRule($indexName, $objectID, $forwardToReplicas = null, $requestOptions = [])
    {
        $response = $this->deleteRuleWithHttpInfo($indexName, $objectID, $forwardToReplicas, $requestOptions);

        return $response->getData();
    }

    /**
     * Deletes a source from the list of allowed sources.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param string $source         IP address range of the source. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|DeleteSourceResponse
     */
    public function deleteSource($source, $requestOptions = [])
    {
        $response = $this->deleteSourceWithHttpInfo($source, $requestOptions);

        return $response->getData();
    }

    /**
     * Deletes a synonym by its ID. To find the object IDs of your synonyms, use the [`search` operation](https://www.algolia.com/doc/rest-api/search/search-synonyms).
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName         Name of the index on which to perform the operation. (required)
     * @param string $objectID          Unique identifier of a synonym object. (required)
     * @param bool   $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array  $requestOptions    the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|DeletedAtResponse
     */
    public function deleteSynonym($indexName, $objectID, $forwardToReplicas = null, $requestOptions = [])
    {
        $response = $this->deleteSynonymWithHttpInfo($indexName, $objectID, $forwardToReplicas, $requestOptions);

        return $response->getData();
    }

    /**
     * Gets the permissions and restrictions of an API key.  When authenticating with the admin API key, you can request information for any of your application's keys. When authenticating with other API keys, you can only retrieve information for that key, with the description replaced by `<redacted>`.
     *
     * Required API Key ACLs:
     *  - search
     *
     * @param string $key            API key. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|GetApiKeyResponse
     */
    public function getApiKey($key, $requestOptions = [])
    {
        $response = $this->getApiKeyWithHttpInfo($key, $requestOptions);

        return $response->getData();
    }

    /**
     * Checks the status of a given application task.
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param int   $taskID         Unique task identifier. (required)
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|GetTaskResponse
     */
    public function getAppTask($taskID, $requestOptions = [])
    {
        $response = $this->getAppTaskWithHttpInfo($taskID, $requestOptions);

        return $response->getData();
    }

    /**
     * Lists supported languages with their supported dictionary types and number of custom entries.
     *
     * Required API Key ACLs:
     *  - settings
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|array<string,Languages>
     */
    public function getDictionaryLanguages($requestOptions = [])
    {
        $response = $this->getDictionaryLanguagesWithHttpInfo($requestOptions);

        return $response->getData();
    }

    /**
     * Retrieves the languages for which standard dictionary entries are turned off.
     *
     * Required API Key ACLs:
     *  - settings
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|GetDictionarySettingsResponse
     */
    public function getDictionarySettings($requestOptions = [])
    {
        $response = $this->getDictionarySettingsWithHttpInfo($requestOptions);

        return $response->getData();
    }

    /**
     * The request must be authenticated by an API key with the [`logs` ACL](https://www.algolia.com/doc/guides/security/api-keys/#access-control-list-acl).  - Logs are held for the last seven days. - Up to 1,000 API requests per server are logged. - This request counts towards your [operations quota](https://support.algolia.com/hc/articles/17245378392977-How-does-Algolia-count-records-and-operations) but doesn't appear in the logs itself.
     *
     * Required API Key ACLs:
     *  - logs
     *
     * @param int    $offset         First log entry to retrieve. The most recent entries are listed first. (optional, default to 0)
     * @param int    $length         Maximum number of entries to retrieve. (optional, default to 10)
     * @param string $indexName      Index for which to retrieve log entries. By default, log entries are retrieved for all indices. (optional)
     * @param array  $type           Type of log entries to retrieve. By default, all log entries are retrieved. (optional)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|GetLogsResponse
     */
    public function getLogs($offset = null, $length = null, $indexName = null, $type = null, $requestOptions = [])
    {
        $response = $this->getLogsWithHttpInfo($offset, $length, $indexName, $type, $requestOptions);

        return $response->getData();
    }

    /**
     * Retrieves one record by its object ID.  To retrieve more than one record, use the [`objects` operation](https://www.algolia.com/doc/rest-api/search/get-objects).
     *
     * Required API Key ACLs:
     *  - search
     *
     * @param string $indexName            Name of the index on which to perform the operation. (required)
     * @param string $objectID             Unique record identifier. (required)
     * @param array  $attributesToRetrieve Attributes to include with the records in the response. This is useful to reduce the size of the API response. By default, all retrievable attributes are returned.  `objectID` is always retrieved.  Attributes included in `unretrievableAttributes` won't be retrieved unless the request is authenticated with the admin API key. (optional)
     * @param array  $requestOptions       the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|object
     */
    public function getObject($indexName, $objectID, $attributesToRetrieve = null, $requestOptions = [])
    {
        $response = $this->getObjectWithHttpInfo($indexName, $objectID, $attributesToRetrieve, $requestOptions);

        return $response->getData();
    }

    /**
     * Retrieves one or more records, potentially from different indices.  Records are returned in the same order as the requests.
     *
     * Required API Key ACLs:
     *  - search
     *
     * @param array|GetObjectsParams $getObjectsParams Request object. (required)
     *                                                 - $getObjectsParams['requests'] => (array)  (required)
     *
     * @see GetObjectsParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|GetObjectsResponse
     */
    public function getObjects($getObjectsParams, $requestOptions = [])
    {
        $response = $this->getObjectsWithHttpInfo($getObjectsParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Retrieves a rule by its ID. To find the object ID of rules, use the [`search` operation](https://www.algolia.com/doc/rest-api/search/search-rules).
     *
     * Required API Key ACLs:
     *  - settings
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param string $objectID       Unique identifier of a rule object. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|Rule
     */
    public function getRule($indexName, $objectID, $requestOptions = [])
    {
        $response = $this->getRuleWithHttpInfo($indexName, $objectID, $requestOptions);

        return $response->getData();
    }

    /**
     * Retrieves an object with non-null index settings.
     *
     * Required API Key ACLs:
     *  - settings
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param int    $getVersion     When set to 2, the endpoint will not include `synonyms` in the response. This parameter is here for backward compatibility. (optional, default to 1)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|SettingsResponse
     */
    public function getSettings($indexName, $getVersion = null, $requestOptions = [])
    {
        $response = $this->getSettingsWithHttpInfo($indexName, $getVersion, $requestOptions);

        return $response->getData();
    }

    /**
     * Retrieves all allowed IP addresses with access to your application.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|Source[]
     */
    public function getSources($requestOptions = [])
    {
        $response = $this->getSourcesWithHttpInfo($requestOptions);

        return $response->getData();
    }

    /**
     * Retrieves a synonym by its ID. To find the object IDs for your synonyms, use the [`search` operation](https://www.algolia.com/doc/rest-api/search/search-synonyms).
     *
     * Required API Key ACLs:
     *  - settings
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param string $objectID       Unique identifier of a synonym object. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|SynonymHit
     */
    public function getSynonym($indexName, $objectID, $requestOptions = [])
    {
        $response = $this->getSynonymWithHttpInfo($indexName, $objectID, $requestOptions);

        return $response->getData();
    }

    /**
     * Checks the status of a given task.  Indexing tasks are asynchronous. When you add, update, or delete records or indices, a task is created on a queue and completed depending on the load on the server.  The indexing tasks' responses include a task ID that you can use to check the status.
     *
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param int    $taskID         Unique task identifier. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|GetTaskResponse
     */
    public function getTask($indexName, $taskID, $requestOptions = [])
    {
        $response = $this->getTaskWithHttpInfo($indexName, $taskID, $requestOptions);

        return $response->getData();
    }

    /**
     * Get the IDs of the 10 users with the highest number of records per cluster.  Since it can take a few seconds to get the data from the different clusters, the response isn't real-time.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|GetTopUserIdsResponse
     *
     * @deprecated
     */
    public function getTopUserIds($requestOptions = [])
    {
        $response = $this->getTopUserIdsWithHttpInfo($requestOptions);

        return $response->getData();
    }

    /**
     * Returns the user ID data stored in the mapping.  Since it can take a few seconds to get the data from the different clusters, the response isn't real-time.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param string $userID         Unique identifier of the user who makes the search request. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UserId
     *
     * @deprecated
     */
    public function getUserId($userID, $requestOptions = [])
    {
        $response = $this->getUserIdWithHttpInfo($userID, $requestOptions);

        return $response->getData();
    }

    /**
     * To determine when the time-consuming process of creating a large batch of users or migrating users from one cluster to another is complete, this operation retrieves the status of the process.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param bool  $getClusters    Whether to include the cluster's pending mapping state in the response. (optional)
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|HasPendingMappingsResponse
     *
     * @deprecated
     */
    public function hasPendingMappings($getClusters = null, $requestOptions = [])
    {
        $response = $this->hasPendingMappingsWithHttpInfo($getClusters, $requestOptions);

        return $response->getData();
    }

    /**
     * Lists all API keys associated with your Algolia application, including their permissions and restrictions.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|ListApiKeysResponse
     */
    public function listApiKeys($requestOptions = [])
    {
        $response = $this->listApiKeysWithHttpInfo($requestOptions);

        return $response->getData();
    }

    /**
     * Lists the available clusters in a multi-cluster setup.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|ListClustersResponse
     *
     * @deprecated
     */
    public function listClusters($requestOptions = [])
    {
        $response = $this->listClustersWithHttpInfo($requestOptions);

        return $response->getData();
    }

    /**
     * Lists all indices in the current Algolia application.  The request follows any index restrictions of the API key you use to make the request.
     *
     * Required API Key ACLs:
     *  - listIndexes
     *
     * @param int   $page           Requested page of the API response. If `null`, the API response is not paginated. (optional)
     * @param int   $hitsPerPage    Number of hits per page. (optional, default to 100)
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|ListIndicesResponse
     */
    public function listIndices($page = null, $hitsPerPage = null, $requestOptions = [])
    {
        $response = $this->listIndicesWithHttpInfo($page, $hitsPerPage, $requestOptions);

        return $response->getData();
    }

    /**
     * Lists the userIDs assigned to a multi-cluster application.  Since it can take a few seconds to get the data from the different clusters, the response isn't real-time.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param int   $page           Requested page of the API response. If `null`, the API response is not paginated. (optional)
     * @param int   $hitsPerPage    Number of hits per page. (optional, default to 100)
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|ListUserIdsResponse
     *
     * @deprecated
     */
    public function listUserIds($page = null, $hitsPerPage = null, $requestOptions = [])
    {
        $response = $this->listUserIdsWithHttpInfo($page, $hitsPerPage, $requestOptions);

        return $response->getData();
    }

    /**
     * Adds, updates, or deletes records in multiple indices with a single API request.  - Actions are applied in the order they are specified. - Actions are equivalent to the individual API requests of the same name.  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     *
     * Required API Key ACLs:
     *  - addObject
     *
     * @param array|BatchParams $batchParams batchParams (required)
     *                                       - $batchParams['requests'] => (array)  (required)
     *
     * @see BatchParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|MultipleBatchResponse
     */
    public function multipleBatch($batchParams, $requestOptions = [])
    {
        $response = $this->multipleBatchWithHttpInfo($batchParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Copies or moves (renames) an index within the same Algolia application.  Notes: - Existing destination indices are overwritten, except for their analytics data. - If the destination index doesn't exist yet, it's created. - This operation is resource-intensive.  **Copy**  - If the source index doesn't exist, copying creates a new index with 0 records and default settings. - API keys from the source index are merged with the existing keys in the destination index. - You can't copy the `enableReRanking`, `mode`, and `replicas` settings. - You can't copy to a destination index that already has replicas. - Be aware of the [size limits](https://www.algolia.com/doc/guides/scaling/algolia-service-limits/#application-record-and-index-limits). - For more information, see [Copy indices](https://www.algolia.com/doc/guides/sending-and-managing-data/manage-indices-and-apps/manage-indices/how-to/copy-indices).  **Move**  - If the source index doesn't exist, moving is ignored without returning an error. - When moving an index, the analytics data keeps its original name, and a new set of analytics data is started for the new name.   To access the original analytics in the dashboard, create an index with the original name. - If the destination index has replicas, moving will overwrite the existing index and copy the data to the replica indices. - For more information, see [Move indices](https://www.algolia.com/doc/guides/sending-and-managing-data/manage-indices-and-apps/manage-indices/how-to/move-indices).  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     *
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string                     $indexName            Name of the index on which to perform the operation. (required)
     * @param array|OperationIndexParams $operationIndexParams operationIndexParams (required)
     *                                                         - $operationIndexParams['operation'] => (array)  (required)
     *                                                         - $operationIndexParams['destination'] => (string) Index name (case-sensitive). (required)
     *                                                         - $operationIndexParams['scope'] => (array) **Only for copying.**  If you specify a scope, only the selected scopes are copied. Records and the other scopes are left unchanged. If you omit the `scope` parameter, everything is copied: records, settings, synonyms, and rules.
     *
     * @see OperationIndexParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function operationIndex($indexName, $operationIndexParams, $requestOptions = [])
    {
        $response = $this->operationIndexWithHttpInfo($indexName, $operationIndexParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Adds new attributes to a record, or updates existing ones.  - If a record with the specified object ID doesn't exist,   a new record is added to the index **if** `createIfNotExists` is true. - If the index doesn't exist yet, this method creates a new index. - Use first-level attributes only. Nested attributes aren't supported.   If you specify a nested attribute, this operation replaces its first-level ancestor.  To update attributes without replacing the full record, use these built-in operations. These operations are useful when the initial data isn't available.  - `Increment`: increment a numeric attribute. - `Decrement`: decrement a numeric attribute. - `Add`: append a number or string element to an array attribute. - `Remove`: remove all matching number or string elements from an array attribute made of numbers or strings. - `AddUnique`: add a number or string element to an array attribute made of numbers or strings only if it's not already present. - `IncrementFrom`: increment a numeric integer attribute only if the provided value matches the current value. Otherwise, the update is ignored.   Example: If you pass an `IncrementFrom` value of 2 for the `version` attribute but the current value is 1, the API ignores the update.   If the object doesn't exist, the API only creates it if you pass an `IncrementFrom` value of 0. - `IncrementSet`: increment a numeric integer attribute only if the provided value is greater than the current value. Otherwise, the update is ignored.   Example: If you pass an `IncrementSet` value of 2 for the `version` attribute and the current value is 1, the API updates the object.   If the object doesn't exist yet, the API only creates it if you pass an `IncrementSet` value greater than 0.  Specify an operation by providing an object with the attribute to update as the key and its value as an object with these properties:  - `_operation`: the operation to apply on the attribute. - `value`: the right-hand side argument to the operation, for example, increment or decrement step, or a value to add or remove.  When updating multiple attributes or using multiple operations targeting the same record, use a single partial update for faster processing.  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     *
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string $indexName          Name of the index on which to perform the operation. (required)
     * @param string $objectID           Unique record identifier. (required)
     * @param array  $attributesToUpdate Attributes with their values. (required)
     * @param bool   $createIfNotExists  Whether to create a new record if it doesn't exist. (optional, default to true)
     * @param array  $requestOptions     the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtWithObjectIdResponse
     */
    public function partialUpdateObject($indexName, $objectID, $attributesToUpdate, $createIfNotExists = null, $requestOptions = [])
    {
        $response = $this->partialUpdateObjectWithHttpInfo($indexName, $objectID, $attributesToUpdate, $createIfNotExists, $requestOptions);

        return $response->getData();
    }

    /**
     * Deletes a user ID and its associated data from the clusters.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param string $userID         Unique identifier of the user who makes the search request. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|RemoveUserIdResponse
     *
     * @deprecated
     */
    public function removeUserId($userID, $requestOptions = [])
    {
        $response = $this->removeUserIdWithHttpInfo($userID, $requestOptions);

        return $response->getData();
    }

    /**
     * Replaces the list of allowed sources.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param array $source         Allowed sources. (required)
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|ReplaceSourceResponse
     */
    public function replaceSources($source, $requestOptions = [])
    {
        $response = $this->replaceSourcesWithHttpInfo($source, $requestOptions);

        return $response->getData();
    }

    /**
     * Restores a deleted API key.  Restoring resets the `validity` attribute to `0`.  Algolia stores up to 1,000 API keys per application. If you create more, the oldest API keys are deleted and can't be restored.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param string $key            API key. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return AddApiKeyResponse|array<string, mixed>
     */
    public function restoreApiKey($key, $requestOptions = [])
    {
        $response = $this->restoreApiKeyWithHttpInfo($key, $requestOptions);

        return $response->getData();
    }

    /**
     * Adds a record to an index or replaces it.  - If the record doesn't have an object ID, a new record with an auto-generated object ID is added to your index. - If a record with the specified object ID exists, the existing record is replaced. - If a record with the specified object ID doesn't exist, a new record is added to your index. - If you add a record to an index that doesn't exist yet, a new index is created.  To update _some_ attributes of a record, use the [`partial` operation](https://www.algolia.com/doc/rest-api/search/partial-update-object). To add, update, or replace multiple records, use the [`batch` operation](https://www.algolia.com/doc/rest-api/search/batch).  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     *
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param array  $body           The record. A schemaless object with attributes that are useful in the context of search and discovery. (required)
     * @param array  $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|SaveObjectResponse
     */
    public function saveObject($indexName, $body, $requestOptions = [])
    {
        $response = $this->saveObjectWithHttpInfo($indexName, $body, $requestOptions);

        return $response->getData();
    }

    /**
     * If a rule with the specified object ID doesn't exist, it's created. Otherwise, the existing rule is replaced.  To create or update more than one rule, use the [`batch` operation](https://www.algolia.com/doc/rest-api/search/save-rules).
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string     $indexName Name of the index on which to perform the operation. (required)
     * @param string     $objectID  Unique identifier of a rule object. (required)
     * @param array|Rule $rule      rule (required)
     *                              - $rule['objectID'] => (string) Unique identifier of a rule object. (required)
     *                              - $rule['conditions'] => (array) Conditions that trigger a rule.  Some consequences require specific conditions or don't require any condition. For more information, see [Conditions](https://www.algolia.com/doc/guides/managing-results/rules/rules-overview/#conditions).
     *                              - $rule['consequence'] => (array)  (required)
     *                              - $rule['description'] => (string) Description of the rule's purpose to help you distinguish between different rules.
     *                              - $rule['enabled'] => (bool) Whether the rule is active.
     *                              - $rule['validity'] => (array) Time periods when the rule is active.
     *                              - $rule['tags'] => (array)
     *                              - $rule['scope'] => (string)
     *                              - $rule['condition'] => (array)
     *
     * @see Rule
     *
     * @param bool  $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array $requestOptions    the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function saveRule($indexName, $objectID, $rule, $forwardToReplicas = null, $requestOptions = [])
    {
        $response = $this->saveRuleWithHttpInfo($indexName, $objectID, $rule, $forwardToReplicas, $requestOptions);

        return $response->getData();
    }

    /**
     * Create or update multiple rules.  If a rule with the specified object ID doesn't exist, Algolia creates a new one. Otherwise, existing rules are replaced.  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName          Name of the index on which to perform the operation. (required)
     * @param array  $rules              rules (required)
     * @param bool   $forwardToReplicas  Whether changes are applied to replica indices. (optional)
     * @param bool   $clearExistingRules Whether existing rules should be deleted before adding this batch. (optional)
     * @param array  $requestOptions     the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function saveRules($indexName, $rules, $forwardToReplicas = null, $clearExistingRules = null, $requestOptions = [])
    {
        $response = $this->saveRulesWithHttpInfo($indexName, $rules, $forwardToReplicas, $clearExistingRules, $requestOptions);

        return $response->getData();
    }

    /**
     * If a synonym with the specified object ID doesn't exist, Algolia adds a new one. Otherwise, the existing synonym is replaced. To add multiple synonyms in a single API request, use the [`batch` operation](https://www.algolia.com/doc/rest-api/search/save-synonyms).
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string           $indexName  Name of the index on which to perform the operation. (required)
     * @param string           $objectID   Unique identifier of a synonym object. (required)
     * @param array|SynonymHit $synonymHit synonymHit (required)
     *                                     - $synonymHit['objectID'] => (string) Unique identifier of a synonym object. (required)
     *                                     - $synonymHit['type'] => (array)  (required)
     *                                     - $synonymHit['synonyms'] => (array) Words or phrases considered equivalent.
     *                                     - $synonymHit['input'] => (string) Word or phrase to appear in query strings (for [`onewaysynonym`s](https://www.algolia.com/doc/guides/managing-results/optimize-search-results/adding-synonyms/in-depth/one-way-synonyms)).
     *                                     - $synonymHit['word'] => (string) Word or phrase to appear in query strings (for [`altcorrection1` and `altcorrection2`](https://www.algolia.com/doc/guides/managing-results/optimize-search-results/adding-synonyms/in-depth/synonyms-alternative-corrections)).
     *                                     - $synonymHit['corrections'] => (array) Words to be matched in records.
     *                                     - $synonymHit['placeholder'] => (string) [Placeholder token](https://www.algolia.com/doc/guides/managing-results/optimize-search-results/adding-synonyms/in-depth/synonyms-placeholders) to be put inside records.
     *                                     - $synonymHit['replacements'] => (array) Query words that will match the [placeholder token](https://www.algolia.com/doc/guides/managing-results/optimize-search-results/adding-synonyms/in-depth/synonyms-placeholders).
     *
     * @see SynonymHit
     *
     * @param bool  $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array $requestOptions    the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|SaveSynonymResponse
     */
    public function saveSynonym($indexName, $objectID, $synonymHit, $forwardToReplicas = null, $requestOptions = [])
    {
        $response = $this->saveSynonymWithHttpInfo($indexName, $objectID, $synonymHit, $forwardToReplicas, $requestOptions);

        return $response->getData();
    }

    /**
     * If a synonym with the `objectID` doesn't exist, Algolia adds a new one. Otherwise, existing synonyms are replaced.  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName               Name of the index on which to perform the operation. (required)
     * @param array  $synonymHit              synonymHit (required)
     * @param bool   $forwardToReplicas       Whether changes are applied to replica indices. (optional)
     * @param bool   $replaceExistingSynonyms Whether to replace all synonyms in the index with the ones sent with this request. (optional)
     * @param array  $requestOptions          the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function saveSynonyms($indexName, $synonymHit, $forwardToReplicas = null, $replaceExistingSynonyms = null, $requestOptions = [])
    {
        $response = $this->saveSynonymsWithHttpInfo($indexName, $synonymHit, $forwardToReplicas, $replaceExistingSynonyms, $requestOptions);

        return $response->getData();
    }

    /**
     * Runs multiple search queries against one or more indices in a single API request.  Use cases include:  - Searching different indices, such as products and marketing content. - Run multiple queries on the same index with different parameters or filters.  If you know the expected result type, use the `searchForHits` or `searchForFacets` helper to simplify the response format.
     *
     * Required API Key ACLs:
     *  - search
     *
     * @param array|SearchMethodParams $searchMethodParams Multi-query search request body. Results are returned in the same order as the requests. (required)
     *                                                     - $searchMethodParams['requests'] => (array)  (required)
     *                                                     - $searchMethodParams['strategy'] => (array)
     *
     * @see SearchMethodParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|SearchResponses
     */
    public function search($searchMethodParams, $requestOptions = [])
    {
        $response = $this->searchWithHttpInfo($searchMethodParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Searches for standard and custom dictionary entries.
     *
     * Required API Key ACLs:
     *  - settings
     *
     * @param array                               $dictionaryName                Dictionary type in which to search. (required)
     * @param array|SearchDictionaryEntriesParams $searchDictionaryEntriesParams searchDictionaryEntriesParams (required)
     *                                                                           - $searchDictionaryEntriesParams['query'] => (string) Search query. (required)
     *                                                                           - $searchDictionaryEntriesParams['page'] => (int) Page of search results to retrieve.
     *                                                                           - $searchDictionaryEntriesParams['hitsPerPage'] => (int) Number of hits per page.
     *                                                                           - $searchDictionaryEntriesParams['language'] => (array)
     *
     * @see SearchDictionaryEntriesParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|SearchDictionaryEntriesResponse
     */
    public function searchDictionaryEntries($dictionaryName, $searchDictionaryEntriesParams, $requestOptions = [])
    {
        $response = $this->searchDictionaryEntriesWithHttpInfo($dictionaryName, $searchDictionaryEntriesParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Searches for values of a specified facet attribute.  - By default, facet values are sorted by decreasing count.   You can adjust this with the `sortFacetValueBy` parameter. - Searching for facet values doesn't work if you have **more than 65 searchable facets and searchable attributes combined**.
     *
     * Required API Key ACLs:
     *  - search
     *
     * @param string                            $indexName                   Name of the index on which to perform the operation. (required)
     * @param string                            $facetName                   Facet attribute in which to search for values.  This attribute must be included in the `attributesForFaceting` index setting with the `searchable()` modifier. (required)
     * @param array|SearchForFacetValuesRequest $searchForFacetValuesRequest searchForFacetValuesRequest (optional)
     *                                                                       - $searchForFacetValuesRequest['params'] => (string) Search parameters as a URL-encoded query string.
     *                                                                       - $searchForFacetValuesRequest['facetQuery'] => (string) Text to search inside the facet's values.
     *                                                                       - $searchForFacetValuesRequest['maxFacetHits'] => (int) Maximum number of facet values to return when [searching for facet values](https://www.algolia.com/doc/guides/managing-results/refine-results/faceting/#search-for-facet-values).
     *
     * @see SearchForFacetValuesRequest
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|SearchForFacetValuesResponse
     */
    public function searchForFacetValues($indexName, $facetName, $searchForFacetValuesRequest = null, $requestOptions = [])
    {
        $response = $this->searchForFacetValuesWithHttpInfo($indexName, $facetName, $searchForFacetValuesRequest, $requestOptions);

        return $response->getData();
    }

    /**
     * Searches for rules in your index.
     *
     * Required API Key ACLs:
     *  - settings
     *
     * @param string                  $indexName         Name of the index on which to perform the operation. (required)
     * @param array|SearchRulesParams $searchRulesParams searchRulesParams (optional)
     *                                                   - $searchRulesParams['query'] => (string) Search query for rules.
     *                                                   - $searchRulesParams['anchoring'] => (array)
     *                                                   - $searchRulesParams['context'] => (string) Only return rules that match the context (exact match).
     *                                                   - $searchRulesParams['page'] => (int) Requested page of the API response.  Algolia uses `page` and `hitsPerPage` to control how search results are displayed ([paginated](https://www.algolia.com/doc/guides/building-search-ui/ui-and-ux-patterns/pagination/js)).  - `hitsPerPage`: sets the number of search results (_hits_) displayed per page. - `page`: specifies the page number of the search results you want to retrieve. Page numbering starts at 0, so the first page is `page=0`, the second is `page=1`, and so on.  For example, to display 10 results per page starting from the third page, set `hitsPerPage` to 10 and `page` to 2.
     *                                                   - $searchRulesParams['hitsPerPage'] => (int) Maximum number of hits per page.  Algolia uses `page` and `hitsPerPage` to control how search results are displayed ([paginated](https://www.algolia.com/doc/guides/building-search-ui/ui-and-ux-patterns/pagination/js)).  - `hitsPerPage`: sets the number of search results (_hits_) displayed per page. - `page`: specifies the page number of the search results you want to retrieve. Page numbering starts at 0, so the first page is `page=0`, the second is `page=1`, and so on.  For example, to display 10 results per page starting from the third page, set `hitsPerPage` to 10 and `page` to 2.
     *                                                   - $searchRulesParams['enabled'] => (bool) If `true`, return only enabled rules. If `false`, return only inactive rules. By default, _all_ rules are returned.
     *
     * @see SearchRulesParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|SearchRulesResponse
     */
    public function searchRules($indexName, $searchRulesParams = null, $requestOptions = [])
    {
        $response = $this->searchRulesWithHttpInfo($indexName, $searchRulesParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Searches a single index and returns matching search results as hits.  This method lets you retrieve up to 1,000 hits. If you need more, use the [`browse` operation](https://www.algolia.com/doc/rest-api/search/browse) or increase the `paginatedLimitedTo` index setting.
     *
     * Required API Key ACLs:
     *  - search
     *
     * @param string             $indexName    Name of the index on which to perform the operation. (required)
     * @param array|SearchParams $searchParams searchParams (optional)
     *
     * @see SearchParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|SearchResponse
     */
    public function searchSingleIndex($indexName, $searchParams = null, $requestOptions = [])
    {
        $response = $this->searchSingleIndexWithHttpInfo($indexName, $searchParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Searches for synonyms in your index.
     *
     * Required API Key ACLs:
     *  - settings
     *
     * @param string                     $indexName            Name of the index on which to perform the operation. (required)
     * @param array|SearchSynonymsParams $searchSynonymsParams Body of the `searchSynonyms` operation. (optional)
     *                                                         - $searchSynonymsParams['query'] => (string) Search query.
     *                                                         - $searchSynonymsParams['type'] => (array)
     *                                                         - $searchSynonymsParams['page'] => (int) Page of search results to retrieve.
     *                                                         - $searchSynonymsParams['hitsPerPage'] => (int) Number of hits per page.
     *
     * @see SearchSynonymsParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|SearchSynonymsResponse
     */
    public function searchSynonyms($indexName, $searchSynonymsParams = null, $requestOptions = [])
    {
        $response = $this->searchSynonymsWithHttpInfo($indexName, $searchSynonymsParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Since it can take a few seconds to get the data from the different clusters, the response isn't real-time.  To ensure rapid updates, the user IDs index isn't built at the same time as the mapping. Instead, it's built every 12 hours, at the same time as the update of user ID usage. For example, if you add or move a user ID, the search will show an old value until the next time the mapping is rebuilt (every 12 hours).
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param array|SearchUserIdsParams $searchUserIdsParams searchUserIdsParams (required)
     *                                                       - $searchUserIdsParams['query'] => (string)  (required)
     *                                                       - $searchUserIdsParams['clusterName'] => (string) Cluster name.
     *                                                       - $searchUserIdsParams['page'] => (int) Page of search results to retrieve.
     *                                                       - $searchUserIdsParams['hitsPerPage'] => (int) Number of hits per page.
     *
     * @see SearchUserIdsParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|SearchUserIdsResponse
     *
     * @deprecated
     */
    public function searchUserIds($searchUserIdsParams, $requestOptions = [])
    {
        $response = $this->searchUserIdsWithHttpInfo($searchUserIdsParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Turns standard stop word dictionary entries on or off for a given language.
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param array|DictionarySettingsParams $dictionarySettingsParams dictionarySettingsParams (required)
     *                                                                 - $dictionarySettingsParams['disableStandardEntries'] => (array)  (required)
     *
     * @see DictionarySettingsParams
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function setDictionarySettings($dictionarySettingsParams, $requestOptions = [])
    {
        $response = $this->setDictionarySettingsWithHttpInfo($dictionarySettingsParams, $requestOptions);

        return $response->getData();
    }

    /**
     * Update the specified index settings.  Index settings that you don't specify are left unchanged. Specify `null` to reset a setting to its default value.  For best performance, update the index settings before you add new records to your index.
     *
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string              $indexName     Name of the index on which to perform the operation. (required)
     * @param array|IndexSettings $indexSettings indexSettings (required)
     *
     * @see IndexSettings
     *
     * @param bool  $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array $requestOptions    the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdatedAtResponse
     */
    public function setSettings($indexName, $indexSettings, $forwardToReplicas = null, $requestOptions = [])
    {
        $response = $this->setSettingsWithHttpInfo($indexName, $indexSettings, $forwardToReplicas, $requestOptions);

        return $response->getData();
    }

    /**
     * Replaces the permissions of an existing API key.  Any unspecified attribute resets that attribute to its default value.
     *
     * Required API Key ACLs:
     *  - admin
     *
     * @param string       $key    API key. (required)
     * @param ApiKey|array $apiKey apiKey (required)
     *                             - $apiKey['acl'] => (array) Permissions that determine the type of API requests this key can make. The required ACL is listed in each endpoint's reference. For more information, see [access control list](https://www.algolia.com/doc/guides/security/api-keys/#access-control-list-acl). (required)
     *                             - $apiKey['description'] => (string) Description of an API key to help you identify this API key.
     *                             - $apiKey['indexes'] => (array) Index names or patterns that this API key can access. By default, an API key can access all indices in the same application.  You can use leading and trailing wildcard characters (`*`):  - `dev_*` matches all indices starting with \"dev_\" - `*_dev` matches all indices ending with \"_dev\" - `*_products_*` matches all indices containing \"_products_\".
     *                             - $apiKey['maxHitsPerQuery'] => (int) Maximum number of results this API key can retrieve in one query. By default, there's no limit.
     *                             - $apiKey['maxQueriesPerIPPerHour'] => (int) Maximum number of API requests allowed per IP address or [user token](https://www.algolia.com/doc/guides/sending-events/concepts/usertoken) per hour.  If this limit is reached, the API returns an error with status code `429`. By default, there's no limit.
     *                             - $apiKey['queryParameters'] => (string) Query parameters to add when making API requests with this API key.  To restrict this API key to specific IP addresses, add the `restrictSources` parameter. You can only add a single source, but you can provide a range of IP addresses.  Creating an API key fails if the request is made from an IP address outside the restricted range.
     *                             - $apiKey['referers'] => (array) Allowed HTTP referrers for this API key.  By default, all referrers are allowed. You can use leading and trailing wildcard characters (`*`):  - `https://algolia.com/_*` allows all referrers starting with \"https://algolia.com/\" - `*.algolia.com` allows all referrers ending with \".algolia.com\" - `*algolia.com*` allows all referrers in the domain \"algolia.com\".  Like all HTTP headers, referrers can be spoofed. Don't rely on them to secure your data. For more information, see [HTTP referrer restrictions](https://www.algolia.com/doc/guides/security/security-best-practices/#http-referrers-restrictions).
     *                             - $apiKey['validity'] => (int) Duration (in seconds) after which the API key expires. By default, API keys don't expire.
     *
     * @see ApiKey
     *
     * @param array $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @return array<string, mixed>|UpdateApiKeyResponse
     */
    public function updateApiKey($key, $apiKey, $requestOptions = [])
    {
        $response = $this->updateApiKeyWithHttpInfo($key, $apiKey, $requestOptions);

        return $response->getData();
    }

    /**
     * Create an API key (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Creates a new API key with specific permissions and restrictions.
     * Required API Key ACLs:
     *  - admin
     *
     * @param ApiKey|array $apiKey         (required)
     * @param array        $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function addApiKeyWithHttpInfo($apiKey, $requestOptions = [])
    {
        // verify the required parameter 'apiKey' is set
        if (!isset($apiKey)) {
            throw new \InvalidArgumentException(
                'Parameter `apiKey` is required when calling `addApiKey`.'
            );
        }

        $resourcePath = '/1/keys';
        $queryParameters = [];
        $headers = [];
        $httpBody = $apiKey;

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Add or replace a record (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * If a record with the specified object ID exists, the existing record is replaced. Otherwise, a new record is added to the index.  If you want to use auto-generated object IDs, use the [`saveObject` operation](https://www.algolia.com/doc/rest-api/search/save-object). To update _some_ attributes of an existing record, use the [`partial` operation](https://www.algolia.com/doc/rest-api/search/partial-update-object) instead. To add, update, or replace multiple records, use the [`batch` operation](https://www.algolia.com/doc/rest-api/search/batch).
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param string $objectID       Unique record identifier. (required)
     * @param array  $body           The record. A schemaless object with attributes that are useful in the context of search and discovery. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function addOrUpdateObjectWithHttpInfo($indexName, $objectID, $body, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `addOrUpdateObject`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `addOrUpdateObject`.'
            );
        }
        // verify the required parameter 'objectID' is set
        if (!isset($objectID)) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `addOrUpdateObject`.'
            );
        }
        // verify the required parameter 'objectID' is not empty
        if (isset($objectID) && '' === $objectID) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `addOrUpdateObject`.'
            );
        }
        // verify the required parameter 'body' is set
        if (!isset($body)) {
            throw new \InvalidArgumentException(
                'Parameter `body` is required when calling `addOrUpdateObject`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/{objectID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = $body;

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $objectID) {
            $resourcePath = str_replace(
                '{objectID}',
                ObjectSerializer::toPathValue($objectID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('PUT', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Add a source (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Adds a source to the list of allowed sources.
     * Required API Key ACLs:
     *  - admin
     *
     * @param array|Source $source         Source to add. (required)
     * @param array        $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function appendSourceWithHttpInfo($source, $requestOptions = [])
    {
        // verify the required parameter 'source' is set
        if (!isset($source)) {
            throw new \InvalidArgumentException(
                'Parameter `source` is required when calling `appendSource`.'
            );
        }

        $resourcePath = '/1/security/sources/append';
        $queryParameters = [];
        $headers = [];
        $httpBody = $source;

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Assign or move a user ID (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Assigns or moves a user ID to a cluster.  The time it takes to move a user is proportional to the amount of data linked to the user ID.
     * Required API Key ACLs:
     *  - admin
     *
     * @param string                   $xAlgoliaUserID     Unique identifier of the user who makes the search request. (required)
     * @param array|AssignUserIdParams $assignUserIdParams (required)
     * @param array                    $requestOptions     Request options
     *
     * @return AlgoliaResponse
     */
    public function assignUserIdWithHttpInfo($xAlgoliaUserID, $assignUserIdParams, $requestOptions = [])
    {
        // verify the required parameter 'xAlgoliaUserID' is set
        if (!isset($xAlgoliaUserID)) {
            throw new \InvalidArgumentException(
                'Parameter `xAlgoliaUserID` is required when calling `assignUserId`.'
            );
        }
        // verify the required parameter 'xAlgoliaUserID' is not empty
        if (isset($xAlgoliaUserID) && '' === $xAlgoliaUserID) {
            throw new \InvalidArgumentException(
                'Parameter `xAlgoliaUserID` is required when calling `assignUserId`.'
            );
        }
        // verify the required parameter 'assignUserIdParams' is set
        if (!isset($assignUserIdParams)) {
            throw new \InvalidArgumentException(
                'Parameter `assignUserIdParams` is required when calling `assignUserId`.'
            );
        }

        $resourcePath = '/1/clusters/mapping';
        $queryParameters = [];
        $headers = [];
        $httpBody = $assignUserIdParams;

        $headers['X-Algolia-User-ID'] = $xAlgoliaUserID;

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Batch indexing operations on one index (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Adds, updates, or deletes records in one index with a single API request.  Batching index updates reduces latency and increases data integrity.  - Actions are applied in the order they're specified. - Actions are equivalent to the individual API requests of the same name.  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string                 $indexName        Name of the index on which to perform the operation. (required)
     * @param array|BatchWriteParams $batchWriteParams (required)
     * @param array                  $requestOptions   Request options
     *
     * @return AlgoliaResponse
     */
    public function batchWithHttpInfo($indexName, $batchWriteParams, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `batch`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `batch`.'
            );
        }
        // verify the required parameter 'batchWriteParams' is set
        if (!isset($batchWriteParams)) {
            throw new \InvalidArgumentException(
                'Parameter `batchWriteParams` is required when calling `batch`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/batch';
        $queryParameters = [];
        $headers = [];
        $httpBody = $batchWriteParams;

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Assign multiple userIDs (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Assigns multiple user IDs to a cluster.  **You can't move users with this operation**.
     * Required API Key ACLs:
     *  - admin
     *
     * @param string                         $xAlgoliaUserID           Unique identifier of the user who makes the search request. (required)
     * @param array|BatchAssignUserIdsParams $batchAssignUserIdsParams (required)
     * @param array                          $requestOptions           Request options
     *
     * @return AlgoliaResponse
     */
    public function batchAssignUserIdsWithHttpInfo($xAlgoliaUserID, $batchAssignUserIdsParams, $requestOptions = [])
    {
        // verify the required parameter 'xAlgoliaUserID' is set
        if (!isset($xAlgoliaUserID)) {
            throw new \InvalidArgumentException(
                'Parameter `xAlgoliaUserID` is required when calling `batchAssignUserIds`.'
            );
        }
        // verify the required parameter 'xAlgoliaUserID' is not empty
        if (isset($xAlgoliaUserID) && '' === $xAlgoliaUserID) {
            throw new \InvalidArgumentException(
                'Parameter `xAlgoliaUserID` is required when calling `batchAssignUserIds`.'
            );
        }
        // verify the required parameter 'batchAssignUserIdsParams' is set
        if (!isset($batchAssignUserIdsParams)) {
            throw new \InvalidArgumentException(
                'Parameter `batchAssignUserIdsParams` is required when calling `batchAssignUserIds`.'
            );
        }

        $resourcePath = '/1/clusters/mapping/batch';
        $queryParameters = [];
        $headers = [];
        $httpBody = $batchAssignUserIdsParams;

        $headers['X-Algolia-User-ID'] = $xAlgoliaUserID;

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Add or delete dictionary entries (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Adds or deletes multiple entries from your plurals, segmentation, or stop word dictionaries.
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param array                              $dictionaryName               Dictionary type in which to search. (required)
     * @param array|BatchDictionaryEntriesParams $batchDictionaryEntriesParams (required)
     * @param array                              $requestOptions               Request options
     *
     * @return AlgoliaResponse
     */
    public function batchDictionaryEntriesWithHttpInfo($dictionaryName, $batchDictionaryEntriesParams, $requestOptions = [])
    {
        // verify the required parameter 'dictionaryName' is set
        if (!isset($dictionaryName)) {
            throw new \InvalidArgumentException(
                'Parameter `dictionaryName` is required when calling `batchDictionaryEntries`.'
            );
        }
        // verify the required parameter 'batchDictionaryEntriesParams' is set
        if (!isset($batchDictionaryEntriesParams)) {
            throw new \InvalidArgumentException(
                'Parameter `batchDictionaryEntriesParams` is required when calling `batchDictionaryEntries`.'
            );
        }

        $resourcePath = '/1/dictionaries/{dictionaryName}/batch';
        $queryParameters = [];
        $headers = [];
        $httpBody = $batchDictionaryEntriesParams;

        // path params
        if (null !== $dictionaryName) {
            $resourcePath = str_replace(
                '{dictionaryName}',
                ObjectSerializer::toPathValue($dictionaryName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Browse for records (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Retrieves records from an index, up to 1,000 per request.  Searching returns _hits_ (records augmented with highlighting and ranking details). Browsing returns matching records only. Use browse to export your indices.  - The Analytics API doesn't collect data when using `browse`. - Records are ranked by attributes and custom ranking. - There's no ranking for typo tolerance, number of matched words, proximity, or geo distance.  Browse requests automatically apply these settings:  - `advancedSyntax`: `false` - `attributesToHighlight`: `[]` - `attributesToSnippet`: `[]` - `distinct`: `false` - `enablePersonalization`: `false` - `enableRules`: `false` - `facets`: `[]` - `getRankingInfo`: `false` - `ignorePlurals`: `false` - `optionalFilters`: `[]` - `typoTolerance`: `true` or `false` (`min` and `strict` evaluate to `true`)  If you send these parameters with your browse requests, they're ignored.
     * Required API Key ACLs:
     *  - browse
     *
     * @param string             $indexName      Name of the index on which to perform the operation. (required)
     * @param array|BrowseParams $browseParams   (optional)
     * @param array              $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function browseWithHttpInfo($indexName, $browseParams = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `browse`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `browse`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/browse';
        $queryParameters = [];
        $headers = [];
        $httpBody = isset($browseParams) ? $browseParams : [];

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions, true);
    }

    /**
     * Delete all records from an index (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Deletes only the records from an index while keeping settings, synonyms, and rules. This operation is resource-intensive and subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     * Required API Key ACLs:
     *  - deleteIndex
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function clearObjectsWithHttpInfo($indexName, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `clearObjects`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `clearObjects`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/clear';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Delete all rules (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Deletes all rules from the index.
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName         Name of the index on which to perform the operation. (required)
     * @param bool   $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array  $requestOptions    Request options
     *
     * @return AlgoliaResponse
     */
    public function clearRulesWithHttpInfo($indexName, $forwardToReplicas = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `clearRules`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `clearRules`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/rules/clear';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $forwardToReplicas) {
            $queryParameters['forwardToReplicas'] = $forwardToReplicas;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Delete all synonyms (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Deletes all synonyms from the index.
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName         Name of the index on which to perform the operation. (required)
     * @param bool   $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array  $requestOptions    Request options
     *
     * @return AlgoliaResponse
     */
    public function clearSynonymsWithHttpInfo($indexName, $forwardToReplicas = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `clearSynonyms`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `clearSynonyms`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/synonyms/clear';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $forwardToReplicas) {
            $queryParameters['forwardToReplicas'] = $forwardToReplicas;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Send requests to the Algolia REST API (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * This method lets you send requests to the Algolia REST API.
     *
     * @param string $path           Path of the endpoint, for example `1/newFeature`. (required)
     * @param array  $parameters     Query parameters to apply to the current query. (optional)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function customDeleteWithHttpInfo($path, $parameters = null, $requestOptions = [])
    {
        // verify the required parameter 'path' is set
        if (!isset($path)) {
            throw new \InvalidArgumentException(
                'Parameter `path` is required when calling `customDelete`.'
            );
        }
        // verify the required parameter 'path' is not empty
        if (isset($path) && '' === $path) {
            throw new \InvalidArgumentException(
                'Parameter `path` is required when calling `customDelete`.'
            );
        }

        $resourcePath = '/{path}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $parameters) {
            $queryParameters = $parameters;
        }

        // path params
        if (null !== $path) {
            $resourcePath = str_replace(
                '{path}',
                $path,
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('DELETE', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Send requests to the Algolia REST API (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * This method lets you send requests to the Algolia REST API.
     *
     * @param string $path           Path of the endpoint, for example `1/newFeature`. (required)
     * @param array  $parameters     Query parameters to apply to the current query. (optional)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function customGetWithHttpInfo($path, $parameters = null, $requestOptions = [])
    {
        // verify the required parameter 'path' is set
        if (!isset($path)) {
            throw new \InvalidArgumentException(
                'Parameter `path` is required when calling `customGet`.'
            );
        }
        // verify the required parameter 'path' is not empty
        if (isset($path) && '' === $path) {
            throw new \InvalidArgumentException(
                'Parameter `path` is required when calling `customGet`.'
            );
        }

        $resourcePath = '/{path}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $parameters) {
            $queryParameters = $parameters;
        }

        // path params
        if (null !== $path) {
            $resourcePath = str_replace(
                '{path}',
                $path,
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Send requests to the Algolia REST API (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * This method lets you send requests to the Algolia REST API.
     *
     * @param string $path           Path of the endpoint, for example `1/newFeature`. (required)
     * @param array  $parameters     Query parameters to apply to the current query. (optional)
     * @param array  $body           Parameters to send with the custom request. (optional)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function customPostWithHttpInfo($path, $parameters = null, $body = null, $requestOptions = [])
    {
        // verify the required parameter 'path' is set
        if (!isset($path)) {
            throw new \InvalidArgumentException(
                'Parameter `path` is required when calling `customPost`.'
            );
        }
        // verify the required parameter 'path' is not empty
        if (isset($path) && '' === $path) {
            throw new \InvalidArgumentException(
                'Parameter `path` is required when calling `customPost`.'
            );
        }

        $resourcePath = '/{path}';
        $queryParameters = [];
        $headers = [];
        $httpBody = isset($body) ? $body : [];

        if (null !== $parameters) {
            $queryParameters = $parameters;
        }

        // path params
        if (null !== $path) {
            $resourcePath = str_replace(
                '{path}',
                $path,
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Send requests to the Algolia REST API (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * This method lets you send requests to the Algolia REST API.
     *
     * @param string $path           Path of the endpoint, for example `1/newFeature`. (required)
     * @param array  $parameters     Query parameters to apply to the current query. (optional)
     * @param array  $body           Parameters to send with the custom request. (optional)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function customPutWithHttpInfo($path, $parameters = null, $body = null, $requestOptions = [])
    {
        // verify the required parameter 'path' is set
        if (!isset($path)) {
            throw new \InvalidArgumentException(
                'Parameter `path` is required when calling `customPut`.'
            );
        }
        // verify the required parameter 'path' is not empty
        if (isset($path) && '' === $path) {
            throw new \InvalidArgumentException(
                'Parameter `path` is required when calling `customPut`.'
            );
        }

        $resourcePath = '/{path}';
        $queryParameters = [];
        $headers = [];
        $httpBody = isset($body) ? $body : [];

        if (null !== $parameters) {
            $queryParameters = $parameters;
        }

        // path params
        if (null !== $path) {
            $resourcePath = str_replace(
                '{path}',
                $path,
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('PUT', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Delete an API key (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Deletes the API key.
     * Required API Key ACLs:
     *  - admin
     *
     * @param string $key            API key. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function deleteApiKeyWithHttpInfo($key, $requestOptions = [])
    {
        // verify the required parameter 'key' is set
        if (!isset($key)) {
            throw new \InvalidArgumentException(
                'Parameter `key` is required when calling `deleteApiKey`.'
            );
        }
        // verify the required parameter 'key' is not empty
        if (isset($key) && '' === $key) {
            throw new \InvalidArgumentException(
                'Parameter `key` is required when calling `deleteApiKey`.'
            );
        }

        $resourcePath = '/1/keys/{key}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $key) {
            $resourcePath = str_replace(
                '{key}',
                ObjectSerializer::toPathValue($key),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('DELETE', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Delete records matching a filter (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * This operation doesn't accept empty filters.  This operation is resource-intensive. Use it only if you can't get the object IDs of the records you want to delete. It's more efficient to get a list of object IDs with the [`browse` operation](https://www.algolia.com/doc/rest-api/search/browse), and then delete the records using the [`batch` operation](https://www.algolia.com/doc/rest-api/search/batch).  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     * Required API Key ACLs:
     *  - deleteIndex
     *
     * @param string               $indexName      Name of the index on which to perform the operation. (required)
     * @param array|DeleteByParams $deleteByParams (required)
     * @param array                $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function deleteByWithHttpInfo($indexName, $deleteByParams, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `deleteBy`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `deleteBy`.'
            );
        }
        // verify the required parameter 'deleteByParams' is set
        if (!isset($deleteByParams)) {
            throw new \InvalidArgumentException(
                'Parameter `deleteByParams` is required when calling `deleteBy`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/deleteByQuery';
        $queryParameters = [];
        $headers = [];
        $httpBody = $deleteByParams;

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Delete an index (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Deletes an index and all its settings.  - Deleting an index doesn't delete its analytics data. - If you try to delete a non-existing index, the operation is ignored without warning. - If the index you want to delete has replica indices, the replicas become independent indices. - If the index you want to delete is a replica index, you must first unlink it from its primary index before you can delete it.   For more information, see [Delete replica indices](https://www.algolia.com/doc/guides/managing-results/refine-results/sorting/how-to/deleting-replicas).
     * Required API Key ACLs:
     *  - deleteIndex
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function deleteIndexWithHttpInfo($indexName, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `deleteIndex`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `deleteIndex`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('DELETE', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Delete a record (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Deletes a record by its object ID.  To delete more than one record, use the [`batch` operation](https://www.algolia.com/doc/rest-api/search/batch). To delete records matching a query, use the [`deleteBy` operation](https://www.algolia.com/doc/rest-api/search/delete-by).
     * Required API Key ACLs:
     *  - deleteObject
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param string $objectID       Unique record identifier. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function deleteObjectWithHttpInfo($indexName, $objectID, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `deleteObject`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `deleteObject`.'
            );
        }
        // verify the required parameter 'objectID' is set
        if (!isset($objectID)) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `deleteObject`.'
            );
        }
        // verify the required parameter 'objectID' is not empty
        if (isset($objectID) && '' === $objectID) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `deleteObject`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/{objectID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $objectID) {
            $resourcePath = str_replace(
                '{objectID}',
                ObjectSerializer::toPathValue($objectID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('DELETE', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Delete a rule (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Deletes a rule by its ID. To find the object ID for rules, use the [`search` operation](https://www.algolia.com/doc/rest-api/search/search-rules).
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName         Name of the index on which to perform the operation. (required)
     * @param string $objectID          Unique identifier of a rule object. (required)
     * @param bool   $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array  $requestOptions    Request options
     *
     * @return AlgoliaResponse
     */
    public function deleteRuleWithHttpInfo($indexName, $objectID, $forwardToReplicas = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `deleteRule`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `deleteRule`.'
            );
        }
        // verify the required parameter 'objectID' is set
        if (!isset($objectID)) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `deleteRule`.'
            );
        }
        // verify the required parameter 'objectID' is not empty
        if (isset($objectID) && '' === $objectID) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `deleteRule`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/rules/{objectID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $forwardToReplicas) {
            $queryParameters['forwardToReplicas'] = $forwardToReplicas;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $objectID) {
            $resourcePath = str_replace(
                '{objectID}',
                ObjectSerializer::toPathValue($objectID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('DELETE', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Delete a source (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Deletes a source from the list of allowed sources.
     * Required API Key ACLs:
     *  - admin
     *
     * @param string $source         IP address range of the source. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function deleteSourceWithHttpInfo($source, $requestOptions = [])
    {
        // verify the required parameter 'source' is set
        if (!isset($source)) {
            throw new \InvalidArgumentException(
                'Parameter `source` is required when calling `deleteSource`.'
            );
        }
        // verify the required parameter 'source' is not empty
        if (isset($source) && '' === $source) {
            throw new \InvalidArgumentException(
                'Parameter `source` is required when calling `deleteSource`.'
            );
        }

        $resourcePath = '/1/security/sources/{source}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $source) {
            $resourcePath = str_replace(
                '{source}',
                ObjectSerializer::toPathValue($source),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('DELETE', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Delete a synonym (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Deletes a synonym by its ID. To find the object IDs of your synonyms, use the [`search` operation](https://www.algolia.com/doc/rest-api/search/search-synonyms).
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName         Name of the index on which to perform the operation. (required)
     * @param string $objectID          Unique identifier of a synonym object. (required)
     * @param bool   $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array  $requestOptions    Request options
     *
     * @return AlgoliaResponse
     */
    public function deleteSynonymWithHttpInfo($indexName, $objectID, $forwardToReplicas = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `deleteSynonym`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `deleteSynonym`.'
            );
        }
        // verify the required parameter 'objectID' is set
        if (!isset($objectID)) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `deleteSynonym`.'
            );
        }
        // verify the required parameter 'objectID' is not empty
        if (isset($objectID) && '' === $objectID) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `deleteSynonym`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/synonyms/{objectID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $forwardToReplicas) {
            $queryParameters['forwardToReplicas'] = $forwardToReplicas;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $objectID) {
            $resourcePath = str_replace(
                '{objectID}',
                ObjectSerializer::toPathValue($objectID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('DELETE', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Retrieve API key permissions (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Gets the permissions and restrictions of an API key.  When authenticating with the admin API key, you can request information for any of your application's keys. When authenticating with other API keys, you can only retrieve information for that key, with the description replaced by `<redacted>`.
     * Required API Key ACLs:
     *  - search
     *
     * @param string $key            API key. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getApiKeyWithHttpInfo($key, $requestOptions = [])
    {
        // verify the required parameter 'key' is set
        if (!isset($key)) {
            throw new \InvalidArgumentException(
                'Parameter `key` is required when calling `getApiKey`.'
            );
        }
        // verify the required parameter 'key' is not empty
        if (isset($key) && '' === $key) {
            throw new \InvalidArgumentException(
                'Parameter `key` is required when calling `getApiKey`.'
            );
        }

        $resourcePath = '/1/keys/{key}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $key) {
            $resourcePath = str_replace(
                '{key}',
                ObjectSerializer::toPathValue($key),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Check application task status (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Checks the status of a given application task.
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param int   $taskID         Unique task identifier. (required)
     * @param array $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getAppTaskWithHttpInfo($taskID, $requestOptions = [])
    {
        // verify the required parameter 'taskID' is set
        if (!isset($taskID)) {
            throw new \InvalidArgumentException(
                'Parameter `taskID` is required when calling `getAppTask`.'
            );
        }

        $resourcePath = '/1/task/{taskID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $taskID) {
            $resourcePath = str_replace(
                '{taskID}',
                ObjectSerializer::toPathValue($taskID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * List available languages (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Lists supported languages with their supported dictionary types and number of custom entries.
     * Required API Key ACLs:
     *  - settings
     *
     * @param array $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getDictionaryLanguagesWithHttpInfo($requestOptions = [])
    {
        $resourcePath = '/1/dictionaries/*/languages';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Retrieve dictionary settings (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Retrieves the languages for which standard dictionary entries are turned off.
     * Required API Key ACLs:
     *  - settings
     *
     * @param array $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getDictionarySettingsWithHttpInfo($requestOptions = [])
    {
        $resourcePath = '/1/dictionaries/*/settings';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Retrieve log entries (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * The request must be authenticated by an API key with the [`logs` ACL](https://www.algolia.com/doc/guides/security/api-keys/#access-control-list-acl).  - Logs are held for the last seven days. - Up to 1,000 API requests per server are logged. - This request counts towards your [operations quota](https://support.algolia.com/hc/articles/17245378392977-How-does-Algolia-count-records-and-operations) but doesn't appear in the logs itself.
     * Required API Key ACLs:
     *  - logs
     *
     * @param int    $offset         First log entry to retrieve. The most recent entries are listed first. (optional)
     * @param int    $length         Maximum number of entries to retrieve. (optional)
     * @param string $indexName      Index for which to retrieve log entries. By default, log entries are retrieved for all indices. (optional)
     * @param array  $type           Type of log entries to retrieve. By default, all log entries are retrieved. (optional)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getLogsWithHttpInfo($offset = null, $length = null, $indexName = null, $type = null, $requestOptions = [])
    {
        $resourcePath = '/1/logs';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $offset) {
            $queryParameters['offset'] = $offset;
        }

        if (null !== $length) {
            $queryParameters['length'] = $length;
        }

        if (null !== $indexName) {
            $queryParameters['indexName'] = $indexName;
        }

        if (null !== $type) {
            $queryParameters['type'] = $type;
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Retrieve a record (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Retrieves one record by its object ID.  To retrieve more than one record, use the [`objects` operation](https://www.algolia.com/doc/rest-api/search/get-objects).
     * Required API Key ACLs:
     *  - search
     *
     * @param string $indexName            Name of the index on which to perform the operation. (required)
     * @param string $objectID             Unique record identifier. (required)
     * @param array  $attributesToRetrieve Attributes to include with the records in the response. This is useful to reduce the size of the API response. By default, all retrievable attributes are returned.  `objectID` is always retrieved.  Attributes included in `unretrievableAttributes` won't be retrieved unless the request is authenticated with the admin API key. (optional)
     * @param array  $requestOptions       Request options
     *
     * @return AlgoliaResponse
     */
    public function getObjectWithHttpInfo($indexName, $objectID, $attributesToRetrieve = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `getObject`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `getObject`.'
            );
        }
        // verify the required parameter 'objectID' is set
        if (!isset($objectID)) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `getObject`.'
            );
        }
        // verify the required parameter 'objectID' is not empty
        if (isset($objectID) && '' === $objectID) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `getObject`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/{objectID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $attributesToRetrieve) {
            $queryParameters['attributesToRetrieve'] = $attributesToRetrieve;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $objectID) {
            $resourcePath = str_replace(
                '{objectID}',
                ObjectSerializer::toPathValue($objectID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Retrieve records (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Retrieves one or more records, potentially from different indices.  Records are returned in the same order as the requests.
     * Required API Key ACLs:
     *  - search
     *
     * @param array|GetObjectsParams $getObjectsParams Request object. (required)
     * @param array                  $requestOptions   Request options
     *
     * @return AlgoliaResponse
     */
    public function getObjectsWithHttpInfo($getObjectsParams, $requestOptions = [])
    {
        // verify the required parameter 'getObjectsParams' is set
        if (!isset($getObjectsParams)) {
            throw new \InvalidArgumentException(
                'Parameter `getObjectsParams` is required when calling `getObjects`.'
            );
        }

        $resourcePath = '/1/indexes/*/objects';
        $queryParameters = [];
        $headers = [];
        $httpBody = $getObjectsParams;

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions, true);
    }

    /**
     * Retrieve a rule (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Retrieves a rule by its ID. To find the object ID of rules, use the [`search` operation](https://www.algolia.com/doc/rest-api/search/search-rules).
     * Required API Key ACLs:
     *  - settings
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param string $objectID       Unique identifier of a rule object. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getRuleWithHttpInfo($indexName, $objectID, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `getRule`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `getRule`.'
            );
        }
        // verify the required parameter 'objectID' is set
        if (!isset($objectID)) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `getRule`.'
            );
        }
        // verify the required parameter 'objectID' is not empty
        if (isset($objectID) && '' === $objectID) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `getRule`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/rules/{objectID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $objectID) {
            $resourcePath = str_replace(
                '{objectID}',
                ObjectSerializer::toPathValue($objectID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Retrieve index settings (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Retrieves an object with non-null index settings.
     * Required API Key ACLs:
     *  - settings
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param int    $getVersion     When set to 2, the endpoint will not include `synonyms` in the response. This parameter is here for backward compatibility. (optional)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getSettingsWithHttpInfo($indexName, $getVersion = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `getSettings`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `getSettings`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/settings';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $getVersion) {
            $queryParameters['getVersion'] = $getVersion;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * List allowed sources (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Retrieves all allowed IP addresses with access to your application.
     * Required API Key ACLs:
     *  - admin
     *
     * @param array $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getSourcesWithHttpInfo($requestOptions = [])
    {
        $resourcePath = '/1/security/sources';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Retrieve a synonym (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Retrieves a synonym by its ID. To find the object IDs for your synonyms, use the [`search` operation](https://www.algolia.com/doc/rest-api/search/search-synonyms).
     * Required API Key ACLs:
     *  - settings
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param string $objectID       Unique identifier of a synonym object. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getSynonymWithHttpInfo($indexName, $objectID, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `getSynonym`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `getSynonym`.'
            );
        }
        // verify the required parameter 'objectID' is set
        if (!isset($objectID)) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `getSynonym`.'
            );
        }
        // verify the required parameter 'objectID' is not empty
        if (isset($objectID) && '' === $objectID) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `getSynonym`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/synonyms/{objectID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $objectID) {
            $resourcePath = str_replace(
                '{objectID}',
                ObjectSerializer::toPathValue($objectID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Check task status (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Checks the status of a given task.  Indexing tasks are asynchronous. When you add, update, or delete records or indices, a task is created on a queue and completed depending on the load on the server.  The indexing tasks' responses include a task ID that you can use to check the status.
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param int    $taskID         Unique task identifier. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getTaskWithHttpInfo($indexName, $taskID, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `getTask`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `getTask`.'
            );
        }
        // verify the required parameter 'taskID' is set
        if (!isset($taskID)) {
            throw new \InvalidArgumentException(
                'Parameter `taskID` is required when calling `getTask`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/task/{taskID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $taskID) {
            $resourcePath = str_replace(
                '{taskID}',
                ObjectSerializer::toPathValue($taskID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Get top user IDs (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Get the IDs of the 10 users with the highest number of records per cluster.  Since it can take a few seconds to get the data from the different clusters, the response isn't real-time.
     * Required API Key ACLs:
     *  - admin
     *
     * @param array $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getTopUserIdsWithHttpInfo($requestOptions = [])
    {
        $resourcePath = '/1/clusters/mapping/top';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Retrieve user ID (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Returns the user ID data stored in the mapping.  Since it can take a few seconds to get the data from the different clusters, the response isn't real-time.
     * Required API Key ACLs:
     *  - admin
     *
     * @param string $userID         Unique identifier of the user who makes the search request. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function getUserIdWithHttpInfo($userID, $requestOptions = [])
    {
        // verify the required parameter 'userID' is set
        if (!isset($userID)) {
            throw new \InvalidArgumentException(
                'Parameter `userID` is required when calling `getUserId`.'
            );
        }
        // verify the required parameter 'userID' is not empty
        if (isset($userID) && '' === $userID) {
            throw new \InvalidArgumentException(
                'Parameter `userID` is required when calling `getUserId`.'
            );
        }

        $resourcePath = '/1/clusters/mapping/{userID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $userID) {
            $resourcePath = str_replace(
                '{userID}',
                ObjectSerializer::toPathValue($userID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Get migration and user mapping status (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * To determine when the time-consuming process of creating a large batch of users or migrating users from one cluster to another is complete, this operation retrieves the status of the process.
     * Required API Key ACLs:
     *  - admin
     *
     * @param bool  $getClusters    Whether to include the cluster's pending mapping state in the response. (optional)
     * @param array $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function hasPendingMappingsWithHttpInfo($getClusters = null, $requestOptions = [])
    {
        $resourcePath = '/1/clusters/mapping/pending';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $getClusters) {
            $queryParameters['getClusters'] = $getClusters;
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * List API keys (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Lists all API keys associated with your Algolia application, including their permissions and restrictions.
     * Required API Key ACLs:
     *  - admin
     *
     * @param array $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function listApiKeysWithHttpInfo($requestOptions = [])
    {
        $resourcePath = '/1/keys';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * List clusters (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Lists the available clusters in a multi-cluster setup.
     * Required API Key ACLs:
     *  - admin
     *
     * @param array $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function listClustersWithHttpInfo($requestOptions = [])
    {
        $resourcePath = '/1/clusters';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * List indices (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Lists all indices in the current Algolia application.  The request follows any index restrictions of the API key you use to make the request.
     * Required API Key ACLs:
     *  - listIndexes
     *
     * @param int   $page           Requested page of the API response. If `null`, the API response is not paginated. (optional)
     * @param int   $hitsPerPage    Number of hits per page. (optional)
     * @param array $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function listIndicesWithHttpInfo($page = null, $hitsPerPage = null, $requestOptions = [])
    {
        $resourcePath = '/1/indexes';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $page) {
            $queryParameters['page'] = $page;
        }

        if (null !== $hitsPerPage) {
            $queryParameters['hitsPerPage'] = $hitsPerPage;
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * List user IDs (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Lists the userIDs assigned to a multi-cluster application.  Since it can take a few seconds to get the data from the different clusters, the response isn't real-time.
     * Required API Key ACLs:
     *  - admin
     *
     * @param int   $page           Requested page of the API response. If `null`, the API response is not paginated. (optional)
     * @param int   $hitsPerPage    Number of hits per page. (optional)
     * @param array $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function listUserIdsWithHttpInfo($page = null, $hitsPerPage = null, $requestOptions = [])
    {
        $resourcePath = '/1/clusters/mapping';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        if (null !== $page) {
            $queryParameters['page'] = $page;
        }

        if (null !== $hitsPerPage) {
            $queryParameters['hitsPerPage'] = $hitsPerPage;
        }

        return $this->sendRequestWithHttpInfo('GET', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Batch indexing operations on multiple indices (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Adds, updates, or deletes records in multiple indices with a single API request.  - Actions are applied in the order they are specified. - Actions are equivalent to the individual API requests of the same name.  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     * Required API Key ACLs:
     *  - addObject
     *
     * @param array|BatchParams $batchParams    (required)
     * @param array             $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function multipleBatchWithHttpInfo($batchParams, $requestOptions = [])
    {
        // verify the required parameter 'batchParams' is set
        if (!isset($batchParams)) {
            throw new \InvalidArgumentException(
                'Parameter `batchParams` is required when calling `multipleBatch`.'
            );
        }

        $resourcePath = '/1/indexes/*/batch';
        $queryParameters = [];
        $headers = [];
        $httpBody = $batchParams;

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Copy or move an index (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Copies or moves (renames) an index within the same Algolia application.  Notes: - Existing destination indices are overwritten, except for their analytics data. - If the destination index doesn't exist yet, it's created. - This operation is resource-intensive.  **Copy**  - If the source index doesn't exist, copying creates a new index with 0 records and default settings. - API keys from the source index are merged with the existing keys in the destination index. - You can't copy the `enableReRanking`, `mode`, and `replicas` settings. - You can't copy to a destination index that already has replicas. - Be aware of the [size limits](https://www.algolia.com/doc/guides/scaling/algolia-service-limits/#application-record-and-index-limits). - For more information, see [Copy indices](https://www.algolia.com/doc/guides/sending-and-managing-data/manage-indices-and-apps/manage-indices/how-to/copy-indices).  **Move**  - If the source index doesn't exist, moving is ignored without returning an error. - When moving an index, the analytics data keeps its original name, and a new set of analytics data is started for the new name.   To access the original analytics in the dashboard, create an index with the original name. - If the destination index has replicas, moving will overwrite the existing index and copy the data to the replica indices. - For more information, see [Move indices](https://www.algolia.com/doc/guides/sending-and-managing-data/manage-indices-and-apps/manage-indices/how-to/move-indices).  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string                     $indexName            Name of the index on which to perform the operation. (required)
     * @param array|OperationIndexParams $operationIndexParams (required)
     * @param array                      $requestOptions       Request options
     *
     * @return AlgoliaResponse
     */
    public function operationIndexWithHttpInfo($indexName, $operationIndexParams, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `operationIndex`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `operationIndex`.'
            );
        }
        // verify the required parameter 'operationIndexParams' is set
        if (!isset($operationIndexParams)) {
            throw new \InvalidArgumentException(
                'Parameter `operationIndexParams` is required when calling `operationIndex`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/operation';
        $queryParameters = [];
        $headers = [];
        $httpBody = $operationIndexParams;

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Add or update attributes (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Adds new attributes to a record, or updates existing ones.  - If a record with the specified object ID doesn't exist,   a new record is added to the index **if** `createIfNotExists` is true. - If the index doesn't exist yet, this method creates a new index. - Use first-level attributes only. Nested attributes aren't supported.   If you specify a nested attribute, this operation replaces its first-level ancestor.  To update attributes without replacing the full record, use these built-in operations. These operations are useful when the initial data isn't available.  - `Increment`: increment a numeric attribute. - `Decrement`: decrement a numeric attribute. - `Add`: append a number or string element to an array attribute. - `Remove`: remove all matching number or string elements from an array attribute made of numbers or strings. - `AddUnique`: add a number or string element to an array attribute made of numbers or strings only if it's not already present. - `IncrementFrom`: increment a numeric integer attribute only if the provided value matches the current value. Otherwise, the update is ignored.   Example: If you pass an `IncrementFrom` value of 2 for the `version` attribute but the current value is 1, the API ignores the update.   If the object doesn't exist, the API only creates it if you pass an `IncrementFrom` value of 0. - `IncrementSet`: increment a numeric integer attribute only if the provided value is greater than the current value. Otherwise, the update is ignored.   Example: If you pass an `IncrementSet` value of 2 for the `version` attribute and the current value is 1, the API updates the object.   If the object doesn't exist yet, the API only creates it if you pass an `IncrementSet` value greater than 0.  Specify an operation by providing an object with the attribute to update as the key and its value as an object with these properties:  - `_operation`: the operation to apply on the attribute. - `value`: the right-hand side argument to the operation, for example, increment or decrement step, or a value to add or remove.  When updating multiple attributes or using multiple operations targeting the same record, use a single partial update for faster processing.  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string $indexName          Name of the index on which to perform the operation. (required)
     * @param string $objectID           Unique record identifier. (required)
     * @param array  $attributesToUpdate Attributes with their values. (required)
     * @param bool   $createIfNotExists  Whether to create a new record if it doesn't exist. (optional)
     * @param array  $requestOptions     Request options
     *
     * @return AlgoliaResponse
     */
    public function partialUpdateObjectWithHttpInfo($indexName, $objectID, $attributesToUpdate, $createIfNotExists = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `partialUpdateObject`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `partialUpdateObject`.'
            );
        }
        // verify the required parameter 'objectID' is set
        if (!isset($objectID)) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `partialUpdateObject`.'
            );
        }
        // verify the required parameter 'objectID' is not empty
        if (isset($objectID) && '' === $objectID) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `partialUpdateObject`.'
            );
        }
        // verify the required parameter 'attributesToUpdate' is set
        if (!isset($attributesToUpdate)) {
            throw new \InvalidArgumentException(
                'Parameter `attributesToUpdate` is required when calling `partialUpdateObject`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/{objectID}/partial';
        $queryParameters = [];
        $headers = [];
        $httpBody = $attributesToUpdate;

        if (null !== $createIfNotExists) {
            $queryParameters['createIfNotExists'] = $createIfNotExists;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $objectID) {
            $resourcePath = str_replace(
                '{objectID}',
                ObjectSerializer::toPathValue($objectID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Delete user ID (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Deletes a user ID and its associated data from the clusters.
     * Required API Key ACLs:
     *  - admin
     *
     * @param string $userID         Unique identifier of the user who makes the search request. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function removeUserIdWithHttpInfo($userID, $requestOptions = [])
    {
        // verify the required parameter 'userID' is set
        if (!isset($userID)) {
            throw new \InvalidArgumentException(
                'Parameter `userID` is required when calling `removeUserId`.'
            );
        }
        // verify the required parameter 'userID' is not empty
        if (isset($userID) && '' === $userID) {
            throw new \InvalidArgumentException(
                'Parameter `userID` is required when calling `removeUserId`.'
            );
        }

        $resourcePath = '/1/clusters/mapping/{userID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $userID) {
            $resourcePath = str_replace(
                '{userID}',
                ObjectSerializer::toPathValue($userID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('DELETE', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Replace allowed sources (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Replaces the list of allowed sources.
     * Required API Key ACLs:
     *  - admin
     *
     * @param array $source         Allowed sources. (required)
     * @param array $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function replaceSourcesWithHttpInfo($source, $requestOptions = [])
    {
        // verify the required parameter 'source' is set
        if (!isset($source)) {
            throw new \InvalidArgumentException(
                'Parameter `source` is required when calling `replaceSources`.'
            );
        }

        $resourcePath = '/1/security/sources';
        $queryParameters = [];
        $headers = [];
        $httpBody = $source;

        return $this->sendRequestWithHttpInfo('PUT', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Restore an API key (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Restores a deleted API key.  Restoring resets the `validity` attribute to `0`.  Algolia stores up to 1,000 API keys per application. If you create more, the oldest API keys are deleted and can't be restored.
     * Required API Key ACLs:
     *  - admin
     *
     * @param string $key            API key. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function restoreApiKeyWithHttpInfo($key, $requestOptions = [])
    {
        // verify the required parameter 'key' is set
        if (!isset($key)) {
            throw new \InvalidArgumentException(
                'Parameter `key` is required when calling `restoreApiKey`.'
            );
        }
        // verify the required parameter 'key' is not empty
        if (isset($key) && '' === $key) {
            throw new \InvalidArgumentException(
                'Parameter `key` is required when calling `restoreApiKey`.'
            );
        }

        $resourcePath = '/1/keys/{key}/restore';
        $queryParameters = [];
        $headers = [];
        $httpBody = null;

        // path params
        if (null !== $key) {
            $resourcePath = str_replace(
                '{key}',
                ObjectSerializer::toPathValue($key),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Add a new record (with auto-generated object ID) (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Adds a record to an index or replaces it.  - If the record doesn't have an object ID, a new record with an auto-generated object ID is added to your index. - If a record with the specified object ID exists, the existing record is replaced. - If a record with the specified object ID doesn't exist, a new record is added to your index. - If you add a record to an index that doesn't exist yet, a new index is created.  To update _some_ attributes of a record, use the [`partial` operation](https://www.algolia.com/doc/rest-api/search/partial-update-object). To add, update, or replace multiple records, use the [`batch` operation](https://www.algolia.com/doc/rest-api/search/batch).  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     * Required API Key ACLs:
     *  - addObject
     *
     * @param string $indexName      Name of the index on which to perform the operation. (required)
     * @param array  $body           The record. A schemaless object with attributes that are useful in the context of search and discovery. (required)
     * @param array  $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function saveObjectWithHttpInfo($indexName, $body, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `saveObject`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `saveObject`.'
            );
        }
        // verify the required parameter 'body' is set
        if (!isset($body)) {
            throw new \InvalidArgumentException(
                'Parameter `body` is required when calling `saveObject`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}';
        $queryParameters = [];
        $headers = [];
        $httpBody = $body;

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Create or replace a rule (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * If a rule with the specified object ID doesn't exist, it's created. Otherwise, the existing rule is replaced.  To create or update more than one rule, use the [`batch` operation](https://www.algolia.com/doc/rest-api/search/save-rules).
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string     $indexName         Name of the index on which to perform the operation. (required)
     * @param string     $objectID          Unique identifier of a rule object. (required)
     * @param array|Rule $rule              (required)
     * @param bool       $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array      $requestOptions    Request options
     *
     * @return AlgoliaResponse
     */
    public function saveRuleWithHttpInfo($indexName, $objectID, $rule, $forwardToReplicas = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `saveRule`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `saveRule`.'
            );
        }
        // verify the required parameter 'objectID' is set
        if (!isset($objectID)) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `saveRule`.'
            );
        }
        // verify the required parameter 'objectID' is not empty
        if (isset($objectID) && '' === $objectID) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `saveRule`.'
            );
        }
        // verify the required parameter 'rule' is set
        if (!isset($rule)) {
            throw new \InvalidArgumentException(
                'Parameter `rule` is required when calling `saveRule`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/rules/{objectID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = $rule;

        if (null !== $forwardToReplicas) {
            $queryParameters['forwardToReplicas'] = $forwardToReplicas;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $objectID) {
            $resourcePath = str_replace(
                '{objectID}',
                ObjectSerializer::toPathValue($objectID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('PUT', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Create or update rules (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Create or update multiple rules.  If a rule with the specified object ID doesn't exist, Algolia creates a new one. Otherwise, existing rules are replaced.  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName          Name of the index on which to perform the operation. (required)
     * @param array  $rules              (required)
     * @param bool   $forwardToReplicas  Whether changes are applied to replica indices. (optional)
     * @param bool   $clearExistingRules Whether existing rules should be deleted before adding this batch. (optional)
     * @param array  $requestOptions     Request options
     *
     * @return AlgoliaResponse
     */
    public function saveRulesWithHttpInfo($indexName, $rules, $forwardToReplicas = null, $clearExistingRules = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `saveRules`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `saveRules`.'
            );
        }
        // verify the required parameter 'rules' is set
        if (!isset($rules)) {
            throw new \InvalidArgumentException(
                'Parameter `rules` is required when calling `saveRules`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/rules/batch';
        $queryParameters = [];
        $headers = [];
        $httpBody = $rules;

        if (null !== $forwardToReplicas) {
            $queryParameters['forwardToReplicas'] = $forwardToReplicas;
        }

        if (null !== $clearExistingRules) {
            $queryParameters['clearExistingRules'] = $clearExistingRules;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Create or replace a synonym (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * If a synonym with the specified object ID doesn't exist, Algolia adds a new one. Otherwise, the existing synonym is replaced. To add multiple synonyms in a single API request, use the [`batch` operation](https://www.algolia.com/doc/rest-api/search/save-synonyms).
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string           $indexName         Name of the index on which to perform the operation. (required)
     * @param string           $objectID          Unique identifier of a synonym object. (required)
     * @param array|SynonymHit $synonymHit        (required)
     * @param bool             $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array            $requestOptions    Request options
     *
     * @return AlgoliaResponse
     */
    public function saveSynonymWithHttpInfo($indexName, $objectID, $synonymHit, $forwardToReplicas = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `saveSynonym`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `saveSynonym`.'
            );
        }
        // verify the required parameter 'objectID' is set
        if (!isset($objectID)) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `saveSynonym`.'
            );
        }
        // verify the required parameter 'objectID' is not empty
        if (isset($objectID) && '' === $objectID) {
            throw new \InvalidArgumentException(
                'Parameter `objectID` is required when calling `saveSynonym`.'
            );
        }
        // verify the required parameter 'synonymHit' is set
        if (!isset($synonymHit)) {
            throw new \InvalidArgumentException(
                'Parameter `synonymHit` is required when calling `saveSynonym`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/synonyms/{objectID}';
        $queryParameters = [];
        $headers = [];
        $httpBody = $synonymHit;

        if (null !== $forwardToReplicas) {
            $queryParameters['forwardToReplicas'] = $forwardToReplicas;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $objectID) {
            $resourcePath = str_replace(
                '{objectID}',
                ObjectSerializer::toPathValue($objectID),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('PUT', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Create or replace synonyms (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * If a synonym with the `objectID` doesn't exist, Algolia adds a new one. Otherwise, existing synonyms are replaced.  This operation is subject to [indexing rate limits](https://support.algolia.com/hc/articles/4406975251089-Is-there-a-rate-limit-for-indexing-on-Algolia).
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string $indexName               Name of the index on which to perform the operation. (required)
     * @param array  $synonymHit              (required)
     * @param bool   $forwardToReplicas       Whether changes are applied to replica indices. (optional)
     * @param bool   $replaceExistingSynonyms Whether to replace all synonyms in the index with the ones sent with this request. (optional)
     * @param array  $requestOptions          Request options
     *
     * @return AlgoliaResponse
     */
    public function saveSynonymsWithHttpInfo($indexName, $synonymHit, $forwardToReplicas = null, $replaceExistingSynonyms = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `saveSynonyms`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `saveSynonyms`.'
            );
        }
        // verify the required parameter 'synonymHit' is set
        if (!isset($synonymHit)) {
            throw new \InvalidArgumentException(
                'Parameter `synonymHit` is required when calling `saveSynonyms`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/synonyms/batch';
        $queryParameters = [];
        $headers = [];
        $httpBody = $synonymHit;

        if (null !== $forwardToReplicas) {
            $queryParameters['forwardToReplicas'] = $forwardToReplicas;
        }

        if (null !== $replaceExistingSynonyms) {
            $queryParameters['replaceExistingSynonyms'] = $replaceExistingSynonyms;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Search multiple queries (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Runs multiple search queries against one or more indices in a single API request.  Use cases include:  - Searching different indices, such as products and marketing content. - Run multiple queries on the same index with different parameters or filters.  If you know the expected result type, use the `searchForHits` or `searchForFacets` helper to simplify the response format.
     * Required API Key ACLs:
     *  - search
     *
     * @param array|SearchMethodParams $searchMethodParams Multi-query search request body. Results are returned in the same order as the requests. (required)
     * @param array                    $requestOptions     Request options
     *
     * @return AlgoliaResponse
     */
    public function searchWithHttpInfo($searchMethodParams, $requestOptions = [])
    {
        // verify the required parameter 'searchMethodParams' is set
        if (!isset($searchMethodParams)) {
            throw new \InvalidArgumentException(
                'Parameter `searchMethodParams` is required when calling `search`.'
            );
        }

        $resourcePath = '/1/indexes/*/queries';
        $queryParameters = [];
        $headers = [];
        $httpBody = $searchMethodParams;

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions, true);
    }

    /**
     * Search dictionary entries (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Searches for standard and custom dictionary entries.
     * Required API Key ACLs:
     *  - settings
     *
     * @param array                               $dictionaryName                Dictionary type in which to search. (required)
     * @param array|SearchDictionaryEntriesParams $searchDictionaryEntriesParams (required)
     * @param array                               $requestOptions                Request options
     *
     * @return AlgoliaResponse
     */
    public function searchDictionaryEntriesWithHttpInfo($dictionaryName, $searchDictionaryEntriesParams, $requestOptions = [])
    {
        // verify the required parameter 'dictionaryName' is set
        if (!isset($dictionaryName)) {
            throw new \InvalidArgumentException(
                'Parameter `dictionaryName` is required when calling `searchDictionaryEntries`.'
            );
        }
        // verify the required parameter 'searchDictionaryEntriesParams' is set
        if (!isset($searchDictionaryEntriesParams)) {
            throw new \InvalidArgumentException(
                'Parameter `searchDictionaryEntriesParams` is required when calling `searchDictionaryEntries`.'
            );
        }

        $resourcePath = '/1/dictionaries/{dictionaryName}/search';
        $queryParameters = [];
        $headers = [];
        $httpBody = $searchDictionaryEntriesParams;

        // path params
        if (null !== $dictionaryName) {
            $resourcePath = str_replace(
                '{dictionaryName}',
                ObjectSerializer::toPathValue($dictionaryName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions, true);
    }

    /**
     * Search for facet values (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Searches for values of a specified facet attribute.  - By default, facet values are sorted by decreasing count.   You can adjust this with the `sortFacetValueBy` parameter. - Searching for facet values doesn't work if you have **more than 65 searchable facets and searchable attributes combined**.
     * Required API Key ACLs:
     *  - search
     *
     * @param string                            $indexName                   Name of the index on which to perform the operation. (required)
     * @param string                            $facetName                   Facet attribute in which to search for values.  This attribute must be included in the `attributesForFaceting` index setting with the `searchable()` modifier. (required)
     * @param array|SearchForFacetValuesRequest $searchForFacetValuesRequest (optional)
     * @param array                             $requestOptions              Request options
     *
     * @return AlgoliaResponse
     */
    public function searchForFacetValuesWithHttpInfo($indexName, $facetName, $searchForFacetValuesRequest = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `searchForFacetValues`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `searchForFacetValues`.'
            );
        }
        // verify the required parameter 'facetName' is set
        if (!isset($facetName)) {
            throw new \InvalidArgumentException(
                'Parameter `facetName` is required when calling `searchForFacetValues`.'
            );
        }
        // verify the required parameter 'facetName' is not empty
        if (isset($facetName) && '' === $facetName) {
            throw new \InvalidArgumentException(
                'Parameter `facetName` is required when calling `searchForFacetValues`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/facets/{facetName}/query';
        $queryParameters = [];
        $headers = [];
        $httpBody = isset($searchForFacetValuesRequest) ? $searchForFacetValuesRequest : [];

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        // path params
        if (null !== $facetName) {
            $resourcePath = str_replace(
                '{facetName}',
                ObjectSerializer::toPathValue($facetName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions, true);
    }

    /**
     * Search for rules (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Searches for rules in your index.
     * Required API Key ACLs:
     *  - settings
     *
     * @param string                  $indexName         Name of the index on which to perform the operation. (required)
     * @param array|SearchRulesParams $searchRulesParams (optional)
     * @param array                   $requestOptions    Request options
     *
     * @return AlgoliaResponse
     */
    public function searchRulesWithHttpInfo($indexName, $searchRulesParams = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `searchRules`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `searchRules`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/rules/search';
        $queryParameters = [];
        $headers = [];
        $httpBody = isset($searchRulesParams) ? $searchRulesParams : [];

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions, true);
    }

    /**
     * Search an index (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Searches a single index and returns matching search results as hits.  This method lets you retrieve up to 1,000 hits. If you need more, use the [`browse` operation](https://www.algolia.com/doc/rest-api/search/browse) or increase the `paginatedLimitedTo` index setting.
     * Required API Key ACLs:
     *  - search
     *
     * @param string             $indexName      Name of the index on which to perform the operation. (required)
     * @param array|SearchParams $searchParams   (optional)
     * @param array              $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function searchSingleIndexWithHttpInfo($indexName, $searchParams = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `searchSingleIndex`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `searchSingleIndex`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/query';
        $queryParameters = [];
        $headers = [];
        $httpBody = isset($searchParams) ? $searchParams : [];

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions, true);
    }

    /**
     * Search for synonyms (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Searches for synonyms in your index.
     * Required API Key ACLs:
     *  - settings
     *
     * @param string                     $indexName            Name of the index on which to perform the operation. (required)
     * @param array|SearchSynonymsParams $searchSynonymsParams Body of the `searchSynonyms` operation. (optional)
     * @param array                      $requestOptions       Request options
     *
     * @return AlgoliaResponse
     */
    public function searchSynonymsWithHttpInfo($indexName, $searchSynonymsParams = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `searchSynonyms`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `searchSynonyms`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/synonyms/search';
        $queryParameters = [];
        $headers = [];
        $httpBody = isset($searchSynonymsParams) ? $searchSynonymsParams : [];

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions, true);
    }

    /**
     * Search for user IDs (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Since it can take a few seconds to get the data from the different clusters, the response isn't real-time.  To ensure rapid updates, the user IDs index isn't built at the same time as the mapping. Instead, it's built every 12 hours, at the same time as the update of user ID usage. For example, if you add or move a user ID, the search will show an old value until the next time the mapping is rebuilt (every 12 hours).
     * Required API Key ACLs:
     *  - admin
     *
     * @param array|SearchUserIdsParams $searchUserIdsParams (required)
     * @param array                     $requestOptions      Request options
     *
     * @return AlgoliaResponse
     */
    public function searchUserIdsWithHttpInfo($searchUserIdsParams, $requestOptions = [])
    {
        // verify the required parameter 'searchUserIdsParams' is set
        if (!isset($searchUserIdsParams)) {
            throw new \InvalidArgumentException(
                'Parameter `searchUserIdsParams` is required when calling `searchUserIds`.'
            );
        }

        $resourcePath = '/1/clusters/mapping/search';
        $queryParameters = [];
        $headers = [];
        $httpBody = $searchUserIdsParams;

        return $this->sendRequestWithHttpInfo('POST', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions, true);
    }

    /**
     * Update dictionary settings (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Turns standard stop word dictionary entries on or off for a given language.
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param array|DictionarySettingsParams $dictionarySettingsParams (required)
     * @param array                          $requestOptions           Request options
     *
     * @return AlgoliaResponse
     */
    public function setDictionarySettingsWithHttpInfo($dictionarySettingsParams, $requestOptions = [])
    {
        // verify the required parameter 'dictionarySettingsParams' is set
        if (!isset($dictionarySettingsParams)) {
            throw new \InvalidArgumentException(
                'Parameter `dictionarySettingsParams` is required when calling `setDictionarySettings`.'
            );
        }

        $resourcePath = '/1/dictionaries/*/settings';
        $queryParameters = [];
        $headers = [];
        $httpBody = $dictionarySettingsParams;

        return $this->sendRequestWithHttpInfo('PUT', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Update index settings (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Update the specified index settings.  Index settings that you don't specify are left unchanged. Specify `null` to reset a setting to its default value.  For best performance, update the index settings before you add new records to your index.
     * Required API Key ACLs:
     *  - editSettings
     *
     * @param string              $indexName         Name of the index on which to perform the operation. (required)
     * @param array|IndexSettings $indexSettings     (required)
     * @param bool                $forwardToReplicas Whether changes are applied to replica indices. (optional)
     * @param array               $requestOptions    Request options
     *
     * @return AlgoliaResponse
     */
    public function setSettingsWithHttpInfo($indexName, $indexSettings, $forwardToReplicas = null, $requestOptions = [])
    {
        // verify the required parameter 'indexName' is set
        if (!isset($indexName)) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `setSettings`.'
            );
        }
        // verify the required parameter 'indexName' is not empty
        if (isset($indexName) && '' === $indexName) {
            throw new \InvalidArgumentException(
                'Parameter `indexName` is required when calling `setSettings`.'
            );
        }
        // verify the required parameter 'indexSettings' is set
        if (!isset($indexSettings)) {
            throw new \InvalidArgumentException(
                'Parameter `indexSettings` is required when calling `setSettings`.'
            );
        }

        $resourcePath = '/1/indexes/{indexName}/settings';
        $queryParameters = [];
        $headers = [];
        $httpBody = $indexSettings;

        if (null !== $forwardToReplicas) {
            $queryParameters['forwardToReplicas'] = $forwardToReplicas;
        }

        // path params
        if (null !== $indexName) {
            $resourcePath = str_replace(
                '{indexName}',
                ObjectSerializer::toPathValue($indexName),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('PUT', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Update an API key (with HTTP info).
     *
     * Returns the response with HTTP metadata (status code, headers, body)
     * Replaces the permissions of an existing API key.  Any unspecified attribute resets that attribute to its default value.
     * Required API Key ACLs:
     *  - admin
     *
     * @param string       $key            API key. (required)
     * @param ApiKey|array $apiKey         (required)
     * @param array        $requestOptions Request options
     *
     * @return AlgoliaResponse
     */
    public function updateApiKeyWithHttpInfo($key, $apiKey, $requestOptions = [])
    {
        // verify the required parameter 'key' is set
        if (!isset($key)) {
            throw new \InvalidArgumentException(
                'Parameter `key` is required when calling `updateApiKey`.'
            );
        }
        // verify the required parameter 'key' is not empty
        if (isset($key) && '' === $key) {
            throw new \InvalidArgumentException(
                'Parameter `key` is required when calling `updateApiKey`.'
            );
        }
        // verify the required parameter 'apiKey' is set
        if (!isset($apiKey)) {
            throw new \InvalidArgumentException(
                'Parameter `apiKey` is required when calling `updateApiKey`.'
            );
        }

        $resourcePath = '/1/keys/{key}';
        $queryParameters = [];
        $headers = [];
        $httpBody = $apiKey;

        // path params
        if (null !== $key) {
            $resourcePath = str_replace(
                '{key}',
                ObjectSerializer::toPathValue($key),
                $resourcePath
            );
        }

        return $this->sendRequestWithHttpInfo('PUT', $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions);
    }

    /**
     * Wait for a task to complete with `indexName` and `taskID`.
     *
     * @param string   $indexName      Index name
     * @param int      $taskId         Task Id
     * @param array    $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     * @param null|int $maxRetries     Maximum number of retries
     * @param null|int $timeout        Timeout
     *
     * @return GetTaskResponse
     *
     * @throws ExceededRetriesException
     */
    public function waitForTask($indexName, $taskId, $requestOptions = [], $maxRetries = null, $timeout = null)
    {
        if (null === $timeout) {
            $timeout = $this->config->getWaitTaskTimeBeforeRetry();
        }

        if (null === $maxRetries) {
            $maxRetries = $this->config->getDefaultMaxRetries();
        }

        return Helpers::retryUntil(
            $this,
            'getTask',
            [$indexName, $taskId, $requestOptions],
            function ($res) {return 'published' === $res['status']; },
            $maxRetries,
            $timeout
        );
    }

    /**
     * Wait for an application-level task to complete with `taskID`.
     *
     * @param int      $taskId         Task Id
     * @param array    $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     * @param null|int $maxRetries     Maximum number of retries
     * @param null|int $timeout        Timeout
     *
     * @return GetTaskResponse
     *
     * @throws ExceededRetriesException
     */
    public function waitForAppTask($taskId, $requestOptions = [], $maxRetries = null, $timeout = null)
    {
        if (null === $timeout) {
            $timeout = $this->config->getWaitTaskTimeBeforeRetry();
        }

        if (null === $maxRetries) {
            $maxRetries = $this->config->getDefaultMaxRetries();
        }

        return Helpers::retryUntil(
            $this,
            'getAppTask',
            [$taskId, $requestOptions],
            function ($res) {return 'published' === $res['status']; },
            $maxRetries,
            $timeout
        );
    }

    /**
     * Wait for an API key to be added, updated or deleted based on a given `operation`.
     *
     * @param string   $key            the `key` that has been added, deleted or updated
     * @param string   $operation      the `operation` that was done on a `key`
     * @param array    $apiKey         necessary to know if an `update` operation has been processed, compare fields of the response with it
     * @param null|int $maxRetries     Maximum number of retries
     * @param null|int $timeout        Timeout
     * @param array    $requestOptions the requestOptions to send along with the query, they will be merged with the transporter requestOptions
     *
     * @throws ExceededRetriesException
     */
    public function waitForApiKey(
        $key,
        $operation,
        $apiKey = null,
        $maxRetries = null,
        $timeout = null,
        $requestOptions = []
    ) {
        if (null === $timeout) {
            $timeout = $this->config->getWaitTaskTimeBeforeRetry();
        }

        if (null === $maxRetries) {
            $maxRetries = $this->config->getDefaultMaxRetries();
        }

        return Helpers::retryForApiKeyUntil(
            $operation,
            $this,
            $key,
            $apiKey,
            $maxRetries,
            $timeout,
            'Algolia\AlgoliaSearch\Support\Helpers::linearTimeout',
            $requestOptions
        );
    }

    /**
     * Helper: Iterate on the `browse` method of the client to allow aggregating objects of an index.
     *
     * @param string $indexName      Index name
     * @param array  $requestOptions Request options
     *
     * @return ObjectIterator
     */
    public function browseObjects($indexName, $requestOptions = [])
    {
        return new ObjectIterator($indexName, $this, $requestOptions);
    }

    /**
     * Helper: Iterate on the `searchRules` method of the client to allow aggregating rules of an index.
     *
     * @param string $indexName      Index name
     * @param array  $requestOptions Request options
     *
     * @return RuleIterator
     */
    public function browseRules($indexName, $requestOptions = [])
    {
        return new RuleIterator($indexName, $this, $requestOptions);
    }

    /**
     * Helper: Iterate on the `searchSynonyms` method of the client to allow aggregating synonyms of an index.
     *
     * @param string $indexName      Index name
     * @param array  $requestOptions Request options
     *
     * @return SynonymIterator
     */
    public function browseSynonyms($indexName, $requestOptions = [])
    {
        return new SynonymIterator($indexName, $this, $requestOptions);
    }

    /**
     * Helper: Similar to the `replaceAllObjects` method but requires a Push connector
     * (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/)
     * to be created first, in order to transform records before indexing them to Algolia.
     * `transformationOptions` must be set on the `SearchConfig` before creating the client,
     * or via `SearchClient::setTransformationOptions()` before calling this method.
     *
     * @see https://www.algolia.com/doc/libraries/sdk/methods/ingestion/
     *
     * Warning: calling this method with an empty `$objects` list replaces the index with an empty one, deleting all existing records.
     *
     * @param string                    $indexName      the `indexName` to replace `objects` in
     * @param array                     $objects        the array of `objects` to store in the given Algolia `indexName`
     * @param array                     $batchSize      The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000.
     * @param array                     $requestOptions Request options
     * @param null|ChunkedHelperOptions $chunkedOptions Optional configuration shared across chunked helpers (e.g. `maxRetries`).
     * @param mixed                     $scopes
     */
    public function replaceAllObjectsWithTransformation($indexName, $objects, $batchSize = 1000, $scopes = ['settings', 'rules', 'synonyms'], $requestOptions = [], ?ChunkedHelperOptions $chunkedOptions = null)
    {
        if (null == $this->ingestionTransporter) {
            throw new \InvalidArgumentException('`transformationOptions` must be set on `SearchConfig` before creating the client, or via `SearchClient::setTransformationOptions(...)` before calling this method. It defaults to the Ingestion API defaults. See https://www.algolia.com/doc/libraries/sdk/methods/ingestion/');
        }

        if (empty($objects)) {
            Algolia::getLogger()->warning("replaceAllObjectsWithTransformation was called with an empty list of objects, which will delete all records currently in the \"{$indexName}\" index.");
        }

        $chunkedOptions ??= new ChunkedHelperOptions(ChunkedHelperOptions::DEFAULT_REPLACE_ALL_OBJECTS_MAX_RETRIES);
        $tmpIndexName = $indexName.'_tmp_'.rand(10000000, 99999999);

        try {
            $copyOperationResponse = $this->operationIndex(
                $indexName,
                [
                    'operation' => 'copy',
                    'destination' => $tmpIndexName,
                    'scope' => $scopes,
                ],
                $requestOptions
            );

            $watchResponses = $this->ingestionTransporter->chunkedPush($tmpIndexName, $objects, 'addObject', true, $batchSize, $indexName, $requestOptions, $chunkedOptions);

            $this->waitForTask($tmpIndexName, $copyOperationResponse['taskID'], [], $chunkedOptions?->maxRetries);

            $copyOperationResponse = $this->operationIndex(
                $indexName,
                [
                    'operation' => 'copy',
                    'destination' => $tmpIndexName,
                    'scope' => $scopes,
                ],
                $requestOptions
            );

            $this->waitForTask($tmpIndexName, $copyOperationResponse['taskID'], [], $chunkedOptions?->maxRetries);

            $moveOperationResponse = $this->operationIndex(
                $tmpIndexName,
                [
                    'operation' => 'move',
                    'destination' => $indexName,
                ],
                $requestOptions
            );

            $this->waitForTask($tmpIndexName, $moveOperationResponse['taskID'], [], $chunkedOptions?->maxRetries);

            return [
                'copyOperationResponse' => $copyOperationResponse,
                'watchResponses' => $watchResponses,
                'moveOperationResponse' => $moveOperationResponse,
            ];
        } catch (\Throwable $e) {
            $this->deleteIndex($tmpIndexName);

            throw $e;
        }
    }

    /**
     * Helper: Replace all objects in an index using a temporary one.
     * See https://api-clients-automation.netlify.app/docs/custom-helpers/#replaceallobjects for implementation details.
     *
     * Warning: calling this method with an empty `$objects` list replaces the index with an empty one, deleting all existing records.
     *
     * @param string                    $indexName      the `indexName` to replace `objects` in
     * @param array                     $objects        the array of `objects` to store in the given Algolia `indexName`
     * @param array                     $batchSize      The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000.
     * @param array                     $requestOptions Request options
     * @param null|ChunkedHelperOptions $chunkedOptions Optional configuration shared across chunked helpers (e.g. `maxRetries`).
     * @param mixed                     $scopes
     */
    public function replaceAllObjects($indexName, $objects, $batchSize = 1000, $scopes = ['settings', 'rules', 'synonyms'], $requestOptions = [], ?ChunkedHelperOptions $chunkedOptions = null)
    {
        if (empty($objects)) {
            Algolia::getLogger()->warning("replaceAllObjects was called with an empty list of objects, which will delete all records currently in the \"{$indexName}\" index.");
        }

        $chunkedOptions ??= new ChunkedHelperOptions(ChunkedHelperOptions::DEFAULT_REPLACE_ALL_OBJECTS_MAX_RETRIES);
        $tmpIndexName = $indexName.'_tmp_'.rand(10000000, 99999999);

        try {
            $copyOperationResponse = $this->operationIndex(
                $indexName,
                [
                    'operation' => 'copy',
                    'destination' => $tmpIndexName,
                    'scope' => $scopes,
                ],
                $requestOptions
            );

            $batchResponses = $this->chunkedBatch($tmpIndexName, $objects, 'addObject', true, $batchSize, $requestOptions, $chunkedOptions);

            $this->waitForTask($tmpIndexName, $copyOperationResponse['taskID'], [], $chunkedOptions?->maxRetries);

            $copyOperationResponse = $this->operationIndex(
                $indexName,
                [
                    'operation' => 'copy',
                    'destination' => $tmpIndexName,
                    'scope' => $scopes,
                ],
                $requestOptions
            );

            $this->waitForTask($tmpIndexName, $copyOperationResponse['taskID'], [], $chunkedOptions?->maxRetries);

            $moveOperationResponse = $this->operationIndex(
                $tmpIndexName,
                [
                    'operation' => 'move',
                    'destination' => $indexName,
                ],
                $requestOptions
            );

            $this->waitForTask($tmpIndexName, $moveOperationResponse['taskID'], [], $chunkedOptions?->maxRetries);

            return [
                'copyOperationResponse' => $copyOperationResponse,
                'batchResponses' => $batchResponses,
                'moveOperationResponse' => $moveOperationResponse,
            ];
        } catch (\Throwable $e) {
            $this->deleteIndex($tmpIndexName);

            throw $e;
        }
    }

    /**
     * Helper: Saves the given array of objects in the given index. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objects in it.
     *
     * @param string                    $indexName      the `indexName` to replace `objects` in
     * @param array                     $objects        the array of `objects` to store in the given Algolia `indexName`
     * @param bool                      $waitForTasks   Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable
     * @param int                       $batchSize      The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000.
     * @param array                     $requestOptions Request options
     * @param null|ChunkedHelperOptions $chunkedOptions Optional configuration shared across chunked helpers (e.g. `maxRetries`).
     */
    public function saveObjects($indexName, $objects, $waitForTasks = false, $batchSize = 1000, $requestOptions = [], ?ChunkedHelperOptions $chunkedOptions = null)
    {
        return $this->chunkedBatch($indexName, $objects, 'addObject', $waitForTasks, $batchSize, $requestOptions, $chunkedOptions);
    }

    /**
     * Helper: Similar to the `saveObjects` method but requires a Push connector
     * (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/)
     * to be created first, in order to transform records before indexing them to Algolia.
     * `transformationOptions` must be set on the `SearchConfig` before creating the client,
     * or via `SearchClient::setTransformationOptions()` before calling this method.
     *
     * @see https://www.algolia.com/doc/libraries/sdk/methods/ingestion/
     *
     * @param string                    $indexName      the `indexName` to replace `objects` in
     * @param array                     $objects        the array of `objects` to store in the given Algolia `indexName`
     * @param bool                      $waitForTasks   Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable
     * @param int                       $batchSize      The size of the chunk of `objects`. The number of `push` calls will be equal to `length(objects) / batchSize`. Defaults to 1000.
     * @param array                     $requestOptions Request options
     * @param null|ChunkedHelperOptions $chunkedOptions Optional configuration shared across chunked helpers (e.g. `maxRetries`).
     */
    public function saveObjectsWithTransformation($indexName, $objects, $waitForTasks = false, $batchSize = 1000, $requestOptions = [], ?ChunkedHelperOptions $chunkedOptions = null)
    {
        if (null == $this->ingestionTransporter) {
            throw new \InvalidArgumentException('`transformationOptions` must be set on `SearchConfig` before creating the client, or via `SearchClient::setTransformationOptions(...)` before calling this method. It defaults to the Ingestion API defaults. See https://www.algolia.com/doc/libraries/sdk/methods/ingestion/');
        }

        return $this->ingestionTransporter->chunkedPush($indexName, $objects, 'addObject', $waitForTasks, $batchSize, null, $requestOptions, $chunkedOptions);
    }

    /**
     * Helper: Deletes every records for the given objectIDs. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objectIDs in it.
     *
     * @param string                    $indexName      the `indexName` to delete `objectIDs` from
     * @param array                     $objectIDs      the `objectIDs` to delete
     * @param bool                      $waitForTasks   Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable
     * @param int                       $batchSize      The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000.
     * @param array                     $requestOptions Request options
     * @param null|ChunkedHelperOptions $chunkedOptions Optional configuration shared across chunked helpers (e.g. `maxRetries`).
     */
    public function deleteObjects($indexName, $objectIDs, $waitForTasks = false, $batchSize = 1000, $requestOptions = [], ?ChunkedHelperOptions $chunkedOptions = null)
    {
        $objects = [];

        foreach ($objectIDs as $id) {
            $objects[] = ['objectID' => $id];
        }

        return $this->chunkedBatch($indexName, $objects, 'deleteObject', $waitForTasks, $batchSize, $requestOptions, $chunkedOptions);
    }

    /**
     * Helper: Replaces object content of all the given objects according to their respective `objectID` field. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objects in it.
     *
     * @param string                    $indexName         the `indexName` to replace `objects` in
     * @param array                     $objects           the array of `objects` to store in the given Algolia `indexName`
     * @param bool                      $createIfNotExists to be provided if non-existing objects are passed, otherwise, the call will fail
     * @param bool                      $waitForTasks      Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable
     * @param int                       $batchSize         The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000.
     * @param array                     $requestOptions    Request options
     * @param null|ChunkedHelperOptions $chunkedOptions    Optional configuration shared across chunked helpers (e.g. `maxRetries`).
     */
    public function partialUpdateObjects($indexName, $objects, $createIfNotExists, $waitForTasks = false, $batchSize = 1000, $requestOptions = [], ?ChunkedHelperOptions $chunkedOptions = null)
    {
        return $this->chunkedBatch($indexName, $objects, (true == $createIfNotExists) ? 'partialUpdateObject' : 'partialUpdateObjectNoCreate', $waitForTasks, $batchSize, $requestOptions, $chunkedOptions);
    }

    /**
     * Helper: Similar to the `partialUpdateObjects` method but requires a Push connector
     * (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/)
     * to be created first, in order to transform records before indexing them to Algolia.
     * `transformationOptions` must be set on the `SearchConfig` before creating the client,
     * or via `SearchClient::setTransformationOptions()` before calling this method.
     *
     * @see https://www.algolia.com/doc/libraries/sdk/methods/ingestion/
     *
     * @param string                    $indexName         the `indexName` to replace `objects` in
     * @param array                     $objects           the array of `objects` to store in the given Algolia `indexName`
     * @param bool                      $createIfNotExists to be provided if non-existing objects are passed, otherwise, the call will fail
     * @param bool                      $waitForTasks      Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable
     * @param int                       $batchSize         The size of the chunk of `objects`. The number of `push` calls will be equal to `length(objects) / batchSize`. Defaults to 1000.
     * @param array                     $requestOptions    Request options
     * @param null|ChunkedHelperOptions $chunkedOptions    Optional configuration shared across chunked helpers (e.g. `maxRetries`).
     */
    public function partialUpdateObjectsWithTransformation($indexName, $objects, $createIfNotExists, $waitForTasks = false, $batchSize = 1000, $requestOptions = [], ?ChunkedHelperOptions $chunkedOptions = null)
    {
        if (null == $this->ingestionTransporter) {
            throw new \InvalidArgumentException('`transformationOptions` must be set on `SearchConfig` before creating the client, or via `SearchClient::setTransformationOptions(...)` before calling this method. It defaults to the Ingestion API defaults. See https://www.algolia.com/doc/libraries/sdk/methods/ingestion/');
        }

        return $this->ingestionTransporter->chunkedPush($indexName, $objects, (true == $createIfNotExists) ? 'partialUpdateObject' : 'partialUpdateObjectNoCreate', $waitForTasks, $batchSize, null, $requestOptions, $chunkedOptions);
    }

    /**
     * Helper: Chunks the given `objects` list in subset of 1000 elements max in order to make it fit in `batch` requests.
     *
     * @param string                    $indexName      the `indexName` to replace `objects` in
     * @param array                     $objects        the array of `objects` to store in the given Algolia `indexName`
     * @param array                     $action         the `batch` `action` to perform on the given array of `objects`, defaults to `addObject`
     * @param bool                      $waitForTasks   whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable
     * @param int                       $batchSize      The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000.
     * @param array                     $requestOptions Request options
     * @param null|ChunkedHelperOptions $chunkedOptions Optional configuration shared across chunked helpers (e.g. `maxRetries`).
     */
    public function chunkedBatch(
        $indexName,
        $objects,
        $action = 'addObject',
        $waitForTasks = true,
        $batchSize = 1000,
        $requestOptions = [],
        ?ChunkedHelperOptions $chunkedOptions = null
    ) {
        $responses = [];
        $requests = [];
        $count = 0;

        $logger = Algolia::getLogger();
        $totalObjects = count($objects);
        $startTime = microtime(true);
        $logger->info('Algolia API client: Batch operation started: '.$action.' on '.$indexName);

        foreach ($objects as $object) {
            $requests[] = [
                'action' => $action,
                'body' => $object,
            ];

            ++$count;

            if (sizeof($requests) === $batchSize || $count === sizeof($objects)) {
                $responses[] = $this->batch($indexName, ['requests' => $requests], $requestOptions);
                $requests = [];

                $logger->info('Algolia API client: Batch progress: '.min($count, $totalObjects).'/'.$totalObjects.' objects processed');
            }
        }

        if (!empty($requests)) {
            $responses[] = $this->batch($indexName, ['requests' => $requests], $requestOptions);
            $logger->info('Algolia API client: Batch progress: '.$totalObjects.'/'.$totalObjects.' objects processed');
        }

        if ($waitForTasks && !empty($responses)) {
            foreach ($responses as $response) {
                $this->waitForTask($indexName, $response['taskID'], [], $chunkedOptions?->maxRetries);
            }
        }

        $durationMs = round((microtime(true) - $startTime) * 1000);
        $logger->info('Algolia API client: Batch operation completed: '.$totalObjects.' objects in '.$durationMs.'ms');

        return $responses;
    }

    /**
     * Helper: Generate a secured API Key.
     *
     * @param string $parentApiKey Parent API Key
     * @param array  $restrictions API Key's restrictions
     *
     * @return string
     */
    public static function generateSecuredApiKey($parentApiKey, $restrictions)
    {
        $formattedRestrictions = $restrictions;
        if (isset($restrictions['searchParams'])) {
            $formattedRestrictions = array_merge($restrictions, $restrictions['searchParams']);
            unset($formattedRestrictions['searchParams']);
        }

        ksort($formattedRestrictions);
        $urlEncodedRestrictions = Helpers::buildQuery($formattedRestrictions);

        $content = hash_hmac('sha256', $urlEncodedRestrictions, $parentApiKey).$urlEncodedRestrictions;

        return base64_encode($content);
    }

    /**
     * Helper: Returns the time the given securedApiKey remains valid in seconds.
     *
     * @param string $securedApiKey the key to check
     *
     * @return int remaining validity in seconds
     *
     * @throws ValidUntilNotFoundException
     */
    public static function getSecuredApiKeyRemainingValidity($securedApiKey)
    {
        $decodedKey = base64_decode($securedApiKey);
        $regex = '/validUntil=(\d+)/';
        preg_match($regex, $decodedKey, $matches);

        if (0 === count($matches)) {
            throw new ValidUntilNotFoundException('validUntil not found in given secured api key.');
        }

        $validUntil = (int) $matches[1];

        return $validUntil - time();
    }

    public function indexExists($indexName)
    {
        try {
            $this->getSettings($indexName);
        } catch (NotFoundException $e) {
            return false;
        } catch (\Throwable $e) {
            throw $e;
        }

        return true;
    }

    /**
     * Builds an ingestion transporter from a `TransformationOptions`, using the Ingestion API
     * defaults and overriding only the fields explicitly set on `$transformationOptions`.
     *
     * @return IngestionClient
     */
    private static function buildIngestionTransporter(SearchConfig $config, TransformationOptions $transformationOptions)
    {
        $ingestionConfig = IngestionConfig::create(
            $config->getAppId(),
            $config->getAlgoliaApiKey(),
            $transformationOptions->getRegion()
        );

        if (null !== ($hosts = $transformationOptions->getHosts())) {
            if ($transformationOptions->getHasFullHosts()) {
                $ingestionConfig->setFullHosts($hosts);
            } else {
                $ingestionConfig->setHosts($hosts);
            }
        }
        if (null !== ($readTimeout = $transformationOptions->getReadTimeout())) {
            $ingestionConfig->setReadTimeout($readTimeout);
        }
        if (null !== ($writeTimeout = $transformationOptions->getWriteTimeout())) {
            $ingestionConfig->setWriteTimeout($writeTimeout);
        }
        if (null !== ($connectTimeout = $transformationOptions->getConnectTimeout())) {
            $ingestionConfig->setConnectTimeout($connectTimeout);
        }
        if (null !== ($waitTaskTimeBeforeRetry = $transformationOptions->getWaitTaskTimeBeforeRetry())) {
            $ingestionConfig->setWaitTaskTimeBeforeRetry($waitTaskTimeBeforeRetry);
        }
        if (null !== ($defaultHeaders = $transformationOptions->getDefaultHeaders())) {
            $ingestionConfig->setDefaultHeaders($defaultHeaders);
        }
        if (null !== ($compressionType = $transformationOptions->getCompressionType())) {
            $ingestionConfig->setCompressionType($compressionType);
        }

        return IngestionClient::createWithConfig($ingestionConfig);
    }

    private function sendRequestWithHttpInfo($method, $resourcePath, $headers, $queryParameters, $httpBody, $requestOptions, $useReadTransporter = false)
    {
        if (!isset($requestOptions['headers'])) {
            $requestOptions['headers'] = [];
        }
        if (!isset($requestOptions['queryParameters'])) {
            $requestOptions['queryParameters'] = [];
        }

        $requestOptions['headers'] = array_merge($headers, $requestOptions['headers']);
        $requestOptions['queryParameters'] = array_merge($queryParameters, $requestOptions['queryParameters']);
        $query = Query::build($requestOptions['queryParameters']);

        return $this->api->sendRequest(
            $method,
            $resourcePath.($query ? "?{$query}" : ''),
            $httpBody,
            $requestOptions,
            $useReadTransporter,
            true
        );
    }
}
