public function doRequest($endpoint, callable $callback)
    {
        // Check for a cached value and return if one is available
        if ($result = $this->getFromCache()) {
            return $result;
        }

        // Otherwise go and request data from the API
        $request = new Request('GET', $endpoint);
        $failureMessage = 'Could not obtain information about module. ';

        try {
            /** @var Response $response */
            $response = $this->getGuzzleClient()->send($request, $this->getClientOptions());
        } catch (GuzzleException $exception) {
            throw new RuntimeException($failureMessage);
        }

        if ($response->getStatusCode() !== 200) {
            throw new RuntimeException($failureMessage . 'Error code ' . $response->getStatusCode());
        }

        if (!in_array('application/json', $response->getHeader('Content-Type'))) {
            throw new RuntimeException($failureMessage . 'Response is not JSON');
        }

        $responseBody = Convert::json2array($response->getBody()->getContents());

        if (empty($responseBody)) {
            throw new RuntimeException($failureMessage . 'Response could not be parsed');
        }

        if (!isset($responseBody['success']) || !$responseBody['success']) {
            throw new RuntimeException($failureMessage . 'Response returned unsuccessfully');
        }

        // Allow callback to handle processing of the response body
        $result = $callback($responseBody);

        // Setting the value to the cache for subsequent requests
        $this->handleCacheFromResponse($response, $result);

        return $result;
    }