Pro
For makers shipping to real customers.
€29 / month
Start Pro- 250 active licenses
- Unlimited products
- Webhook events
- Email support
Desktop, CLI & Plugins licensing · MCP-ready
License keys for desktop apps, CLI tools, IDE extensions, and plugins. REST API documented with OpenAPI 3.1. Your AI agent (Claude Code, Cursor, ChatGPT) handles the wiring. Open-source TypeScript SDK and MCP server included. A Keygen, Cryptlex, or Lemon Squeezy alternative built for indie devs.
100 free licenses · No credit card required
import { createClient, getFingerprint } from '@paperkeyhq/sdk';
const paperkey = createClient({ apiKey: process.env.PAPERKEY_PK! });
const fp = await getFingerprint();
const result = await paperkey.validate(licenseKey, fp.fingerprint);
if (!result.valid) throw new Error(result.error);curl https://api.paperkey.dev/v1/licenses/validate \
-H "Authorization: Bearer $PAPERKEY_PK" \
-H "Content-Type: application/json" \
-d '{
"license_key": "K7WX9-M3NP4-H8TRC-R2",
"fingerprint": "paperkey_fp_v1_abc123..."
}'import os, requests
resp = requests.post(
"https://api.paperkey.dev/v1/licenses/validate",
headers={"Authorization": f"Bearer {os.environ['PAPERKEY_PK']}"},
json={"license_key": license_key, "fingerprint": fp},
)
resp.raise_for_status()
result = resp.json()
if not result["valid"]:
raise RuntimeError(result["error"])use Paperkey\Paperkey;
$paperkey = Paperkey::createClient(apiKey: getenv('PAPERKEY_PK'));
$result = $paperkey->validate('K7WX9-M3NP4-H8TRC-R2');
if (!$result->valid) {
throw new RuntimeException($result->error ?? 'invalid_license');
}body, _ := json.Marshal(map[string]string{
"license_key": licenseKey,
"fingerprint": fp,
})
req, _ := http.NewRequest("POST",
"https://api.paperkey.dev/v1/licenses/validate",
bytes.NewBuffer(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("PAPERKEY_PK"))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()Inside the dashboard
Every license, every activation, every webhook delivery in one place. Search by key, by customer, by status. AI agents read the same view through the MCP server.
Why Paperkey
One takes a long prompt and a lot of luck. The other takes a package.
Vibecode a Paperkey-like
If the agent gets it right.
Use Paperkey
Done.
MCP server
Drop @paperkeyhq/mcp into your AI client. Ask, list, audit, revoke in plain English, from any chat. The protocol is open, the SDK is yours.
you show licenses with more than 5 activations this week
claude Found 3 licenses with more than 5 activations this week:
Want me to revoke any of these, or send a warning email first?
Predictable on purpose. Stable, affordable, extensible.
Three endpoints, one SDK. Drop it in your app and forget about license servers, secrets, and rotation flows.
Stable identifiers across reinstalls and updates. CI mode for build pipelines. Tamper-resistant by default.
Free tier of 100 licenses. Predictable pricing. No vendor calls, no enterprise sales motion.
TypeScript on npm, Python on PyPI, PHP on Packagist — same surface, same HMAC verifier, cross-language test vector. MIT-licensed. The trust contract is the source code, not a marketing promise.
Per-IP and per-license limiters out of the box. Never wake up to a brute-force on your activation endpoint.
Drop @paperkeyhq/mcp into Claude Desktop, Cursor, or Continue. Drive licenses, audit activations, revoke abuse, all in plain English.
Headers
Body
{
"id": "evt_4b8c9a2f…",
"event": "license.created",
"createdAt": "2026-04-25T12:34:56Z",
"data": {
"id": "clx7w8…",
"key": "K7WX9-M3NP4-H8TRC-R2",
"email": "customer@acme.io",
"maxActivations": 3
}
} Webhooks signed end-to-end
Six events, one HMAC. Verify with three lines of SDK code. Auto-pause after 10 consecutive failures so a misbehaving endpoint doesn't drown your inbox.
license.created/revoked/reinstated/expired activation.created/removed delivery id Install the MCP server in Claude Desktop and run your first action.
I want to drive Paperkey (a software-licensing API) from Claude Desktop using MCP.
Read the full integration spec first: https://paperkey.dev/llms-full.txt
Then:
1. Add this server to my claude_desktop_config.json (under mcpServers):
{
"paperkey": {
"command": "npx",
"args": ["-y", "@paperkeyhq/mcp"],
"env": { "PAPERKEY_API_TOKEN": "<paste-my-dashboard-jwt>" }
}
}
2. Tell me how to grab my dashboard JWT from app.paperkey.dev (Settings → AI integrations).
3. Tell me to fully restart Claude Desktop so the MCP server is picked up.
4. Once it's connected, create a product called "Demo App" and issue one license to me@example.com so I can verify the wiring works.
If anything fails, surface the exact MCP error and tell me how to fix it. Don't ask clarifying questions about the config; the snippet above is canonical. Register the MCP server in Cursor and wire the SDK into the project.
I'm in Cursor. I want to integrate Paperkey (a software-licensing API) into this project.
Read the full integration spec first: https://paperkey.dev/llms-full.txt
Then:
1. Create or update .cursor/mcp.json at the repo root with:
{
"mcpServers": {
"paperkey": {
"command": "npx",
"args": ["-y", "@paperkeyhq/mcp"],
"env": { "PAPERKEY_API_TOKEN": "<paste-my-dashboard-jwt>" }
}
}
}
2. Add @paperkeyhq/sdk to the project (npm install @paperkeyhq/sdk).
3. Create a small helper that calls validate() on launch and activate() if the license isn't bound to this machine yet. Read pk_… from process.env.PAPERKEY_PUBLIC_KEY.
4. Cache the validate result for 24 h on disk so the app stays offline-tolerant.
5. Show a clear error UI when valid:false (revoked, expired, or invalid_key).
Once MCP is live, use it to create a product and issue a test license. Don't mock the values; pull them from my real account. Patterns to follow live in section 10 of the spec. Hand the spec to your no-code assistant (Lovable, n8n, ChatGPT) for integration with your review.
I'm using a no-code or web AI agent (Lovable, n8n, ChatGPT, Bolt, v0). I want to integrate Paperkey (a software-licensing API) into the project I'm building with you.
Read the full integration spec first: https://paperkey.dev/llms-full.txt
Then:
1. Tell me which of my fields/inputs needs to become a license-key field.
2. Wire the validate endpoint: POST {API}/v1/licenses/validate with the public key (pk_…) in the Authorization header. Cache the result for 24 h.
3. If activate() is needed for this stack (desktop / per-device), wire it on first launch.
4. Add a clear error state when valid:false. Show "License revoked", "License expired", or "Invalid key" depending on the reason.
5. Tell me where to drop my pk_ public key (env var, secret manager, n8n credential, etc.). Never inline it in the source.
Use the patterns from section 10 of the spec. If you don't have a built-in HTTP node (n8n, Zapier), give me the exact node config to add. Don't mock; wire it against real endpoints. Drop into your AI
Pick your client, copy the prompt, paste it. Your client reads llms-full.txt, configures the MCP server (Claude or Cursor) or wires the SDK (no-code), and runs your first command. You stay in the loop at every step. No backend engineer required.
The integration surface is small on purpose. Here is what holds it.
Tools are read-by-default. Your assistant always asks before revoking. Each write requires explicit confirmation.
HMAC-SHA-256 per delivery. 5-second timeout. Auto-pause after 10 consecutive failures.
AgentEvent records carry no IP, no email, no raw fingerprint. Cascade delete on owner removal.
203 unit + integration tests passing. Playwright E2E covers the full vendor and customer flow.
Built in public
No "trusted by 50+ startups" badge until 50+ startups actually ship with us. Until then, public metrics, public source, public roadmap.
500+ unit + integration · live on every push
99.9% target · status.paperkey.dev
<50ms p95 · EU origin
SDK + MCP + monorepo on GitHub
Your name lands on this page next to ours. We will help you wire it up live, then write up what we learned.
Email hello@paperkey.devAlternatives
See the side-by-side: feature matrix, pricing models, and the integration code your AI agent will write.
Pay for active licenses, not seats or events. Cancel any time.
For makers shipping to real customers.
€29 / month
Start ProOr start smaller
For prototypes and side projects.
For teams scaling to many products.
Run Paperkey on your own servers. Single Postgres, single Docker compose, source open. Drop the SaaS dependency the day a customer asks.
Free, MIT
Get the repoPaperkey is opinionated for indie devs shipping local-first apps (desktop, CLI, IDE extensions, plugins): open-source SDK, predictable pricing, integration your AI agent can wire in 30 seconds. The competition targets enterprise, with quotes, demos, and seat-based pricing. We are deliberately not that.
Yes. The full monorepo (API, dashboard, marketing site) is MIT-licensed. Single Docker compose, single Postgres, no phone-home. PAPERKEY_MODE=selfhost flips Stripe and email to optional, lifts the active-license cap, and hides billing UI. See SELFHOST.md in the repo.
A license that has at least one activation in the last 30 days. Revoked or expired licenses do not count.
The SDK hashes a small set of stable system identifiers (machine ID, MAC, CPU class) and never sends raw values to our servers. CI mode swaps in environment-derived identifiers so build pipelines do not consume activations.
You own your data and the code. Export licenses + activations from the dashboard at any time, and the entire stack is MIT — clone the monorepo, point your SDK at your own instance, keep running. SELFHOST.md walks through the deploy.
Yes. 100 active licenses, 1 product, community support. No credit card required to start.
The managed API runs on Fly with regional failover. We do not publish a formal SLA yet. It will land before general availability, alongside a status page and incident history.
Revocation is immediate at the API layer: the next validate call returns license_revoked, typically under one second after the dashboard click. There is no edge cache to bust. The SDK re-validates on app launch and on a schedule, so a revoked license stops working at the next online check.
Activation requires a network call: the server must record the new fingerprint slot. Once activated, validation is offline-tolerant: the SDK caches the last positive verdict and replays it for up to 72 hours when the API is unreachable. Authoritative negatives (revocation, expiration) are never cached. The grace window is configurable.
Apps already activated keep running for up to 72 hours thanks to the SDK validate cache. New activations are queued and resume when the API is back. Live status is at status.paperkey.dev. If you need full independence, self-host the monorepo against your own infra — same API contract.
Export your existing licenses and activations from the current vendor, then POST them to /licenses (we accept arbitrary key formats via the product config). The SDK in your shipped app stays the same. Email hello@paperkey.dev for a 30-minute walkthrough against your real data.
Read the 5-minute quickstart. Or skip it: the SDK has decent defaults and the dashboard explains itself.