Welcome to the Hangar Open Beta. Please report any issue you encounter on GitHub!
Avatar for Spolzer

Trade items, money, experience and points between players on your server

Report InTrade?

Safe and convenient player-to-player trading: items, money, experience levels and points in a single window with double confirmation.


About

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.

How a trade works

  1. Run /trade <player> or Shift + right click a player. They accept with /trade accept.
  2. Add items from your inventory. To take an item back, click it in the trade window.
  3. Choose a currency and enter an amount.
  4. 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.

Optional integrations:

Plugin Adds
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

Items and experience levels work without any dependencies.


Installation

  1. Put InTrade-x.x.x.jar into the plugins folder.
  2. Restart the server.
  3. If needed, edit plugins/InTrade/config.yml and run /trade reload.

Commands

Command Description
/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

Alias: /intrade. By default a request lasts 60 seconds, with a 5-second cooldown between requests.


Permissions and rank-based access

Permission Default Access
intrade.player everyone All player permissions
intrade.use everyone Requests and /trade claim
intrade.sneak everyone Requests via Shift + right click
intrade.toggle everyone Toggling incoming requests
intrade.history everyone Own history
intrade.currency.money everyone Vault money
intrade.currency.experience everyone Experience levels
intrade.currency.playerpoints everyone PlayerPoints
intrade.admin op All staff permissions
intrade.history.others op Other players' history
intrade.reload op Reloading settings
intrade.bypass.distance op Bypass distance and world restrictions
intrade.bypass.cooldown op Bypass request cooldown
intrade.bypass.blocked op Trade blocked items

Wildcard nodes: intrade.*, intrade.currency.*, intrade.bypass.*.

Trading only from a certain rank. Set in the config:

permissions:
  open-to-everyone: false

Run /trade reload and grant access to a group:

/lp group rank3 permission set intrade.player true

Higher ranks get access if you have group inheritance set up. Example: trading is available from rank 3, but money only from rank 5:

/lp group rank3 permission set intrade.currency.money false
/lp group rank5 permission set intrade.currency.money true

config.yml

# 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

PlaceholderAPI placeholders

Placeholder Value
%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

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.


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.

import me.spolzer.intrade.api.InTrade;

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.

FAQ

Is a client mod required? No, the plugin is fully server-side.

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.


GitHub • CurseForge • Support

Found a bug or have an idea? Open an issue on GitHub.

Information

Category
Economy
Published
September 25, 2026
License
MIT
0Downloads
1Stars
Addon

Pinned Versions

Members

1