The CLV1 protocol is now publicRead the spec
Browse the library

Documentation libraryLicensing

End users

End users are the accounts (a username and a password) your customers use to sign in to your software. Each account belongs to one app and is linked to a license; you add, find, ban, reset and delete them right in the dashboard.

6 min read

When an app has end users

Accounts only work when the app's sign-in mode is Account or Account + license key. You pick the mode under Licensing & releases › Sign-in & license plans, in the Sign-in mode card. In License key mode the software uses activate(key) and trial() only, and register() and login() are refused with mode_not_allowed. Each mode is covered in Sign-in modes and trials.

A few ground rules:

  • A username is unique within an app, 3 to 64 characters long, and may contain ASCII letters, digits, dots, dashes and underscores. Sign-in matches it exactly, so it is case-sensitive.
  • A password is 8 to 128 characters and is only ever stored as an Argon2id hash.
  • Term, machines and entitlements come from the license the account is linked to, not from the account.

Where accounts come from

SourceThe account's license
Your software calls register() with a keyThat key's license
Your software calls register() without a keyA license created automatically from the default plan, listed under Licenses as ACCT-…
You click Add user in the dashboardThe key you enter, or no license if you leave it empty
Seller API (POST /apps/{appId}/users, scope users:write)Same as the dashboard

The default plan is the one with Default for new keys and free accounts turned on under Sign-in & license plans. If the app has no default plan, the automatic license has no expiry, allows 1 machine and grants no entitlements.

Viewing and finding users

Open End users › Users (or press G then U while an app is open). The table shows Username, Status (Active or Banned), Email, Last sign-in and Created, newest first. The Search users… box matches part of a username or email, ignoring case. Rows load 50 at a time; click Load older for more.

To see which account holds a key, open that license under Licensing & releases › Licenses: the Linked users section lists the username and its last sign-in.

Adding a user from the dashboard

  1. Go to End users › Users and click Add user.
  2. Enter a Username and a Password (at least 8 characters).
  3. Email is optional.
  4. In License key, paste an existing key of this same app if the account should work right away.
  5. Click Create.

The dialog shows an error when the name exists (Username already taken), when the key is not in this app (License key not found in this app) or when your plan is full (Your plan allows … end users). A new account shows Never under Last sign-in until its first sign-in.

Linking to a license

From the software side, a license links to one account only: registering or upgrading with a key that already has an owner returns license_already_registered. If the key was never used, its term starts at the first registration or sign-in.

In Account + license key mode, people sign up for free and upgrade later with redeem(key). The account keeps its name, password and current machine and moves to the new license; the old session ends and the software receives a new one. The automatic free license it started on is revoked, while a real key it held before is left as it was. Redeeming the key already in use returns already_redeemed.

The dashboard has no action to change a created account's username, email or license.

To send settings to one person, use Integration › Variables with the One user scope; the account ID (usr_…) comes in the user.created webhook payload and the Seller API. See App variables.

Banning and unbanning

  1. In End users › Users, click the ⋯ button at the end of the row.
  2. Choose Ban.

The status turns Banned and every open session of the account ends at once. Running software gets session_expired on its next request (usually the heartbeat), and the next sign-in with the right password gets user_banned. The license and its bound machines are left alone. Banning fires the user.banned webhook.

Unban sets the status back to Active. Ended sessions do not come back; the person simply signs in again.

Resetting a password

Clavis has no self-service "forgot password" flow for end users, so resets go through you:

  1. Click ⋯ on the user's row and choose Reset password.
  2. Enter the new password (at least 8 characters) and click Save.

Every open session of the account ends immediately, so each machine has to sign in again with the new password. Send it to your customer through your own support channel.

Deleting a user

Choose ⋯ › Delete. The account is removed right away, with no confirmation dialog and no undo. After that:

  • The username is free again and the license can be linked to a new account.
  • The license stays, including an automatic ACCT-… license. Bound machines keep their slots on it.
  • Open sessions are not ended.

The user limit per plan

When your software registers an account or you add one in the dashboard, the platform counts the accounts that app already has (banned ones included) and compares the number with the End users limit of your workspace's plan:

  • Registering from the software when full: refused with user_limit.
  • Adding from the dashboard when full: the dialog shows an error and no account is created.
  • Plans with soft limits never block.
Plan (default settings)End usersAt the ceiling
Basic500New accounts are blocked
Premium50,000Soft limit, nothing is blocked

The numbers that apply to your workspace are under Account & organization › Plan & usage, next to the total number of users across all your apps. Deleting accounts nobody uses gives the room back. See Basic, Premium and limits and pricing.

Signing in from your software

With the JavaScript SDK, registering and signing in return the same signed answer: the session, the license, its entitlements and your variables. A successful registration means the person is already signed in on that machine.

import { ClavisClient, ClavisError } from "@clavisauh/sdk";

const clavis = new ClavisClient({
  baseUrl: "https://api.example.com",
  appId: "app_…",
  appPublicKey: "…",
  device, // this machine's identity, see the Quickstart
});

const { app } = await clavis.init();
if (app.loginMode === "key") showKeyForm();

try {
  // First run: key may be null (a free account on the default plan)
  const grant = await clavis.register(key ?? null, username, password, email);
  // Later runs: const grant = await clavis.login(username, password);
  if (clavis.has("export_pdf")) enableExport();
  showExpiry(grant.license.expiresAt);
} catch (err) {
  if (!(err instanceof ClavisError)) throw err;
  showError(err.code); // map the code to your own message
}

// Account + license key mode: upgrade the signed-in account
await clavis.redeem(paidKey);

Every sign-in binds the machine to the account's license, so the machine limit is per license (see Devices, HWID and transfers). clavis.logout() ends the current session.

Common error codes:

CodeMeaning
invalid_credentialsWrong username or password. A wrong key at registration returns this too
username_takenThe username already exists in this app
license_already_registeredThe key is linked to another account
user_limitThe app has reached the plan's account limit
user_bannedThe account is banned
no_licenseThe account has no linked license
too_many_attempts20 failures from one IP within 15 minutes; wait and try again
device_limitThe license is already on its maximum number of machines

Every user.register, user.login and user.redeem is recorded under App security › Activity log, with the reason when it was refused.

How can we help?

Frequently asked

What is ClavisAUH?

A licensing and authentication service for desktop software: license keys, device binding, end-user sign-in and signed responses. All run from one dashboard

Why can't a cracker fake your server?

The SDK only trusts answers signed with your app's private key. That key never leaves our servers, so a fake server can't sign and gets rejected

What ends up in my binary?

Your app id and public key. Nothing secret, because each device makes its own key pair on first run

Does it work offline?

Yes. Every plan gets a signed offline token for 7 days, and your app checks it locally. Premium lets you choose how long. A revoked license can keep working offline for that time, unless Online-Only Mode is on

Which languages are supported?

JavaScript and TypeScript today. C++, C# and Python are next, on the same open protocol

Is Basic really free?

Yes. No time limit, no card. Move to Premium when you need more

Get in touch