<?php
/**
 * DealsApi
 * PHP version 7.3
 *
 * @category Class
 * @package  Pipedrive
 * @author   OpenAPI Generator team
 * @link     https://openapi-generator.tech
 */

/**
 * Pipedrive API v1
 *
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 *
 * The version of the OpenAPI document: 1.0.0
 * Generated by: https://openapi-generator.tech
 * OpenAPI Generator version: 5.3.0
 */

/**
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

namespace Pipedrive\Api;

use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Psr7\MultipartStream;
use GuzzleHttp\Psr7\Query;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\RequestOptions;
use GuzzleHttp\Utils;
use InvalidArgumentException;
use Pipedrive\ApiException;
use Pipedrive\Configuration;
use Pipedrive\Exceptions\OAuthProviderException;
use Pipedrive\HeaderSelector;
use Pipedrive\ObjectSerializer;
use RuntimeException;

/**
 * DealsApi Class Doc Comment
 *
 * @category Class
 * @package  Pipedrive
 * @author   OpenAPI Generator team
 * @link     https://openapi-generator.tech
 */
class DealsApi
{
    /**
     * @var ClientInterface
     */
    protected $client;

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

    /**
     * @var HeaderSelector
     */
    protected $headerSelector;

    /**
     * @var int Host index
     */
    protected $hostIndex;

    /**
     * @param ClientInterface|null $client
     * @param Configuration|null   $config
     * @param HeaderSelector|null  $selector
     * @param int                  $hostIndex (Optional) host index to select the list of hosts if defined in the OpenAPI spec
     */
    public function __construct(
        ClientInterface $client = null,
        Configuration $config = null,
        HeaderSelector $selector = null,
        int $hostIndex = 0
    ) {
        $this->client = $client ?: new Client();
        $this->config = $config ?: new Configuration();
        $this->headerSelector = $selector ?: new HeaderSelector();
        $this->hostIndex = $hostIndex;
    }

    /**
     * Set the host index
     *
     * @param int $hostIndex Host index (required)
     */
    public function setHostIndex(int $hostIndex): void
    {
        $this->hostIndex = $hostIndex;
    }

    /**
     * Get the host index
     *
     * @return int Host index
     */
    public function getHostIndex(): int
    {
        return $this->hostIndex;
    }

    /**
     * @return Configuration
     */
    public function getConfig(): Configuration
    {
        return $this->config;
    }

    /**
     * Operation addDeal
     *
     * Add a deal
     *
     * @param  \Pipedrive\Model\NewDeal|null $new_deal new_deal (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetAddedDeal
     */
    public function addDeal($new_deal = null)
    {
        list($response) = $this->addDealWithHttpInfo($new_deal);
        return $response;
    }

    /**
     * Operation addDealWithHttpInfo
     *
     * Add a deal
     *
     * @param  \Pipedrive\Model\NewDeal|null $new_deal (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetAddedDeal, HTTP status code, HTTP response headers (array of strings)
     */
    public function addDealWithHttpInfo($new_deal = null)
    {
        $request = $this->addDealRequest($new_deal);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->addDealRequest($new_deal);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 201:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\GetAddedDeal' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetAddedDeal', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\GetAddedDeal' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetAddedDeal', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 201:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\GetAddedDeal',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation addDealAsync
     *
     * Add a deal
     *
     * @param  \Pipedrive\Model\NewDeal|null $new_deal (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addDealAsync($new_deal = null): PromiseInterface
    {
        return $this->addDealAsyncWithHttpInfo($new_deal)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation addDealAsyncWithHttpInfo
     *
     * Add a deal
     *
     * @param  \Pipedrive\Model\NewDeal|null $new_deal (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addDealAsyncWithHttpInfo($new_deal = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetAddedDeal';
        $request = $this->addDealRequest($new_deal);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'addDeal'
     *
     * @param  \Pipedrive\Model\NewDeal|null $new_deal (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function addDealRequest($new_deal = null): Request
    {

        $resourcePath = '/deals';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;





        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }

        // for model (json/xml)
        if (isset($new_deal)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode(ObjectSerializer::sanitizeForSerialization($new_deal));
            } else {
                $httpBody = $new_deal;
            }
        } elseif (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'POST',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation addDealFollower
     *
     * Add a follower to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\AddDealFollowerRequest|null $add_deal_follower_request add_deal_follower_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\AddedDealFollower
     */
    public function addDealFollower($id, $add_deal_follower_request = null)
    {
        list($response) = $this->addDealFollowerWithHttpInfo($id, $add_deal_follower_request);
        return $response;
    }

    /**
     * Operation addDealFollowerWithHttpInfo
     *
     * Add a follower to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\AddDealFollowerRequest|null $add_deal_follower_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\AddedDealFollower, HTTP status code, HTTP response headers (array of strings)
     */
    public function addDealFollowerWithHttpInfo($id, $add_deal_follower_request = null)
    {
        $request = $this->addDealFollowerRequest($id, $add_deal_follower_request);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->addDealFollowerRequest($id, $add_deal_follower_request);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\AddedDealFollower' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\AddedDealFollower', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\AddedDealFollower' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\AddedDealFollower', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\AddedDealFollower',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation addDealFollowerAsync
     *
     * Add a follower to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\AddDealFollowerRequest|null $add_deal_follower_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addDealFollowerAsync($id, $add_deal_follower_request = null): PromiseInterface
    {
        return $this->addDealFollowerAsyncWithHttpInfo($id, $add_deal_follower_request)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation addDealFollowerAsyncWithHttpInfo
     *
     * Add a follower to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\AddDealFollowerRequest|null $add_deal_follower_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addDealFollowerAsyncWithHttpInfo($id, $add_deal_follower_request = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\AddedDealFollower';
        $request = $this->addDealFollowerRequest($id, $add_deal_follower_request);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'addDealFollower'
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\AddDealFollowerRequest|null $add_deal_follower_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function addDealFollowerRequest($id, $add_deal_follower_request = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling addDealFollower'
            );
        }

        $resourcePath = '/deals/{id}/followers';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }

        // for model (json/xml)
        if (isset($add_deal_follower_request)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode(ObjectSerializer::sanitizeForSerialization($add_deal_follower_request));
            } else {
                $httpBody = $add_deal_follower_request;
            }
        } elseif (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'POST',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation addDealParticipant
     *
     * Add a participant to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\AddDealParticipantRequest|null $add_deal_participant_request add_deal_participant_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\PostDealParticipants
     */
    public function addDealParticipant($id, $add_deal_participant_request = null)
    {
        list($response) = $this->addDealParticipantWithHttpInfo($id, $add_deal_participant_request);
        return $response;
    }

    /**
     * Operation addDealParticipantWithHttpInfo
     *
     * Add a participant to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\AddDealParticipantRequest|null $add_deal_participant_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\PostDealParticipants, HTTP status code, HTTP response headers (array of strings)
     */
    public function addDealParticipantWithHttpInfo($id, $add_deal_participant_request = null)
    {
        $request = $this->addDealParticipantRequest($id, $add_deal_participant_request);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->addDealParticipantRequest($id, $add_deal_participant_request);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\PostDealParticipants' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\PostDealParticipants', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\PostDealParticipants' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\PostDealParticipants', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\PostDealParticipants',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation addDealParticipantAsync
     *
     * Add a participant to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\AddDealParticipantRequest|null $add_deal_participant_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addDealParticipantAsync($id, $add_deal_participant_request = null): PromiseInterface
    {
        return $this->addDealParticipantAsyncWithHttpInfo($id, $add_deal_participant_request)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation addDealParticipantAsyncWithHttpInfo
     *
     * Add a participant to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\AddDealParticipantRequest|null $add_deal_participant_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addDealParticipantAsyncWithHttpInfo($id, $add_deal_participant_request = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\PostDealParticipants';
        $request = $this->addDealParticipantRequest($id, $add_deal_participant_request);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'addDealParticipant'
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\AddDealParticipantRequest|null $add_deal_participant_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function addDealParticipantRequest($id, $add_deal_participant_request = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling addDealParticipant'
            );
        }

        $resourcePath = '/deals/{id}/participants';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }

        // for model (json/xml)
        if (isset($add_deal_participant_request)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode(ObjectSerializer::sanitizeForSerialization($add_deal_participant_request));
            } else {
                $httpBody = $add_deal_participant_request;
            }
        } elseif (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'POST',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation addDealProduct
     *
     * Add a product to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\NewDealProduct|null $new_deal_product new_deal_product (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetAddProductAttachmentDetails
     */
    public function addDealProduct($id, $new_deal_product = null)
    {
        list($response) = $this->addDealProductWithHttpInfo($id, $new_deal_product);
        return $response;
    }

    /**
     * Operation addDealProductWithHttpInfo
     *
     * Add a product to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\NewDealProduct|null $new_deal_product (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetAddProductAttachmentDetails, HTTP status code, HTTP response headers (array of strings)
     */
    public function addDealProductWithHttpInfo($id, $new_deal_product = null)
    {
        $request = $this->addDealProductRequest($id, $new_deal_product);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->addDealProductRequest($id, $new_deal_product);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\GetAddProductAttachmentDetails' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetAddProductAttachmentDetails', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\GetAddProductAttachmentDetails' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetAddProductAttachmentDetails', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\GetAddProductAttachmentDetails',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation addDealProductAsync
     *
     * Add a product to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\NewDealProduct|null $new_deal_product (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addDealProductAsync($id, $new_deal_product = null): PromiseInterface
    {
        return $this->addDealProductAsyncWithHttpInfo($id, $new_deal_product)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation addDealProductAsyncWithHttpInfo
     *
     * Add a product to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\NewDealProduct|null $new_deal_product (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addDealProductAsyncWithHttpInfo($id, $new_deal_product = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetAddProductAttachmentDetails';
        $request = $this->addDealProductRequest($id, $new_deal_product);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'addDealProduct'
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\NewDealProduct|null $new_deal_product (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function addDealProductRequest($id, $new_deal_product = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling addDealProduct'
            );
        }

        $resourcePath = '/deals/{id}/products';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }

        // for model (json/xml)
        if (isset($new_deal_product)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode(ObjectSerializer::sanitizeForSerialization($new_deal_product));
            } else {
                $httpBody = $new_deal_product;
            }
        } elseif (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'POST',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation deleteDeal
     *
     * Delete a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DeleteDeal
     */
    public function deleteDeal($id)
    {
        list($response) = $this->deleteDealWithHttpInfo($id);
        return $response;
    }

    /**
     * Operation deleteDealWithHttpInfo
     *
     * Delete a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\DeleteDeal, HTTP status code, HTTP response headers (array of strings)
     */
    public function deleteDealWithHttpInfo($id)
    {
        $request = $this->deleteDealRequest($id);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->deleteDealRequest($id);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\DeleteDeal' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeleteDeal', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\DeleteDeal' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeleteDeal', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\DeleteDeal',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation deleteDealAsync
     *
     * Delete a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deleteDealAsync($id): PromiseInterface
    {
        return $this->deleteDealAsyncWithHttpInfo($id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation deleteDealAsyncWithHttpInfo
     *
     * Delete a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deleteDealAsyncWithHttpInfo($id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DeleteDeal';
        $request = $this->deleteDealRequest($id);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'deleteDeal'
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function deleteDealRequest($id): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling deleteDeal'
            );
        }

        $resourcePath = '/deals/{id}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'DELETE',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation deleteDealFollower
     *
     * Delete a follower from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $follower_id The ID of the follower (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DeleteDealFollower
     */
    public function deleteDealFollower($id, $follower_id)
    {
        list($response) = $this->deleteDealFollowerWithHttpInfo($id, $follower_id);
        return $response;
    }

    /**
     * Operation deleteDealFollowerWithHttpInfo
     *
     * Delete a follower from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $follower_id The ID of the follower (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\DeleteDealFollower, HTTP status code, HTTP response headers (array of strings)
     */
    public function deleteDealFollowerWithHttpInfo($id, $follower_id)
    {
        $request = $this->deleteDealFollowerRequest($id, $follower_id);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->deleteDealFollowerRequest($id, $follower_id);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\DeleteDealFollower' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeleteDealFollower', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\DeleteDealFollower' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeleteDealFollower', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\DeleteDealFollower',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation deleteDealFollowerAsync
     *
     * Delete a follower from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $follower_id The ID of the follower (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deleteDealFollowerAsync($id, $follower_id): PromiseInterface
    {
        return $this->deleteDealFollowerAsyncWithHttpInfo($id, $follower_id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation deleteDealFollowerAsyncWithHttpInfo
     *
     * Delete a follower from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $follower_id The ID of the follower (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deleteDealFollowerAsyncWithHttpInfo($id, $follower_id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DeleteDealFollower';
        $request = $this->deleteDealFollowerRequest($id, $follower_id);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'deleteDealFollower'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $follower_id The ID of the follower (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function deleteDealFollowerRequest($id, $follower_id): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling deleteDealFollower'
            );
        }
        // verify the required parameter 'follower_id' is set
        /* @phpstan-ignore-next-line */
        if ($follower_id === null || (is_array($follower_id) && count($follower_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $follower_id when calling deleteDealFollower'
            );
        }

        $resourcePath = '/deals/{id}/followers/{follower_id}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'DELETE',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation deleteDealParticipant
     *
     * Delete a participant from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $deal_participant_id The ID of the participant of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DeleteDealParticipant
     */
    public function deleteDealParticipant($id, $deal_participant_id)
    {
        list($response) = $this->deleteDealParticipantWithHttpInfo($id, $deal_participant_id);
        return $response;
    }

    /**
     * Operation deleteDealParticipantWithHttpInfo
     *
     * Delete a participant from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $deal_participant_id The ID of the participant of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\DeleteDealParticipant, HTTP status code, HTTP response headers (array of strings)
     */
    public function deleteDealParticipantWithHttpInfo($id, $deal_participant_id)
    {
        $request = $this->deleteDealParticipantRequest($id, $deal_participant_id);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->deleteDealParticipantRequest($id, $deal_participant_id);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\DeleteDealParticipant' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeleteDealParticipant', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\DeleteDealParticipant' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeleteDealParticipant', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\DeleteDealParticipant',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation deleteDealParticipantAsync
     *
     * Delete a participant from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $deal_participant_id The ID of the participant of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deleteDealParticipantAsync($id, $deal_participant_id): PromiseInterface
    {
        return $this->deleteDealParticipantAsyncWithHttpInfo($id, $deal_participant_id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation deleteDealParticipantAsyncWithHttpInfo
     *
     * Delete a participant from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $deal_participant_id The ID of the participant of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deleteDealParticipantAsyncWithHttpInfo($id, $deal_participant_id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DeleteDealParticipant';
        $request = $this->deleteDealParticipantRequest($id, $deal_participant_id);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'deleteDealParticipant'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $deal_participant_id The ID of the participant of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function deleteDealParticipantRequest($id, $deal_participant_id): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling deleteDealParticipant'
            );
        }
        // verify the required parameter 'deal_participant_id' is set
        /* @phpstan-ignore-next-line */
        if ($deal_participant_id === null || (is_array($deal_participant_id) && count($deal_participant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $deal_participant_id when calling deleteDealParticipant'
            );
        }

        $resourcePath = '/deals/{id}/participants/{deal_participant_id}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'DELETE',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation deleteDealProduct
     *
     * Delete an attached product from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $product_attachment_id The product attachment ID (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DeleteDealProduct
     */
    public function deleteDealProduct($id, $product_attachment_id)
    {
        list($response) = $this->deleteDealProductWithHttpInfo($id, $product_attachment_id);
        return $response;
    }

    /**
     * Operation deleteDealProductWithHttpInfo
     *
     * Delete an attached product from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $product_attachment_id The product attachment ID (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\DeleteDealProduct, HTTP status code, HTTP response headers (array of strings)
     */
    public function deleteDealProductWithHttpInfo($id, $product_attachment_id)
    {
        $request = $this->deleteDealProductRequest($id, $product_attachment_id);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->deleteDealProductRequest($id, $product_attachment_id);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\DeleteDealProduct' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeleteDealProduct', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\DeleteDealProduct' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeleteDealProduct', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\DeleteDealProduct',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation deleteDealProductAsync
     *
     * Delete an attached product from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $product_attachment_id The product attachment ID (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deleteDealProductAsync($id, $product_attachment_id): PromiseInterface
    {
        return $this->deleteDealProductAsyncWithHttpInfo($id, $product_attachment_id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation deleteDealProductAsyncWithHttpInfo
     *
     * Delete an attached product from a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $product_attachment_id The product attachment ID (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deleteDealProductAsyncWithHttpInfo($id, $product_attachment_id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DeleteDealProduct';
        $request = $this->deleteDealProductRequest($id, $product_attachment_id);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'deleteDealProduct'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $product_attachment_id The product attachment ID (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function deleteDealProductRequest($id, $product_attachment_id): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling deleteDealProduct'
            );
        }
        // verify the required parameter 'product_attachment_id' is set
        /* @phpstan-ignore-next-line */
        if ($product_attachment_id === null || (is_array($product_attachment_id) && count($product_attachment_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $product_attachment_id when calling deleteDealProduct'
            );
        }

        $resourcePath = '/deals/{id}/products/{product_attachment_id}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'DELETE',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation deleteDeals
     *
     * Delete multiple deals in bulk
     *
     * @param  string $ids The comma-separated IDs that will be deleted (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DeleteMultipleDeals
     */
    public function deleteDeals($ids)
    {
        list($response) = $this->deleteDealsWithHttpInfo($ids);
        return $response;
    }

    /**
     * Operation deleteDealsWithHttpInfo
     *
     * Delete multiple deals in bulk
     *
     * @param  string $ids The comma-separated IDs that will be deleted (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\DeleteMultipleDeals, HTTP status code, HTTP response headers (array of strings)
     */
    public function deleteDealsWithHttpInfo($ids)
    {
        $request = $this->deleteDealsRequest($ids);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->deleteDealsRequest($ids);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\DeleteMultipleDeals' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeleteMultipleDeals', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\DeleteMultipleDeals' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeleteMultipleDeals', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\DeleteMultipleDeals',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation deleteDealsAsync
     *
     * Delete multiple deals in bulk
     *
     * @param  string $ids The comma-separated IDs that will be deleted (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deleteDealsAsync($ids): PromiseInterface
    {
        return $this->deleteDealsAsyncWithHttpInfo($ids)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation deleteDealsAsyncWithHttpInfo
     *
     * Delete multiple deals in bulk
     *
     * @param  string $ids The comma-separated IDs that will be deleted (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deleteDealsAsyncWithHttpInfo($ids): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DeleteMultipleDeals';
        $request = $this->deleteDealsRequest($ids);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'deleteDeals'
     *
     * @param  string $ids The comma-separated IDs that will be deleted (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function deleteDealsRequest($ids): Request
    {
        // verify the required parameter 'ids' is set
        /* @phpstan-ignore-next-line */
        if ($ids === null || (is_array($ids) && count($ids) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $ids when calling deleteDeals'
            );
        }

        $resourcePath = '/deals';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($ids)) {
            $ids = ObjectSerializer::serializeCollection($ids, '', true);
        }
        if ($ids !== null) {
            $queryParams['ids'] = $ids;
        }




        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'DELETE',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation duplicateDeal
     *
     * Duplicate deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetDuplicatedDeal
     */
    public function duplicateDeal($id)
    {
        list($response) = $this->duplicateDealWithHttpInfo($id);
        return $response;
    }

    /**
     * Operation duplicateDealWithHttpInfo
     *
     * Duplicate deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetDuplicatedDeal, HTTP status code, HTTP response headers (array of strings)
     */
    public function duplicateDealWithHttpInfo($id)
    {
        $request = $this->duplicateDealRequest($id);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->duplicateDealRequest($id);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\GetDuplicatedDeal' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDuplicatedDeal', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\GetDuplicatedDeal' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDuplicatedDeal', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\GetDuplicatedDeal',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation duplicateDealAsync
     *
     * Duplicate deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function duplicateDealAsync($id): PromiseInterface
    {
        return $this->duplicateDealAsyncWithHttpInfo($id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation duplicateDealAsyncWithHttpInfo
     *
     * Duplicate deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function duplicateDealAsyncWithHttpInfo($id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetDuplicatedDeal';
        $request = $this->duplicateDealRequest($id);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'duplicateDeal'
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function duplicateDealRequest($id): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling duplicateDeal'
            );
        }

        $resourcePath = '/deals/{id}/duplicate';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'POST',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDeal
     *
     * Get details of a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetDeal
     */
    public function getDeal($id)
    {
        list($response) = $this->getDealWithHttpInfo($id);
        return $response;
    }

    /**
     * Operation getDealWithHttpInfo
     *
     * Get details of a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetDeal, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealWithHttpInfo($id)
    {
        $request = $this->getDealRequest($id);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealRequest($id);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\GetDeal' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDeal', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\GetDeal' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDeal', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\GetDeal',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealAsync
     *
     * Get details of a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealAsync($id): PromiseInterface
    {
        return $this->getDealAsyncWithHttpInfo($id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealAsyncWithHttpInfo
     *
     * Get details of a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealAsyncWithHttpInfo($id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetDeal';
        $request = $this->getDealRequest($id);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDeal'
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealRequest($id): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDeal'
            );
        }

        $resourcePath = '/deals/{id}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealActivities
     *
     * List activities associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $done Whether the activity is done or not. 0 &#x3D; Not done, 1 &#x3D; Done. If omitted, returns both Done and Not done activities. (optional)
     * @param  string|null $exclude A comma-separated string of activity IDs to exclude from result (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DealListActivitiesResponse
     */
    public function getDealActivities($id, $start = 0, $limit = null, $done = null, $exclude = null)
    {
        list($response) = $this->getDealActivitiesWithHttpInfo($id, $start, $limit, $done, $exclude);
        return $response;
    }

    /**
     * Operation getDealActivitiesWithHttpInfo
     *
     * List activities associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $done Whether the activity is done or not. 0 &#x3D; Not done, 1 &#x3D; Done. If omitted, returns both Done and Not done activities. (optional)
     * @param  string|null $exclude A comma-separated string of activity IDs to exclude from result (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\DealListActivitiesResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealActivitiesWithHttpInfo($id, $start = 0, $limit = null, $done = null, $exclude = null)
    {
        $request = $this->getDealActivitiesRequest($id, $start, $limit, $done, $exclude);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealActivitiesRequest($id, $start, $limit, $done, $exclude);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\DealListActivitiesResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DealListActivitiesResponse', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\DealListActivitiesResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\DealListActivitiesResponse', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\DealListActivitiesResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealActivitiesAsync
     *
     * List activities associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $done Whether the activity is done or not. 0 &#x3D; Not done, 1 &#x3D; Done. If omitted, returns both Done and Not done activities. (optional)
     * @param  string|null $exclude A comma-separated string of activity IDs to exclude from result (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealActivitiesAsync($id, $start = 0, $limit = null, $done = null, $exclude = null): PromiseInterface
    {
        return $this->getDealActivitiesAsyncWithHttpInfo($id, $start, $limit, $done, $exclude)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealActivitiesAsyncWithHttpInfo
     *
     * List activities associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $done Whether the activity is done or not. 0 &#x3D; Not done, 1 &#x3D; Done. If omitted, returns both Done and Not done activities. (optional)
     * @param  string|null $exclude A comma-separated string of activity IDs to exclude from result (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealActivitiesAsyncWithHttpInfo($id, $start = 0, $limit = null, $done = null, $exclude = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DealListActivitiesResponse';
        $request = $this->getDealActivitiesRequest($id, $start, $limit, $done, $exclude);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealActivities'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $done Whether the activity is done or not. 0 &#x3D; Not done, 1 &#x3D; Done. If omitted, returns both Done and Not done activities. (optional)
     * @param  string|null $exclude A comma-separated string of activity IDs to exclude from result (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealActivitiesRequest($id, $start = 0, $limit = null, $done = null, $exclude = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDealActivities'
            );
        }

        $resourcePath = '/deals/{id}/activities';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($start)) {
            $start = ObjectSerializer::serializeCollection($start, '', true);
        }
        if ($start !== null) {
            $queryParams['start'] = $start;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($done)) {
            $done = ObjectSerializer::serializeCollection($done, '', true);
        }
        if ($done !== null) {
            $queryParams['done'] = $done;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($exclude)) {
            $exclude = ObjectSerializer::serializeCollection($exclude, '', true);
        }
        if ($exclude !== null) {
            $queryParams['exclude'] = $exclude;
        }


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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealChangelog
     *
     * List updates about deal field values
     *
     * @param  int $id The ID of the deal (required)
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\ChangelogResponse
     */
    public function getDealChangelog($id, $cursor = null, $limit = null)
    {
        list($response) = $this->getDealChangelogWithHttpInfo($id, $cursor, $limit);
        return $response;
    }

    /**
     * Operation getDealChangelogWithHttpInfo
     *
     * List updates about deal field values
     *
     * @param  int $id The ID of the deal (required)
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\ChangelogResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealChangelogWithHttpInfo($id, $cursor = null, $limit = null)
    {
        $request = $this->getDealChangelogRequest($id, $cursor, $limit);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealChangelogRequest($id, $cursor, $limit);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\ChangelogResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ChangelogResponse', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\ChangelogResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\ChangelogResponse', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\ChangelogResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealChangelogAsync
     *
     * List updates about deal field values
     *
     * @param  int $id The ID of the deal (required)
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealChangelogAsync($id, $cursor = null, $limit = null): PromiseInterface
    {
        return $this->getDealChangelogAsyncWithHttpInfo($id, $cursor, $limit)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealChangelogAsyncWithHttpInfo
     *
     * List updates about deal field values
     *
     * @param  int $id The ID of the deal (required)
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealChangelogAsyncWithHttpInfo($id, $cursor = null, $limit = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ChangelogResponse';
        $request = $this->getDealChangelogRequest($id, $cursor, $limit);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealChangelog'
     *
     * @param  int $id The ID of the deal (required)
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealChangelogRequest($id, $cursor = null, $limit = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDealChangelog'
            );
        }

        $resourcePath = '/deals/{id}/changelog';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($cursor)) {
            $cursor = ObjectSerializer::serializeCollection($cursor, '', true);
        }
        if ($cursor !== null) {
            $queryParams['cursor'] = $cursor;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }


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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealFiles
     *
     * List files attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $sort The field names and sorting mode separated by a comma (&#x60;field_name_1 ASC&#x60;, &#x60;field_name_2 DESC&#x60;). Only first-level field keys are supported (no nested keys). Supported fields: &#x60;id&#x60;, &#x60;user_id&#x60;, &#x60;deal_id&#x60;, &#x60;person_id&#x60;, &#x60;org_id&#x60;, &#x60;product_id&#x60;, &#x60;add_time&#x60;, &#x60;update_time&#x60;, &#x60;file_name&#x60;, &#x60;file_type&#x60;, &#x60;file_size&#x60;, &#x60;comment&#x60;. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\ListFilesResponse
     */
    public function getDealFiles($id, $start = 0, $limit = null, $sort = null)
    {
        list($response) = $this->getDealFilesWithHttpInfo($id, $start, $limit, $sort);
        return $response;
    }

    /**
     * Operation getDealFilesWithHttpInfo
     *
     * List files attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $sort The field names and sorting mode separated by a comma (&#x60;field_name_1 ASC&#x60;, &#x60;field_name_2 DESC&#x60;). Only first-level field keys are supported (no nested keys). Supported fields: &#x60;id&#x60;, &#x60;user_id&#x60;, &#x60;deal_id&#x60;, &#x60;person_id&#x60;, &#x60;org_id&#x60;, &#x60;product_id&#x60;, &#x60;add_time&#x60;, &#x60;update_time&#x60;, &#x60;file_name&#x60;, &#x60;file_type&#x60;, &#x60;file_size&#x60;, &#x60;comment&#x60;. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\ListFilesResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealFilesWithHttpInfo($id, $start = 0, $limit = null, $sort = null)
    {
        $request = $this->getDealFilesRequest($id, $start, $limit, $sort);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealFilesRequest($id, $start, $limit, $sort);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\ListFilesResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListFilesResponse', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\ListFilesResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListFilesResponse', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\ListFilesResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealFilesAsync
     *
     * List files attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $sort The field names and sorting mode separated by a comma (&#x60;field_name_1 ASC&#x60;, &#x60;field_name_2 DESC&#x60;). Only first-level field keys are supported (no nested keys). Supported fields: &#x60;id&#x60;, &#x60;user_id&#x60;, &#x60;deal_id&#x60;, &#x60;person_id&#x60;, &#x60;org_id&#x60;, &#x60;product_id&#x60;, &#x60;add_time&#x60;, &#x60;update_time&#x60;, &#x60;file_name&#x60;, &#x60;file_type&#x60;, &#x60;file_size&#x60;, &#x60;comment&#x60;. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealFilesAsync($id, $start = 0, $limit = null, $sort = null): PromiseInterface
    {
        return $this->getDealFilesAsyncWithHttpInfo($id, $start, $limit, $sort)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealFilesAsyncWithHttpInfo
     *
     * List files attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $sort The field names and sorting mode separated by a comma (&#x60;field_name_1 ASC&#x60;, &#x60;field_name_2 DESC&#x60;). Only first-level field keys are supported (no nested keys). Supported fields: &#x60;id&#x60;, &#x60;user_id&#x60;, &#x60;deal_id&#x60;, &#x60;person_id&#x60;, &#x60;org_id&#x60;, &#x60;product_id&#x60;, &#x60;add_time&#x60;, &#x60;update_time&#x60;, &#x60;file_name&#x60;, &#x60;file_type&#x60;, &#x60;file_size&#x60;, &#x60;comment&#x60;. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealFilesAsyncWithHttpInfo($id, $start = 0, $limit = null, $sort = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListFilesResponse';
        $request = $this->getDealFilesRequest($id, $start, $limit, $sort);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealFiles'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $sort The field names and sorting mode separated by a comma (&#x60;field_name_1 ASC&#x60;, &#x60;field_name_2 DESC&#x60;). Only first-level field keys are supported (no nested keys). Supported fields: &#x60;id&#x60;, &#x60;user_id&#x60;, &#x60;deal_id&#x60;, &#x60;person_id&#x60;, &#x60;org_id&#x60;, &#x60;product_id&#x60;, &#x60;add_time&#x60;, &#x60;update_time&#x60;, &#x60;file_name&#x60;, &#x60;file_type&#x60;, &#x60;file_size&#x60;, &#x60;comment&#x60;. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealFilesRequest($id, $start = 0, $limit = null, $sort = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDealFiles'
            );
        }

        $resourcePath = '/deals/{id}/files';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($start)) {
            $start = ObjectSerializer::serializeCollection($start, '', true);
        }
        if ($start !== null) {
            $queryParams['start'] = $start;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($sort)) {
            $sort = ObjectSerializer::serializeCollection($sort, '', true);
        }
        if ($sort !== null) {
            $queryParams['sort'] = $sort;
        }


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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealFollowers
     *
     * List followers of a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\ListFollowersResponse
     */
    public function getDealFollowers($id)
    {
        list($response) = $this->getDealFollowersWithHttpInfo($id);
        return $response;
    }

    /**
     * Operation getDealFollowersWithHttpInfo
     *
     * List followers of a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\ListFollowersResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealFollowersWithHttpInfo($id)
    {
        $request = $this->getDealFollowersRequest($id);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealFollowersRequest($id);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\ListFollowersResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListFollowersResponse', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\ListFollowersResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListFollowersResponse', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\ListFollowersResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealFollowersAsync
     *
     * List followers of a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealFollowersAsync($id): PromiseInterface
    {
        return $this->getDealFollowersAsyncWithHttpInfo($id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealFollowersAsyncWithHttpInfo
     *
     * List followers of a deal
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealFollowersAsyncWithHttpInfo($id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListFollowersResponse';
        $request = $this->getDealFollowersRequest($id);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealFollowers'
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealFollowersRequest($id): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDealFollowers'
            );
        }

        $resourcePath = '/deals/{id}/followers';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealMailMessages
     *
     * List mail messages associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\ListMailMessagesResponse
     */
    public function getDealMailMessages($id, $start = 0, $limit = null)
    {
        list($response) = $this->getDealMailMessagesWithHttpInfo($id, $start, $limit);
        return $response;
    }

    /**
     * Operation getDealMailMessagesWithHttpInfo
     *
     * List mail messages associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\ListMailMessagesResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealMailMessagesWithHttpInfo($id, $start = 0, $limit = null)
    {
        $request = $this->getDealMailMessagesRequest($id, $start, $limit);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealMailMessagesRequest($id, $start, $limit);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\ListMailMessagesResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListMailMessagesResponse', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\ListMailMessagesResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListMailMessagesResponse', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\ListMailMessagesResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealMailMessagesAsync
     *
     * List mail messages associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealMailMessagesAsync($id, $start = 0, $limit = null): PromiseInterface
    {
        return $this->getDealMailMessagesAsyncWithHttpInfo($id, $start, $limit)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealMailMessagesAsyncWithHttpInfo
     *
     * List mail messages associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealMailMessagesAsyncWithHttpInfo($id, $start = 0, $limit = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListMailMessagesResponse';
        $request = $this->getDealMailMessagesRequest($id, $start, $limit);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealMailMessages'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealMailMessagesRequest($id, $start = 0, $limit = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDealMailMessages'
            );
        }

        $resourcePath = '/deals/{id}/mailMessages';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($start)) {
            $start = ObjectSerializer::serializeCollection($start, '', true);
        }
        if ($start !== null) {
            $queryParams['start'] = $start;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }


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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealParticipants
     *
     * List participants of a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DealParticipants
     */
    public function getDealParticipants($id, $start = 0, $limit = null)
    {
        list($response) = $this->getDealParticipantsWithHttpInfo($id, $start, $limit);
        return $response;
    }

    /**
     * Operation getDealParticipantsWithHttpInfo
     *
     * List participants of a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\DealParticipants, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealParticipantsWithHttpInfo($id, $start = 0, $limit = null)
    {
        $request = $this->getDealParticipantsRequest($id, $start, $limit);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealParticipantsRequest($id, $start, $limit);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\DealParticipants' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DealParticipants', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\DealParticipants' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\DealParticipants', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\DealParticipants',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealParticipantsAsync
     *
     * List participants of a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealParticipantsAsync($id, $start = 0, $limit = null): PromiseInterface
    {
        return $this->getDealParticipantsAsyncWithHttpInfo($id, $start, $limit)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealParticipantsAsyncWithHttpInfo
     *
     * List participants of a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealParticipantsAsyncWithHttpInfo($id, $start = 0, $limit = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DealParticipants';
        $request = $this->getDealParticipantsRequest($id, $start, $limit);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealParticipants'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealParticipantsRequest($id, $start = 0, $limit = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDealParticipants'
            );
        }

        $resourcePath = '/deals/{id}/participants';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($start)) {
            $start = ObjectSerializer::serializeCollection($start, '', true);
        }
        if ($start !== null) {
            $queryParams['start'] = $start;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }


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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealParticipantsChangelog
     *
     * List updates about participants of a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\ParticipantsChangelog
     */
    public function getDealParticipantsChangelog($id, $limit = null, $cursor = null)
    {
        list($response) = $this->getDealParticipantsChangelogWithHttpInfo($id, $limit, $cursor);
        return $response;
    }

    /**
     * Operation getDealParticipantsChangelogWithHttpInfo
     *
     * List updates about participants of a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\ParticipantsChangelog, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealParticipantsChangelogWithHttpInfo($id, $limit = null, $cursor = null)
    {
        $request = $this->getDealParticipantsChangelogRequest($id, $limit, $cursor);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealParticipantsChangelogRequest($id, $limit, $cursor);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\ParticipantsChangelog' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ParticipantsChangelog', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\ParticipantsChangelog' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\ParticipantsChangelog', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\ParticipantsChangelog',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealParticipantsChangelogAsync
     *
     * List updates about participants of a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealParticipantsChangelogAsync($id, $limit = null, $cursor = null): PromiseInterface
    {
        return $this->getDealParticipantsChangelogAsyncWithHttpInfo($id, $limit, $cursor)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealParticipantsChangelogAsyncWithHttpInfo
     *
     * List updates about participants of a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealParticipantsChangelogAsyncWithHttpInfo($id, $limit = null, $cursor = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ParticipantsChangelog';
        $request = $this->getDealParticipantsChangelogRequest($id, $limit, $cursor);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealParticipantsChangelog'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealParticipantsChangelogRequest($id, $limit = null, $cursor = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDealParticipantsChangelog'
            );
        }

        $resourcePath = '/deals/{id}/participantsChangelog';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($cursor)) {
            $cursor = ObjectSerializer::serializeCollection($cursor, '', true);
        }
        if ($cursor !== null) {
            $queryParams['cursor'] = $cursor;
        }


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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealPersons
     *
     * List all persons associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\ListPersonsResponse
     */
    public function getDealPersons($id, $start = 0, $limit = null)
    {
        list($response) = $this->getDealPersonsWithHttpInfo($id, $start, $limit);
        return $response;
    }

    /**
     * Operation getDealPersonsWithHttpInfo
     *
     * List all persons associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\ListPersonsResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealPersonsWithHttpInfo($id, $start = 0, $limit = null)
    {
        $request = $this->getDealPersonsRequest($id, $start, $limit);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealPersonsRequest($id, $start, $limit);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\ListPersonsResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListPersonsResponse', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\ListPersonsResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListPersonsResponse', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\ListPersonsResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealPersonsAsync
     *
     * List all persons associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealPersonsAsync($id, $start = 0, $limit = null): PromiseInterface
    {
        return $this->getDealPersonsAsyncWithHttpInfo($id, $start, $limit)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealPersonsAsyncWithHttpInfo
     *
     * List all persons associated with a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealPersonsAsyncWithHttpInfo($id, $start = 0, $limit = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListPersonsResponse';
        $request = $this->getDealPersonsRequest($id, $start, $limit);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealPersons'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealPersonsRequest($id, $start = 0, $limit = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDealPersons'
            );
        }

        $resourcePath = '/deals/{id}/persons';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($start)) {
            $start = ObjectSerializer::serializeCollection($start, '', true);
        }
        if ($start !== null) {
            $queryParams['start'] = $start;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }


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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealProducts
     *
     * List products attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $include_product_data Whether to fetch product data along with each attached product (1) or not (0, default) (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\ListProductsResponse
     */
    public function getDealProducts($id, $start = 0, $limit = null, $include_product_data = null)
    {
        list($response) = $this->getDealProductsWithHttpInfo($id, $start, $limit, $include_product_data);
        return $response;
    }

    /**
     * Operation getDealProductsWithHttpInfo
     *
     * List products attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $include_product_data Whether to fetch product data along with each attached product (1) or not (0, default) (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\ListProductsResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealProductsWithHttpInfo($id, $start = 0, $limit = null, $include_product_data = null)
    {
        $request = $this->getDealProductsRequest($id, $start, $limit, $include_product_data);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealProductsRequest($id, $start, $limit, $include_product_data);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\ListProductsResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListProductsResponse', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\ListProductsResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListProductsResponse', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\ListProductsResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealProductsAsync
     *
     * List products attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $include_product_data Whether to fetch product data along with each attached product (1) or not (0, default) (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealProductsAsync($id, $start = 0, $limit = null, $include_product_data = null): PromiseInterface
    {
        return $this->getDealProductsAsyncWithHttpInfo($id, $start, $limit, $include_product_data)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealProductsAsyncWithHttpInfo
     *
     * List products attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $include_product_data Whether to fetch product data along with each attached product (1) or not (0, default) (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealProductsAsyncWithHttpInfo($id, $start = 0, $limit = null, $include_product_data = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListProductsResponse';
        $request = $this->getDealProductsRequest($id, $start, $limit, $include_product_data);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealProducts'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $include_product_data Whether to fetch product data along with each attached product (1) or not (0, default) (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealProductsRequest($id, $start = 0, $limit = null, $include_product_data = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDealProducts'
            );
        }

        $resourcePath = '/deals/{id}/products';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($start)) {
            $start = ObjectSerializer::serializeCollection($start, '', true);
        }
        if ($start !== null) {
            $queryParams['start'] = $start;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($include_product_data)) {
            $include_product_data = ObjectSerializer::serializeCollection($include_product_data, '', true);
        }
        if ($include_product_data !== null) {
            $queryParams['include_product_data'] = $include_product_data;
        }


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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealUpdates
     *
     * List updates about a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $all_changes Whether to show custom field updates or not. 1 &#x3D; Include custom field changes. If omitted returns changes without custom field updates. (optional)
     * @param  string|null $items A comma-separated string for filtering out item specific updates. (Possible values - call, activity, plannedActivity, change, note, deal, file, dealChange, personChange, organizationChange, follower, dealFollower, personFollower, organizationFollower, participant, comment, mailMessage, mailMessageWithAttachment, invoice, document, marketing_campaign_stat, marketing_status_change). (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DealFlowResponse
     */
    public function getDealUpdates($id, $start = 0, $limit = null, $all_changes = null, $items = null)
    {
        list($response) = $this->getDealUpdatesWithHttpInfo($id, $start, $limit, $all_changes, $items);
        return $response;
    }

    /**
     * Operation getDealUpdatesWithHttpInfo
     *
     * List updates about a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $all_changes Whether to show custom field updates or not. 1 &#x3D; Include custom field changes. If omitted returns changes without custom field updates. (optional)
     * @param  string|null $items A comma-separated string for filtering out item specific updates. (Possible values - call, activity, plannedActivity, change, note, deal, file, dealChange, personChange, organizationChange, follower, dealFollower, personFollower, organizationFollower, participant, comment, mailMessage, mailMessageWithAttachment, invoice, document, marketing_campaign_stat, marketing_status_change). (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\DealFlowResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealUpdatesWithHttpInfo($id, $start = 0, $limit = null, $all_changes = null, $items = null)
    {
        $request = $this->getDealUpdatesRequest($id, $start, $limit, $all_changes, $items);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealUpdatesRequest($id, $start, $limit, $all_changes, $items);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\DealFlowResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DealFlowResponse', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\DealFlowResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\DealFlowResponse', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\DealFlowResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealUpdatesAsync
     *
     * List updates about a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $all_changes Whether to show custom field updates or not. 1 &#x3D; Include custom field changes. If omitted returns changes without custom field updates. (optional)
     * @param  string|null $items A comma-separated string for filtering out item specific updates. (Possible values - call, activity, plannedActivity, change, note, deal, file, dealChange, personChange, organizationChange, follower, dealFollower, personFollower, organizationFollower, participant, comment, mailMessage, mailMessageWithAttachment, invoice, document, marketing_campaign_stat, marketing_status_change). (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealUpdatesAsync($id, $start = 0, $limit = null, $all_changes = null, $items = null): PromiseInterface
    {
        return $this->getDealUpdatesAsyncWithHttpInfo($id, $start, $limit, $all_changes, $items)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealUpdatesAsyncWithHttpInfo
     *
     * List updates about a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $all_changes Whether to show custom field updates or not. 1 &#x3D; Include custom field changes. If omitted returns changes without custom field updates. (optional)
     * @param  string|null $items A comma-separated string for filtering out item specific updates. (Possible values - call, activity, plannedActivity, change, note, deal, file, dealChange, personChange, organizationChange, follower, dealFollower, personFollower, organizationFollower, participant, comment, mailMessage, mailMessageWithAttachment, invoice, document, marketing_campaign_stat, marketing_status_change). (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealUpdatesAsyncWithHttpInfo($id, $start = 0, $limit = null, $all_changes = null, $items = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DealFlowResponse';
        $request = $this->getDealUpdatesRequest($id, $start, $limit, $all_changes, $items);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealUpdates'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $all_changes Whether to show custom field updates or not. 1 &#x3D; Include custom field changes. If omitted returns changes without custom field updates. (optional)
     * @param  string|null $items A comma-separated string for filtering out item specific updates. (Possible values - call, activity, plannedActivity, change, note, deal, file, dealChange, personChange, organizationChange, follower, dealFollower, personFollower, organizationFollower, participant, comment, mailMessage, mailMessageWithAttachment, invoice, document, marketing_campaign_stat, marketing_status_change). (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealUpdatesRequest($id, $start = 0, $limit = null, $all_changes = null, $items = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDealUpdates'
            );
        }

        $resourcePath = '/deals/{id}/flow';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($start)) {
            $start = ObjectSerializer::serializeCollection($start, '', true);
        }
        if ($start !== null) {
            $queryParams['start'] = $start;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($all_changes)) {
            $all_changes = ObjectSerializer::serializeCollection($all_changes, '', true);
        }
        if ($all_changes !== null) {
            $queryParams['all_changes'] = $all_changes;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($items)) {
            $items = ObjectSerializer::serializeCollection($items, '', true);
        }
        if ($items !== null) {
            $queryParams['items'] = $items;
        }


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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealUsers
     *
     * List permitted users
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\ListPermittedUsersResponse
     */
    public function getDealUsers($id)
    {
        list($response) = $this->getDealUsersWithHttpInfo($id);
        return $response;
    }

    /**
     * Operation getDealUsersWithHttpInfo
     *
     * List permitted users
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\ListPermittedUsersResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealUsersWithHttpInfo($id)
    {
        $request = $this->getDealUsersRequest($id);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealUsersRequest($id);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\ListPermittedUsersResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListPermittedUsersResponse', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\ListPermittedUsersResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListPermittedUsersResponse', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\ListPermittedUsersResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealUsersAsync
     *
     * List permitted users
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealUsersAsync($id): PromiseInterface
    {
        return $this->getDealUsersAsyncWithHttpInfo($id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealUsersAsyncWithHttpInfo
     *
     * List permitted users
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealUsersAsyncWithHttpInfo($id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListPermittedUsersResponse';
        $request = $this->getDealUsersRequest($id);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealUsers'
     *
     * @param  int $id The ID of the deal (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealUsersRequest($id): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling getDealUsers'
            );
        }

        $resourcePath = '/deals/{id}/permittedUsers';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDeals
     *
     * Get all deals
     *
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned. However, &#x60;filter_id&#x60; and &#x60;owned_by_you&#x60; takes precedence over &#x60;user_id&#x60; when supplied. (optional)
     * @param  int|null $filter_id The ID of the filter to use (optional)
     * @param  int|null $stage_id If supplied, only deals within the given stage will be returned (optional)
     * @param  string|'all_not_deleted' $status Only fetch deals with a specific status. If omitted, all not deleted deals are returned. If set to deleted, deals that have been deleted up to 30 days ago will be included. (optional, default to 'all_not_deleted')
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $sort The field names and sorting mode separated by a comma (&#x60;field_name_1 ASC&#x60;, &#x60;field_name_2 DESC&#x60;). Only first-level field keys are supported (no nested keys). (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $owned_by_you When supplied, only deals owned by you are returned. However, &#x60;filter_id&#x60; takes precedence over &#x60;owned_by_you&#x60; when both are supplied. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetDeals
     */
    public function getDeals($user_id = null, $filter_id = null, $stage_id = null, $status = 'all_not_deleted', $start = 0, $limit = null, $sort = null, $owned_by_you = null)
    {
        list($response) = $this->getDealsWithHttpInfo($user_id, $filter_id, $stage_id, $status, $start, $limit, $sort, $owned_by_you);
        return $response;
    }

    /**
     * Operation getDealsWithHttpInfo
     *
     * Get all deals
     *
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned. However, &#x60;filter_id&#x60; and &#x60;owned_by_you&#x60; takes precedence over &#x60;user_id&#x60; when supplied. (optional)
     * @param  int|null $filter_id The ID of the filter to use (optional)
     * @param  int|null $stage_id If supplied, only deals within the given stage will be returned (optional)
     * @param  string|'all_not_deleted' $status Only fetch deals with a specific status. If omitted, all not deleted deals are returned. If set to deleted, deals that have been deleted up to 30 days ago will be included. (optional, default to 'all_not_deleted')
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $sort The field names and sorting mode separated by a comma (&#x60;field_name_1 ASC&#x60;, &#x60;field_name_2 DESC&#x60;). Only first-level field keys are supported (no nested keys). (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $owned_by_you When supplied, only deals owned by you are returned. However, &#x60;filter_id&#x60; takes precedence over &#x60;owned_by_you&#x60; when both are supplied. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetDeals, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealsWithHttpInfo($user_id = null, $filter_id = null, $stage_id = null, $status = 'all_not_deleted', $start = 0, $limit = null, $sort = null, $owned_by_you = null)
    {
        $request = $this->getDealsRequest($user_id, $filter_id, $stage_id, $status, $start, $limit, $sort, $owned_by_you);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealsRequest($user_id, $filter_id, $stage_id, $status, $start, $limit, $sort, $owned_by_you);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\GetDeals' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDeals', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\GetDeals' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDeals', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\GetDeals',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealsAsync
     *
     * Get all deals
     *
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned. However, &#x60;filter_id&#x60; and &#x60;owned_by_you&#x60; takes precedence over &#x60;user_id&#x60; when supplied. (optional)
     * @param  int|null $filter_id The ID of the filter to use (optional)
     * @param  int|null $stage_id If supplied, only deals within the given stage will be returned (optional)
     * @param  string|'all_not_deleted' $status Only fetch deals with a specific status. If omitted, all not deleted deals are returned. If set to deleted, deals that have been deleted up to 30 days ago will be included. (optional, default to 'all_not_deleted')
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $sort The field names and sorting mode separated by a comma (&#x60;field_name_1 ASC&#x60;, &#x60;field_name_2 DESC&#x60;). Only first-level field keys are supported (no nested keys). (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $owned_by_you When supplied, only deals owned by you are returned. However, &#x60;filter_id&#x60; takes precedence over &#x60;owned_by_you&#x60; when both are supplied. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealsAsync($user_id = null, $filter_id = null, $stage_id = null, $status = 'all_not_deleted', $start = 0, $limit = null, $sort = null, $owned_by_you = null): PromiseInterface
    {
        return $this->getDealsAsyncWithHttpInfo($user_id, $filter_id, $stage_id, $status, $start, $limit, $sort, $owned_by_you)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealsAsyncWithHttpInfo
     *
     * Get all deals
     *
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned. However, &#x60;filter_id&#x60; and &#x60;owned_by_you&#x60; takes precedence over &#x60;user_id&#x60; when supplied. (optional)
     * @param  int|null $filter_id The ID of the filter to use (optional)
     * @param  int|null $stage_id If supplied, only deals within the given stage will be returned (optional)
     * @param  string|'all_not_deleted' $status Only fetch deals with a specific status. If omitted, all not deleted deals are returned. If set to deleted, deals that have been deleted up to 30 days ago will be included. (optional, default to 'all_not_deleted')
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $sort The field names and sorting mode separated by a comma (&#x60;field_name_1 ASC&#x60;, &#x60;field_name_2 DESC&#x60;). Only first-level field keys are supported (no nested keys). (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $owned_by_you When supplied, only deals owned by you are returned. However, &#x60;filter_id&#x60; takes precedence over &#x60;owned_by_you&#x60; when both are supplied. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealsAsyncWithHttpInfo($user_id = null, $filter_id = null, $stage_id = null, $status = 'all_not_deleted', $start = 0, $limit = null, $sort = null, $owned_by_you = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetDeals';
        $request = $this->getDealsRequest($user_id, $filter_id, $stage_id, $status, $start, $limit, $sort, $owned_by_you);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDeals'
     *
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned. However, &#x60;filter_id&#x60; and &#x60;owned_by_you&#x60; takes precedence over &#x60;user_id&#x60; when supplied. (optional)
     * @param  int|null $filter_id The ID of the filter to use (optional)
     * @param  int|null $stage_id If supplied, only deals within the given stage will be returned (optional)
     * @param  string|'all_not_deleted' $status Only fetch deals with a specific status. If omitted, all not deleted deals are returned. If set to deleted, deals that have been deleted up to 30 days ago will be included. (optional, default to 'all_not_deleted')
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     * @param  string|null $sort The field names and sorting mode separated by a comma (&#x60;field_name_1 ASC&#x60;, &#x60;field_name_2 DESC&#x60;). Only first-level field keys are supported (no nested keys). (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $owned_by_you When supplied, only deals owned by you are returned. However, &#x60;filter_id&#x60; takes precedence over &#x60;owned_by_you&#x60; when both are supplied. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealsRequest($user_id = null, $filter_id = null, $stage_id = null, $status = 'all_not_deleted', $start = 0, $limit = null, $sort = null, $owned_by_you = null): Request
    {

        $resourcePath = '/deals';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($user_id)) {
            $user_id = ObjectSerializer::serializeCollection($user_id, '', true);
        }
        if ($user_id !== null) {
            $queryParams['user_id'] = $user_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($filter_id)) {
            $filter_id = ObjectSerializer::serializeCollection($filter_id, '', true);
        }
        if ($filter_id !== null) {
            $queryParams['filter_id'] = $filter_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($stage_id)) {
            $stage_id = ObjectSerializer::serializeCollection($stage_id, '', true);
        }
        if ($stage_id !== null) {
            $queryParams['stage_id'] = $stage_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($status)) {
            $status = ObjectSerializer::serializeCollection($status, '', true);
        }
        if ($status !== null) {
            $queryParams['status'] = $status;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($start)) {
            $start = ObjectSerializer::serializeCollection($start, '', true);
        }
        if ($start !== null) {
            $queryParams['start'] = $start;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($sort)) {
            $sort = ObjectSerializer::serializeCollection($sort, '', true);
        }
        if ($sort !== null) {
            $queryParams['sort'] = $sort;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($owned_by_you)) {
            $owned_by_you = ObjectSerializer::serializeCollection($owned_by_you, '', true);
        }
        if ($owned_by_you !== null) {
            $queryParams['owned_by_you'] = $owned_by_you;
        }




        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealsCollection
     *
     * Get all deals (BETA)
     *
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     * @param  int|null $limit For pagination, the limit of entries to be returned. If not provided, 100 items will be returned. Please note that a maximum value of 500 is allowed. (optional)
     * @param  string|null $since The time boundary that points to the start of the range of data. Datetime in ISO 8601 format. E.g. 2022-11-01 08:55:59. Operates on the &#x60;update_time&#x60; field. (optional)
     * @param  string|null $until The time boundary that points to the end of the range of data. Datetime in ISO 8601 format. E.g. 2022-11-01 08:55:59. Operates on the &#x60;update_time&#x60; field. (optional)
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned (optional)
     * @param  int|null $stage_id If supplied, only deals within the given stage will be returned (optional)
     * @param  string|null $status Only fetch deals with a specific status. If omitted, all not deleted deals are returned. If set to deleted, deals that have been deleted up to 30 days ago will be included. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetDealsCollection|\Pipedrive\Model\FailResponse
     */
    public function getDealsCollection($cursor = null, $limit = null, $since = null, $until = null, $user_id = null, $stage_id = null, $status = null)
    {
        list($response) = $this->getDealsCollectionWithHttpInfo($cursor, $limit, $since, $until, $user_id, $stage_id, $status);
        return $response;
    }

    /**
     * Operation getDealsCollectionWithHttpInfo
     *
     * Get all deals (BETA)
     *
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     * @param  int|null $limit For pagination, the limit of entries to be returned. If not provided, 100 items will be returned. Please note that a maximum value of 500 is allowed. (optional)
     * @param  string|null $since The time boundary that points to the start of the range of data. Datetime in ISO 8601 format. E.g. 2022-11-01 08:55:59. Operates on the &#x60;update_time&#x60; field. (optional)
     * @param  string|null $until The time boundary that points to the end of the range of data. Datetime in ISO 8601 format. E.g. 2022-11-01 08:55:59. Operates on the &#x60;update_time&#x60; field. (optional)
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned (optional)
     * @param  int|null $stage_id If supplied, only deals within the given stage will be returned (optional)
     * @param  string|null $status Only fetch deals with a specific status. If omitted, all not deleted deals are returned. If set to deleted, deals that have been deleted up to 30 days ago will be included. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetDealsCollection|\Pipedrive\Model\FailResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealsCollectionWithHttpInfo($cursor = null, $limit = null, $since = null, $until = null, $user_id = null, $stage_id = null, $status = null)
    {
        $request = $this->getDealsCollectionRequest($cursor, $limit, $since, $until, $user_id, $stage_id, $status);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealsCollectionRequest($cursor, $limit, $since, $until, $user_id, $stage_id, $status);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\GetDealsCollection' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDealsCollection', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                case 403:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\FailResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\FailResponse', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\GetDealsCollection' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDealsCollection', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\GetDealsCollection',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 403:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\FailResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealsCollectionAsync
     *
     * Get all deals (BETA)
     *
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     * @param  int|null $limit For pagination, the limit of entries to be returned. If not provided, 100 items will be returned. Please note that a maximum value of 500 is allowed. (optional)
     * @param  string|null $since The time boundary that points to the start of the range of data. Datetime in ISO 8601 format. E.g. 2022-11-01 08:55:59. Operates on the &#x60;update_time&#x60; field. (optional)
     * @param  string|null $until The time boundary that points to the end of the range of data. Datetime in ISO 8601 format. E.g. 2022-11-01 08:55:59. Operates on the &#x60;update_time&#x60; field. (optional)
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned (optional)
     * @param  int|null $stage_id If supplied, only deals within the given stage will be returned (optional)
     * @param  string|null $status Only fetch deals with a specific status. If omitted, all not deleted deals are returned. If set to deleted, deals that have been deleted up to 30 days ago will be included. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealsCollectionAsync($cursor = null, $limit = null, $since = null, $until = null, $user_id = null, $stage_id = null, $status = null): PromiseInterface
    {
        return $this->getDealsCollectionAsyncWithHttpInfo($cursor, $limit, $since, $until, $user_id, $stage_id, $status)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealsCollectionAsyncWithHttpInfo
     *
     * Get all deals (BETA)
     *
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     * @param  int|null $limit For pagination, the limit of entries to be returned. If not provided, 100 items will be returned. Please note that a maximum value of 500 is allowed. (optional)
     * @param  string|null $since The time boundary that points to the start of the range of data. Datetime in ISO 8601 format. E.g. 2022-11-01 08:55:59. Operates on the &#x60;update_time&#x60; field. (optional)
     * @param  string|null $until The time boundary that points to the end of the range of data. Datetime in ISO 8601 format. E.g. 2022-11-01 08:55:59. Operates on the &#x60;update_time&#x60; field. (optional)
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned (optional)
     * @param  int|null $stage_id If supplied, only deals within the given stage will be returned (optional)
     * @param  string|null $status Only fetch deals with a specific status. If omitted, all not deleted deals are returned. If set to deleted, deals that have been deleted up to 30 days ago will be included. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealsCollectionAsyncWithHttpInfo($cursor = null, $limit = null, $since = null, $until = null, $user_id = null, $stage_id = null, $status = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetDealsCollection';
        $request = $this->getDealsCollectionRequest($cursor, $limit, $since, $until, $user_id, $stage_id, $status);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealsCollection'
     *
     * @param  string|null $cursor For pagination, the marker (an opaque string value) representing the first item on the next page (optional)
     * @param  int|null $limit For pagination, the limit of entries to be returned. If not provided, 100 items will be returned. Please note that a maximum value of 500 is allowed. (optional)
     * @param  string|null $since The time boundary that points to the start of the range of data. Datetime in ISO 8601 format. E.g. 2022-11-01 08:55:59. Operates on the &#x60;update_time&#x60; field. (optional)
     * @param  string|null $until The time boundary that points to the end of the range of data. Datetime in ISO 8601 format. E.g. 2022-11-01 08:55:59. Operates on the &#x60;update_time&#x60; field. (optional)
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned (optional)
     * @param  int|null $stage_id If supplied, only deals within the given stage will be returned (optional)
     * @param  string|null $status Only fetch deals with a specific status. If omitted, all not deleted deals are returned. If set to deleted, deals that have been deleted up to 30 days ago will be included. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealsCollectionRequest($cursor = null, $limit = null, $since = null, $until = null, $user_id = null, $stage_id = null, $status = null): Request
    {

        $resourcePath = '/deals/collection';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($cursor)) {
            $cursor = ObjectSerializer::serializeCollection($cursor, '', true);
        }
        if ($cursor !== null) {
            $queryParams['cursor'] = $cursor;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($since)) {
            $since = ObjectSerializer::serializeCollection($since, '', true);
        }
        if ($since !== null) {
            $queryParams['since'] = $since;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($until)) {
            $until = ObjectSerializer::serializeCollection($until, '', true);
        }
        if ($until !== null) {
            $queryParams['until'] = $until;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($user_id)) {
            $user_id = ObjectSerializer::serializeCollection($user_id, '', true);
        }
        if ($user_id !== null) {
            $queryParams['user_id'] = $user_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($stage_id)) {
            $stage_id = ObjectSerializer::serializeCollection($stage_id, '', true);
        }
        if ($stage_id !== null) {
            $queryParams['stage_id'] = $stage_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($status)) {
            $status = ObjectSerializer::serializeCollection($status, '', true);
        }
        if ($status !== null) {
            $queryParams['status'] = $status;
        }




        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealsSummary
     *
     * Get deals summary
     *
     * @param  string|null $status Only fetch deals with a specific status. open &#x3D; Open, won &#x3D; Won, lost &#x3D; Lost. (optional)
     * @param  int|null $filter_id &lt;code&gt;user_id&lt;/code&gt; will not be considered. Only deals matching the given filter will be returned. (optional)
     * @param  int|null $user_id Only deals matching the given user will be returned. &#x60;user_id&#x60; will not be considered if you use &#x60;filter_id&#x60;. (optional)
     * @param  int|null $stage_id Only deals within the given stage will be returned (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetDealsSummary
     */
    public function getDealsSummary($status = null, $filter_id = null, $user_id = null, $stage_id = null)
    {
        list($response) = $this->getDealsSummaryWithHttpInfo($status, $filter_id, $user_id, $stage_id);
        return $response;
    }

    /**
     * Operation getDealsSummaryWithHttpInfo
     *
     * Get deals summary
     *
     * @param  string|null $status Only fetch deals with a specific status. open &#x3D; Open, won &#x3D; Won, lost &#x3D; Lost. (optional)
     * @param  int|null $filter_id &lt;code&gt;user_id&lt;/code&gt; will not be considered. Only deals matching the given filter will be returned. (optional)
     * @param  int|null $user_id Only deals matching the given user will be returned. &#x60;user_id&#x60; will not be considered if you use &#x60;filter_id&#x60;. (optional)
     * @param  int|null $stage_id Only deals within the given stage will be returned (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetDealsSummary, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealsSummaryWithHttpInfo($status = null, $filter_id = null, $user_id = null, $stage_id = null)
    {
        $request = $this->getDealsSummaryRequest($status, $filter_id, $user_id, $stage_id);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealsSummaryRequest($status, $filter_id, $user_id, $stage_id);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\GetDealsSummary' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDealsSummary', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\GetDealsSummary' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDealsSummary', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\GetDealsSummary',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealsSummaryAsync
     *
     * Get deals summary
     *
     * @param  string|null $status Only fetch deals with a specific status. open &#x3D; Open, won &#x3D; Won, lost &#x3D; Lost. (optional)
     * @param  int|null $filter_id &lt;code&gt;user_id&lt;/code&gt; will not be considered. Only deals matching the given filter will be returned. (optional)
     * @param  int|null $user_id Only deals matching the given user will be returned. &#x60;user_id&#x60; will not be considered if you use &#x60;filter_id&#x60;. (optional)
     * @param  int|null $stage_id Only deals within the given stage will be returned (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealsSummaryAsync($status = null, $filter_id = null, $user_id = null, $stage_id = null): PromiseInterface
    {
        return $this->getDealsSummaryAsyncWithHttpInfo($status, $filter_id, $user_id, $stage_id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealsSummaryAsyncWithHttpInfo
     *
     * Get deals summary
     *
     * @param  string|null $status Only fetch deals with a specific status. open &#x3D; Open, won &#x3D; Won, lost &#x3D; Lost. (optional)
     * @param  int|null $filter_id &lt;code&gt;user_id&lt;/code&gt; will not be considered. Only deals matching the given filter will be returned. (optional)
     * @param  int|null $user_id Only deals matching the given user will be returned. &#x60;user_id&#x60; will not be considered if you use &#x60;filter_id&#x60;. (optional)
     * @param  int|null $stage_id Only deals within the given stage will be returned (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealsSummaryAsyncWithHttpInfo($status = null, $filter_id = null, $user_id = null, $stage_id = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetDealsSummary';
        $request = $this->getDealsSummaryRequest($status, $filter_id, $user_id, $stage_id);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealsSummary'
     *
     * @param  string|null $status Only fetch deals with a specific status. open &#x3D; Open, won &#x3D; Won, lost &#x3D; Lost. (optional)
     * @param  int|null $filter_id &lt;code&gt;user_id&lt;/code&gt; will not be considered. Only deals matching the given filter will be returned. (optional)
     * @param  int|null $user_id Only deals matching the given user will be returned. &#x60;user_id&#x60; will not be considered if you use &#x60;filter_id&#x60;. (optional)
     * @param  int|null $stage_id Only deals within the given stage will be returned (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealsSummaryRequest($status = null, $filter_id = null, $user_id = null, $stage_id = null): Request
    {

        $resourcePath = '/deals/summary';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($status)) {
            $status = ObjectSerializer::serializeCollection($status, '', true);
        }
        if ($status !== null) {
            $queryParams['status'] = $status;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($filter_id)) {
            $filter_id = ObjectSerializer::serializeCollection($filter_id, '', true);
        }
        if ($filter_id !== null) {
            $queryParams['filter_id'] = $filter_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($user_id)) {
            $user_id = ObjectSerializer::serializeCollection($user_id, '', true);
        }
        if ($user_id !== null) {
            $queryParams['user_id'] = $user_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($stage_id)) {
            $stage_id = ObjectSerializer::serializeCollection($stage_id, '', true);
        }
        if ($stage_id !== null) {
            $queryParams['stage_id'] = $stage_id;
        }




        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getDealsTimeline
     *
     * Get deals timeline
     *
     * @param  \DateTime $start_date The date when the first interval starts. Format: YYYY-MM-DD. (required)
     * @param  string $interval The type of the interval&lt;table&gt;&lt;tr&gt;&lt;th&gt;Value&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;day&#x60;&lt;/td&gt;&lt;td&gt;Day&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;week&#x60;&lt;/td&gt;&lt;td&gt;A full week (7 days) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;month&#x60;&lt;/td&gt;&lt;td&gt;A full month (depending on the number of days in given month) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;quarter&#x60;&lt;/td&gt;&lt;td&gt;A full quarter (3 months) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; (required)
     * @param  int $amount The number of given intervals, starting from &#x60;start_date&#x60;, to fetch. E.g. 3 (months). (required)
     * @param  string $field_key The date field key which deals will be retrieved from (required)
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned (optional)
     * @param  int|null $pipeline_id If supplied, only deals matching the given pipeline will be returned (optional)
     * @param  int|null $filter_id If supplied, only deals matching the given filter will be returned (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $exclude_deals Whether to exclude deals list (1) or not (0). Note that when deals are excluded, the timeline summary (counts and values) is still returned. (optional)
     * @param  string|null $totals_convert_currency The 3-letter currency code of any of the supported currencies. When supplied, &#x60;totals_converted&#x60; is returned per each interval which contains the currency-converted total amounts in the given currency. You may also set this parameter to &#x60;default_currency&#x60; in which case the user&#39;s default currency is used. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetDealsTimeline
     */
    public function getDealsTimeline($start_date, $interval, $amount, $field_key, $user_id = null, $pipeline_id = null, $filter_id = null, $exclude_deals = null, $totals_convert_currency = null)
    {
        list($response) = $this->getDealsTimelineWithHttpInfo($start_date, $interval, $amount, $field_key, $user_id, $pipeline_id, $filter_id, $exclude_deals, $totals_convert_currency);
        return $response;
    }

    /**
     * Operation getDealsTimelineWithHttpInfo
     *
     * Get deals timeline
     *
     * @param  \DateTime $start_date The date when the first interval starts. Format: YYYY-MM-DD. (required)
     * @param  string $interval The type of the interval&lt;table&gt;&lt;tr&gt;&lt;th&gt;Value&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;day&#x60;&lt;/td&gt;&lt;td&gt;Day&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;week&#x60;&lt;/td&gt;&lt;td&gt;A full week (7 days) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;month&#x60;&lt;/td&gt;&lt;td&gt;A full month (depending on the number of days in given month) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;quarter&#x60;&lt;/td&gt;&lt;td&gt;A full quarter (3 months) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; (required)
     * @param  int $amount The number of given intervals, starting from &#x60;start_date&#x60;, to fetch. E.g. 3 (months). (required)
     * @param  string $field_key The date field key which deals will be retrieved from (required)
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned (optional)
     * @param  int|null $pipeline_id If supplied, only deals matching the given pipeline will be returned (optional)
     * @param  int|null $filter_id If supplied, only deals matching the given filter will be returned (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $exclude_deals Whether to exclude deals list (1) or not (0). Note that when deals are excluded, the timeline summary (counts and values) is still returned. (optional)
     * @param  string|null $totals_convert_currency The 3-letter currency code of any of the supported currencies. When supplied, &#x60;totals_converted&#x60; is returned per each interval which contains the currency-converted total amounts in the given currency. You may also set this parameter to &#x60;default_currency&#x60; in which case the user&#39;s default currency is used. (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetDealsTimeline, HTTP status code, HTTP response headers (array of strings)
     */
    public function getDealsTimelineWithHttpInfo($start_date, $interval, $amount, $field_key, $user_id = null, $pipeline_id = null, $filter_id = null, $exclude_deals = null, $totals_convert_currency = null)
    {
        $request = $this->getDealsTimelineRequest($start_date, $interval, $amount, $field_key, $user_id, $pipeline_id, $filter_id, $exclude_deals, $totals_convert_currency);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->getDealsTimelineRequest($start_date, $interval, $amount, $field_key, $user_id, $pipeline_id, $filter_id, $exclude_deals, $totals_convert_currency);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\GetDealsTimeline' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDealsTimeline', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\GetDealsTimeline' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetDealsTimeline', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\GetDealsTimeline',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation getDealsTimelineAsync
     *
     * Get deals timeline
     *
     * @param  \DateTime $start_date The date when the first interval starts. Format: YYYY-MM-DD. (required)
     * @param  string $interval The type of the interval&lt;table&gt;&lt;tr&gt;&lt;th&gt;Value&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;day&#x60;&lt;/td&gt;&lt;td&gt;Day&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;week&#x60;&lt;/td&gt;&lt;td&gt;A full week (7 days) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;month&#x60;&lt;/td&gt;&lt;td&gt;A full month (depending on the number of days in given month) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;quarter&#x60;&lt;/td&gt;&lt;td&gt;A full quarter (3 months) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; (required)
     * @param  int $amount The number of given intervals, starting from &#x60;start_date&#x60;, to fetch. E.g. 3 (months). (required)
     * @param  string $field_key The date field key which deals will be retrieved from (required)
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned (optional)
     * @param  int|null $pipeline_id If supplied, only deals matching the given pipeline will be returned (optional)
     * @param  int|null $filter_id If supplied, only deals matching the given filter will be returned (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $exclude_deals Whether to exclude deals list (1) or not (0). Note that when deals are excluded, the timeline summary (counts and values) is still returned. (optional)
     * @param  string|null $totals_convert_currency The 3-letter currency code of any of the supported currencies. When supplied, &#x60;totals_converted&#x60; is returned per each interval which contains the currency-converted total amounts in the given currency. You may also set this parameter to &#x60;default_currency&#x60; in which case the user&#39;s default currency is used. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealsTimelineAsync($start_date, $interval, $amount, $field_key, $user_id = null, $pipeline_id = null, $filter_id = null, $exclude_deals = null, $totals_convert_currency = null): PromiseInterface
    {
        return $this->getDealsTimelineAsyncWithHttpInfo($start_date, $interval, $amount, $field_key, $user_id, $pipeline_id, $filter_id, $exclude_deals, $totals_convert_currency)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getDealsTimelineAsyncWithHttpInfo
     *
     * Get deals timeline
     *
     * @param  \DateTime $start_date The date when the first interval starts. Format: YYYY-MM-DD. (required)
     * @param  string $interval The type of the interval&lt;table&gt;&lt;tr&gt;&lt;th&gt;Value&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;day&#x60;&lt;/td&gt;&lt;td&gt;Day&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;week&#x60;&lt;/td&gt;&lt;td&gt;A full week (7 days) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;month&#x60;&lt;/td&gt;&lt;td&gt;A full month (depending on the number of days in given month) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;quarter&#x60;&lt;/td&gt;&lt;td&gt;A full quarter (3 months) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; (required)
     * @param  int $amount The number of given intervals, starting from &#x60;start_date&#x60;, to fetch. E.g. 3 (months). (required)
     * @param  string $field_key The date field key which deals will be retrieved from (required)
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned (optional)
     * @param  int|null $pipeline_id If supplied, only deals matching the given pipeline will be returned (optional)
     * @param  int|null $filter_id If supplied, only deals matching the given filter will be returned (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $exclude_deals Whether to exclude deals list (1) or not (0). Note that when deals are excluded, the timeline summary (counts and values) is still returned. (optional)
     * @param  string|null $totals_convert_currency The 3-letter currency code of any of the supported currencies. When supplied, &#x60;totals_converted&#x60; is returned per each interval which contains the currency-converted total amounts in the given currency. You may also set this parameter to &#x60;default_currency&#x60; in which case the user&#39;s default currency is used. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getDealsTimelineAsyncWithHttpInfo($start_date, $interval, $amount, $field_key, $user_id = null, $pipeline_id = null, $filter_id = null, $exclude_deals = null, $totals_convert_currency = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetDealsTimeline';
        $request = $this->getDealsTimelineRequest($start_date, $interval, $amount, $field_key, $user_id, $pipeline_id, $filter_id, $exclude_deals, $totals_convert_currency);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getDealsTimeline'
     *
     * @param  \DateTime $start_date The date when the first interval starts. Format: YYYY-MM-DD. (required)
     * @param  string $interval The type of the interval&lt;table&gt;&lt;tr&gt;&lt;th&gt;Value&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;day&#x60;&lt;/td&gt;&lt;td&gt;Day&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;week&#x60;&lt;/td&gt;&lt;td&gt;A full week (7 days) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;month&#x60;&lt;/td&gt;&lt;td&gt;A full month (depending on the number of days in given month) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&#x60;quarter&#x60;&lt;/td&gt;&lt;td&gt;A full quarter (3 months) starting from &#x60;start_date&#x60;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; (required)
     * @param  int $amount The number of given intervals, starting from &#x60;start_date&#x60;, to fetch. E.g. 3 (months). (required)
     * @param  string $field_key The date field key which deals will be retrieved from (required)
     * @param  int|null $user_id If supplied, only deals matching the given user will be returned (optional)
     * @param  int|null $pipeline_id If supplied, only deals matching the given pipeline will be returned (optional)
     * @param  int|null $filter_id If supplied, only deals matching the given filter will be returned (optional)
     * @param  \Pipedrive\Model\NumberBoolean|null $exclude_deals Whether to exclude deals list (1) or not (0). Note that when deals are excluded, the timeline summary (counts and values) is still returned. (optional)
     * @param  string|null $totals_convert_currency The 3-letter currency code of any of the supported currencies. When supplied, &#x60;totals_converted&#x60; is returned per each interval which contains the currency-converted total amounts in the given currency. You may also set this parameter to &#x60;default_currency&#x60; in which case the user&#39;s default currency is used. (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getDealsTimelineRequest($start_date, $interval, $amount, $field_key, $user_id = null, $pipeline_id = null, $filter_id = null, $exclude_deals = null, $totals_convert_currency = null): Request
    {
        // verify the required parameter 'start_date' is set
        /* @phpstan-ignore-next-line */
        if ($start_date === null || (is_array($start_date) && count($start_date) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $start_date when calling getDealsTimeline'
            );
        }
        // verify the required parameter 'interval' is set
        /* @phpstan-ignore-next-line */
        if ($interval === null || (is_array($interval) && count($interval) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $interval when calling getDealsTimeline'
            );
        }
        // verify the required parameter 'amount' is set
        /* @phpstan-ignore-next-line */
        if ($amount === null || (is_array($amount) && count($amount) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $amount when calling getDealsTimeline'
            );
        }
        // verify the required parameter 'field_key' is set
        /* @phpstan-ignore-next-line */
        if ($field_key === null || (is_array($field_key) && count($field_key) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $field_key when calling getDealsTimeline'
            );
        }

        $resourcePath = '/deals/timeline';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($start_date)) {
            $start_date = ObjectSerializer::serializeCollection($start_date, '', true);
        }
        if ($start_date !== null) {
            $queryParams['start_date'] = $start_date;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($interval)) {
            $interval = ObjectSerializer::serializeCollection($interval, '', true);
        }
        if ($interval !== null) {
            $queryParams['interval'] = $interval;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($amount)) {
            $amount = ObjectSerializer::serializeCollection($amount, '', true);
        }
        if ($amount !== null) {
            $queryParams['amount'] = $amount;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($field_key)) {
            $field_key = ObjectSerializer::serializeCollection($field_key, '', true);
        }
        if ($field_key !== null) {
            $queryParams['field_key'] = $field_key;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($user_id)) {
            $user_id = ObjectSerializer::serializeCollection($user_id, '', true);
        }
        if ($user_id !== null) {
            $queryParams['user_id'] = $user_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($pipeline_id)) {
            $pipeline_id = ObjectSerializer::serializeCollection($pipeline_id, '', true);
        }
        if ($pipeline_id !== null) {
            $queryParams['pipeline_id'] = $pipeline_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($filter_id)) {
            $filter_id = ObjectSerializer::serializeCollection($filter_id, '', true);
        }
        if ($filter_id !== null) {
            $queryParams['filter_id'] = $filter_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($exclude_deals)) {
            $exclude_deals = ObjectSerializer::serializeCollection($exclude_deals, '', true);
        }
        if ($exclude_deals !== null) {
            $queryParams['exclude_deals'] = $exclude_deals;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($totals_convert_currency)) {
            $totals_convert_currency = ObjectSerializer::serializeCollection($totals_convert_currency, '', true);
        }
        if ($totals_convert_currency !== null) {
            $queryParams['totals_convert_currency'] = $totals_convert_currency;
        }




        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation mergeDeals
     *
     * Merge two deals
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\MergeDealsRequest|null $merge_deals_request merge_deals_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetMergedDeal
     */
    public function mergeDeals($id, $merge_deals_request = null)
    {
        list($response) = $this->mergeDealsWithHttpInfo($id, $merge_deals_request);
        return $response;
    }

    /**
     * Operation mergeDealsWithHttpInfo
     *
     * Merge two deals
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\MergeDealsRequest|null $merge_deals_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetMergedDeal, HTTP status code, HTTP response headers (array of strings)
     */
    public function mergeDealsWithHttpInfo($id, $merge_deals_request = null)
    {
        $request = $this->mergeDealsRequest($id, $merge_deals_request);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->mergeDealsRequest($id, $merge_deals_request);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\GetMergedDeal' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetMergedDeal', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\GetMergedDeal' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetMergedDeal', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\GetMergedDeal',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation mergeDealsAsync
     *
     * Merge two deals
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\MergeDealsRequest|null $merge_deals_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function mergeDealsAsync($id, $merge_deals_request = null): PromiseInterface
    {
        return $this->mergeDealsAsyncWithHttpInfo($id, $merge_deals_request)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation mergeDealsAsyncWithHttpInfo
     *
     * Merge two deals
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\MergeDealsRequest|null $merge_deals_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function mergeDealsAsyncWithHttpInfo($id, $merge_deals_request = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetMergedDeal';
        $request = $this->mergeDealsRequest($id, $merge_deals_request);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'mergeDeals'
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\MergeDealsRequest|null $merge_deals_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function mergeDealsRequest($id, $merge_deals_request = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling mergeDeals'
            );
        }

        $resourcePath = '/deals/{id}/merge';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }

        // for model (json/xml)
        if (isset($merge_deals_request)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode(ObjectSerializer::sanitizeForSerialization($merge_deals_request));
            } else {
                $httpBody = $merge_deals_request;
            }
        } elseif (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'PUT',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation searchDeals
     *
     * Search deals
     *
     * @param  string $term The search term to look for. Minimum 2 characters (or 1 if using &#x60;exact_match&#x60;). Please note that the search term has to be URL encoded. (required)
     * @param  string|null $fields A comma-separated string array. The fields to perform the search from. Defaults to all of them. Only the following custom field types are searchable: &#x60;address&#x60;, &#x60;varchar&#x60;, &#x60;text&#x60;, &#x60;varchar_auto&#x60;, &#x60;double&#x60;, &#x60;monetary&#x60; and &#x60;phone&#x60;. Read more about searching by custom fields &lt;a href&#x3D;\&quot;https://support.pipedrive.com/en/article/search-finding-what-you-need#searching-by-custom-fields\&quot; target&#x3D;\&quot;_blank\&quot; rel&#x3D;\&quot;noopener noreferrer\&quot;&gt;here&lt;/a&gt;. (optional)
     * @param  bool|null $exact_match When enabled, only full exact matches against the given term are returned. It is &lt;b&gt;not&lt;/b&gt; case sensitive. (optional)
     * @param  int|null $person_id Will filter deals by the provided person ID. The upper limit of found deals associated with the person is 2000. (optional)
     * @param  int|null $organization_id Will filter deals by the provided organization ID. The upper limit of found deals associated with the organization is 2000. (optional)
     * @param  string|null $status Will filter deals by the provided specific status. open &#x3D; Open, won &#x3D; Won, lost &#x3D; Lost. The upper limit of found deals associated with the status is 2000. (optional)
     * @param  string|null $include_fields Supports including optional fields in the results which are not provided by default (optional)
     * @param  int|0 $start Pagination start. Note that the pagination is based on main results and does not include related items when using &#x60;search_for_related_items&#x60; parameter. (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DealSearchResponse
     */
    public function searchDeals($term, $fields = null, $exact_match = null, $person_id = null, $organization_id = null, $status = null, $include_fields = null, $start = 0, $limit = null)
    {
        list($response) = $this->searchDealsWithHttpInfo($term, $fields, $exact_match, $person_id, $organization_id, $status, $include_fields, $start, $limit);
        return $response;
    }

    /**
     * Operation searchDealsWithHttpInfo
     *
     * Search deals
     *
     * @param  string $term The search term to look for. Minimum 2 characters (or 1 if using &#x60;exact_match&#x60;). Please note that the search term has to be URL encoded. (required)
     * @param  string|null $fields A comma-separated string array. The fields to perform the search from. Defaults to all of them. Only the following custom field types are searchable: &#x60;address&#x60;, &#x60;varchar&#x60;, &#x60;text&#x60;, &#x60;varchar_auto&#x60;, &#x60;double&#x60;, &#x60;monetary&#x60; and &#x60;phone&#x60;. Read more about searching by custom fields &lt;a href&#x3D;\&quot;https://support.pipedrive.com/en/article/search-finding-what-you-need#searching-by-custom-fields\&quot; target&#x3D;\&quot;_blank\&quot; rel&#x3D;\&quot;noopener noreferrer\&quot;&gt;here&lt;/a&gt;. (optional)
     * @param  bool|null $exact_match When enabled, only full exact matches against the given term are returned. It is &lt;b&gt;not&lt;/b&gt; case sensitive. (optional)
     * @param  int|null $person_id Will filter deals by the provided person ID. The upper limit of found deals associated with the person is 2000. (optional)
     * @param  int|null $organization_id Will filter deals by the provided organization ID. The upper limit of found deals associated with the organization is 2000. (optional)
     * @param  string|null $status Will filter deals by the provided specific status. open &#x3D; Open, won &#x3D; Won, lost &#x3D; Lost. The upper limit of found deals associated with the status is 2000. (optional)
     * @param  string|null $include_fields Supports including optional fields in the results which are not provided by default (optional)
     * @param  int|0 $start Pagination start. Note that the pagination is based on main results and does not include related items when using &#x60;search_for_related_items&#x60; parameter. (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\DealSearchResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function searchDealsWithHttpInfo($term, $fields = null, $exact_match = null, $person_id = null, $organization_id = null, $status = null, $include_fields = null, $start = 0, $limit = null)
    {
        $request = $this->searchDealsRequest($term, $fields, $exact_match, $person_id, $organization_id, $status, $include_fields, $start, $limit);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->searchDealsRequest($term, $fields, $exact_match, $person_id, $organization_id, $status, $include_fields, $start, $limit);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\DealSearchResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DealSearchResponse', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\DealSearchResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\DealSearchResponse', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\DealSearchResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation searchDealsAsync
     *
     * Search deals
     *
     * @param  string $term The search term to look for. Minimum 2 characters (or 1 if using &#x60;exact_match&#x60;). Please note that the search term has to be URL encoded. (required)
     * @param  string|null $fields A comma-separated string array. The fields to perform the search from. Defaults to all of them. Only the following custom field types are searchable: &#x60;address&#x60;, &#x60;varchar&#x60;, &#x60;text&#x60;, &#x60;varchar_auto&#x60;, &#x60;double&#x60;, &#x60;monetary&#x60; and &#x60;phone&#x60;. Read more about searching by custom fields &lt;a href&#x3D;\&quot;https://support.pipedrive.com/en/article/search-finding-what-you-need#searching-by-custom-fields\&quot; target&#x3D;\&quot;_blank\&quot; rel&#x3D;\&quot;noopener noreferrer\&quot;&gt;here&lt;/a&gt;. (optional)
     * @param  bool|null $exact_match When enabled, only full exact matches against the given term are returned. It is &lt;b&gt;not&lt;/b&gt; case sensitive. (optional)
     * @param  int|null $person_id Will filter deals by the provided person ID. The upper limit of found deals associated with the person is 2000. (optional)
     * @param  int|null $organization_id Will filter deals by the provided organization ID. The upper limit of found deals associated with the organization is 2000. (optional)
     * @param  string|null $status Will filter deals by the provided specific status. open &#x3D; Open, won &#x3D; Won, lost &#x3D; Lost. The upper limit of found deals associated with the status is 2000. (optional)
     * @param  string|null $include_fields Supports including optional fields in the results which are not provided by default (optional)
     * @param  int|0 $start Pagination start. Note that the pagination is based on main results and does not include related items when using &#x60;search_for_related_items&#x60; parameter. (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function searchDealsAsync($term, $fields = null, $exact_match = null, $person_id = null, $organization_id = null, $status = null, $include_fields = null, $start = 0, $limit = null): PromiseInterface
    {
        return $this->searchDealsAsyncWithHttpInfo($term, $fields, $exact_match, $person_id, $organization_id, $status, $include_fields, $start, $limit)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation searchDealsAsyncWithHttpInfo
     *
     * Search deals
     *
     * @param  string $term The search term to look for. Minimum 2 characters (or 1 if using &#x60;exact_match&#x60;). Please note that the search term has to be URL encoded. (required)
     * @param  string|null $fields A comma-separated string array. The fields to perform the search from. Defaults to all of them. Only the following custom field types are searchable: &#x60;address&#x60;, &#x60;varchar&#x60;, &#x60;text&#x60;, &#x60;varchar_auto&#x60;, &#x60;double&#x60;, &#x60;monetary&#x60; and &#x60;phone&#x60;. Read more about searching by custom fields &lt;a href&#x3D;\&quot;https://support.pipedrive.com/en/article/search-finding-what-you-need#searching-by-custom-fields\&quot; target&#x3D;\&quot;_blank\&quot; rel&#x3D;\&quot;noopener noreferrer\&quot;&gt;here&lt;/a&gt;. (optional)
     * @param  bool|null $exact_match When enabled, only full exact matches against the given term are returned. It is &lt;b&gt;not&lt;/b&gt; case sensitive. (optional)
     * @param  int|null $person_id Will filter deals by the provided person ID. The upper limit of found deals associated with the person is 2000. (optional)
     * @param  int|null $organization_id Will filter deals by the provided organization ID. The upper limit of found deals associated with the organization is 2000. (optional)
     * @param  string|null $status Will filter deals by the provided specific status. open &#x3D; Open, won &#x3D; Won, lost &#x3D; Lost. The upper limit of found deals associated with the status is 2000. (optional)
     * @param  string|null $include_fields Supports including optional fields in the results which are not provided by default (optional)
     * @param  int|0 $start Pagination start. Note that the pagination is based on main results and does not include related items when using &#x60;search_for_related_items&#x60; parameter. (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function searchDealsAsyncWithHttpInfo($term, $fields = null, $exact_match = null, $person_id = null, $organization_id = null, $status = null, $include_fields = null, $start = 0, $limit = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DealSearchResponse';
        $request = $this->searchDealsRequest($term, $fields, $exact_match, $person_id, $organization_id, $status, $include_fields, $start, $limit);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'searchDeals'
     *
     * @param  string $term The search term to look for. Minimum 2 characters (or 1 if using &#x60;exact_match&#x60;). Please note that the search term has to be URL encoded. (required)
     * @param  string|null $fields A comma-separated string array. The fields to perform the search from. Defaults to all of them. Only the following custom field types are searchable: &#x60;address&#x60;, &#x60;varchar&#x60;, &#x60;text&#x60;, &#x60;varchar_auto&#x60;, &#x60;double&#x60;, &#x60;monetary&#x60; and &#x60;phone&#x60;. Read more about searching by custom fields &lt;a href&#x3D;\&quot;https://support.pipedrive.com/en/article/search-finding-what-you-need#searching-by-custom-fields\&quot; target&#x3D;\&quot;_blank\&quot; rel&#x3D;\&quot;noopener noreferrer\&quot;&gt;here&lt;/a&gt;. (optional)
     * @param  bool|null $exact_match When enabled, only full exact matches against the given term are returned. It is &lt;b&gt;not&lt;/b&gt; case sensitive. (optional)
     * @param  int|null $person_id Will filter deals by the provided person ID. The upper limit of found deals associated with the person is 2000. (optional)
     * @param  int|null $organization_id Will filter deals by the provided organization ID. The upper limit of found deals associated with the organization is 2000. (optional)
     * @param  string|null $status Will filter deals by the provided specific status. open &#x3D; Open, won &#x3D; Won, lost &#x3D; Lost. The upper limit of found deals associated with the status is 2000. (optional)
     * @param  string|null $include_fields Supports including optional fields in the results which are not provided by default (optional)
     * @param  int|0 $start Pagination start. Note that the pagination is based on main results and does not include related items when using &#x60;search_for_related_items&#x60; parameter. (optional, default to 0)
     * @param  int|null $limit Items shown per page (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function searchDealsRequest($term, $fields = null, $exact_match = null, $person_id = null, $organization_id = null, $status = null, $include_fields = null, $start = 0, $limit = null): Request
    {
        // verify the required parameter 'term' is set
        /* @phpstan-ignore-next-line */
        if ($term === null || (is_array($term) && count($term) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $term when calling searchDeals'
            );
        }

        $resourcePath = '/deals/search';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($term)) {
            $term = ObjectSerializer::serializeCollection($term, '', true);
        }
        if ($term !== null) {
            $queryParams['term'] = $term;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($fields)) {
            $fields = ObjectSerializer::serializeCollection($fields, '', true);
        }
        if ($fields !== null) {
            $queryParams['fields'] = $fields;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($exact_match)) {
            $exact_match = ObjectSerializer::serializeCollection($exact_match, '', true);
        }
        if ($exact_match !== null) {
            $queryParams['exact_match'] = $exact_match;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($person_id)) {
            $person_id = ObjectSerializer::serializeCollection($person_id, '', true);
        }
        if ($person_id !== null) {
            $queryParams['person_id'] = $person_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($organization_id)) {
            $organization_id = ObjectSerializer::serializeCollection($organization_id, '', true);
        }
        if ($organization_id !== null) {
            $queryParams['organization_id'] = $organization_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($status)) {
            $status = ObjectSerializer::serializeCollection($status, '', true);
        }
        if ($status !== null) {
            $queryParams['status'] = $status;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($include_fields)) {
            $include_fields = ObjectSerializer::serializeCollection($include_fields, '', true);
        }
        if ($include_fields !== null) {
            $queryParams['include_fields'] = $include_fields;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($start)) {
            $start = ObjectSerializer::serializeCollection($start, '', true);
        }
        if ($start !== null) {
            $queryParams['start'] = $start;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($limit)) {
            $limit = ObjectSerializer::serializeCollection($limit, '', true);
        }
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }




        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }

        // for model (json/xml)
        if (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation updateDeal
     *
     * Update a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\UpdateDealRequest|null $update_deal_request update_deal_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetAddedDeal
     */
    public function updateDeal($id, $update_deal_request = null)
    {
        list($response) = $this->updateDealWithHttpInfo($id, $update_deal_request);
        return $response;
    }

    /**
     * Operation updateDealWithHttpInfo
     *
     * Update a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\UpdateDealRequest|null $update_deal_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetAddedDeal, HTTP status code, HTTP response headers (array of strings)
     */
    public function updateDealWithHttpInfo($id, $update_deal_request = null)
    {
        $request = $this->updateDealRequest($id, $update_deal_request);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->updateDealRequest($id, $update_deal_request);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\GetAddedDeal' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetAddedDeal', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\GetAddedDeal' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetAddedDeal', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\GetAddedDeal',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation updateDealAsync
     *
     * Update a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\UpdateDealRequest|null $update_deal_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function updateDealAsync($id, $update_deal_request = null): PromiseInterface
    {
        return $this->updateDealAsyncWithHttpInfo($id, $update_deal_request)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation updateDealAsyncWithHttpInfo
     *
     * Update a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\UpdateDealRequest|null $update_deal_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function updateDealAsyncWithHttpInfo($id, $update_deal_request = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetAddedDeal';
        $request = $this->updateDealRequest($id, $update_deal_request);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'updateDeal'
     *
     * @param  int $id The ID of the deal (required)
     * @param  \Pipedrive\Model\UpdateDealRequest|null $update_deal_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function updateDealRequest($id, $update_deal_request = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling updateDeal'
            );
        }

        $resourcePath = '/deals/{id}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }

        // for model (json/xml)
        if (isset($update_deal_request)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode(ObjectSerializer::sanitizeForSerialization($update_deal_request));
            } else {
                $httpBody = $update_deal_request;
            }
        } elseif (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'PUT',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation updateDealProduct
     *
     * Update the product attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $product_attachment_id The ID of the deal-product (the ID of the product attached to the deal) (required)
     * @param  \Pipedrive\Model\UpdateDealProduct|null $update_deal_product update_deal_product (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetProductAttachmentDetails
     */
    public function updateDealProduct($id, $product_attachment_id, $update_deal_product = null)
    {
        list($response) = $this->updateDealProductWithHttpInfo($id, $product_attachment_id, $update_deal_product);
        return $response;
    }

    /**
     * Operation updateDealProductWithHttpInfo
     *
     * Update the product attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $product_attachment_id The ID of the deal-product (the ID of the product attached to the deal) (required)
     * @param  \Pipedrive\Model\UpdateDealProduct|null $update_deal_product (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetProductAttachmentDetails, HTTP status code, HTTP response headers (array of strings)
     */
    public function updateDealProductWithHttpInfo($id, $product_attachment_id, $update_deal_product = null)
    {
        $request = $this->updateDealProductRequest($id, $product_attachment_id, $update_deal_product);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                if ($e->getCode() === 401 && $this->config->isRefreshPossible()) {
                    $this->config->refreshToken();
                    $request = $this->updateDealProductRequest($id, $product_attachment_id, $update_deal_product);
                    $response = $this->client->send($request, $options);
                } else {
                    throw new ApiException(
                        "[{$e->getCode()}] {$e->getMessage()}",
                        (int) $e->getCode(),
                        $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                        $e->getResponse() ? (string) $e->getResponse()->getBody() : null
                    );
                }
            } catch (ConnectException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    (int) $e->getCode(),
                    null,
                    null
                );
            }

            $statusCode = $response->getStatusCode();


            switch($statusCode) {
                case 200:
                    /* @phpstan-ignore-next-line */
                    if ('\Pipedrive\Model\GetProductAttachmentDetails' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetProductAttachmentDetails', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        (string) $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    (string) $response->getBody()
                );
            }

            /* @phpstan-ignore-next-line */
            if ('\Pipedrive\Model\GetProductAttachmentDetails' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

            return [
                ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetProductAttachmentDetails', []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\GetProductAttachmentDetails',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation updateDealProductAsync
     *
     * Update the product attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $product_attachment_id The ID of the deal-product (the ID of the product attached to the deal) (required)
     * @param  \Pipedrive\Model\UpdateDealProduct|null $update_deal_product (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function updateDealProductAsync($id, $product_attachment_id, $update_deal_product = null): PromiseInterface
    {
        return $this->updateDealProductAsyncWithHttpInfo($id, $product_attachment_id, $update_deal_product)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation updateDealProductAsyncWithHttpInfo
     *
     * Update the product attached to a deal
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $product_attachment_id The ID of the deal-product (the ID of the product attached to the deal) (required)
     * @param  \Pipedrive\Model\UpdateDealProduct|null $update_deal_product (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function updateDealProductAsyncWithHttpInfo($id, $product_attachment_id, $update_deal_product = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetProductAttachmentDetails';
        $request = $this->updateDealProductRequest($id, $product_attachment_id, $update_deal_product);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    /* @phpstan-ignore-next-line */
                    if ($returnType === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        (string) $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'updateDealProduct'
     *
     * @param  int $id The ID of the deal (required)
     * @param  int $product_attachment_id The ID of the deal-product (the ID of the product attached to the deal) (required)
     * @param  \Pipedrive\Model\UpdateDealProduct|null $update_deal_product (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function updateDealProductRequest($id, $product_attachment_id, $update_deal_product = null): Request
    {
        // verify the required parameter 'id' is set
        /* @phpstan-ignore-next-line */
        if ($id === null || (is_array($id) && count($id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $id when calling updateDealProduct'
            );
        }
        // verify the required parameter 'product_attachment_id' is set
        /* @phpstan-ignore-next-line */
        if ($product_attachment_id === null || (is_array($product_attachment_id) && count($product_attachment_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $product_attachment_id when calling updateDealProduct'
            );
        }

        $resourcePath = '/deals/{id}/products/{product_attachment_id}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;



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


        /* @phpstan-ignore-next-line */
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }

        // for model (json/xml)
        if (isset($update_deal_product)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode(ObjectSerializer::sanitizeForSerialization($update_deal_product));
            } else {
                $httpBody = $update_deal_product;
            }
        } elseif (count($formParams) > 0) {
            /* @phpstan-ignore-next-line */
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = Query::build($formParams);
            }
        }

        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('api_token');
        if ($apiKey !== null) {
            $queryParams['api_token'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            // If access token is expired
            if ($this->config->isRefreshPossible() && $this->config->getExpiresAt() <= time()) {
                $this->config->refreshToken();
            }
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = Query::build($queryParams);
        return new Request(
            'PUT',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Create http client option
     *
     * @throws RuntimeException on file opening failure
     * @return array<string, resource> of http client options
     */
    protected function createHttpClientOption(): array
    {
        $options = [];
        if ($this->config->getDebug()) {
            $options[RequestOptions::DEBUG] = fopen($this->config->getDebugFile(), 'a');
            if (!$options[RequestOptions::DEBUG]) {
                throw new RuntimeException('Failed to open the debug file: ' . $this->config->getDebugFile());
            }
        }

        return $options;
    }
}
