Safe and convenient player-to-player trading: items, money, experience levels and points in a single window with double confirmation.
Requires Paper 1.21.7+ (does not run on plain Spigot)
About
Requires Paper 1.21.7+ (does not run on plain Spigot)
InTrade is a server-side plugin for direct trading between players. Your offer is on the left, your partner's offer is on the right. Each side has 16 item slots plus buttons for the available currencies. No client mods are needed, everything works through a regular inventory menu.
The main goal of the plugin is to keep trades fair. Swapping an item at the last moment is impossible: any change resets both players' readiness and is immediately highlighted for the partner.
Features
- One window for both players: 16 slots per side. Left click adds a stack, right click adds a single item.
- Multiple currencies: money (Vault), whole experience levels, PlayerPoints. Amounts can be entered as 1500, 2.5k or 1m.
- Anti-scam protection: after any change the "Ready" button is locked for 3 seconds, changed items are highlighted for 6 seconds, and a red marker stays where an item was removed. The final countdown after both players confirm lasts 3 seconds, and any change stops it.
- Shulker box and bundle preview: view the contents of your partner's containers before the trade.
- Inventory space check: the trade won't complete if the items have nowhere to go.
- Item recovery: anything that doesn't fit when returned, and the items of a player who dies during a trade, are saved for /trade claim.
- Trade history: a menu showing the items and currencies of every completed trade.
- Stats and leaderboard: trade counter and top list that are not reset when history is cleaned up.
- SQLite or MySQL/MariaDB: works out of the box, and several servers can share one database if needed.
- Per-client language: in auto mode every player sees menus and messages in their game language. English and Russian are included, texts use MiniMessage.
- Bedrock support: Geyser/Floodgate players enter amounts through a native form.
- Rank-based access: trading and individual currencies can be unlocked from a specific rank via LuckPerms.
- Quick request: Shift + right click on a player.
- PlaceholderAPI and a developer API.
Screenshots
Trade window
How a trade works
- Run /trade <player> or Shift + right click a player. They accept with /trade accept.
- Add items from your inventory. To take an item back, click it in the trade window.
- Choose a currency and enter an amount.
- Check your partner's offer and click Ready. Once both players confirm, a short countdown starts, after which the trade completes.
Requirements
- Paper 1.21.7 or newer.
- The Java version your Paper build requires (21 minimum).
- Internet access on first launch: Paper downloads the required libraries automatically.
- Vault + an economy plugin: money in the trade window
- PlayerPoints: trading points
- Floodgate: native amount input form for Bedrock players
- PlaceholderAPI: stats and player state placeholders
Installation
- Put InTrade-x.x.x.jar into the plugins folder.
- Restart the server.
- If needed, edit plugins/InTrade/config.yml and run /trade reload.
Commands
- /trade <player> - send a request or accept an incoming one from this player
- /trade accept [player] - accept a request
- /trade deny [player] - deny a request
- /trade toggle - enable or disable incoming requests
- /trade claim - collect items saved for you
- /trade history [player] - your own history; for staff, another player's history
- /trade reload - reload configuration and translations
Spoiler: Permissions and rank-based access
Player permissions (default: everyone)
Trading only from a certain rank. Set in the config:
Run
/trade reload and grant access to a group:
Higher ranks get access if you have group inheritance set up. Example: trading is available from rank 3, but money only from rank 5:
- intrade.player - all player permissions
- intrade.use - requests and /trade claim
- intrade.sneak - requests via Shift + right click
- intrade.toggle - toggling incoming requests
- intrade.history - own history
- intrade.currency.money - Vault money
- intrade.currency.experience - experience levels
- intrade.currency.playerpoints - PlayerPoints
- intrade.admin - all staff permissions
- intrade.history.others - other players' history
- intrade.reload - reloading settings
- intrade.bypass.distance - bypass distance and world restrictions
- intrade.bypass.cooldown - bypass request cooldown
- intrade.bypass.blocked - trade blocked items
Trading only from a certain rank. Set in the config:
Code (Text):
permissions:
open-to-everyone: false
open-to-everyone: false
Code (Text):
/lp group rank3 permission set intrade.player true
Code (Text):
/lp group rank3 permission set intrade.currency.money false
/lp group rank5 permission set intrade.currency.money true
/lp group rank5 permission set intrade.currency.money true
Spoiler: config.yml
Code (Text):
# InTrade configuration.
# Messages and menu texts are in lang/<language>.yml.
# "auto" shows every player the messages in their game language. English and Russian are included,
# other languages can be added as new files in lang/. Any other value (for example "ru") uses one
# language for everyone.
language: auto
# Used for the console and for game languages without a file in lang/.
default-language: en
permissions:
# true: all players can trade by default.
# false: players need intrade.player (or individual permissions) from a permissions plugin such as LuckPerms.
# Staff permissions are always limited to operators by default.
open-to-everyone: true
requests:
# Time before an unanswered request expires.
expire-seconds: 60
# Minimum time between two requests from the same player.
cooldown-seconds: 5
# Allow sending a request by sneaking and right-clicking a player.
sneak-click: true
# Maximum distance between players. 0 disables the check.
max-distance: 0
# Allow trades only between players in the same world.
same-world: false
safety:
# Time after any change during which the "Ready" button is locked.
change-lock-seconds: 3
# Time a changed or removed item stays highlighted for the partner.
highlight-seconds: 6
# Countdown after both players are ready. Any change stops it.
confirm-seconds: 3
currencies:
# Requires Vault and an economy plugin.
money:
enabled: true
# Whole experience levels.
experience:
enabled: true
# Requires PlayerPoints.
playerpoints:
enabled: true
# Materials that cannot be traded.
blocked-items: []
# - BEDROCK
# - BARRIER
# Worlds where trades cannot be started.
disabled-worlds: []
history:
enabled: true
# Trades older than this are deleted on startup. 0 keeps all trades.
# Trade counts and the top list are not affected.
keep-days: 90
# Changes in this section require a server restart.
storage:
# sqlite: local file plugins/InTrade/trades.db, no setup required.
# mysql: MySQL or MariaDB server, configured below.
type: sqlite
# Unique name of this server. Only needed when several servers use the same MySQL database.
# Items in open trade windows and /trade claim mail are kept per server,
# trade history and trade counts are shared.
server-id: main
mysql:
host: localhost
port: 3306
database: minecraft
user: root
password: ""
# Number of connections. One is used for writing, the rest for reading.
pool-size: 4
# Additional JDBC driver properties.
properties:
useSSL: false
allowPublicKeyRetrieval: true
# Messages and menu texts are in lang/<language>.yml.
# "auto" shows every player the messages in their game language. English and Russian are included,
# other languages can be added as new files in lang/. Any other value (for example "ru") uses one
# language for everyone.
language: auto
# Used for the console and for game languages without a file in lang/.
default-language: en
permissions:
# true: all players can trade by default.
# false: players need intrade.player (or individual permissions) from a permissions plugin such as LuckPerms.
# Staff permissions are always limited to operators by default.
open-to-everyone: true
requests:
# Time before an unanswered request expires.
expire-seconds: 60
# Minimum time between two requests from the same player.
cooldown-seconds: 5
# Allow sending a request by sneaking and right-clicking a player.
sneak-click: true
# Maximum distance between players. 0 disables the check.
max-distance: 0
# Allow trades only between players in the same world.
same-world: false
safety:
# Time after any change during which the "Ready" button is locked.
change-lock-seconds: 3
# Time a changed or removed item stays highlighted for the partner.
highlight-seconds: 6
# Countdown after both players are ready. Any change stops it.
confirm-seconds: 3
currencies:
# Requires Vault and an economy plugin.
money:
enabled: true
# Whole experience levels.
experience:
enabled: true
# Requires PlayerPoints.
playerpoints:
enabled: true
# Materials that cannot be traded.
blocked-items: []
# - BEDROCK
# - BARRIER
# Worlds where trades cannot be started.
disabled-worlds: []
history:
enabled: true
# Trades older than this are deleted on startup. 0 keeps all trades.
# Trade counts and the top list are not affected.
keep-days: 90
# Changes in this section require a server restart.
storage:
# sqlite: local file plugins/InTrade/trades.db, no setup required.
# mysql: MySQL or MariaDB server, configured below.
type: sqlite
# Unique name of this server. Only needed when several servers use the same MySQL database.
# Items in open trade windows and /trade claim mail are kept per server,
# trade history and trade counts are shared.
server-id: main
mysql:
host: localhost
port: 3306
database: minecraft
user: root
password: ""
# Number of connections. One is used for writing, the rest for reading.
pool-size: 4
# Additional JDBC driver properties.
properties:
useSSL: false
allowPublicKeyRetrieval: true
Spoiler: PlaceholderAPI placeholders
- %intrade_trades% - number of the player's completed trades
- %intrade_trading% - whether the player is currently in a trade
- %intrade_accepting% - whether the player accepts incoming requests
- %intrade_top_<1-10>_name% - name of the player at the given leaderboard position
- %intrade_top_<1-10>_trades% - trade count of the player at that position
Spoiler: History and database
By default history is kept for
90 days, cleanup runs on server startup.
history.keep-days: 0 disables deletion. Trade counters and the leaderboard are stored separately and are not reset by cleanup.
SQLite works without setup, the database is located at plugins/InTrade/trades.db. For MySQL or MariaDB set storage.type: mysql, fill in the storage.mysql section and restart the server. Tables with the intrade_ prefix are created automatically.
Server networks. Several servers can use one database with shared history and stats. Each server needs a unique storage.server-id: pending offers and items for /trade claim are bound to a specific server.
SQLite works without setup, the database is located at plugins/InTrade/trades.db. For MySQL or MariaDB set storage.type: mysql, fill in the storage.mysql section and restart the server. Tables with the intrade_ prefix are created automatically.
Server networks. Several servers can use one database with shared history and stats. Each server needs a unique storage.server-id: pending offers and items for /trade claim are bound to a specific server.
Spoiler: Developer API
The
api module gives access to stats and trade events. Add it as
compileOnly and put InTrade in your plugin's
depend or
softdepend.
Code (Text):
import me.spolzer.intrade.api.InTrade;
InTrade trade = InTrade.get();
trade.tradeCount(player.getUniqueId()).thenAccept(count ->
getLogger().info("Completed trades: " + count));
InTrade trade = InTrade.get();
trade.tradeCount(player.getUniqueId()).thenAccept(count ->
getLogger().info("Completed trades: " + count));
- TradeRequestEvent and TradeStartEvent are cancellable.
- TradeCompleteEvent contains both offers.
- TradeCancelEvent provides the cancellation reason.
- Stats are returned as a CompletableFuture. Switch to the main server thread when working with Bukkit objects.
Spoiler: FAQ
Is a client mod required?
No, the plugin is fully server-side.
Does it work on Spigot?
No, InTrade requires Paper 1.21.7 or newer (or a Paper fork such as Purpur).
Can I block certain items from being traded?
Yes, via the blocked-items list in the config. Staff with intrade.bypass.blocked can still trade them.
Can I restrict trading by distance or world?
Yes: max-distance, same-world and disabled-worlds.
What happens if a player leaves or dies during a trade?
The trade is cancelled and items are returned to their owners. Anything that doesn't fit in the inventory is saved for /trade claim.
How do I add my own language?
Create a lang/<code>.yml file based on en.yml or ru.yml.
Is there absolute protection against server crashes?
Pending offers are written to the database and restored after a restart. However, player data saving, database writes and third-party economy operations are not combined into a single transaction, so a 100% guarantee cannot be given if the server crashes.
No, the plugin is fully server-side.
Does it work on Spigot?
No, InTrade requires Paper 1.21.7 or newer (or a Paper fork such as Purpur).
Can I block certain items from being traded?
Yes, via the blocked-items list in the config. Staff with intrade.bypass.blocked can still trade them.
Can I restrict trading by distance or world?
Yes: max-distance, same-world and disabled-worlds.
What happens if a player leaves or dies during a trade?
The trade is cancelled and items are returned to their owners. Anything that doesn't fit in the inventory is saved for /trade claim.
How do I add my own language?
Create a lang/<code>.yml file based on en.yml or ru.yml.
Is there absolute protection against server crashes?
Pending offers are written to the database and restored after a restart. However, player data saving, database writes and third-party economy operations are not combined into a single transaction, so a 100% guarantee cannot be given if the server crashes.
Links
GitHub • CurseForge • Support
Found a bug or have an idea? Post in the discussion thread or open an issue on GitHub.
GitHub • CurseForge • Support
Found a bug or have an idea? Post in the discussion thread or open an issue on GitHub.
Quick facts
- Edition: Minecraft Java
- File type: .jar
- Minecraft versions listed: 1.21, 26.1, 26.2
- How to install: Install the matching mod loader (Forge, Fabric or NeoForge) for your Minecraft version. → Download the .jar. → Put it in the .minecraft/mods folder and launch that loader profile.
- Where to get it: Opens on Spigot — not every file is mirrored on our own servers.
Install steps are the general flow for this file type — How to install Minecraft Java mods & modpacks walks through it step by step.
InTrade - Player-to-Player Trading System is a free Minecraft Java mod. Compatible with Minecraft 1.21, 26.1, 26.2, 26.3. Downloaded 12 times (via Spigot). Download it and open it directly in the game.