private function _sendRequest($method, $uri, $data = '')
  {
    if(function_exists('mb_internal_encoding'))
      mb_internal_encoding(self::DEFAULT_ENCODING);

    if (substr($uri,0,4) != 'http')
      $uri = $this->baseUri() . $uri;

    $this->_verifyUri($uri);

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $uri);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    if (self::$CACertPath) {
      curl_setopt($ch, CURLOPT_CAINFO, self::$CACertPath);
    }
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
    curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
    curl_setopt($ch, CURLOPT_HEADER, TRUE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_TIMEOUT, 45);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
      'Content-Type: application/xml; charset=utf-8',
      'Accept: application/xml',
      Recurly_Client::__userAgent(),
      'Accept-Language: ' . $this->_acceptLanguage,
      'X-Api-Version: ' . Recurly_Client::$apiVersion
    ));
    curl_setopt($ch, CURLOPT_USERPWD, $this->apiKey());

    if ('POST' == $method)
    {
      curl_setopt($ch, CURLOPT_POST, TRUE);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }
    else if ('PUT' == $method)
    {
      curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
      curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }
    else if ('HEAD' == $method)
    {
      curl_setopt($ch, CURLOPT_NOBODY, TRUE);
    }
    else if('GET' != $method)
    {
      curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
    }

    $response = curl_exec($ch);

    if ($response === false)
    {
      $errorNumber = curl_errno($ch);
      $message = curl_error($ch);
      curl_close($ch);
      $this->_raiseCurlError($errorNumber, $message);
    }

    $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    list($header, $body) = explode("\r\n\r\n", $response, 2);
    // Larger responses end up prefixed by "HTTP/1.1 100 Continue\r\n\r\n" which
    // needs to be discarded.
    if (strpos($header," 100 Continue") !== false ) {
      list($header, $body) = explode("\r\n\r\n", $body, 2);
    }
    $headers = $this->_getHeaders($header);

    return new Recurly_ClientResponse($statusCode, $headers, $body);
  }