> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nmcrate.com/llms.txt
> Use this file to discover all available pages before exploring further.

# NMKey licensing

> NMCrate's first-party plugin licensing — per-buyer keys baked into the jar, locked to one live server, validated with Ed25519-signed responses.

NMKey is NMCrate's own licensing backend for paid plugins. Unlike third-party license services, the entire validation pipeline runs on NMCrate itself — there is nothing external to spoof, throttle, or take offline.

## How it protects your plugin

1. A buyer completes checkout on NMCrate.
2. NMCrate mints a unique `NMK-…` key bound to **one live server** at a time.
3. The download bakes the buyer's key into their `plugin.jar` as an embedded `nmkey.txt` — there is nothing for buyers to copy or configure.
4. On boot, your plugin validates the key via the [NMKey library](/publicapi/docs/nmkey-plugin-integration) (asynchronously), which verifies the Ed25519-signed response.
5. The first server claims the license seat; any second server is rejected with `max_servers`. A leaked key simply refuses to boot anywhere else.

Responses are cryptographically signed, so even if an attacker reroutes the API to a fake server that always answers "valid", the library verifies the signature against NMCrate's public key and rejects the forgery.

## The NMKey library

The officially endorsed client is an ultra-lightweight Kotlin/JVM library ([GuavaDealer/NMKey](https://github.com/GuavaDealer/NMKey), Apache 2.0):

* **No networking bloat** — no Ktor, no coroutine dispatchers; just the native Java 17 `HttpClient` and the Bukkit API, with `kotlinx.serialization` for reflection-free JSON.
* **Dynamic fingerprinting** — identifies the server with in-memory JVM heuristics (processors, OS arch, server port) to prevent seat spoofing in containerized environments.
* **Offline grace period** — a 256-bit AES-GCM encrypted cache keyed to the server's fingerprint lets valid buyers survive API outages for up to 48 hours.
* **Self-Cleaning architecture** — hooks Bukkit's `PluginDisableEvent` to automatically release the license seat and destroy HTTP threads on shutdown or `/reload`; no manual cleanup needed.

### Requirements

|           |                                                     |
| --------- | --------------------------------------------------- |
| Java      | 17+                                                 |
| Paper API | 1.17+                                               |
| Kotlin    | 2.4+ (stdlib + serialization, shaded into your jar) |

## Enabling NMKey for a product

In your studio dashboard, open **Licensing → Add license**, pick the plugin, and choose **NMKey Plugin Safe**. You'll get an 8-character plugin id — that's the `PLUGIN_ID` your code passes to the library. Default policy (servers per key, expiration) is configurable per product, and individual keys can be revoked or adjusted from the same tab.

Not on the JVM? The raw HTTP endpoints are public — see the [NMKey HTTP API](/publicapi/docs/nmkey-http-api).
