Activate a license in your app
Preliminary documentation: it describes the planned product and will change before the beta.
When your customer types their email and key, your app calls your Worker, receives a signed token and stores it. From then on, it verifies the token offline on every launch and renews it in the background.
The examples use https://licenses.example.com as your Worker’s address and myapp as your app’s slug.
1. Ask for the email and the key
Activation requires the purchase email and the key. If they don’t match, the Worker answers invalid_key without saying which one is wrong, on purpose.
Before going online, normalize the key (uppercase, no spaces) and, if it has your app’s prefix and the right length, check its check digit locally: that way a typo shows up as “There’s a typo in the key” without a network call.
Note: the server compares the email after trimming spaces and lowercasing it, so you don’t need to normalize it yourself.
2. Call activate
Send a POST with JSON to /v1/activate:
curl -sS https://licenses.example.com/v1/activate \
-H 'content-type: application/json' \
-d '{
"app": "myapp",
"email": "ana@example.com",
"key": "MYAPP-7Q2KD-H9XNM-4TRVA-C8PWZ-K",
"dev": "9f2c4e6a8b0d1f3e5a7c9e1b3d5f7a9c2e4b6d8f0a1c3e5b7d9f1a3c5e7b9d0f",
"appVersion": "2.4.0",
"os": "Windows 11 24H2"
}'
dev is the SHA-256, in lowercase hex, of "myapp:" + machine id. A successful response looks like this:
{ "token": "eyJ2IjoxLCJhcHAiOiJteWFwcCIs….3vQ2JmXo8w…", "status": "active" }
status is active, or past_due if a payment failed but the grace period isn’t over: show a notice without locking anything.
3. Store the token and verify it offline
Store the token in the system’s secure storage (for example DPAPI on Windows or the Keychain on Mac). On every launch:
- Split the token at the dot and check the Ed25519 signature with the public key your app ships with.
- Check that
appis your app anddevis this device. - Check that the license isn’t in the revocation list you downloaded.
- If
expisn’tnulland has passed, tryPOST /v1/refresh; if you can’t, switch to free mode.
The app never waits for the network to start: renewing happens in the background.
Important: never ship the private signing key in your app. It lives only in your Worker; the app only needs the public key.
Possible errors
error |
What to tell the user |
|---|---|
invalid_key |
“Wrong email or key”; remind them it’s the purchase email |
wrong_app |
“This key belongs to another app” |
seats_exhausted |
Explain how to free up a device (your app or the customer portal) |
expired, past_due |
Link to renew or update the card |
revoked |
“This license has been revoked” |
rate_limited |
“Try again in a moment”; respect Retry-After |
The full list is in the reference for POST /v1/activate.
Next steps
- Renew in the background with
POST /v1/refreshand free up the device withPOST /v1/deactivate. - See SDKs and API for token verification examples in several languages.