Skip to main content
If your product doesn’t run on the JVM (or you want full control), NMKey is just a signed HTTP endpoint. Anything that can POST JSON can validate a key. All endpoints are public — the license key itself is the credential, no API key is needed.

Base URL

https://nmcrate.com/api/nmkey/v1

POST /validate

Checks a key and claims (or refreshes) this server’s license slot. Call on boot and periodically as a heartbeat.
curl -sX POST "https://nmcrate.com/api/nmkey/v1/validate" \
  -H "Content-Type: application/json" \
  -d '{
    "pluginId": "a7f3k9q2",
    "key": "NMK-XXXXXXXX-XXXXXXXX-XXXXXXXX",
    "fingerprint": "stable-per-server-hash",
    "nonce": "random-per-request-value",
    "hostname": "mc.example.com"
  }'
Body fieldRequiredDescription
pluginIdyesYour 8-character NMKey plugin id (Licensing tab).
keyyesThe buyer’s NMK-… license key.
fingerprintyesA stable per-server hash — this is the unit the seat lock counts against.
nonceyesA fresh random value per request; echoed into the signature (replay defence).
hostnamenoDisplay name for the studio’s key-management UI.
The response is always HTTP 200 — the verdict is in the body:
{
  "status": "valid",
  "ok": true,
  "pluginId": "a7f3k9q2",
  "issuedAt": "2026-07-13T18:00:00.000Z",
  "nonce": "random-per-request-value",
  "maxServers": 1,
  "activeServers": 1,
  "expiresAt": null,
  "signature": "base64url-ed25519-signature"
}
statusMeaning
validRun. This server holds a seat (ok: true, only for this status).
max_serversThe key is already live on its maximum number of other servers.
expiredPast the key’s expiresAt.
disabledRevoked / disabled by the studio.
not_foundNo such license for this plugin.
invalid_formatMalformed pluginId / key, or missing required fields.
Non-valid responses include a human-readable message.

Verifying the signature

When signing is enabled, signature is a base64url Ed25519 signature over this pipe-delimited canonical string, which you rebuild from values you already know plus the returned status / issuedAt:
v1|{pluginId}|{key}|{fingerprint}|{status}|{nonce}|{issuedAt}
Verify it (raw message, no pre-hash) against the public key from GET /public-key. Embed that public key in your plugin rather than fetching it at runtime from the same host you’re distrusting — otherwise a rerouted API could serve both a fake “valid” and a matching fake key.

POST /release

Frees this server’s seat on graceful shutdown, so the buyer can move hosts instantly instead of waiting for the seat to go stale.
curl -sX POST "https://nmcrate.com/api/nmkey/v1/release" \
  -H "Content-Type: application/json" \
  -d '{ "pluginId": "a7f3k9q2", "key": "NMK-…", "fingerprint": "stable-per-server-hash" }'
Returns { "ok": true } when a seat was released.

GET /public-key

Returns the Ed25519 public key as SPKI PEM (text/plain). 404 when response signing is not enabled on the server.

GET /health

Reachability check plus integration hints:
{
  "ok": true,
  "signing": true,
  "heartbeatMs": 300000,
  "staleAfterMs": 900000
}
heartbeatMs is the recommended re-validation interval; a seat that hasn’t validated for staleAfterMs is considered stale and can be claimed by another server.