TeamsAPI The universal bridge between team plugins and everything else.
What is TeamsAPI?
TeamsAPI is a passive, server-side bridge plugin for Paper, Spigot, Purpur, and Folia servers, inspired by
Vault.
It defines a clean, stable interface for team operations so that any plugin needing team data can work with any compatible team plugin, without either plugin knowing about the other.
Providers - faction, clan, guild, or custom team plugins implementTeamsService and register with TeamsAPI on startup.
Consumers - scoreboard plugins, chat formatters, quest plugins, or any plugin that needs team data calls TeamsAPI.getService() once and uses the returned interface.
Server owners - install TeamsAPI.jar alongside one compatible team plugin. Done.
Features
Official extensions - ready-to-use provider bridges for BetterTeams, Towny Advanced, and KingdomsX - bundled inside the main JAR, install in-game with /teamsapi install <name>.
Provider-agnostic - works with any team plugin that ships a TeamsService implementation.
Graceful fallback - if no provider is present, [/icode]TeamsAPI.isAvailable()[/icode] returns false; consumers can disable team features cleanly instead of crashing.
Read-only snapshots - Team and TeamMember are immutable interfaces; providers own the backing data.
Role hierarchy - built-in OWNER > ADMIN > MEMBER with outranks() and canManage() helpers.
Optional invite service - providers can expose TeamsInviteService for invitation workflows.
Optional warp service - providers can expose TeamsWarpService for named team warps.
Optional chest service - providers can expose TeamsChestService for team chest contents and add/remove operations.
Optional claim service - providers can expose TeamsClaimService for chunk-claim management, including SafeZone and WarZone support.
Optional power service - providers can expose TeamsPowerService for player and team power values.
Optional power-history service - providers can expose TeamsPowerHistoryService for reading and managing player/team power-history entries.
Optional relation service - providers can expose TeamsRelationService for inter-team diplomacy (ally / truce / neutral / enemy).
Optional notification service - providers can expose TeamsNotificationService for cross-plugin player notifications with built-in enum types and custom string types.
Custom subcommands - any plugin registers a TeamsSubcommand via TeamsAPI.registerSubcommand(); team plugins call TeamsAPI.getSubcommands() in their own command handler to dispatch them without coupling.
Cancellable events - fifteen Bukkit events that providers can fire so other plugins can react to or cancel team operations.
Lightweight - a single shaded JAR with no required runtime dependencies beyond the Bukkit API (optional: Vault for the built-in power shop).
JitPack-ready - depend on just the API module at compile time via Maven or Gradle.
Velocity bridge(experimental) - optional teams-api-velocity plugin queries team data from the Velocity proxy. Supports multi-proxy networks via Redis.
BungeeCord bridge(experimental) - optional teams-api-bungeecord plugin for BungeeCord / Waterfall proxies. Supports multi-proxy networks via Redis.
Requirements
Server software: Paper, Spigot, Purpur, or Folia 1.16+
Java:17+ (25 recommended)
Plugin dependencies: None (optional: Vault for power shop)
Installation (server owners)
Download teams-api-plugin-VERSION.jar from the Download button at the top of this page or from GitHub Releases.
Drop it into your server's plugins/ folder.
Install a compatible team plugin. Official extensions for BetterTeams, Towny Advanced, and KingdomsX are bundled -- run /teamsapi install betterteams (or towny / kingdomsx) in-game, or let TeamsAPI provision them automatically to plugins/TeamsAPI/extensions/.
Restart the server.
TeamsAPI has no configuration files.
For Developers
Add the API artifact to your project via
JitPack. Use scope: provided (Maven) or compileOnly (Gradle), the classes are provided by TeamsAPI.jar at runtime.
Declare the dependency in plugin.yml (use softdepend if team support is optional):
Code (YAML):
depend: - TeamsAPI
Then use the API at runtime:
Code (Java):
@Override
publicvoid onEnable
(){ if(!TeamsAPI.
isAvailable()){ getLogger
().
warning("No team plugin found. Team features disabled."); return; } getLogger
().
info("TeamsAPI found. Team features enabled."); }
// In a command or listener: TeamsService teams
= TeamsAPI.
getService(); Optional
<Team
> team
= teams.
getPlayerTeam(player.
getUniqueId()); team.
ifPresent(t
-> player.
sendMessage("Your team: "+ t.
getDisplayName()));
Provider quick-start
Declare a soft-dependency in plugin.yml and register your implementation:
Code (YAML):
softdepend: - TeamsAPI
Code (Java):
@Override
publicvoid onEnable
(){ TeamsAPI.
registerProvider(this,
new MyTeamsService
(this)); }
isSafeZone(world, x, z) -> boolean - Whether the chunk is a SafeZone
isWarZone(world, x, z) -> boolean - Whether the chunk is a WarZone
getTeamMaxClaims(teamId) -> int - Claim limit (-1 means unlimited)
Power service (optional)
Check availability with TeamsAPI.isPowerAvailable() before calling TeamsAPI.getPowerService().
getPlayerPower(playerUUID) -> double - Current power of the player
getPlayerMaxPower(playerUUID) -> double - Maximum power the player can hold
setPlayerPower(playerUUID, power) -> boolean - Sets the player's power
getTeamPower(teamId) -> double - Combined power of all team members
getTeamMaxPower(teamId) -> double - Maximum combined power the team can hold
Power history service (optional)
Check availability with TeamsAPI.isPowerHistoryAvailable() before calling TeamsAPI.getPowerHistoryService().
getPlayerPowerHistory(playerUUID, limit) -> Collection<TeamPowerHistoryEntry> - Recent entries for a player, newest first.
getPlayerPowerHistory(playerUUID, fromInclusive, toExclusive, limit) -> Collection<TeamPowerHistoryEntry> - Player entries in a time window, newest first.
getTeamPowerHistory(teamId, limit) -> Collection<TeamPowerHistoryEntry> - Recent entries linked to a team.
addPowerHistoryEntry(entryId, playerUUID, teamId, delta, type, reason, actorUUID, occurredAt, details) -> boolean - Inserts a history entry.
removePowerHistoryEntry(entryId) -> boolean - Deletes one entry by ID.
clearPlayerPowerHistory(playerUUID) -> int - Deletes all player entries; returns removed count.
clearTeamPowerHistory(teamId) -> int - Deletes all team-linked entries; returns removed count.
Relation service (optional)
Check availability with TeamsAPI.isRelationAvailable() before calling TeamsAPI.getRelationService().
setRelation(fromTeamId, toTeamId, relation, initiatorUUID) -> boolean - Declares a relation toward another team. Fires TeamRelationChangeEvent; returns false if cancelled. Setting NEUTRAL removes the relation.
getRelation(fromTeamId, toTeamId) -> TeamRelation - Returns the declared relation (defaults to NEUTRAL if none set).
getRelations(teamId) -> Map<UUID, TeamRelation> - All non-neutral relations declared by the team.
clearRelations(teamId) -> boolean - Removes all relations declared by or toward the team (use on disband).
areAllies(teamAId, teamBId) -> boolean - true when both teams have declared ALLY toward each other.
areEnemies(teamAId, teamBId) -> boolean - true when either team has declared ENEMY toward the other.
getTeamsInRelation(teamId, relation) -> Collection<UUID> - All team UUIDs toward which teamId has declared the given relation; providers may override for efficiency.
getRelationColor(relation) -> String - #RRGGBB hex color for the relation. Default returns TeamRelation.getDefaultHexColor(); providers override to supply server-configured colors.
TeamRelation display names, legacy color codes, and hex colors:
Check availability with TeamsAPI.isNotificationAvailable() before calling TeamsAPI.getNotificationService().
sendNotification(senderPlugin, recipientUUID, type, message) -> boolean - Sends a notification using built-in TeamNotificationType.
sendNotification(senderPlugin, recipientUUID, notificationType, message) -> boolean - Sends a notification using a custom string type (non-null, non-blank).
isNotificationEnabled(playerUUID, type) -> boolean - Whether this built-in notification type is enabled for the player.
isNotificationEnabled(playerUUID, notificationType) -> boolean - Whether this custom notification type is enabled for the player.
setNotificationEnabled(playerUUID, type, enabled) -> boolean - Enables or disables a built-in notification type for the player.
setNotificationEnabled(playerUUID, notificationType, enabled) -> boolean - Enables or disables a custom notification type for the player.
Built-in TeamNotificationType values:
Code (Text):
GENERAL, TEAM_JOIN, TEAM_LEAVE, TEAM_INVITE, TEAM_INVITE_ACCEPT, TEAM_INVITE_DECLINE
Custom subcommands
Any plugin registers a TeamsSubcommand and team plugins call TeamsAPI.getSubcommands() in their own command executor to dispatch them. This extends the team plugin's command tree without any coupling between plugins.
Code (Java):
// onEnable TeamsAPI.
registerSubcommand(this,
new MySubcommand
());
getName() -> String - Matched case-insensitively against the first argument
getDescription() -> String - Optional description for help output
getPermission() -> String - Permission required, or null for no check
execute(sender, args) -> boolean - Called when the subcommand is dispatched; return false to show usage
getUsage() -> String - Usage hint sent when execute returns false
tabComplete(sender, args) -> List<String> - Tab-completion suggestions; default: empty list
Commands & permissions
/teamsapi / /teamsapi help - requires teamsapi.use (default: everyone) - Lists commands the sender can use
/teamsapi version - requires teamsapi.use (default: everyone) -- Prints plugin and API version
/teamsapi status - requires teamsapi.status (default: everyone) -- Active provider, team count, registered services
/teamsapi info - requires teamsapi.admin (default: op) -- Full internal diagnostic
/teamsapi power status - requires teamsapi.power (default: op) -- Sender's current and max power
/teamsapi power buy <n> - requires teamsapi.power.buy (default: disabled) - Disabled by default; enable with power-shop.enabled: true in config.yml. Requires Vault.
/teamsapi install <extension> - requires teamsapi.install (default: op) - Copies a bundled extension JAR to plugins/TeamsAPI/extensions/. Valid names: betterteams, towny, kingdomsx.
/teamsapi load <file>.jar - requires teamsapi.load (default: op) -- Loads and enables an extension from plugins/TeamsAPI/extensions/ without a server restart.
Events
All events live in com.skyblockexp.teamsapi.event.
Providers are encouraged (but not required) to fire them.
TeamCreateEvent(cancellable) - fired before a team is created
TeamDeleteEvent(cancellable) - fired before a team is deleted
TeamJoinEvent(cancellable) - fired before a player joins a team
TeamLeaveEvent(cancellable) - fired before a player leaves a team
TeamRoleChangeEvent(cancellable) - fired before a member's role changes
TeamInviteEvent(cancellable) - fired before an invitation is sent
TeamInviteAcceptEvent(informational) - fired after a player accepts an invitation
TeamInviteDeclineEvent(informational) - fired after a player declines an invitation
TeamWarpSetEvent(cancellable) - fired before a warp is created or updated
TeamWarpDeleteEvent(cancellable) - fired before a warp is deleted
TeamClaimEvent(cancellable) - fired before a chunk is claimed
TeamUnclaimEvent(cancellable) - fired before a chunk is unclaimed
Roles
OWNER (priority 100) - Full control; cannot be removed by others
ADMIN (priority 50) - Can manage members with a lower priority