Many parts of Polymart require JavaScript to function correctly.
Click here to enable JavaScript.

Using the Polymart API in your Minecraft plugin

Posted Aug 10, 2022  •  Updated Aug 11, 2022

So you've coded your Minecraft plugin and are ready to upload it to Polymart. Great! But, did you know about all of the awesome features you can take advantage of using the Polymart Developer API? It's fast and easy to use the Polymart Web API in your plugin, and in this blog, we'll go through how you can do that! Experienced developers might find this a little boring, so feel free to just head over to the Polymart Developer API documentation at https://polymart.org/wiki/api to get a breakdown of all of the available API actions. Ready? Let's go!

What is the Polymart Developer API?

The Polymart Developer API is a a web API that you can use to interact with the Polymart website — whether that's from your own website, a Discord bot, or your plugin. Using the Developer API, you can do things like download an updated version of your plugin, check how many downloads you have, or even verify purchases to stop piracy!

Intro to Using the Polymart Devloper API

The basic premise is simple: Just find the API action that you want to run, and then send an HTTP request. 

// Put your resource ID here, or just use "%%__RESOURCE__%%" to have it automatically injected by the Polymart injector
String yourResourceID = "%%__RESOURCE__%%";

// This is the API action we'll be using. Check out https://polymart.org/wiki/api#getResourceInfoSimple to see how we decided on this URL.
// This says we'll be running the getResourceInfoSimple action, and the resource_id is yourResourceID (above), and the key we'd like to
// get is lastUpdateTime 
String urlString = "https://api.polymart.org/v1/getResourceInfoSimple?resource_id=" + yourResourceID + "&key=lastUpdateTime";

// Make a URL object and open a connection
URL url = new URL(urlString);
URLConnection con = url.openConnection();
HttpURLConnection http = (HttpURLConnection) con;
http.setRequestMethod("GET");
http.setDoOutput(true);

 

For example, if your resource ID was 4, this will open a connection to https://api.polymart.org/v1/getResourceInfoSimple?resource_id=4&key=lastUpdateTime. Now we have an open connection to the Polymart Developer API for the action getResourceInfoSimple. But, how do we read the response?

// Get the response code and make sure it's a success
int responseCode = http.getResponseCode();
System.out.println("Response Code for " + urlString + " is " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) { // success
    BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
    }
    in.close();

    // print result
    System.out.println(response.toString());
}
else{
    System.out.println("GET request failed");
}

 

There's one more very important thing we need to do before we can put this code in our plugin. As it currently stands, this code will block the main thread, which means that while your plugin is making this request (which could take up to 5-10 seconds), the server will completely freeze — there will be a lag spike an no one will be able to interact in the server. Even if this only happens when your plugin starts up, this is really horrible behavior and will likely cause users to uninstall your plugin.

To fix this, we need to run our code asynchronously. And, that's pretty simple! It just means wrapping it in a Bukkit asynchronous block.

// Main.instance should be the instance of your plugin's Main class
Bukkit.getScheduler().runTaskAsynchronously(Main.instance, () -> {
  // put all of your code here
});

 

Putting it all together, we could make a method that runs our getResourceInfoSimple action, and asynchronously returns the resulting String in a Consumer<String>

  Putting it all together

 

Using the Polymart Developer API for more Complex Requests

You'll notice that the above action is really useful for super simple API actions like getResourceInfoSimple that return a single string. For most actions, the response will be JSON, and we need to parse that so we can read it!

String originalJsonString = "{\"example\": \"Hello, World!\"}";

Gson gson = new Gson();

// This is generally a pretty bad way of parsing the JSON string, because
// You'll quickly end up with lots of maps nested in maps nested in lists nested in other maps... Yeah, it gets confusing.
// I recommend that you look for an alternative way for parsing JSON, but this method is
// simple and works for this example!
Map map = gson.fromJson(originalJsonString, Map.class);
String example = map.get("example"); // Should be "Hello, World!"

 

One other thing we might want to put in our API calling method is an easy way to pass in parameters. For that, we could turn a Map<String, Object> into the GET parameters

Map<String, Object> parameters;

char splitChar = '?';
StringBuilder paramString = new StringBuilder();
for(String key : parameters.keySet()){
    paramString.append(splitChar);
    paramString.append(URLEncoder.encode(key, StandardCharsets.UTF_8.toString()));
    paramString.append('=');
    paramString.append(URLEncoder.encode(Objects.toString(parameters.get(key)), StandardCharsets.UTF_8.toString()));

    splitChar = '&';
}

 

Putting it all together, here's a method we could use to call actions on the Polymart API

public static void runPolymartAPIAction(String action, Map<String, Object> parameters, Consumer<Map<?, ?>> callback){
    Bukkit.getScheduler().runTaskAsynchronously(Main.instance, () -> {
        try{
            char splitChar = '?';
            StringBuilder paramString = new StringBuilder();
            for(String key : parameters.keySet()){
                paramString.append(splitChar);
                paramString.append(URLEncoder.encode(key, StandardCharsets.UTF_8.toString()));
                paramString.append('=');
                paramString.append(URLEncoder.encode(Objects.toString(parameters.get(key)), StandardCharsets.UTF_8.toString()));
        
                splitChar = '&';
            }
     
            String urlString = "https://api.polymart.org/v1/" + action + paramString.toString();

            System.out.println("Making a GET request to " + urlString);

            URL url = new URL(urlString);
            URLConnection con = url.openConnection();
            HttpURLConnection http = (HttpURLConnection) con;
            http.setRequestMethod("GET");
            http.setDoOutput(true);

            int responseCode = http.getResponseCode();
        
            if (responseCode == HttpURLConnection.HTTP_OK) { // success
                BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
                String inputLine;
                StringBuffer response = new StringBuffer();

                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();

                Gson gson = new Gson();
                Map map = gson.fromJson(response.toString(), Map.class);

                callback.accept(map);
            }
            else{
                callback.accept(null);
            }
        }
        catch(Exception ex){
            System.err.println("Encountered an error while trying to run the Polymart API action " + action + ". Is there internet connection?")
            ex.printStackTrace();
            
            callback.accept(null);
        }
    });
}

 

We can then use this method to run any of the Polymart API actions! For example

Map<String, Object> parameters = new HashMap<>();
parameters.put("query", "Custom Items");
parameters.put("limit", 10);

runPolymartAPIAction("search", parameters, (Map<?, ?> result) -> {
    // Again, I recommend you find a better way of parsing the response than this,
    // as this can get very complicated and unsafe very quickly. But, using a Map as the
    // result gets the job done for this example

    Map<?, ?> response = (Map) result.get("response");
    List<?> list = (List) response.get("result");
    Map<?, ?> first = (Map) list.get(0);
    String url = (String) first.get("url");

    System.out.println("The url for the first resource is " + url);
});

 

If you're planning on using the Polymart API to prevent piracy using the verifyPurchase action, remember that your security is only as good as you can hide it! A bad actor can always go in and modify your code, so make sure it's not easy to simply find and remove your piracy check. To prevent piracy, we recommend that you turn on automatic .jar obfuscation, and use some advanced placeholders like %%__SIGNATURE__%% as well as the verifyPurchase API action.

 

That's all for now. Thanks for reading! If you have any questions, or have any API actions you think would be useful, please don't hesitate to send me a PM or reach out on Discord

  DEVELOPER OF POLYMART    PRO    ELITE  
I'm the developer of plugins like CustomItems, CustomEvents, and ItemBridge. I also just so happen to be the developer of Polymart! If you have any questions or suggestions about Polymart, o... Visit jojodmo's profile
More Blog Posts