Available SDKs
Python SDK
authforge-sdk on PyPIPython 3.9+; cryptography pulled in automatically.C# SDK
AuthForge on NuGet.NET 6+ with BouncyCastle.Cryptography.C++ SDK
CMake library from GitHubC++17, libsodium, OpenSSL, libcurl.
Rust SDK
authforge on crates.ioRust 1.70+, blocking HTTP via ureq.Go SDK
github.com/AuthForgeCC/authforge-goGo 1.21+, standard library only.Node.js SDK
@authforgecc/sdk on npmNode.js 18+, zero runtime dependencies.Official installs
How it works
All SDKs implement the same flow:- Initialize: Create a client with your App ID and public key. Include the App Secret for online
login()/validateLicense. For air-gappedloginFromFileonly, omit the secret (or pass empty /None); do not ship it in offline binaries. - Login or validate-only: Call
login(licenseKey)(orLogin, etc.) for a long-lived session: the SDK collects the machine’s HWID (or useshwidOverride), generates a nonce, and sends/auth/validate. For bots, cron, or per-request checks, use the validate-only API (validateLicensein Node,validate_licensein Python and Rust,ValidateLicensein C# / C++ / Go): same request and signature verification, no background loop and no persisted session on the client (C++ returns a result struct; others match theirloginresult shape or a dedicated result type). - Verify the validate response: The SDK verifies the Ed25519 signature on
/auth/validateusing your app’s configuredpublicKey. - Grace period: After
login, the app runs on the signed session with no further network calls. A background thread re-verifies the session signature locally and stops when the session expires (session TTL: default 24 hours, configurable viattlSeconds, clamped to 1 hour minimum and 7 days maximum). Expiry is reported toonFailureassession_expired; the Rust SDK reports it asAuthForgeError::Expired(expired) until its next major release. - Online check-ins (optional): Enable
onlineHeartbeatto sendPOST /auth/heartbeatat the configured interval (default 15 minutes) for fast revocation and concurrent-use detection. Success responses are Ed25519-signed and verified with the same app public key, and each check-in refreshes the session. Validate-only calls never start this loop. - Failure: If authentication fails, a check-in fails, or the session expires, the SDK calls your
onFailurecallback with a reason ("login_failed"or"heartbeat_failed") and the exception (Go:OnHeartbeatFailureor legacyOnFailure; Rust:on_heartbeat_failureor legacyon_failure). Since 1.4.0 the error carries the code and a transient/definitive classification. On a definitive failure (revoked,expired,hwid_mismatch,blocked,session_expired, …) the SDK clears the stored session and stops check-ins before the callback runs; on a transient one (network errors,rate_limited,system_error,no_credits,unexpected_response, …) it keeps the session and checks in again on the next interval, until the session TTL runs out. If no callback is set (1.4.1+), a transient background check failure writes a one-line warning to stderr and check-ins continue in every SDK; a definitive failure (including thesession_expireda transient failure becomes once the TTL has passed) or a rejected login exits the process in the Python, Node.js, C#, and C++ SDKs, while Go and Rust clear the session and never exit. See Check-in and session failure handling.
Offline license files (separate mode)
For machines that can never reach AuthForge, every SDK (1.2.0+) also verifies cloud-minted offline license files (.authforge) with zero network access. This is not a variant of the grace period; it is a different credential:
The customer should not type the HWID into an email. Prefer an activation request (
.authforge-request): the SDK writes it with no network and no app secret, and the dashboard checksums it in the browser before prefilling the mint dialog. machineName is omitted unless the caller opts in (include_machine_name / includeMachineName). This is not a second offline product and it is not the grace period.
loginFromFile verifies the file against the client’s configured app id, public key(s) and HWID, then populates the same session accessors as login() (isAuthenticated, variables). It never starts the grace-period timer or online check-ins, and it never exits the process; rejections arrive as onFailure("offline_login_failed", error) with one of bad_armor, bad_signature, unsupported_version, malformed_payload, wrong_app, expired, hwid_mismatch (Go returns ErrOffline* sentinels, Rust an OfflineLicenseError enum). Online login() and the grace period are unchanged. Air-gapped builds should omit the App Secret: loginFromFile does not use it; online APIs still require it and fail locally if it is missing.
Common constructor parameters
Every SDK accepts the same conceptual parameters, named according to each language’s conventions. The table below shows the logical parameter names; see each SDK’s page for exact syntax.Billing model
All SDKs follow the same billing rules:- Each successful
login()/Login()orvalidateLicense-style call costs 1 credit (one/auth/validatedebit). - The grace period is free: local session re-verification consumes no credits.
- Online check-ins (if enabled) cost 1 credit per 10 successful heartbeats (debited on every 10th heartbeat).
- With online check-ins, revocations take effect on the next check-in regardless of the configured interval; without them, at session expiry.
- Minting an offline license file costs 1 credit (charged to the operator at mint time).
loginFromFile/verifyLicenseFilecost nothing.
Migrating from heartbeat_mode
Older SDK versions required a heartbeatMode / heartbeat_mode of "SERVER" or "LOCAL". Cached GitHub README snippets still show that required constructor; current docs and current SDKs use the grace-period model. Follow docs.authforge.cc and check the installed SDK version before copying examples.
The option is deprecated across all SDKs:
"LOCAL": remove the option; the grace period is now the default behavior."SERVER": enable online check-ins instead (onlineHeartbeat: trueor the language equivalent).
heartbeatMode in new code.