License Check Integration
Learn how to integrate ILicence verification into your Minecraft plugin. We cover one-liner setup, advanced configuration, and best practices.
One-Liner Setup
The simplest way to integrate ILicence is a single method call in your plugin's onEnable():
import ch.irixiagroup.ilicence.ILicence;
private ILicence licence;
@Override
public void onEnable() {
licence = ILicence.verify(this, "YOUR-LICENSE-KEY", "your-plugin-slug");
}
@Override
public void onDisable() {
if (licence != null) licence.stop();
}What happens
ILicence.verify() will immediately check your license with our API. If valid, your plugin loads normally. If invalid or API is unreachable, the plugin disables itself.
Advanced Configuration
For production plugins, use the builder pattern to configure caching, heartbeat, and callbacks:
ILicence licence = ILicence.builder()
.plugin(this)
.licenseKey("XXXX-XXXX-XXXX-XXXX")
.pluginId("my-plugin-slug")
.cacheDuration(Duration.ofHours(12))
.heartbeat(Duration.ofHours(6))
.gracePeriod(Duration.ofHours(24))
.onValid(response -> {
getLogger().info("License valid! Type: " + response.type());
})
.onInvalid(response -> {
getLogger().severe("License invalid: " + response.error());
getServer().getPluginManager().disablePlugin(this);
})
.onStatusChange((wasValid, isNowValid) -> {
if (!isNowValid) {
getLogger().severe("License revoked! Shutting down.");
getServer().getPluginManager().disablePlugin(this);
}
})
.verify();Cache Duration
How long to cache the license verification result. Default is 12 hours. During the cache period, no API call is made.
cacheDuration(Duration.ofHours(12))
Set to 0 to disable caching (API called every startup) or higher values like 24h for offline networks.
Heartbeat
Periodically verify the license while the server is running. Detects revocations without restarting. Default is 6 hours.
heartbeat(Duration.ofHours(6))
Runs on a background thread. Safe to use in production. 30 minutes is a good balance.
Grace Period
If API is unreachable during heartbeat, allow the plugin to continue for this duration. Default is 24 hours. Prevents false positives from network issues.
gracePeriod(Duration.ofHours(24))
After 24h of API downtime, plugin disables. Good for isolated servers with unreliable connectivity.
Status Callbacks
onValid()
Called when license check passes. Great for logging or triggering features.
.onValid(response -> {
getLogger().info("License valid! Type: " + response.type());
// response.type() can be: PERMANENT, SUBSCRIPTION, TRIAL
})onInvalid()
Called when license check fails. Disable the plugin here if you want manual control.
.onInvalid(response -> {
getLogger().severe("License invalid: " + response.error());
// response.error() can be: revoked, expired, not_found, invalid_key
getServer().getPluginManager().disablePlugin(this);
})onStatusChange()
Called when license status changes during heartbeat (e.g., revoked while running).
.onStatusChange((wasValid, isNowValid) -> {
if (!isNowValid) {
getLogger().severe("License revoked! Shutting down.");
getServer().getPluginManager().disablePlugin(this);
}
})Instance Methods
Instant check (no API call). Returns cached status or grace period status.
PERMANENT, SUBSCRIPTION, or TRIAL. Only valid if isValid() is true.
Expiration date for SUBSCRIPTION/TRIAL. Null for PERMANENT.
Maximum concurrent servers allowed. Check before starting a new instance.
How many servers are currently using this license.
Stops heartbeat thread. Call in onDisable(). Safe to call multiple times.
Config File Setup
Never hardcode license keys. Always read from config.yml:
// In onEnable()
String licenseKey = getConfig().getString("license-key", "");
if (licenseKey.isEmpty()) {
getLogger().severe("No license key configured! Set 'license-key' in config.yml");
getServer().getPluginManager().disablePlugin(this);
return;
}
ILicence licence = ILicence.verify(this, licenseKey, "my-plugin");# config.yml license-key: "XXXX-XXXX-XXXX-XXXX" # Optional: your plugin slug if different from plugin name plugin-slug: "my-plugin-slug"
Error Handling
Cause: Key format is wrong or doesn't exist
Action: Check dashboard for correct key. Re-generate if needed.
Cause: Owner deleted or suspended the license
Action: Contact the plugin owner. License must be re-purchased.
Cause: SUBSCRIPTION/TRIAL expired without renewal
Action: Renew subscription in the dashboard. Or upgrade to PERMANENT.
Cause: License already used on other servers
Action: Use a different key or upgrade to higher plan (more servers).
Cause: Server can't reach ilicence.ch
Action: Check network. Grace period kicks in after 24h of downtime.
Best Practices
- Always call licence.stop() in onDisable() to stop the heartbeat thread cleanly.
- Read license key from config.yml, never hardcode it.
- Use onStatusChange() callback to detect revocations mid-game.
- Set heartbeat to 30 minutes for most use cases.
- Set grace period to 24 hours to tolerate brief network outages.
- Don't disable the plugin automatically on invalid — let owner decide by reading onEnable() logs.
- For extra security, implement dispersed license checks (see Advanced Protection guide).