protected function _makeRequest($url, $params = array(), $photos = array())
    {
        // if any photos exist, let's merge them into the params
        if (count($photos)) {
            $params = array_merge($params, $photos);
        }

        foreach ($params as $key => $value) {
            if (is_array($value)) {
                $flattened = $this->_flattenMultiDimensionalParams($params);
                $params = $flattened;
            }
        }

        // send along some headers for reporting
        $headers = array(
            'X-WRAPPER: ' . $this->_version
        );

        // init curl to make the request
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

        // the API response
        $response = curl_exec($curl);
        $info = curl_getinfo($curl);
        $error = curl_error($curl);
        $errno = curl_errno($curl);

        if ($error) {
            throw new Sp_CurlException($error, $errno);
        }

        if (!$response) {
            throw new Sp_NoResponseException('The API did not return any response. Error #' . $info['http_code']);
        }

        $json = json_decode($response, true);

        if ($json['stat'] != 'ok') {
            throw new Sp_Exception(
                'The API did not return an OK response. ' . $json['msg'],
                0,
                $response
            );
        }

        return $json;
    }