The CLV1 protocol is now publicRead the spec
Browse the library

Documentation librarySecurity

Activity log

Every time your software activates a key, signs in, starts a trial or downloads an update, ClavisAUH writes one line: what happened, whether it was allowed or denied, and why. When a customer says "it won't let me in", this is the first page to open.

10 min read

Opening the log

  1. Go to Workspace › Apps and open the app.
  2. Choose App security › Activity log. Inside an app you can also press g then y.

Every member of the workspace can view this page. The newest line is on top, the list refreshes itself every 20 seconds and loads 50 lines at a time; click Load older at the bottom to keep going.

To look at one key only, open Licensing & releases › Licenses and click the key's row (or View details in the row menu). The Recent SDK calls section of the drawer lists the latest 10 log lines for that license, with the reason when one was denied.

What each line records

FieldContent
EventThe kind of request, such as license.activate (see the table below)
Outcomeok, denied or error
ReasonThe reason code for a denial or error, the same err.code the SDK receives
LicenseThe license involved, once the server has identified it
UserThe end-user account, for successful registrations, sign-ins and redemptions
DeviceThe machine involved, for successful requests
IPThe request's IP address
CountryCountry code of requests from the software, only when the API server runs behind Cloudflare
TimeWhen the line was written

The table on the page shows an outcome dot, Event, Reason, IP (hidden on narrow screens) and Time as a relative time; hover over the time for the exact date and hour. License, user, device and country are stored with each line but have no column yet; to see activity per key, use the Recent SDK calls section mentioned above.

The three outcomes:

  • Allowed (green dot): the request succeeded.
  • Denied (red dot): the request was well formed but the license state or your rules refused it. These lines can carry the license involved, but never a user or a device.
  • Errors (amber dot): something failed unexpectedly on the server. The reason is always internal_error (Server error) and no license is attached.

Events that are recorded

EventDashboard labelWhen
license.activateKey activationclavis.activate(key)
trial.startTrialclavis.trial()
user.registerUser registrationclavis.register(...)
user.loginUser sign-inclavis.login(...)
user.redeemKey redeemedclavis.redeem(key)
device.releaseSeat released by the buyerclavis.transfer()
session.logoutSign-outA successful clavis.logout()
release.checkUpdate checkclavis.checkUpdates() when the channel has a release
release.downloadUpdate downloadedThe software downloads a file through a link from the update manifest
client.reportSDK tamper reportThe SDK reports tampering or answers it could not verify
portal.device_release(shown as the raw code)The buyer removes a machine in the customer portal

The first six events are logged with all three outcomes. The other five are logged only when they succeed. Download links you open from the dashboard do not create a release.download line. For client.report, Allowed means the server accepted the report, not that the machine is clean; at most 5 reports per session per hour are logged.

What the log does not contain

  • init(), heartbeat() and variables() write no line, even when they fail (for example session_expired on a heartbeat). Session errors on checkUpdates() are not logged either.
  • Requests stopped at the protocol layer, before any handler runs: missing headers, a bad signature, a replayed request, a wrong clock (clock_skew), a malformed body, a paused app, an IP blocked by Protect, or a rule on the Access Rules tab (access_blocked). The software still gets the exact error code, and most of these are recorded by Protect 24/7 as signals such as Forged signature, Replayed request, Clock drift or Blocked by an access rule. For clock_skew, the JavaScript SDK corrects its clock from the server and retries once on its own.
  • The codes unsigned_response, unknown_key, invalid_response_signature and stale_response are raised inside the SDK when it cannot verify an answer, so they never appear as a reason in the log. On the next answer that does verify, the JavaScript SDK reports them to the server and you see an SDK tamper report line.

Filtering

The bar at the top of the page has four options: All, Allowed, Denied and Errors. Your choice is kept in the URL (for example ?outcome=denied), so you can bookmark it or send a teammate a link that opens straight onto the denials. Today the page filters by outcome only.

When a customer reports a problem, the quickest route is:

  1. Open App security › Activity log and choose Denied.
  2. Find the line by the time they tried and their IP.
  3. Read the Reason column and look it up below.
  4. If you know the key, open that license for its Recent SDK calls and its devices.

Denial reasons

The Label column is the text shown under Reason. A code without a label is shown as is. The protocol's full list of error codes is in the protocol reference.

Keys, licenses and sign-in

CodeLabelMeaning
invalid_credentialsThese credentials are not validWrong username or password. With the JavaScript SDK (protocol CLV1.1), a key that is unknown, suspended, revoked or expired also answers this code, unless the asking machine already holds a seat on that key, so someone guessing keys cannot tell which ones exist
invalid_keyUnknown keyThe key does not belong to this app; only older CLV1 clients receive this code
license_expiredLicense expiredPast its expiry date and the plan's grace days
license_suspendedLicense suspendedThe key was suspended with Suspend
license_revokedLicense revokedThe key was revoked with Revoke, or deleted
too_many_attemptsToo many attemptsOne IP entered a wrong key or password 20 times for this app; that IP waits up to 15 minutes, other IPs are unaffected
mode_not_allowedwrong sign-in doorThe software called something the app's sign-in mode does not accept; see Sign-in modes and trials

Devices and sessions

CodeLabelMeaning
device_limitDevice limit reachedThe key is on as many machines as it allows; see Devices, HWID and transfers
device_blockeddevice blockedThe machine is blocked in this app
session_limittoo many sessions at onceThe key reached its concurrent session limit
session_device_mismatchsession from another machineA session ID arrived from a machine with a different device key, usually a copied session
transfer_limitedmoves limited for nowNo transfers left, or still in the cooldown
transfer_not_allowedbuyer moves not allowedThe plan does not let buyers move machines themselves

Protect 24/7 counts device_limit and session_device_mismatch as Key sharing signals, and session_limit as Session overflow.

End-user accounts

CodeLabelMeaning
user_bannedUser bannedThe account was banned with Ban
no_licenseAccount without licenseThe account has no license attached
username_takenUsername takenThe username is already used in this app
license_already_registeredLicense already registeredThe key is already linked to another account
user_limitaccount limit reachedThe app holds as many end users as the workspace plan allows; plans with soft limits (Premium by default) do not refuse here
account_requiredaccount sign-in neededredeem() was called without an account session
already_redeemedkey already on this accountThe account redeemed the key it already uses

Trials

CodeLabelMeaning
trial_unavailableno trial offeredNo plan of the app has Trial days above 0
trial_usedtrial already used on this machineThis machine used its trial and later activated a purchased key
trial_expiredtrial endedThe trial is over and the plan's After the trial is set to Stop
trial_deniedrisky machine, no trialThe machine's IP has a high risk score in Protect 24/7

Versions and maintenance

CodeLabelMeaning
update_requiredupdate requiredThe version is below the Minimum version set in Licensing & releases › Releases
build_blockedbuild blockedThe running version or file belongs to a release marked with Block this build
unknown_buildunknown buildBuild Integrity Verification is set to Block, the app has published releases, and the running file's hash matches none of their files
maintenanceunder maintenanceMaintenance mode is on

Reading denial reasons in your software

The code in the Reason column is the err.code the SDK throws. Use it to show customers a clear message, and to match their report with the log when you help them.

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

const MESSAGES: Record<string, string> = {
  invalid_credentials: "This key or account is not valid.",
  device_limit: "This key is on all the machines it allows. Remove an old one and try again.",
  license_expired: "Your license has expired.",
  too_many_attempts: "Too many failed attempts. Please wait a few minutes.",
  update_required: "Please update to the latest version.",
};

try {
  await clavis.activate(licenseKey);
} catch (err) {
  if (err instanceof ClavisVerificationError) {
    // The answer could not be verified: treat it as no connection, change nothing
  } else if (err instanceof ClavisError) {
    // Show the code so the customer can quote it and you can find the line in the Activity log
    showMessage(`${MESSAGES[err.code] ?? err.message} (${err.code})`);
  }
}

Overview charts

Workspace › Overview sums up the log of every app in the workspace:

  • The Sign-ins · 30 days tile adds up the allowed sign-ins of the last 30 days (the same numbers as the chart below), with a small trend line.
  • The Sign-ins chart plots each day (UTC) of the last 30 days: Allowed as a filled area, Denied as a dashed line. Only three events count: key activations, user sign-ins and user registrations. Trials, redemptions, sign-outs and updates are left out.
  • The Why access was denied card lists up to 6 of the most frequent reasons over the last 7 days, across all events. Denials without a code are grouped under Other.

Each app's Overview page has the same Sign-ins chart for that app alone. The Active licenses, Unused keys and Live sessions tiles come from licenses and sessions, not from the log.

The log also feeds Protect 24/7: its hourly chart counts allowed and denied requests, and the Denial spike signal fires when one hour has 20 or more denials, well above the app's usual rate over the previous 14 days.

How long the log is kept

The log follows your workspace plan's Log retention (days) limit, shown in Account & organization › Plan & usage. By default, Basic keeps 7 days and Premium keeps 90. Compare plans on the pricing page.

Cleanup runs every night at 03:30 Vietnam time and never deletes silently:

  1. When the oldest line in the workspace is less than 3 days from passing the retention, every Owner of the workspace gets an email saying logs older than the retention will be cleared in 3 days. Nothing is deleted that night.
  2. Once that email is at least 3 days old, each nightly run deletes what is older than the retention.
  3. While cleanup keeps running, the reminder email goes out again at most once every 30 days, and after each reminder deletion waits another 3 days.

The same retention applies to Seller API request logs, Protect 24/7 signals and finished webhook deliveries. Audit logs are never touched.

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