Activate a license in your app

Updated 2 min read

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:

  1. Split the token at the dot and check the Ed25519 signature with the public key your app ships with.
  2. Check that app is your app and dev is this device.
  3. Check that the license isn’t in the revocation list you downloaded.
  4. If exp isn’t null and has passed, try POST /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/refresh and free up the device with POST /v1/deactivate.
  • See SDKs and API for token verification examples in several languages.