Frequently Asked Questions
Licensing
What happens when my credits run out?
Auth calls returnno_credits.
Apps with online check-ins enabled fail on the next check-in.
Apps running through the grace period (the default) continue until the signed session expires (24 hours by default, or whatever TTL the SDK requested; up to 7 days).
Set up auto-refill to prevent this.
Can a customer use one key on multiple devices?
Yes. ConfiguremaxHwidSlots (1-16) when generating the license. Each new device uses one slot.
How do I let a customer move to a new computer?
Reset their HWID bindings from the dashboard (app -> license -> Reset HWID) or via the Developer API.
If the app uses self-serve offline activation, a reset does not free offline machines. The new computer activates as a new machine, up to the license’s maxHwidSlots. Once the buyer reaches that cap, release their old machine on the license page (its file keeps working) or raise the license’s HWID slots.
What license key format does AuthForge use?
XXXX-XXXX-XXXX-XXXX using A-Z (excluding I and O) and digits 2-9.
Does AuthForge support offline or air-gapped machines?
Yes, in three different ways, and it matters which one you mean.- The grace period (default) lets an app keep running for up to 7 days after an online activation. It is session continuation, not offline licensing: the machine must reach AuthForge at least once, and again when the session lapses.
- Offline license files (
.authforge) are for machines that never connect. You mint a signed file in the dashboard or Developer API (1 credit), deliver it out-of-band, and the SDK verifies it locally with your public key and the machine HWID vialoginFromFile. No network, ever. Collect the HWID as an activation request (.authforge-request) rather than a pasted string. - Self-serve activation is for one-time-purchase apps that should run offline forever. The app sends the buyer’s key once to
POST /auth/offline/activateand gets a lifetime file bound to that machine (2 credits per new machine). The license must be perpetual and seat-limited, and the app must opt in. See Sell offline apps.
I revoked a license but the offline machine still works
Expected. Revoking online (by hand, or automatically after a refund or chargeback) blocks new mints, self-serve activations and online activations, but a.authforge file already on a machine is a standalone signed document with no server to ask. It runs until its expiresAt. The license page’s mint history shows every outstanding file and when it lapses; stop re-issuing and the entitlement ends on schedule. Self-serve files are lifetime files: A refund or chargeback revokes the license online but cannot reach files already issued. For a lifetime file, that means the buyer keeps the app.
Can buyers activate an offline app themselves?
Yes, with self-serve offline activation. Turn it on for the app, sell perpetual licenses with a few seats, and have the app callactivate_offline (or the language equivalent) with the buyer’s key and a file path. It costs 2 credits per new machine, once. A license can activate at most maxHwidSlots distinct machines, ever; when a buyer hits offline_activation_limit_reached, they contact you. Walkthrough: Sell offline apps.
SDK & Integration
My users are getting hwid_mismatch errors
For onlinelogin(), their HWID slots are full. Either increase maxHwidSlots on the license or reset their HWID bindings. HWIDs can change after OS reinstalls, hardware upgrades, or VM migrations.
If this is an offline .authforge file, the bound string was probably truncated or wrapped in email. Ask for an activation request from the same SDK that will call loginFromFile; do not re-mint to the old pasted value. See Finding a machine’s HWID.
Heartbeats are using too many credits
Heartbeats only happen if you enabled online check-ins, and they’re cheap: 10 successful heartbeats cost 1 credit (billed on every 10th call). At the default 15-minute interval, an always-on app costs about 10 credits/day. If that’s still more than you want, increase the check-in interval (the credit cost scales directly with the number of heartbeats sent), or disable online check-ins entirely and rely on the grace period: the SDK re-verifies the signed session locally, with zero heartbeat credits, until it expires (24h by default). With online check-ins, revocations apply on the next check-in, regardless of interval. Without them, revocations apply when the session expires.The SDK can’t reach the API
Check thatauth.authforge.cc is reachable. The SDK uses HTTPS on port 443.
Some corporate firewalls and China’s GFW may block it.
The SDK respects the apiBaseUrl constructor param if you need to proxy.
I’m getting rate_limited errors
/auth/validate is rate-limited to 5 requests per license per minute and 30 per IP per minute. /auth/heartbeat is rate-limited to 6 requests per license per minute (not IP rate-limited). /auth/offline/activate is rate-limited to 10 per IP and 3 per license per minute.
This usually means something is calling login() in a loop instead of once at startup.
Billing
Do failed auth attempts use credits?
No. Only successful validations (1 credit), successful heartbeats (1 credit per 10), successful offline file mints (1 credit each) and self-serve offline activations of a new machine (2 credits each) consume credits. Refused activations are free. Verifying an offline file on the end machine is free.What payment methods do you accept?
Credit and debit cards via Stripe. No PayPal or crypto at this time.Can I get a refund on credits?
Contact support. Unused credits don’t expire.Security
Is my App Secret safe in the binary?
The App Secret authenticates/auth/validate requests, not webhook delivery and not Developer API access.
Extracting it doesn’t let an attacker create or revoke licenses.
However, obfuscating your binary is still recommended.
Can someone replay a captured auth request?
/auth/validate requests include a unique nonce and the server rejects duplicate nonces.
Validate and heartbeat success responses are Ed25519-signed by AuthForge with your app’s private signing key. SDKs verify every signed payload using your app’s public key. /auth/validate additionally enforces per-request nonce matching; heartbeats rely on the short-lived session token + signature chain for replay protection.