def retrieve(self, thing, thing_type=None):
        """
        Retrieve a report from VirusTotal based on a hash, IP, domain, file or URL or ScanID.  NOTE: URLs must include the scheme
         (e.g. http://)\n

        :param thing: a file name on the local system, a URL or list of URLs,
                      an IP or list of IPs, a domain or list of domains, a hash or list of hashes
        :param thing_type: Optional, a hint to the function as to what you are sending it
        :return: Returns a a dictionary with thing as key and the API json response as the value
                If thing was a list of things to query the results will be a dictionary with every thing in the list
                as a key
        :raises TypeError: if it gets something other than a URL, IP domain, hash or ScanID
        :raises TypeError: if VirusTotal returns something we can't parse.
        """
        # trust the user-supplied type over the automatic identification
        thing_id = self._whatis(thing)
        if thing_type is None:
            thing_type = thing_id

        query_parameters = {}

        # Query API for URL(s)
        if thing_type == API_Constants.URL:  # Get the scan results for a given URL or list of URLs.
            query = API_Constants.CONST_API_URL + API_Constants.API_ACTION_GET_URL_REPORT
            if not isinstance(thing, list):
                thing = [thing]
            grouped_urls = self._grouped(thing, self._urls_per_retrieve)  # break list of URLS down to API limits
            results = {}

            for group in grouped_urls:
                query_parameters = {"resource": "\n".join([url for url in group])}
                self._limit_call_handler()
                try:
                    response = self._post_query(query, query_parameters)
                except:
                    raise TypeError

                # If we get a list of URLs that has N urls and N mod '_url_per_retrieve' is 1
                # for example  [url, url, url], when limit is 2, the last query will not return a list
                if not isinstance(response, list):
                    response = [response]

                for index, scanid in enumerate(group):
                    results[scanid] = response[index]

            result = results

        # Query API for domain(s)
        elif thing_type == API_Constants.DOMAIN:

            query = API_Constants.CONST_API_URL + API_Constants.API_ACTION_GET_DOMAIN_REPORT
            if not isinstance(thing, list):
                thing = [thing]
            results = {}
            for domain in thing:
                query_parameters["domain"] = domain
                self._limit_call_handler()
                response = self._get_query(query, query_parameters)
                results[domain] = response

            result = results

        # Query API for IP(s)
        elif thing_type == API_Constants.IP:

            query = API_Constants.CONST_API_URL + API_Constants.API_ACTION_GET_IP_REPORT

            if not isinstance(thing, list):
                thing = [thing]

            results = {}
            for ip in thing:
                query_parameters["ip"] = ip
                self._limit_call_handler()
                try:
                    response = self._get_query(query, query_parameters)
                except:
                    raise TypeError
                results[ip] = response

            result = results

        # Query API for HASH, bulk HASH queries not possible
        elif thing_type == API_Constants.HASH:

            query = API_Constants.CONST_API_URL + API_Constants.API_ACTION_GET_FILE_REPORT

            results = {}
            if not isinstance(thing, list):
                thing = [thing]
            query_parameters["resource"] = ", ".join(thing)
            self._limit_call_handler()
            response = self._get_query(query, query_parameters)

            if not isinstance(response, list):
                response = [response]

            for index, hash in enumerate(thing):
                results[hash] = response[index]
            result = results

        elif thing_type == "scanid":
            query = API_Constants.CONST_API_URL + API_Constants.API_ACTION_GET_URL_REPORT
            if not isinstance(thing, list):
                thing = [thing]
            results = {}

            for scanid in thing:
                query_parameters["resource"] = scanid
                self._limit_call_handler()
                try:
                    response = self._post_query(query, query_parameters)
                except:
                    raise TypeError
                results[scanid] = response

            result = results
        else:
            raise TypeError("Unimplemented '%s'." % thing_type)

        return result
Retrieve a report from VirusTotal based on a hash, IP, domain, file or URL or ScanID.  NOTE: URLs must include the scheme
         (e.g. http://)\n

        :param thing: a file name on the local system, a URL or list of URLs,
                      an IP or list of IPs, a domain or list of domains, a hash or list of hashes
        :param thing_type: Optional, a hint to the function as to what you are sending it
        :return: Returns a a dictionary with thing as key and the API json response as the value
                If thing was a list of things to query the results will be a dictionary with every thing in the list
                as a key
        :raises TypeError: if it gets something other than a URL, IP domain, hash or ScanID
        :raises TypeError: if VirusTotal returns something we can't parse.