private function _request($method, $url, $data = null, $isRetry = false)
    {
        $token = $this->getAccessToken($isRetry);

        // make request, retrying auth failures ONCE with a new token
        try {
            list($code, $json, $rawData) = Http::bearerRequest($method, $url, $token, $data);
        } catch (AuthException $e) {
            sleep(self::AUTH_RETRY_WAIT_S); // @todo investigate why this is necessary
            return $this->_request($method, $url, $data, true);
        } catch (RemoteException $e) {
            if (ValidationException::looksValidationy($e)) {
                throw new ValidationException('Validation error', $e->getCode(), $e);
            } else {
                throw $e; // re-throw
            }
        }

        // record the raw response data, in case we want to check it later on
        $this->_raw = $rawData;

        return $json;
    }