๐๏ธTiers & Entitlements
Sell Basic, Premium and one-off deals from a single build, using values the plugin can trust because they are signed.
Every license can carry a tier (a free-form label like basic or premium) and an entitlement bag (any flags and limits you like). Both are delivered inside the signed server response, so your plugin can read them at runtime and trust them.
That means one build, sold several ways. No separate Basic and Premium jars to compile, upload and keep in sync.
Setting them
On any license, in the dashboard:
Tier:
premiumEntitlements:
{
"max_homes": 25,
"addons": true,
"support_priority": "24h"
}Change them whenever you like. The new values apply the next time that server checks its license, so an upgrade from Basic to Premium takes effect on the customer's next restart with nothing to redeliver.
Reading them
With the license check:
ObsidianLicense.Result license = client.check(key, "my-plugin", machineId);
boolean premium = "premium".equals(license.tier());
boolean addons = license.has("addons");
Object limit = license.entitlements().get("max_homes");
int maxHomes = limit instanceof Number n ? n.intValue() : 3;With a protected plugin, the same values arrive on PluginContext:
Why this is safe to gate on
The tier and entitlement block is part of the message the server signs with its Ed25519 key, and your plugin verifies that signature against the public key you pinned in the config. A customer cannot edit the JSON in flight, and a fake server cannot mint a premium answer without the private key.
The usual caveat applies: in license-check mode someone who edits your jar can change what your code does with the answer. Signing guarantees the values are authentic, not that your own code honours them.
Practical patterns
Free tier in the same build. Issue a license with tier: free and no entitlements, and gate the paid features. Now the free version and the paid version are one artifact, and an upgrade is a dashboard edit.
Per-customer limits. max_players, max_regions, max_homes. A customer who outgrows their plan gets a number changed, not a new download.
Time-limited add-ons. Combine an entitlement with the license expiry to sell a season pass on top of a perpetual license.
Beta features. Put beta_ui: true on a handful of licenses, ship the code to everyone, and enable it only where you want feedback. Pair it with the beta release channel when the change is big enough to need a separate build.
Last updated