docs: private JsonNode performAPIAction(
  			String action,
  			String id,
  			String site,
  			String title,
  			String newEntity,
  			Map<String, String> parameters,
  			String summary,
  			long baserevid,
  			boolean bot)
  			throws IOException, MediaWikiApiErrorException {
  		
  		parameters.put(ApiConnection.PARAM_ACTION, action);
  		
  		if (newEntity != null) {
  			parameters.put("new", newEntity);
  			if (title != null || site != null || id != null) {
  				throw new IllegalArgumentException(
  						"Cannot use parameters \"id\", \"site\", or \"title\" when creating a new entity.");
  			}
  		} else if (id != null) {
  			parameters.put("id", id);
  			if (title != null || site != null) {
  				throw new IllegalArgumentException(
  						"Cannot use parameters \"site\" or \"title\" when using id to edit entity data");
  			}
  		} else if (title != null) {
  			if (site == null) {
  				throw new IllegalArgumentException(
  						"Site parameter is required when using title parameter to edit entity data.");
  			}
  			parameters.put("site", site);
  			parameters.put("title", title);
  		} else if (!"wbsetclaim".equals(action) && !"wbremoveclaims".equals(action)) {
  			throw new IllegalArgumentException(
  					"This action must create a new item, or specify an id, or specify a site and title.");
  		}
  		
  		if (bot) {
  			parameters.put("bot", "");
  		}
  		
  		if (baserevid != 0) {
  			parameters.put("baserevid", Long.toString(baserevid));
  		}
  		
  		if (summary != null) {
  			parameters.put("summary", summary);
  		}
  
  		parameters.put("maxlag", Integer.toString(this.maxLag));
  		parameters.put("token", getCsrfToken());
  
  		if (this.remainingEdits > 0) {
  			this.remainingEdits--;
  		} else if (this.remainingEdits == 0) {
  			logger.info("Not editing entity (simulation mode). Request parameters were: "
  					+ parameters.toString());
  			return null;
  		}
  
  		checkEditSpeed();
  		JsonNode result = null;
  		
  		int retry = 5;
  		MediaWikiApiErrorException lastException = null;
  		while (retry > 0) {
  			try {
  				result = this.connection.sendJsonRequest("POST", parameters);
  				break;
  			} catch (TokenErrorException e) { // try again with a fresh token
  				lastException = e;
  				refreshCsrfToken();
  				parameters.put("token", getCsrfToken());
  			} catch (MaxlagErrorException e) { // wait for 5 seconds
  				lastException = e;
  				logger.warn(e.getMessage() + " -- pausing for 5 seconds.");
  				try {
  					Thread.sleep(MAXLAG_SLEEP_TIME);
  				} catch (InterruptedException ex) {
  					Thread.currentThread().interrupt();
  				}
  			}
  			retry--;
  		}
  
  		if (lastException != null) {
  			logger.error("Gave up after several retries. Last error was: "
  					+ lastException.toString());
  			throw lastException;
  		}
  
  		return result;
  	}