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():

MyPlugin.java
java
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:

Advanced Setup
java
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

isValid()->boolean

Instant check (no API call). Returns cached status or grace period status.

getType()->LicenseType

PERMANENT, SUBSCRIPTION, or TRIAL. Only valid if isValid() is true.

getExpiresAt()->LocalDateTime

Expiration date for SUBSCRIPTION/TRIAL. Null for PERMANENT.

getMaxServers()->int

Maximum concurrent servers allowed. Check before starting a new instance.

getActiveServers()->int

How many servers are currently using this license.

stop()->void

Stops heartbeat thread. Call in onDisable(). Safe to call multiple times.

Config File Setup

Never hardcode license keys. Always read from config.yml:

MyPlugin.java
java
// 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
yaml
# config.yml
license-key: "XXXX-XXXX-XXXX-XXXX"

# Optional: your plugin slug if different from plugin name
plugin-slug: "my-plugin-slug"

Error Handling

Invalid License Key

Cause: Key format is wrong or doesn't exist

Action: Check dashboard for correct key. Re-generate if needed.

License Revoked

Cause: Owner deleted or suspended the license

Action: Contact the plugin owner. License must be re-purchased.

License Expired

Cause: SUBSCRIPTION/TRIAL expired without renewal

Action: Renew subscription in the dashboard. Or upgrade to PERMANENT.

Max Servers Exceeded

Cause: License already used on other servers

Action: Use a different key or upgrade to higher plan (more servers).

API Timeout

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).