public function request($url, $params = array(), $method = 'GET', $json_body = true, array $headers = array()): array
    {
        $headers = array_merge(array(
            'Accept' => self::VERSION_STRING,
            'User-Agent' => self::USER_AGENT,
        ), $headers);

        $method = strtoupper($method);

        // If a pre-defined `Authorization` header isn't present, then add a bearer token or client information.
        if (!isset($headers['Authorization'])) {
            if (!empty($this->_access_token)) {
                $headers['Authorization'] = 'Bearer ' . $this->_access_token;
            } else {
                // this may be a call to get the tokens, so we add the client info.
                $headers['Authorization'] = 'Basic ' . $this->_authHeader();
            }
        }

        //  Set the methods, determine the URL that we should actually request and prep the body.
        $curl_opts = array();
        switch ($method) {
            case 'GET':
            case 'HEAD':
                if (!empty($params)) {
                    $query_component = '?' . http_build_query($params, '', '&');
                } else {
                    $query_component = '';
                }

                $curl_url = self::ROOT_ENDPOINT . $url . $query_component;
                break;

            case 'POST':
            case 'PATCH':
            case 'PUT':
            case 'DELETE':
                if ($json_body && !empty($params)) {
                    $headers['Content-Type'] = 'application/json';
                    $body = json_encode($params);
                } else {
                    $body = http_build_query($params, '', '&');
                }

                $curl_url = self::ROOT_ENDPOINT . $url;
                $curl_opts = array(
                    CURLOPT_POST => true,
                    CURLOPT_CUSTOMREQUEST => $method,
                    CURLOPT_POSTFIELDS => $body
                );
                break;

            default:
                throw new VimeoRequestException('This library does not support ' . $method . ' requests.');
        }

        // Set the headers
        foreach ($headers as $key => $value) {
            $curl_opts[CURLOPT_HTTPHEADER][] = sprintf('%s: %s', $key, $value);
        }

        $response = $this->_request($curl_url, $curl_opts);

        $response['body'] = json_decode($response['body'], true);

        return $response;
    }