Documentation · SoftActivate Licensing

Statuses and errors

There are three families of results, in the order you typically meet them: validation statuses describe the license's verdict, configuration errors mean your integration is set up wrong and should be fixed rather than retried, and transport errors mean the call itself failed.

Validation statuses

After validate_license / ValidateLicenseAsync, the result carries one status. Native constants are SWS_LICENSE_STATUS_*; .NET uses the LicenseStatus enum.

Native .NET Meaning - and what your application should do
VALID Valid Proceed. Persist the updated license if one was issued.
NOT_FOUND NotFound No license, and none could be acquired: no license key or vendor id is configured, or the service refused the key. The error detail says which refusal: an unknown key (license_not_found), a wrong vendor id (vendor_mismatch), an inactive vendor account (account_inactive), or a device whose hardware fingerprint is too weak to recognise again (device_unidentifiable). For an unknown key, have the customer copy it from the license email again; for a vendor mismatch, check the vendor id your app is built with; for a weak fingerprint, see hardware IDs.
BAD_SIGNATURE BadSignature The stored license fails verification, usually because it is corrupted or was tampered with. Delete the local file and re-activate online.
EXPIRED Expired The license is past its validity, either its stored certificate or, refused at activation, the license itself. On a license whose duration counts from each device's first activation, such as an automatic trial, it can also mean that this device's own period has ended, while other devices go on; for a trial, show your purchase page. For subscriptions this usually resolves itself at the next online validation, since renewal is a form of re-issuance; for fixed-term licenses, prompt the customer to renew or purchase. A perpetual license with a maximum offline period reports EXPIRED when the device has not reached the licensing service for the whole period, and recovers at the next validation with connectivity.
NOT_YET_VALID NotYetValid Validity starts in the future. On a stored license this is almost always a wrong device clock: tell the customer to fix the clock, and do not disable features silently. Refused at activation, the license's own start date is in the future.
REVOKED Revoked The license was revoked in the console, for example after a refund, a chargeback, or a leaked key. Deny the licensed functionality and direct the customer to support. A device sees the revocation at its next start with connectivity, through the revocation list; a device that stays offline stops validating when its maximum offline period ends, at the latest. A trial license is the exception: its certificates are never on the revocation list, so a running trial keeps validating until its certificate ends at the latest: the trial's own end, or sooner when the product sets a maximum offline period (revocation).
BAD_CONTEXT BadContext The license belongs to a different device, because the hardware changed beyond the allowed tolerance or the file was copied. Offer re-activation, and deactivate the old machine first if it still exists. Refused at activation, the license activates only with a different kind of context (context_type_mismatch).
BAD_SCOPE BadScope The license carries no scope attribute at all: a malformed or hand-assembled license file, never a normally issued one. Delete the local file and re-activate online.
PAYMENT_REQUIRED PaymentRequired The subscription behind the license has lapsed, or your plan accepts no new devices. The status message carries the subscription state (past_due, canceled, and so on), or the plan reason (plan_limit, trial_expired). Show state-appropriate messaging: "update your payment method" for past_due calls for a different conversation than canceled.
SEAT_LIMIT SeatLimit This is a floating license and every seat is leased. The status message carries the soonest lease expiry in seconds ("" if unknown), which is the earliest a retry can succeed. Offer "try again in a few minutes"; never retry in a tight loop.
BAD_PRODUCT BadProduct The license belongs to a different product than the one your app declared with set_product_id() / SetProductId. Tell the customer which product the key actually matches (it's on their receipt) and where to get the right one. Reported only when your app declares a product; licenses without a stamped product pass this check.
ACTIVATION_LIMIT ActivationLimit Since SDK 1.1.0. The license is already in use on its maximum number of devices, or its activations are used up. Point the customer at deactivating it on a machine they no longer use, or at buying another seat.
UNAVAILABLE Unavailable Since SDK 1.1.0. A first activation could not be completed: the licensing service could not be reached or gave no usable answer (network, DNS, TLS, proxy, timeout, a server fault, throttling). Ask the customer to check the connection and try again later. Do not ask for a new key. One kind of throttling is specific to trials: a product trial's daily limit on new machines (new_device_limit), which lifts at midnight UTC.

The forward-compatibility rule: future SDK and service versions may add new statuses. Treat an unknown status as invalid, never as probably fine.

Why an activation failed

Since SDK 1.1.0, when the online activation (or renewal) of a validation call fails, the result also says why: .NET result.Error (an ActivationError: HttpStatus, Code, Message, Exception; ToString() gives one line), native get_error_http_status(), get_error_code() and get_error_message(). Log it whenever validation is not valid. It is the difference between "the key is unknown" and "the network is down", and it is what support asks for first.

Code Meaning
license_not_found No license has this key (HTTP 401).
vendor_mismatch The vendor id is missing or belongs to a different vendor than the key (HTTP 401).
account_inactive The vendor account that owns the license is suspended (HTTP 401).
license_revoked, license_expired, license_not_yet_valid The license itself refuses activation (HTTP 403). license_expired also refuses a device whose own period ended, on a license whose duration counts from each device's first activation, such as a trial; its expired_at field gives the moment the license, or that device's period, ended.
context_limit, activation_limit, context_activation_limit, seat_limit No seat or activation is left (HTTP 403).
wrong_product, context_type_mismatch, invalid_scope, condition_failed, invalid_request The request does not fit the license, or is malformed (HTTP 403 / 400).
device_unidentifiable This device's hardware fingerprint is too weak to recognise it again (HTTP 403). The SDK reports NOT_FOUND. See hardware IDs.
vm_not_allowed A license that does not allow virtual machines (Allow virtual machines unticked in its terms, on the product or on the license) refused a new device that reported running in one (HTTP 403, NOT_FOUND). Devices already activated are never refused. Only SDK 1.2.0 and later report virtual machines. See virtual machines.
payment_required A lapsed subscription, or the vendor's plan (HTTP 402).
rate_limited, renewal_too_early Throttled; retry after the indicated time (HTTP 429). Since SDK 1.2.0, a first activation refused with renewal_too_early, which happens when the application was reinstalled or lost its stored license while this machine's license is still fresh, releases this machine's seat and activates once more by itself.
new_device_limit A product trial's daily limit on new machines is reached (HTTP 429). SDK 1.1.0 reports UNAVAILABLE. Retry after the next midnight UTC; renewals and returning devices are never capped.
network, timeout No answer at all (HTTP status 0): connection, DNS, TLS, proxy, or a timeout.
bad_response The service answered with success but without a usable certificate.
client_error A local failure before or while sending the request.

SDK 1.0.0 reports every failed first activation as NotFound, including a request that never left the machine, and does not keep the reason. If you are on 1.0.0 and see NotFound for a key you know is right, upgrade to see the cause.

Transport errors

Native Meaning
SWS_OK Success.
SWS_EFAIL Unknown/unclassified failure.
SWS_ENOTIMPL Not implemented.
SWS_EINVAL Invalid argument, including an offline-activation import whose reply does not match the pending file.
SWS_ENOMEM Out of memory.
SWS_EAUTH Authentication failed at the service.

In .NET these surface as exceptions: SwsException (the base class), SwsArgumentException for an invalid argument, and SwsServerException when the service rejected the call. Cancelling ValidateLicenseAsync through its cancellation token throws OperationCanceledException (since SDK 1.1.0). Network unreachability during a renewal attempt is not fatal while the stored license is still valid, because the SDK validates locally. Design your UX so that a temporarily offline machine with a valid license never nags the customer.

Troubleshooting matrix

Symptom Likely cause Fix
Worked yesterday, BAD_CONTEXT today Hardware change beyond fingerprint tolerance, or copied license file Re-activate; deactivate the old machine if reachable
EXPIRED on a healthy subscription Machine offline past the renewal window Get online once; validation renews automatically
NOT_YET_VALID Device clock set in the past Fix the clock
SEAT_LIMIT with a retry hint All floating seats leased Wait out the hint; ensure clients deactivate on exit
NOT_FOUND for a key you minted moments ago Key mistyped, or wrong vendor id: the error code says which Copy the key from the license email again (SDK 1.1.0 fixes case, spaces and dashes for you); check the vendor id
NOT_FOUND in a .NET app published trimmed or Native AOT, on SDK 1.0.0 SDK 1.0.0 cannot build its request in such an app, so nothing is sent Upgrade to SDK 1.1.0, or see Publishing your app
UNAVAILABLE No answer from the service: offline, a proxy or firewall, or a service fault Check the connection; see proxies and private CAs; retry later
UNAVAILABLE with new_device_limit on a first run The product trial's daily limit on new machines is used up The machine can start its trial after midnight UTC; ask the customer to try again then
NOT_FOUND with device_unidentifiable The device cannot be identified reliably enough to recognise it again, typically a .NET Native AOT app built with SDK 1.1.0, on some Windows machines Upgrade to SDK 1.2.0 or later, or publish without Native AOT; see hardware IDs
ACTIVATION_LIMIT Every seat or activation of the license is used Deactivate an old machine, or buy another seat
BAD_PRODUCT on a key you sold The key belongs to a different product than the app declared (set_product_id) The customer bought product A and is running product B. Point them at the right download or the right key

Still stuck? Write to support@softactivate.com with the status, the SDK version, and (for activation problems) your vendor id, the activation error line and roughly when it happened - never send license private keys or license.pending files.