<?php
/**
 * PersonsApi
 * 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;

/**
 * PersonsApi Class Doc Comment
 *
 * @category Class
 * @package  Pipedrive
 * @author   OpenAPI Generator team
 * @link     https://openapi-generator.tech
 */
class PersonsApi
{
    /**
     * @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 addPerson
     *
     * Add a person
     *
     * @param  \Pipedrive\Model\NewPerson|null $new_person new_person (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\AddPersonResponse
     */
    public function addPerson($new_person = null)
    {
        list($response) = $this->addPersonWithHttpInfo($new_person);
        return $response;
    }

    /**
     * Operation addPersonWithHttpInfo
     *
     * Add a person
     *
     * @param  \Pipedrive\Model\NewPerson|null $new_person (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\AddPersonResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function addPersonWithHttpInfo($new_person = null)
    {
        $request = $this->addPersonRequest($new_person);

        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->addPersonRequest($new_person);
                    $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\AddPersonResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\AddPersonResponse', []),
                        $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\AddPersonResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

    /**
     * Operation addPersonAsync
     *
     * Add a person
     *
     * @param  \Pipedrive\Model\NewPerson|null $new_person (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addPersonAsync($new_person = null): PromiseInterface
    {
        return $this->addPersonAsyncWithHttpInfo($new_person)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation addPersonAsyncWithHttpInfo
     *
     * Add a person
     *
     * @param  \Pipedrive\Model\NewPerson|null $new_person (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addPersonAsyncWithHttpInfo($new_person = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\AddPersonResponse';
        $request = $this->addPersonRequest($new_person);

        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 'addPerson'
     *
     * @param  \Pipedrive\Model\NewPerson|null $new_person (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function addPersonRequest($new_person = null): Request
    {

        $resourcePath = '/persons';
        $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_person)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode(ObjectSerializer::sanitizeForSerialization($new_person));
            } else {
                $httpBody = $new_person;
            }
        } 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 addPersonFollower
     *
     * Add a follower to a person
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\AddPersonFollowerRequest|null $add_person_follower_request add_person_follower_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\AddFollowerToPersonResponse
     */
    public function addPersonFollower($id, $add_person_follower_request = null)
    {
        list($response) = $this->addPersonFollowerWithHttpInfo($id, $add_person_follower_request);
        return $response;
    }

    /**
     * Operation addPersonFollowerWithHttpInfo
     *
     * Add a follower to a person
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\AddPersonFollowerRequest|null $add_person_follower_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\AddFollowerToPersonResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function addPersonFollowerWithHttpInfo($id, $add_person_follower_request = null)
    {
        $request = $this->addPersonFollowerRequest($id, $add_person_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->addPersonFollowerRequest($id, $add_person_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\AddFollowerToPersonResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\AddFollowerToPersonResponse', []),
                        $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\AddFollowerToPersonResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

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

    /**
     * Operation addPersonFollowerAsyncWithHttpInfo
     *
     * Add a follower to a person
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\AddPersonFollowerRequest|null $add_person_follower_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addPersonFollowerAsyncWithHttpInfo($id, $add_person_follower_request = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\AddFollowerToPersonResponse';
        $request = $this->addPersonFollowerRequest($id, $add_person_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 'addPersonFollower'
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\AddPersonFollowerRequest|null $add_person_follower_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function addPersonFollowerRequest($id, $add_person_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 addPersonFollower'
            );
        }

        $resourcePath = '/persons/{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_person_follower_request)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode(ObjectSerializer::sanitizeForSerialization($add_person_follower_request));
            } else {
                $httpBody = $add_person_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 addPersonPicture
     *
     * Add person picture
     *
     * @param  int $id The ID of the person (required)
     * @param  \SplFileObject $file One image supplied in the multipart/form-data encoding (required)
     * @param  int|null $crop_x X coordinate to where start cropping form (in pixels) (optional)
     * @param  int|null $crop_y Y coordinate to where start cropping form (in pixels) (optional)
     * @param  int|null $crop_width The width of the cropping area (in pixels) (optional)
     * @param  int|null $crop_height The height of the cropping area (in pixels) (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\AddPersonPictureResponse
     */
    public function addPersonPicture($id, $file, $crop_x = null, $crop_y = null, $crop_width = null, $crop_height = null)
    {
        list($response) = $this->addPersonPictureWithHttpInfo($id, $file, $crop_x, $crop_y, $crop_width, $crop_height);
        return $response;
    }

    /**
     * Operation addPersonPictureWithHttpInfo
     *
     * Add person picture
     *
     * @param  int $id The ID of the person (required)
     * @param  \SplFileObject $file One image supplied in the multipart/form-data encoding (required)
     * @param  int|null $crop_x X coordinate to where start cropping form (in pixels) (optional)
     * @param  int|null $crop_y Y coordinate to where start cropping form (in pixels) (optional)
     * @param  int|null $crop_width The width of the cropping area (in pixels) (optional)
     * @param  int|null $crop_height The height of the cropping area (in pixels) (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\AddPersonPictureResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function addPersonPictureWithHttpInfo($id, $file, $crop_x = null, $crop_y = null, $crop_width = null, $crop_height = null)
    {
        $request = $this->addPersonPictureRequest($id, $file, $crop_x, $crop_y, $crop_width, $crop_height);

        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->addPersonPictureRequest($id, $file, $crop_x, $crop_y, $crop_width, $crop_height);
                    $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\AddPersonPictureResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\AddPersonPictureResponse', []),
                        $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\AddPersonPictureResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

    /**
     * Operation addPersonPictureAsync
     *
     * Add person picture
     *
     * @param  int $id The ID of the person (required)
     * @param  \SplFileObject $file One image supplied in the multipart/form-data encoding (required)
     * @param  int|null $crop_x X coordinate to where start cropping form (in pixels) (optional)
     * @param  int|null $crop_y Y coordinate to where start cropping form (in pixels) (optional)
     * @param  int|null $crop_width The width of the cropping area (in pixels) (optional)
     * @param  int|null $crop_height The height of the cropping area (in pixels) (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addPersonPictureAsync($id, $file, $crop_x = null, $crop_y = null, $crop_width = null, $crop_height = null): PromiseInterface
    {
        return $this->addPersonPictureAsyncWithHttpInfo($id, $file, $crop_x, $crop_y, $crop_width, $crop_height)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation addPersonPictureAsyncWithHttpInfo
     *
     * Add person picture
     *
     * @param  int $id The ID of the person (required)
     * @param  \SplFileObject $file One image supplied in the multipart/form-data encoding (required)
     * @param  int|null $crop_x X coordinate to where start cropping form (in pixels) (optional)
     * @param  int|null $crop_y Y coordinate to where start cropping form (in pixels) (optional)
     * @param  int|null $crop_width The width of the cropping area (in pixels) (optional)
     * @param  int|null $crop_height The height of the cropping area (in pixels) (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function addPersonPictureAsyncWithHttpInfo($id, $file, $crop_x = null, $crop_y = null, $crop_width = null, $crop_height = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\AddPersonPictureResponse';
        $request = $this->addPersonPictureRequest($id, $file, $crop_x, $crop_y, $crop_width, $crop_height);

        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 'addPersonPicture'
     *
     * @param  int $id The ID of the person (required)
     * @param  \SplFileObject $file One image supplied in the multipart/form-data encoding (required)
     * @param  int|null $crop_x X coordinate to where start cropping form (in pixels) (optional)
     * @param  int|null $crop_y Y coordinate to where start cropping form (in pixels) (optional)
     * @param  int|null $crop_width The width of the cropping area (in pixels) (optional)
     * @param  int|null $crop_height The height of the cropping area (in pixels) (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function addPersonPictureRequest($id, $file, $crop_x = null, $crop_y = null, $crop_width = null, $crop_height = 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 addPersonPicture'
            );
        }
        // verify the required parameter 'file' is set
        /* @phpstan-ignore-next-line */
        if ($file === null || (is_array($file) && count($file) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $file when calling addPersonPicture'
            );
        }

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



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

        // form params
        if ($file !== null) {
            $multipart = true;
            $formParams['file'] = [];
            /* @phpstan-ignore-next-line */
            $paramFiles = is_array($file) ? $file : [$file];
            foreach ($paramFiles as $paramFile) {
                $formParams['file'][] = \GuzzleHttp\Psr7\Utils::tryFopen(
                    ObjectSerializer::toFormValue($paramFile),
                    'rb'
                );
            }
        }
        // form params
        if ($crop_x !== null) {
            $formParams['crop_x'] = ObjectSerializer::toFormValue($crop_x);
        }
        // form params
        if ($crop_y !== null) {
            $formParams['crop_y'] = ObjectSerializer::toFormValue($crop_y);
        }
        // form params
        if ($crop_width !== null) {
            $formParams['crop_width'] = ObjectSerializer::toFormValue($crop_width);
        }
        // form params
        if ($crop_height !== null) {
            $formParams['crop_height'] = ObjectSerializer::toFormValue($crop_height);
        }

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

        // 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 deletePerson
     *
     * Delete a person
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DeletePersonResponse
     */
    public function deletePerson($id)
    {
        list($response) = $this->deletePersonWithHttpInfo($id);
        return $response;
    }

    /**
     * Operation deletePersonWithHttpInfo
     *
     * Delete a person
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\DeletePersonResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function deletePersonWithHttpInfo($id)
    {
        $request = $this->deletePersonRequest($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->deletePersonRequest($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\DeletePersonResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeletePersonResponse', []),
                        $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\DeletePersonResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

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

    /**
     * Operation deletePersonAsyncWithHttpInfo
     *
     * Delete a person
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deletePersonAsyncWithHttpInfo($id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DeletePersonResponse';
        $request = $this->deletePersonRequest($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 'deletePerson'
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function deletePersonRequest($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 deletePerson'
            );
        }

        $resourcePath = '/persons/{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 deletePersonFollower
     *
     * Delete a follower from a person
     *
     * @param  int $id The ID of the person (required)
     * @param  int $follower_id The ID of the follower (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DeletePersonResponse
     */
    public function deletePersonFollower($id, $follower_id)
    {
        list($response) = $this->deletePersonFollowerWithHttpInfo($id, $follower_id);
        return $response;
    }

    /**
     * Operation deletePersonFollowerWithHttpInfo
     *
     * Delete a follower from a person
     *
     * @param  int $id The ID of the person (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\DeletePersonResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function deletePersonFollowerWithHttpInfo($id, $follower_id)
    {
        $request = $this->deletePersonFollowerRequest($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->deletePersonFollowerRequest($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\DeletePersonResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeletePersonResponse', []),
                        $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\DeletePersonResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

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

    /**
     * Operation deletePersonFollowerAsyncWithHttpInfo
     *
     * Delete a follower from a person
     *
     * @param  int $id The ID of the person (required)
     * @param  int $follower_id The ID of the follower (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deletePersonFollowerAsyncWithHttpInfo($id, $follower_id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DeletePersonResponse';
        $request = $this->deletePersonFollowerRequest($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 'deletePersonFollower'
     *
     * @param  int $id The ID of the person (required)
     * @param  int $follower_id The ID of the follower (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function deletePersonFollowerRequest($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 deletePersonFollower'
            );
        }
        // 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 deletePersonFollower'
            );
        }

        $resourcePath = '/persons/{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 deletePersonPicture
     *
     * Delete person picture
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\DeletePersonResponse
     */
    public function deletePersonPicture($id)
    {
        list($response) = $this->deletePersonPictureWithHttpInfo($id);
        return $response;
    }

    /**
     * Operation deletePersonPictureWithHttpInfo
     *
     * Delete person picture
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\DeletePersonResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function deletePersonPictureWithHttpInfo($id)
    {
        $request = $this->deletePersonPictureRequest($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->deletePersonPictureRequest($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\DeletePersonResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeletePersonResponse', []),
                        $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\DeletePersonResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

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

    /**
     * Operation deletePersonPictureAsyncWithHttpInfo
     *
     * Delete person picture
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deletePersonPictureAsyncWithHttpInfo($id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DeletePersonResponse';
        $request = $this->deletePersonPictureRequest($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 'deletePersonPicture'
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function deletePersonPictureRequest($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 deletePersonPicture'
            );
        }

        $resourcePath = '/persons/{id}/picture';
        $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 deletePersons
     *
     * Delete multiple persons 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\DeletePersonsInBulkResponse
     */
    public function deletePersons($ids)
    {
        list($response) = $this->deletePersonsWithHttpInfo($ids);
        return $response;
    }

    /**
     * Operation deletePersonsWithHttpInfo
     *
     * Delete multiple persons 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\DeletePersonsInBulkResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function deletePersonsWithHttpInfo($ids)
    {
        $request = $this->deletePersonsRequest($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->deletePersonsRequest($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\DeletePersonsInBulkResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\DeletePersonsInBulkResponse', []),
                        $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\DeletePersonsInBulkResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

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

    /**
     * Operation deletePersonsAsyncWithHttpInfo
     *
     * Delete multiple persons in bulk
     *
     * @param  string $ids The comma-separated IDs that will be deleted (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function deletePersonsAsyncWithHttpInfo($ids): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\DeletePersonsInBulkResponse';
        $request = $this->deletePersonsRequest($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 'deletePersons'
     *
     * @param  string $ids The comma-separated IDs that will be deleted (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function deletePersonsRequest($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 deletePersons'
            );
        }

        $resourcePath = '/persons';
        $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 getPerson
     *
     * Get details of a person
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetPersonDetailsResponse
     */
    public function getPerson($id)
    {
        list($response) = $this->getPersonWithHttpInfo($id);
        return $response;
    }

    /**
     * Operation getPersonWithHttpInfo
     *
     * Get details of a person
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetPersonDetailsResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getPersonWithHttpInfo($id)
    {
        $request = $this->getPersonRequest($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->getPersonRequest($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\GetPersonDetailsResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetPersonDetailsResponse', []),
                        $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\GetPersonDetailsResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

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

    /**
     * Operation getPersonAsyncWithHttpInfo
     *
     * Get details of a person
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getPersonAsyncWithHttpInfo($id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetPersonDetailsResponse';
        $request = $this->getPersonRequest($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 'getPerson'
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getPersonRequest($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 getPerson'
            );
        }

        $resourcePath = '/persons/{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 getPersonActivities
     *
     * List activities associated with a person
     *
     * @param  int $id The ID of the person (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\ListActivitiesResponse
     */
    public function getPersonActivities($id, $start = 0, $limit = null, $done = null, $exclude = null)
    {
        list($response) = $this->getPersonActivitiesWithHttpInfo($id, $start, $limit, $done, $exclude);
        return $response;
    }

    /**
     * Operation getPersonActivitiesWithHttpInfo
     *
     * List activities associated with a person
     *
     * @param  int $id The ID of the person (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\ListActivitiesResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getPersonActivitiesWithHttpInfo($id, $start = 0, $limit = null, $done = null, $exclude = null)
    {
        $request = $this->getPersonActivitiesRequest($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->getPersonActivitiesRequest($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\ListActivitiesResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListActivitiesResponse', []),
                        $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\ListActivitiesResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

    /**
     * Operation getPersonActivitiesAsync
     *
     * List activities associated with a person
     *
     * @param  int $id The ID of the person (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 getPersonActivitiesAsync($id, $start = 0, $limit = null, $done = null, $exclude = null): PromiseInterface
    {
        return $this->getPersonActivitiesAsyncWithHttpInfo($id, $start, $limit, $done, $exclude)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getPersonActivitiesAsyncWithHttpInfo
     *
     * List activities associated with a person
     *
     * @param  int $id The ID of the person (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 getPersonActivitiesAsyncWithHttpInfo($id, $start = 0, $limit = null, $done = null, $exclude = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListActivitiesResponse';
        $request = $this->getPersonActivitiesRequest($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 'getPersonActivities'
     *
     * @param  int $id The ID of the person (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 getPersonActivitiesRequest($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 getPersonActivities'
            );
        }

        $resourcePath = '/persons/{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 getPersonChangelog
     *
     * List updates about person field values
     *
     * @param  int $id The ID of the person (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 getPersonChangelog($id, $cursor = null, $limit = null)
    {
        list($response) = $this->getPersonChangelogWithHttpInfo($id, $cursor, $limit);
        return $response;
    }

    /**
     * Operation getPersonChangelogWithHttpInfo
     *
     * List updates about person field values
     *
     * @param  int $id The ID of the person (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 getPersonChangelogWithHttpInfo($id, $cursor = null, $limit = null)
    {
        $request = $this->getPersonChangelogRequest($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->getPersonChangelogRequest($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 getPersonChangelogAsync
     *
     * List updates about person field values
     *
     * @param  int $id The ID of the person (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 getPersonChangelogAsync($id, $cursor = null, $limit = null): PromiseInterface
    {
        return $this->getPersonChangelogAsyncWithHttpInfo($id, $cursor, $limit)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getPersonChangelogAsyncWithHttpInfo
     *
     * List updates about person field values
     *
     * @param  int $id The ID of the person (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 getPersonChangelogAsyncWithHttpInfo($id, $cursor = null, $limit = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ChangelogResponse';
        $request = $this->getPersonChangelogRequest($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 'getPersonChangelog'
     *
     * @param  int $id The ID of the person (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 getPersonChangelogRequest($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 getPersonChangelog'
            );
        }

        $resourcePath = '/persons/{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 getPersonDeals
     *
     * List deals associated with a person
     *
     * @param  int $id The ID of the person (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (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  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)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\ListDealsResponse
     */
    public function getPersonDeals($id, $start = 0, $limit = null, $status = 'all_not_deleted', $sort = null)
    {
        list($response) = $this->getPersonDealsWithHttpInfo($id, $start, $limit, $status, $sort);
        return $response;
    }

    /**
     * Operation getPersonDealsWithHttpInfo
     *
     * List deals associated with a person
     *
     * @param  int $id The ID of the person (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (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  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)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\ListDealsResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getPersonDealsWithHttpInfo($id, $start = 0, $limit = null, $status = 'all_not_deleted', $sort = null)
    {
        $request = $this->getPersonDealsRequest($id, $start, $limit, $status, $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->getPersonDealsRequest($id, $start, $limit, $status, $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\ListDealsResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListDealsResponse', []),
                        $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\ListDealsResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

    /**
     * Operation getPersonDealsAsync
     *
     * List deals associated with a person
     *
     * @param  int $id The ID of the person (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (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  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)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getPersonDealsAsync($id, $start = 0, $limit = null, $status = 'all_not_deleted', $sort = null): PromiseInterface
    {
        return $this->getPersonDealsAsyncWithHttpInfo($id, $start, $limit, $status, $sort)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getPersonDealsAsyncWithHttpInfo
     *
     * List deals associated with a person
     *
     * @param  int $id The ID of the person (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (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  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)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getPersonDealsAsyncWithHttpInfo($id, $start = 0, $limit = null, $status = 'all_not_deleted', $sort = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListDealsResponse';
        $request = $this->getPersonDealsRequest($id, $start, $limit, $status, $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 'getPersonDeals'
     *
     * @param  int $id The ID of the person (required)
     * @param  int|0 $start Pagination start (optional, default to 0)
     * @param  int|null $limit Items shown per page (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  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)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getPersonDealsRequest($id, $start = 0, $limit = null, $status = 'all_not_deleted', $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 getPersonDeals'
            );
        }

        $resourcePath = '/persons/{id}/deals';
        $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($status)) {
            $status = ObjectSerializer::serializeCollection($status, '', true);
        }
        if ($status !== null) {
            $queryParams['status'] = $status;
        }
        // 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 getPersonFiles
     *
     * List files attached to a person
     *
     * @param  int $id The ID of the person (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 getPersonFiles($id, $start = 0, $limit = null, $sort = null)
    {
        list($response) = $this->getPersonFilesWithHttpInfo($id, $start, $limit, $sort);
        return $response;
    }

    /**
     * Operation getPersonFilesWithHttpInfo
     *
     * List files attached to a person
     *
     * @param  int $id The ID of the person (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 getPersonFilesWithHttpInfo($id, $start = 0, $limit = null, $sort = null)
    {
        $request = $this->getPersonFilesRequest($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->getPersonFilesRequest($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 getPersonFilesAsync
     *
     * List files attached to a person
     *
     * @param  int $id The ID of the person (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 getPersonFilesAsync($id, $start = 0, $limit = null, $sort = null): PromiseInterface
    {
        return $this->getPersonFilesAsyncWithHttpInfo($id, $start, $limit, $sort)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getPersonFilesAsyncWithHttpInfo
     *
     * List files attached to a person
     *
     * @param  int $id The ID of the person (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 getPersonFilesAsyncWithHttpInfo($id, $start = 0, $limit = null, $sort = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListFilesResponse';
        $request = $this->getPersonFilesRequest($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 'getPersonFiles'
     *
     * @param  int $id The ID of the person (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 getPersonFilesRequest($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 getPersonFiles'
            );
        }

        $resourcePath = '/persons/{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 getPersonFollowers
     *
     * List followers of a person
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\ListFollowersResponse
     */
    public function getPersonFollowers($id)
    {
        list($response) = $this->getPersonFollowersWithHttpInfo($id);
        return $response;
    }

    /**
     * Operation getPersonFollowersWithHttpInfo
     *
     * List followers of a person
     *
     * @param  int $id The ID of the person (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 getPersonFollowersWithHttpInfo($id)
    {
        $request = $this->getPersonFollowersRequest($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->getPersonFollowersRequest($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 getPersonFollowersAsync
     *
     * List followers of a person
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getPersonFollowersAsync($id): PromiseInterface
    {
        return $this->getPersonFollowersAsyncWithHttpInfo($id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getPersonFollowersAsyncWithHttpInfo
     *
     * List followers of a person
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getPersonFollowersAsyncWithHttpInfo($id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListFollowersResponse';
        $request = $this->getPersonFollowersRequest($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 'getPersonFollowers'
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getPersonFollowersRequest($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 getPersonFollowers'
            );
        }

        $resourcePath = '/persons/{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 getPersonMailMessages
     *
     * List mail messages associated with a person
     *
     * @param  int $id The ID of the person (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 getPersonMailMessages($id, $start = 0, $limit = null)
    {
        list($response) = $this->getPersonMailMessagesWithHttpInfo($id, $start, $limit);
        return $response;
    }

    /**
     * Operation getPersonMailMessagesWithHttpInfo
     *
     * List mail messages associated with a person
     *
     * @param  int $id The ID of the person (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 getPersonMailMessagesWithHttpInfo($id, $start = 0, $limit = null)
    {
        $request = $this->getPersonMailMessagesRequest($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->getPersonMailMessagesRequest($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 getPersonMailMessagesAsync
     *
     * List mail messages associated with a person
     *
     * @param  int $id The ID of the person (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 getPersonMailMessagesAsync($id, $start = 0, $limit = null): PromiseInterface
    {
        return $this->getPersonMailMessagesAsyncWithHttpInfo($id, $start, $limit)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getPersonMailMessagesAsyncWithHttpInfo
     *
     * List mail messages associated with a person
     *
     * @param  int $id The ID of the person (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 getPersonMailMessagesAsyncWithHttpInfo($id, $start = 0, $limit = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListMailMessagesResponse';
        $request = $this->getPersonMailMessagesRequest($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 'getPersonMailMessages'
     *
     * @param  int $id The ID of the person (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 getPersonMailMessagesRequest($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 getPersonMailMessages'
            );
        }

        $resourcePath = '/persons/{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 getPersonProducts
     *
     * List products associated with a person
     *
     * @param  int $id The ID of the person (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\ListPersonProductsResponse
     */
    public function getPersonProducts($id, $start = 0, $limit = null)
    {
        list($response) = $this->getPersonProductsWithHttpInfo($id, $start, $limit);
        return $response;
    }

    /**
     * Operation getPersonProductsWithHttpInfo
     *
     * List products associated with a person
     *
     * @param  int $id The ID of the person (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\ListPersonProductsResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getPersonProductsWithHttpInfo($id, $start = 0, $limit = null)
    {
        $request = $this->getPersonProductsRequest($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->getPersonProductsRequest($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\ListPersonProductsResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListPersonProductsResponse', []),
                        $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\ListPersonProductsResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

    /**
     * Operation getPersonProductsAsync
     *
     * List products associated with a person
     *
     * @param  int $id The ID of the person (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 getPersonProductsAsync($id, $start = 0, $limit = null): PromiseInterface
    {
        return $this->getPersonProductsAsyncWithHttpInfo($id, $start, $limit)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getPersonProductsAsyncWithHttpInfo
     *
     * List products associated with a person
     *
     * @param  int $id The ID of the person (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 getPersonProductsAsyncWithHttpInfo($id, $start = 0, $limit = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListPersonProductsResponse';
        $request = $this->getPersonProductsRequest($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 'getPersonProducts'
     *
     * @param  int $id The ID of the person (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 getPersonProductsRequest($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 getPersonProducts'
            );
        }

        $resourcePath = '/persons/{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;
        }


        // 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 getPersonUpdates
     *
     * List updates about a person
     *
     * @param  int $id The ID of the person (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\PersonFlowResponse
     */
    public function getPersonUpdates($id, $start = 0, $limit = null, $all_changes = null, $items = null)
    {
        list($response) = $this->getPersonUpdatesWithHttpInfo($id, $start, $limit, $all_changes, $items);
        return $response;
    }

    /**
     * Operation getPersonUpdatesWithHttpInfo
     *
     * List updates about a person
     *
     * @param  int $id The ID of the person (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\PersonFlowResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getPersonUpdatesWithHttpInfo($id, $start = 0, $limit = null, $all_changes = null, $items = null)
    {
        $request = $this->getPersonUpdatesRequest($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->getPersonUpdatesRequest($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\PersonFlowResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\PersonFlowResponse', []),
                        $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\PersonFlowResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

    /**
     * Operation getPersonUpdatesAsync
     *
     * List updates about a person
     *
     * @param  int $id The ID of the person (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 getPersonUpdatesAsync($id, $start = 0, $limit = null, $all_changes = null, $items = null): PromiseInterface
    {
        return $this->getPersonUpdatesAsyncWithHttpInfo($id, $start, $limit, $all_changes, $items)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getPersonUpdatesAsyncWithHttpInfo
     *
     * List updates about a person
     *
     * @param  int $id The ID of the person (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 getPersonUpdatesAsyncWithHttpInfo($id, $start = 0, $limit = null, $all_changes = null, $items = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\PersonFlowResponse';
        $request = $this->getPersonUpdatesRequest($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 'getPersonUpdates'
     *
     * @param  int $id The ID of the person (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 getPersonUpdatesRequest($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 getPersonUpdates'
            );
        }

        $resourcePath = '/persons/{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 getPersonUsers
     *
     * List permitted users
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\ListPermittedUsersResponse1
     */
    public function getPersonUsers($id)
    {
        list($response) = $this->getPersonUsersWithHttpInfo($id);
        return $response;
    }

    /**
     * Operation getPersonUsersWithHttpInfo
     *
     * List permitted users
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\ListPermittedUsersResponse1, HTTP status code, HTTP response headers (array of strings)
     */
    public function getPersonUsersWithHttpInfo($id)
    {
        $request = $this->getPersonUsersRequest($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->getPersonUsersRequest($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\ListPermittedUsersResponse1' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\ListPermittedUsersResponse1', []),
                        $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\ListPermittedUsersResponse1' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

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

    /**
     * Operation getPersonUsersAsyncWithHttpInfo
     *
     * List permitted users
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getPersonUsersAsyncWithHttpInfo($id): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\ListPermittedUsersResponse1';
        $request = $this->getPersonUsersRequest($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 'getPersonUsers'
     *
     * @param  int $id The ID of the person (required)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getPersonUsersRequest($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 getPersonUsers'
            );
        }

        $resourcePath = '/persons/{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 getPersons
     *
     * Get all persons
     *
     * @param  int|null $user_id If supplied, only persons owned by the given user will be returned. However, &#x60;filter_id&#x60; takes precedence over &#x60;user_id&#x60; when both are supplied. (optional)
     * @param  int|null $filter_id The ID of the filter to use (optional)
     * @param  string|null $first_char If supplied, only persons whose name starts with the specified letter will be returned (case-insensitive) (optional)
     * @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)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\GetAllPersonsResponse
     */
    public function getPersons($user_id = null, $filter_id = null, $first_char = null, $start = 0, $limit = null, $sort = null)
    {
        list($response) = $this->getPersonsWithHttpInfo($user_id, $filter_id, $first_char, $start, $limit, $sort);
        return $response;
    }

    /**
     * Operation getPersonsWithHttpInfo
     *
     * Get all persons
     *
     * @param  int|null $user_id If supplied, only persons owned by the given user will be returned. However, &#x60;filter_id&#x60; takes precedence over &#x60;user_id&#x60; when both are supplied. (optional)
     * @param  int|null $filter_id The ID of the filter to use (optional)
     * @param  string|null $first_char If supplied, only persons whose name starts with the specified letter will be returned (case-insensitive) (optional)
     * @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)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\GetAllPersonsResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getPersonsWithHttpInfo($user_id = null, $filter_id = null, $first_char = null, $start = 0, $limit = null, $sort = null)
    {
        $request = $this->getPersonsRequest($user_id, $filter_id, $first_char, $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->getPersonsRequest($user_id, $filter_id, $first_char, $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\GetAllPersonsResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\GetAllPersonsResponse', []),
                        $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\GetAllPersonsResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

    /**
     * Operation getPersonsAsync
     *
     * Get all persons
     *
     * @param  int|null $user_id If supplied, only persons owned by the given user will be returned. However, &#x60;filter_id&#x60; takes precedence over &#x60;user_id&#x60; when both are supplied. (optional)
     * @param  int|null $filter_id The ID of the filter to use (optional)
     * @param  string|null $first_char If supplied, only persons whose name starts with the specified letter will be returned (case-insensitive) (optional)
     * @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)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getPersonsAsync($user_id = null, $filter_id = null, $first_char = null, $start = 0, $limit = null, $sort = null): PromiseInterface
    {
        return $this->getPersonsAsyncWithHttpInfo($user_id, $filter_id, $first_char, $start, $limit, $sort)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getPersonsAsyncWithHttpInfo
     *
     * Get all persons
     *
     * @param  int|null $user_id If supplied, only persons owned by the given user will be returned. However, &#x60;filter_id&#x60; takes precedence over &#x60;user_id&#x60; when both are supplied. (optional)
     * @param  int|null $filter_id The ID of the filter to use (optional)
     * @param  string|null $first_char If supplied, only persons whose name starts with the specified letter will be returned (case-insensitive) (optional)
     * @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)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getPersonsAsyncWithHttpInfo($user_id = null, $filter_id = null, $first_char = null, $start = 0, $limit = null, $sort = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\GetAllPersonsResponse';
        $request = $this->getPersonsRequest($user_id, $filter_id, $first_char, $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 'getPersons'
     *
     * @param  int|null $user_id If supplied, only persons owned by the given user will be returned. However, &#x60;filter_id&#x60; takes precedence over &#x60;user_id&#x60; when both are supplied. (optional)
     * @param  int|null $filter_id The ID of the filter to use (optional)
     * @param  string|null $first_char If supplied, only persons whose name starts with the specified letter will be returned (case-insensitive) (optional)
     * @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)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getPersonsRequest($user_id = null, $filter_id = null, $first_char = null, $start = 0, $limit = null, $sort = null): Request
    {

        $resourcePath = '/persons';
        $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($first_char)) {
            $first_char = ObjectSerializer::serializeCollection($first_char, '', true);
        }
        if ($first_char !== null) {
            $queryParams['first_char'] = $first_char;
        }
        // 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;
        }




        /* @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 getPersonsCollection
     *
     * Get all persons (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 $owner_id If supplied, only persons owned by the given user will be returned (optional)
     * @param  string|null $first_char If supplied, only persons whose name starts with the specified letter will be returned (case-insensitive) (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\InlineResponse2002|\Pipedrive\Model\FailResponse
     */
    public function getPersonsCollection($cursor = null, $limit = null, $since = null, $until = null, $owner_id = null, $first_char = null)
    {
        list($response) = $this->getPersonsCollectionWithHttpInfo($cursor, $limit, $since, $until, $owner_id, $first_char);
        return $response;
    }

    /**
     * Operation getPersonsCollectionWithHttpInfo
     *
     * Get all persons (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 $owner_id If supplied, only persons owned by the given user will be returned (optional)
     * @param  string|null $first_char If supplied, only persons whose name starts with the specified letter will be returned (case-insensitive) (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\InlineResponse2002|\Pipedrive\Model\FailResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getPersonsCollectionWithHttpInfo($cursor = null, $limit = null, $since = null, $until = null, $owner_id = null, $first_char = null)
    {
        $request = $this->getPersonsCollectionRequest($cursor, $limit, $since, $until, $owner_id, $first_char);

        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->getPersonsCollectionRequest($cursor, $limit, $since, $until, $owner_id, $first_char);
                    $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\InlineResponse2002' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\InlineResponse2002', []),
                        $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\InlineResponse2002' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\Pipedrive\Model\InlineResponse2002',
                        $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 getPersonsCollectionAsync
     *
     * Get all persons (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 $owner_id If supplied, only persons owned by the given user will be returned (optional)
     * @param  string|null $first_char If supplied, only persons whose name starts with the specified letter will be returned (case-insensitive) (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getPersonsCollectionAsync($cursor = null, $limit = null, $since = null, $until = null, $owner_id = null, $first_char = null): PromiseInterface
    {
        return $this->getPersonsCollectionAsyncWithHttpInfo($cursor, $limit, $since, $until, $owner_id, $first_char)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getPersonsCollectionAsyncWithHttpInfo
     *
     * Get all persons (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 $owner_id If supplied, only persons owned by the given user will be returned (optional)
     * @param  string|null $first_char If supplied, only persons whose name starts with the specified letter will be returned (case-insensitive) (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function getPersonsCollectionAsyncWithHttpInfo($cursor = null, $limit = null, $since = null, $until = null, $owner_id = null, $first_char = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\InlineResponse2002';
        $request = $this->getPersonsCollectionRequest($cursor, $limit, $since, $until, $owner_id, $first_char);

        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 'getPersonsCollection'
     *
     * @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 $owner_id If supplied, only persons owned by the given user will be returned (optional)
     * @param  string|null $first_char If supplied, only persons whose name starts with the specified letter will be returned (case-insensitive) (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function getPersonsCollectionRequest($cursor = null, $limit = null, $since = null, $until = null, $owner_id = null, $first_char = null): Request
    {

        $resourcePath = '/persons/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($owner_id)) {
            $owner_id = ObjectSerializer::serializeCollection($owner_id, '', true);
        }
        if ($owner_id !== null) {
            $queryParams['owner_id'] = $owner_id;
        }
        // query params
        /* @phpstan-ignore-next-line */
        if (is_array($first_char)) {
            $first_char = ObjectSerializer::serializeCollection($first_char, '', true);
        }
        if ($first_char !== null) {
            $queryParams['first_char'] = $first_char;
        }




        /* @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 mergePersons
     *
     * Merge two persons
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\MergePersonsRequest|null $merge_persons_request merge_persons_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\MergePersonsResponse
     */
    public function mergePersons($id, $merge_persons_request = null)
    {
        list($response) = $this->mergePersonsWithHttpInfo($id, $merge_persons_request);
        return $response;
    }

    /**
     * Operation mergePersonsWithHttpInfo
     *
     * Merge two persons
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\MergePersonsRequest|null $merge_persons_request (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return array<mixed> of \Pipedrive\Model\MergePersonsResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function mergePersonsWithHttpInfo($id, $merge_persons_request = null)
    {
        $request = $this->mergePersonsRequest($id, $merge_persons_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->mergePersonsRequest($id, $merge_persons_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\MergePersonsResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\MergePersonsResponse', []),
                        $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\MergePersonsResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

    /**
     * Operation mergePersonsAsync
     *
     * Merge two persons
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\MergePersonsRequest|null $merge_persons_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function mergePersonsAsync($id, $merge_persons_request = null): PromiseInterface
    {
        return $this->mergePersonsAsyncWithHttpInfo($id, $merge_persons_request)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation mergePersonsAsyncWithHttpInfo
     *
     * Merge two persons
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\MergePersonsRequest|null $merge_persons_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function mergePersonsAsyncWithHttpInfo($id, $merge_persons_request = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\MergePersonsResponse';
        $request = $this->mergePersonsRequest($id, $merge_persons_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 'mergePersons'
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\MergePersonsRequest|null $merge_persons_request (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function mergePersonsRequest($id, $merge_persons_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 mergePersons'
            );
        }

        $resourcePath = '/persons/{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_persons_request)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode(ObjectSerializer::sanitizeForSerialization($merge_persons_request));
            } else {
                $httpBody = $merge_persons_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 searchPersons
     *
     * Search persons
     *
     * @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 $organization_id Will filter persons by the provided organization ID. The upper limit of found persons associated with the organization 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\PersonSearchResponse
     */
    public function searchPersons($term, $fields = null, $exact_match = null, $organization_id = null, $include_fields = null, $start = 0, $limit = null)
    {
        list($response) = $this->searchPersonsWithHttpInfo($term, $fields, $exact_match, $organization_id, $include_fields, $start, $limit);
        return $response;
    }

    /**
     * Operation searchPersonsWithHttpInfo
     *
     * Search persons
     *
     * @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 $organization_id Will filter persons by the provided organization ID. The upper limit of found persons associated with the organization 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\PersonSearchResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function searchPersonsWithHttpInfo($term, $fields = null, $exact_match = null, $organization_id = null, $include_fields = null, $start = 0, $limit = null)
    {
        $request = $this->searchPersonsRequest($term, $fields, $exact_match, $organization_id, $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->searchPersonsRequest($term, $fields, $exact_match, $organization_id, $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\PersonSearchResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\PersonSearchResponse', []),
                        $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\PersonSearchResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

    /**
     * Operation searchPersonsAsync
     *
     * Search persons
     *
     * @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 $organization_id Will filter persons by the provided organization ID. The upper limit of found persons associated with the organization 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 searchPersonsAsync($term, $fields = null, $exact_match = null, $organization_id = null, $include_fields = null, $start = 0, $limit = null): PromiseInterface
    {
        return $this->searchPersonsAsyncWithHttpInfo($term, $fields, $exact_match, $organization_id, $include_fields, $start, $limit)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation searchPersonsAsyncWithHttpInfo
     *
     * Search persons
     *
     * @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 $organization_id Will filter persons by the provided organization ID. The upper limit of found persons associated with the organization 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 searchPersonsAsyncWithHttpInfo($term, $fields = null, $exact_match = null, $organization_id = null, $include_fields = null, $start = 0, $limit = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\PersonSearchResponse';
        $request = $this->searchPersonsRequest($term, $fields, $exact_match, $organization_id, $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 'searchPersons'
     *
     * @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 $organization_id Will filter persons by the provided organization ID. The upper limit of found persons associated with the organization 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 searchPersonsRequest($term, $fields = null, $exact_match = null, $organization_id = 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 searchPersons'
            );
        }

        $resourcePath = '/persons/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($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($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 updatePerson
     *
     * Update a person
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\UpdatePerson|null $update_person update_person (optional)
     *
     * @throws ApiException on non-2xx response
     * @throws InvalidArgumentException|GuzzleException
     * @return \Pipedrive\Model\UpdatePersonResponse
     */
    public function updatePerson($id, $update_person = null)
    {
        list($response) = $this->updatePersonWithHttpInfo($id, $update_person);
        return $response;
    }

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

        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->updatePersonRequest($id, $update_person);
                    $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\UpdatePersonResponse' === '\SplFileObject') {
                        $content = $response->getBody(); //stream goes to serializer
                    } else {
                        $content = (string) $response->getBody();
                    }

                    return [
                        ObjectSerializer::deserialize($content, '\Pipedrive\Model\UpdatePersonResponse', []),
                        $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\UpdatePersonResponse' === '\SplFileObject') {
                $content = $response->getBody(); //stream goes to serializer
            } else {
                $content = (string) $response->getBody();
            }

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

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

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

    /**
     * Operation updatePersonAsyncWithHttpInfo
     *
     * Update a person
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\UpdatePerson|null $update_person (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return PromiseInterface
     */
    public function updatePersonAsyncWithHttpInfo($id, $update_person = null): PromiseInterface
    {
        $returnType = '\Pipedrive\Model\UpdatePersonResponse';
        $request = $this->updatePersonRequest($id, $update_person);

        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 'updatePerson'
     *
     * @param  int $id The ID of the person (required)
     * @param  \Pipedrive\Model\UpdatePerson|null $update_person (optional)
     *
     * @throws InvalidArgumentException|OAuthProviderException
     * @return Request
     */
    public function updatePersonRequest($id, $update_person = 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 updatePerson'
            );
        }

        $resourcePath = '/persons/{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_person)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = Utils::jsonEncode(ObjectSerializer::sanitizeForSerialization($update_person));
            } else {
                $httpBody = $update_person;
            }
        } 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;
    }
}
