How it works
How it works
MinMaxKey is a small server that issues license keys for the software you sell and checks them when customers run your app. One container, two minutes to deploy, works offline.
This page is the whole mental model. Everything else in these docs is reference for one of the steps here.
The loop, start to finish
1. YOU DEPLOY docker run — one container, your machine
2. YOU CREATE a product ("PixelForge Pro") — you get two things to
embed in your app: an api_key and a public key
3. CUSTOMER BUYS Stripe → payment → MinMaxKey issues a license key
and emails it to the buyer
4. CUSTOMER ACTIVATES they paste the key into your app → your app calls
MinMaxKey once → the key locks to their machine
5. YOUR APP VERIFIES the activation returns a signed offline token; your app
checks it locally — works with no internet after that
6. YOU STAY IN CONTROL revoke on a refund, free a seat on reinstall, watch
devices in the dashboard
That's the product. Everything else is details.
Two directions, don't mix them up
MinMaxKey talks to two different kinds of software, and it's worth being explicit because "webhook" blurs it:
┌──────────── your server (you) ────────────┐
│ │
STRIPE ──payment──▶ MinMaxKey ──license.created/revoked──▶ YOUR SERVER
│ │
└────────────────────────────────────────────┘
(server-to-server, via webhooks)
┌──────────── your customer's machine ──────┐
│ │
YOUR APP ──activate/validate──▶ MinMaxKey (the SDK, direct calls)
YOUR APP ──verifies the signed token locally, offline────────▶ OK
└────────────────────────────────────────────┘
- Webhooks are server-to-server. Payment providers post into MinMaxKey
(Stripe's
invoice.paid, refunds); MinMaxKey posts out to your backend (license.created,license.revoked) so you can react — cut off a refunded customer's cloud account, update your own records. Your webhook receiver is optional for a desktop app: if the license state lives entirely in MinMaxKey, you never need to receive a webhook. - The SDK is what your app uses. It's not a webhook. The customer's app calls MinMaxKey directly to activate/validate, and verifies the signed offline token locally so your app keeps working when it's offline. If you ship a VS Code extension, a desktop app, a Unity game — the SDK is the piece that goes inside it.
The four objects
Product ──▶ License type ──▶ License ──▶ Activation(s)
│ │
└── public key (embed └── the key string your customer
in your app) types: 9TMC-5TS9-0MKQ-VS8A-87Q0
- Product — one app you sell. Gives you an
api_key(gates activate/validate; treat it as public) and apublic_key(embed the PEM in your app for offline token verification). - License type — how a license behaves: lifetime, subscription
(expires after N days), trial, or floating (seat count is the whole
story). Each has a seat limit:
max_seatsmachines bound at once. - License — one issued key. Status, optional customer email, optional metadata. The key has a checksum, so your app can reject typos without asking the server.
- Activation — binds a license to one machine fingerprint. Same machine
reuses its seat; a new machine consumes one until
max_seats; deactivation frees a seat; revocation stops every machine validating.
Offline tokens, in one sentence
Every activation returns an Ed25519-signed token your app verifies locally — so a revoked license keeps working until the app next checks in (minutes to days, your call), and the public key living in your binary is the cost of that. Read the honest trade-off.
Where to go next
- Deploy — actually run it.
- Use it — the dashboard and CLI, same actions.
- Sell with Stripe — buy → key emailed → refund → revoked.
- Add it to your app — the code your app embeds.
- API reference — every endpoint, when you want them.