docs: def __api_request(self, method, endpoint, params={}, files={}, headers={}, access_token_override=None, do_ratelimiting=True, use_json = False):
          """
          Internal API request helper.
          """
          response = None
          remaining_wait = 0
          # "pace" mode ratelimiting: Assume constant rate of requests, sleep a little less long than it
          # would take to not hit the rate limit at that request rate.
          if do_ratelimiting and self.ratelimit_method == "pace":
              if self.ratelimit_remaining == 0:
                  to_next = self.ratelimit_reset - time.time()
                  if to_next > 0:
                      # As a precaution, never sleep longer than 5 minutes
                      to_next = min(to_next, 5 * 60)
                      time.sleep(to_next)
              else:
                  time_waited = time.time() - self.ratelimit_lastcall
                  time_wait = float(self.ratelimit_reset - time.time()) / float(self.ratelimit_remaining)
                  remaining_wait = time_wait - time_waited
  
              if remaining_wait > 0:
                  to_next = remaining_wait / self.ratelimit_pacefactor
                  to_next = min(to_next, 5 * 60)
                  time.sleep(to_next)
  
          # Generate request headers
          headers = copy.deepcopy(headers)
          if not self.access_token is None:
              headers['Authorization'] = 'Bearer ' + self.access_token
          if not access_token_override is None:
              headers['Authorization'] = 'Bearer ' + access_token_override
  
          if self.debug_requests:
              print('Mastodon: Request to endpoint "' + endpoint + '" using method "' + method + '".')
              print('Parameters: ' + str(params))
              print('Headers: ' + str(headers))
              print('Files: ' + str(files))
  
          # Make request
          request_complete = False
          while not request_complete:
              request_complete = True
  
              response_object = None
              try:
                  kwargs = dict(headers=headers, files=files,
                                timeout=self.request_timeout)
                  if use_json == False:
                      if method == 'GET':
                          kwargs['params'] = params
                      else:
                          kwargs['data'] = params
                  else:
                      kwargs['json'] = params
                      
                  response_object = self.session.request(
                          method, self.api_base_url + endpoint, **kwargs)
              except Exception as e:
                  raise MastodonNetworkError("Could not complete request: %s" % e)
  
              if response_object is None:
                  raise MastodonIllegalArgumentError("Illegal request.")
  
              # Parse rate limiting headers
              if 'X-RateLimit-Remaining' in response_object.headers and do_ratelimiting:
                  self.ratelimit_remaining = int(response_object.headers['X-RateLimit-Remaining'])
                  self.ratelimit_limit = int(response_object.headers['X-RateLimit-Limit'])
  
                  try:
                      ratelimit_reset_datetime = dateutil.parser.parse(response_object.headers['X-RateLimit-Reset'])
                      self.ratelimit_reset = self.__datetime_to_epoch(ratelimit_reset_datetime)
  
                      # Adjust server time to local clock
                      if 'Date' in response_object.headers:
                          server_time_datetime = dateutil.parser.parse(response_object.headers['Date'])
                          server_time = self.__datetime_to_epoch(server_time_datetime)
                          server_time_diff = time.time() - server_time
                          self.ratelimit_reset += server_time_diff
                          self.ratelimit_lastcall = time.time()
                  except Exception as e:
                      raise MastodonRatelimitError("Rate limit time calculations failed: %s" % e)
  
              # Handle response
              if self.debug_requests:
                  print('Mastodon: Response received with code ' + str(response_object.status_code) + '.')
                  print('response headers: ' + str(response_object.headers))
                  print('Response text content: ' + str(response_object.text))
  
              if not response_object.ok:
                  try:
                      response = response_object.json(object_hook=self.__json_hooks)
                      if isinstance(response, dict) and 'error' in response:
                          error_msg = response['error']
                      elif isinstance(response, str):
                          error_msg = response
                      else:
                          error_msg = None
                  except ValueError:
                      error_msg = None
  
                  # Handle rate limiting
                  if response_object.status_code == 429:
                      if self.ratelimit_method == 'throw' or not do_ratelimiting:
                          raise MastodonRatelimitError('Hit rate limit.')
                      elif self.ratelimit_method in ('wait', 'pace'):
                          to_next = self.ratelimit_reset - time.time()
                          if to_next > 0:
                              # As a precaution, never sleep longer than 5 minutes
                              to_next = min(to_next, 5 * 60)
                              time.sleep(to_next)
                              request_complete = False
                              continue
  
                  if response_object.status_code == 404:
                      ex_type = MastodonNotFoundError
                      if not error_msg:
                          error_msg = 'Endpoint not found.'
                          # this is for compatibility with older versions
                          # which raised MastodonAPIError('Endpoint not found.')
                          # on any 404
                  elif response_object.status_code == 401:
                      ex_type = MastodonUnauthorizedError
                  elif response_object.status_code == 502:
                      ex_type = MastodonServerError
                  else:
                      ex_type = MastodonAPIError
  
                  raise ex_type(
                          'Mastodon API returned error',
                          response_object.status_code,
                          response_object.reason,
                          error_msg)
  
              try:
                  response = response_object.json(object_hook=self.__json_hooks)
              except:
                  raise MastodonAPIError(
                      "Could not parse response as JSON, response code was %s, "
                      "bad json content was '%s'" % (response_object.status_code,
                                                     response_object.content))
  
              # Parse link headers
              if isinstance(response, list) and \
                      'Link' in response_object.headers and \
                      response_object.headers['Link'] != "":
                  tmp_urls = requests.utils.parse_header_links(
                      response_object.headers['Link'].rstrip('>').replace('>,<', ',<'))
                  for url in tmp_urls:
                      if 'rel' not in url:
                          continue
  
                      if url['rel'] == 'next':
                          # Be paranoid and extract max_id specifically
                          next_url = url['url']
                          matchgroups = re.search(r"[?&]max_id=([^&]+)", next_url)
  
                          if matchgroups:
                              next_params = copy.deepcopy(params)
                              next_params['_pagination_method'] = method
                              next_params['_pagination_endpoint'] = endpoint
                              max_id = matchgroups.group(1)
                              if max_id.isdigit():
                                  next_params['max_id'] = int(max_id)
                              else:
                                  next_params['max_id'] = max_id
                              if "since_id" in next_params:
                                  del next_params['since_id']
                              if "min_id" in next_params:
                                  del next_params['min_id']
                              response[-1]._pagination_next = next_params
  
                      if url['rel'] == 'prev':
                          # Be paranoid and extract since_id or min_id specifically
                          prev_url = url['url']
                          
                          # Old and busted (pre-2.6.0): since_id pagination
                          matchgroups = re.search(r"[?&]since_id=([^&]+)", prev_url)
                          if matchgroups:
                              prev_params = copy.deepcopy(params)
                              prev_params['_pagination_method'] = method
                              prev_params['_pagination_endpoint'] = endpoint
                              since_id = matchgroups.group(1)
                              if since_id.isdigit():
                                  prev_params['since_id'] = int(since_id)
                              else:
                                  prev_params['since_id'] = since_id
                              if "max_id" in prev_params:
                                  del prev_params['max_id']
                              response[0]._pagination_prev = prev_params
                              
                          # New and fantastico (post-2.6.0): min_id pagination
                          matchgroups = re.search(r"[?&]min_id=([^&]+)", prev_url)
                          if matchgroups:
                              prev_params = copy.deepcopy(params)
                              prev_params['_pagination_method'] = method
                              prev_params['_pagination_endpoint'] = endpoint
                              min_id = matchgroups.group(1)
                              if min_id.isdigit():
                                  prev_params['min_id'] = int(min_id)
                              else:
                                  prev_params['min_id'] = min_id
                              if "max_id" in prev_params:
                                  del prev_params['max_id']
                              response[0]._pagination_prev = prev_params
  
          return response