diff --git a/docs/api/versions/v7.md b/docs/api/versions/v7.md
new file mode 100644
index 0000000..2e087e3
--- /dev/null
+++ b/docs/api/versions/v7.md
@@ -0,0 +1,450 @@
+# API Version 7
+
+The CoreProtect API enables you to log your own block changes, perform lookups, rollbacks, restores, and more.
+
+| API Details | |
+| --- | --- |
+| **API Version:** | 7 |
+| **Plugin Version:** | v20.0+ |
+| **Maven:** | [maven.playpro.com](https://maven.playpro.com) |
+
+*Documentation for the latest API version can be found [here](/api/).*
+
+---
+
+## Upgrading from API v6
+
+The changes from the previous API version are as follows:
+
+- The following methods have been added:
+```java
+parseResult(String[] result).getTimestamp()
+```
+
+---
+
+- The following methods have been deprecated:
+```java
+parseResult(String[] result).getTime()
+```
+
+---
+
+- The following methods have been removed:
+```java
+parseResult(String[] result).getTypeId()
+```
+
+---
+
+## Getting Started
+
+Ensure you're using CoreProtect 20.0 or higher. Add it as an external jar to your plugin in your IDE.
+Alternatively, if using Maven, you can add it via the repository [https://maven.playpro.com](https://maven.playpro.com) (net.coreprotect, 20.0).
+
+The first thing you need to do is get access to CoreProtect. You can do this by using code similar to the following:
+
+```java
+import net.coreprotect.CoreProtect;
+import net.coreprotect.CoreProtectAPI;
+
+private CoreProtectAPI getCoreProtect() {
+ Plugin plugin = getServer().getPluginManager().getPlugin("CoreProtect");
+
+ // Check that CoreProtect is loaded
+ if (plugin == null || !(plugin instanceof CoreProtect)) {
+ return null;
+ }
+
+ // Check that the API is enabled
+ CoreProtectAPI CoreProtect = ((CoreProtect) plugin).getAPI();
+ if (CoreProtect.isEnabled() == false) {
+ return null;
+ }
+
+ // Check that a compatible version of the API is loaded
+ if (CoreProtect.APIVersion() < 7) {
+ return null;
+ }
+
+ return CoreProtect;
+}
+```
+
+With this code, you can then access the API with a call like the following:
+
+```java
+CoreProtectAPI api = getCoreProtect();
+if (api != null){ // Ensure we have access to the API
+ api.testAPI(); // Will print out "[CoreProtect] API test successful." in the console.
+}
+```
+
+Yay, you're now using the CoreProtect API!
+
+---
+
+## API Overview
+
+### Available Methods
+
+```java
+boolean isEnabled()
+
+void testAPI()
+
+List performLookup(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location)
+
+List performRollback(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location)
+
+List performRestore(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location)
+
+List blockLookup(Block block, int time)
+
+ParseResult parseResult(String[] result)
+
+boolean logChat(Player player, String message)
+
+boolean logCommand(Player player, String command)
+
+boolean logPlacement(String user, Location location, Material type, BlockData blockData)
+
+boolean logRemoval(String user, Location location, Material type, BlockData blockData)
+
+boolean logContainerTransaction(String user, Location location)
+
+boolean logInteraction(String user, Location location)
+
+boolean hasPlaced(String user, Block block, int time, int offset)
+
+boolean hasRemoved(String user, Block block, int time, int offset)
+
+void performPurge(int time)
+```
+
+---
+
+### Method Usage
+
+*Detailed method information is listed below.*
+
+#### `isEnabled()`
+
+Calling this will return true if the server has the CoreProtect API enabled, and false if it does not.
+
+---
+
+#### `testAPI()`
+
+Running this will print out "[CoreProtect] API Test Successful." in the server console.
+
+---
+
+#### `performLookup(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location)`
+
+This will perform a lookup.
+
+* **time:** Specify the amount of time to search back. "5" would return results from the last 5 seconds.
+* **restrict_users:** Specify any usernames to perform the lookup on. Can be set to "null" if both a radius and a location are specified.
+* **exclude_users:** Specify any usernames to exclude from the lookup. Can be set to "null".
+* **restrict_blocks:** Specify a list of EntityType's or Material's to restrict the search to. Can be set to "null".
+* **exclude_blocks:** Specify a list of EntityType's or Material's to exclude from the search. Can be set to "null".
+* **action_list:** Specify a list of action types to restrict the search to. Can be set to "null"
+* **radius:** Specify a radius to restrict the search to. A location must be specified if using this. Set to "0" to disable.
+* **radius_location:** Specify a location to search around. Can be set to "null" if no radius is specified, and a user is specified.
+
+---
+
+#### `performRollback(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location)`
+
+This will perform a rollback. Method must be called async.
+
+* **time:** Specify the amount of time to rollback. "5" would return results from the last 5 seconds.
+* **restrict_users:** Specify any usernames to perform the rollback on. Can be set to "null" if both a radius and a location are specified.
+* **exclude_users:** Specify any usernames to exclude from the rollback. Can be set to "null".
+* **restrict_blocks:** Specify a list of EntityType's or Material's to restrict the rollback to. Can be set to "null".
+* **exclude_blocks:** Specify a list of EntityType's or Material's to exclude from the rollback. Can be set to "null".
+* **action_list:** Specify a list of action types to restrict the rollback to. Can be set to "null"
+* **radius:** Specify a radius to restrict the rollback to. A location must be specified if using this. Set to "0" to disable.
+* **radius_location:** Specify a location to rollback around. Can be set to "null" if no radius is specified, and a user is specified.
+
+---
+
+#### `performRestore(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location)`
+
+This will perform a restore.
+
+* **time:** Specify the amount of time to restore. "5" would return results from the last 5 seconds.
+* **restrict_users:** Specify any usernames to perform the restore on. Can be set to "null" if both a radius and a location are specified.
+* **exclude_users:** Specify any usernames to exclude from the restore. Can be set to "null".
+* **restrict_blocks:** Specify a list of EntityType's or Material's to restrict the restore to. Can be set to "null".
+* **exclude_blocks:** Specify a list of EntityType's or Material's to exclude from the restore. Can be set to "null".
+* **action_list:** Specify a list of action types to restrict the restore to. Can be set to "null"
+* **radius:** Specify a radius to restrict the restore to. A location must be specified if using this. Set to "0" to disable.
+* **radius_location:** Specify a location to restore around. Can be set to "null" if no radius is specified, and a user is specified.
+
+---
+
+#### `blockLookup(Block block, int time)`
+
+This will perform a full lookup on a single block.
+
+* **block:** The block to perform the lookup on.
+* **time:** Specify the amount of time to lookup. "5" would return results from the last 5 seconds.
+
+---
+
+#### `ParseResult parseResult(String[] result)`
+
+This will parse results from a lookup. You'll then be able to view the following:
+
+* **getX():** Get the X coordinate of the block.
+* **getY():** Get the Y coordinate of the block.
+* **getZ():** Get the Z coordinate of the block.
+* **getType():** Get the Material of the block.
+* **getBlockData():** Get the BlockData of the block.
+* **getPlayer():** Get the username as a string..
+* **getTimestamp():** Get the time of the action.
+* **getActionId():** Get the action ID. (0=removed, 1=placed, 2=interaction)
+* **getActionString():** Get the action as a string. (Removal, Placement, Interaction)
+* **isRolledBack():** If the block is currently rolled back or not.
+* **worldName():** The name of the world the block is located in.
+
+---
+
+#### `logPlacement(String user, Location location, Material type, BlockData blockData)`
+
+This will log a block as being placed.
+
+* **user:** Specify the username to log as having placed the block.
+* **location:** Specify the location of the block you're logging.
+* **type:** Specify the Material of the block you're logging.
+* **blockData:** Specify the BlockData of the block you're logging. Can be set to "null".
+
+---
+
+#### `logRemoval(String user, Location location, Material type, BlockData blockData)`
+
+This will log a block as being removed/broken, and will log the block's inventory (if applicable).
+
+* **user:** Specify the username to log as having removed the block.
+* **location:** Specify the location of the block you're logging.
+* **type:** Specify the Material of the block you're logging.
+* **blockData:** Specify the BlockData of the block you're logging. Can be set to "null".
+
+---
+
+#### `logContainerTransaction(String user, Location location)`
+
+This will log any transactions made to a block's inventory immediately after calling the method.
+
+* **user:** Specify the username to log as having added/removed the items.
+* **location:** Specify the location of the block inventory you're logging.
+
+---
+
+#### `logInteraction(String user, Location location)`
+
+This will log a block as having been interacted with.
+
+* **user:** Specify the username to log as having caused the interaction.
+* **location:** Specify the location of the interaction you're logging.
+
+---
+
+#### `hasPlaced(String user, Block block, int time, int offset)`
+
+This will return true if a user has already placed a block at the location within the specified time limit.
+
+* **user:** The username you're checking to see if they've placed a block already.
+* **block:** The block you're checking.
+* **time:** How far back to check. "5" would only check through the last 5 seconds of logged blocks.
+* **offset:** A time offset. "2" would ignore the last 2 seconds of most recently ignored data. (0=no offset)
+
+---
+
+#### `hasRemoved(String user, Block block, int time, int offset)`
+
+This will return true if a user has already removed a block at the location within the specified time limit.
+
+* **user:** The username you're checking to see if they've removed a block already.
+* **block:** The block you're checking.
+* **time:** How far back to check. "5" would only check through the last 5 seconds of logged blocks.
+* **offset:** A time offset. "2" would ignore the last 2 seconds of most recently ignored data. (0=no offset)
+
+---
+
+#### `performPurge(int time)`
+
+This will perform a purge on the CoreProtect database.
+
+* **time:** Purge any data earlier than this. "120" would purge any data older than 120 seconds (2 minutes).
+
+---
+
+
+### Examples
+
+- Get the last 60 seconds of block data for the user "Notch".
+```java
+CoreProtectAPI CoreProtect = getCoreProtect();
+if (CoreProtect!=null){ //Ensure we have access to the API
+ List lookup = CoreProtect.performLookup(60, Arrays.asList("Notch"), null, null, null, null, 0, null);
+ if (lookup!=null){
+ for (String[] result : lookup){
+ ParseResult parseResult = CoreProtect.parseResult(result);
+ int x = parseResult.getX();
+ int y = parseResult.getY();
+ int z = parseResult.getZ();
+ //...
+ }
+ }
+}
+```
+
+---
+
+- Get the last 60 seconds of block data for the user "Notch", excluding dirt and grass blocks.
+```java
+CoreProtectAPI CoreProtect = getCoreProtect();
+if (CoreProtect!=null){ //Ensure we have access to the API
+ List exclude = Arrays.asList(Material.DIRT, Material.GRASS);
+ List lookup = CoreProtect.performLookup(60, Arrays.asList("Notch"), null, null, exclude, null, 0, null);
+ if (lookup!=null){
+ for (String[] value : lookup){
+ ParseResult result = CoreProtect.parseResult(value);
+ int x = result.getX();
+ int y = result.getY();
+ int z = result.getZ();
+ //...
+ }
+ }
+}
+```
+
+---
+
+- Get the last 60 seconds of block data within 5 blocks of a location.
+```java
+CoreProtectAPI CoreProtect = getCoreProtect();
+if (CoreProtect!=null){ //Ensure we have access to the API
+ List lookup = CoreProtect.performLookup(60, null, null, null, null, null, 5, location);
+ if (lookup!=null){
+ for (String[] value : lookup){
+ ParseResult result = CoreProtect.parseResult(value);
+ int x = result.getX();
+ int y = result.getY();
+ int z = result.getZ();
+ //...
+ }
+ }
+}
+```
+
+---
+
+- Rollbacks / restores use the same code structure as the above examples. For example:
+```java
+class BasicThread implements Runnable {
+@Override
+public void run() {
+ try {
+ CoreProtectAPI CoreProtect = getCoreProtect();
+ if (CoreProtect!=null){ //Ensure we have access to the API
+ List lookup = CoreProtect.performRollback(60, Arrays.asList("Notch"), null, null, null, null, 0, null);
+ if (lookup!=null){
+ for (String[] value : lookup){
+ ParseResult result = CoreProtect.parseResult(value);
+ int x = result.getX();
+ int y = result.getY();
+ int z = result.getZ();
+ //...
+ }
+ }
+ }
+ }
+ catch (Exception e){
+ e.printStackTrace();
+ }
+}
+}
+Runnable runnable = new BasicThread();
+Thread thread = new Thread(runnable);
+thread.start();
+```
+
+---
+
+- Check if the user "Notch" has already placed a block at a location within the last 60 seconds.
+```java
+CoreProtectAPI CoreProtect = getCoreProtect();
+if (CoreProtect!=null){ //Ensure we have access to the API
+ boolean hasPlaced = CoreProtect.HasPlaced("Notch", block, 60, 0);
+}
+```
+
+---
+
+- Get the last 60 seconds of block data for a specific block.
+```java
+CoreProtectAPI CoreProtect = getCoreProtect();
+if (CoreProtect!=null){ //Ensure we have access to the API
+ List lookup = CoreProtect.blockLookup(block, 60);
+ if (lookup!=null){
+ for (String[] result : lookup){
+ ParseResult parseResult = CoreProtect.parseResult(value);
+ int x = parseResult.getX();
+ int y = parseResult.getY();
+ int z = parseResult.getZ();
+ //...
+ }
+ }
+}
+```
+
+---
+
+- Log the placement of a block at a location by the user "Notch".
+```java
+CoreProtectAPI CoreProtect = getCoreProtect();
+if (CoreProtect!=null){ //Ensure we have access to the API
+ boolean success = CoreProtect.logPlacement("Notch", block.getLocation(), block.getType(), block.getData());
+}
+```
+
+---
+
+- Log adding/remove items in a chest (or some other block inventory).
+```java
+CoreProtectAPI CoreProtect = getCoreProtect();
+if (CoreProtect!=null){ //Ensure we have access to the API
+ boolean success = CoreProtect.logContainerTransaction("Notch", inventory.getLocation());
+ // modify your container contents immediately after (e.g. [i]inventory.addItem(itemStack);[/i])
+}
+```
+
+---
+
+- Perform a multi-threaded placement check to see if the user "Notch" has already placed a block at a location within the last 60 seconds. This ignores the most recent 1 second of logged data, to account for the fact that that new block data may have already been logged, depending on your code.
+```java
+final Block block = null; //Should be an actual block
+class BasicThread implements Runnable {
+ @Override
+ public void run() {
+ try {
+ CoreProtectAPI CoreProtect = getCoreProtect();
+ if (CoreProtect!=null){ //Ensure we have access to the API
+ boolean hasPlaced = CoreProtect.hasPlaced("Notch", block, 60, 1);
+ }
+ }
+ catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+}
+Runnable runnable = new BasicThread();
+Thread thread = new Thread(runnable);
+thread.start();
+```
+
+---
\ No newline at end of file