> ## Documentation Index
> Fetch the complete documentation index at: https://docs.authforge.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# HWID Override Guide

> Implement identity-based binding with AuthForge by overriding HWID in SDKs.

This guide shows how to bind licenses to an external identity (Telegram/Discord user ID, account ID, etc.) by setting SDK HWID override fields.

## When to use this

Use HWID override when device fingerprinting is the wrong abstraction:

* bot users
* web users
* cloud workers
* multi-tenant service identities

For desktop apps, use default machine HWID behavior.

## Flow

1. User requests access in your app/bot.
2. Prompt for a license key.
3. Build a stable identity string (for example `tg:123456789`).
4. Initialize SDK with HWID override set to that identity.
5. Call `validateLicense()` / `validate_license` / `ValidateLicense` (or `login()` if you want a long-lived session and heartbeats).
6. Allow features only after success.

Prefer **validate-license** APIs for **stateless or per-request** checks (API gateways, bots, cron): they run the same `/auth/validate` flow and signature verification as `login` without starting heartbeat threads or timers.

## Identity format and rules

* Include a provider prefix (`tg:`, `discord:`, `user:`).
* Use immutable IDs (platform numeric user IDs), not usernames.
* Keep values under AuthForge limits (short strings are best).

## SDK examples

### Node

```javascript theme={null}
const client = new AuthForgeClient({
  appId: process.env.AUTHFORGE_APP_ID,
  appSecret: process.env.AUTHFORGE_APP_SECRET,
  publicKey: process.env.AUTHFORGE_PUBLIC_KEY,
  heartbeatMode: "SERVER",
  hwidOverride: `tg:${telegramUserId}`,
});
```

### Python

```python theme={null}
client = AuthForgeClient(
    app_id=APP_ID,
    app_secret=APP_SECRET,
    public_key=PUBLIC_KEY,
    heartbeat_mode="SERVER",
    hwid_override=f"discord:{discord_user_id}",
)
```

### Go

```go theme={null}
client, err := authforge.New(authforge.Config{
    AppID:         appID,
    AppSecret:     appSecret,
    PublicKey:     publicKey,
    HeartbeatMode: "server",
    HWIDOverride:  fmt.Sprintf("tg:%d", telegramUserID),
})
```

### C\#

```csharp theme={null}
var client = new AuthForgeClient(
    appId: appId,
    appSecret: appSecret,
    publicKey: publicKey,
    heartbeatMode: "SERVER",
    hwidOverride: $"discord:{discordUserId}"
);
```

### Rust

```rust theme={null}
let client = AuthForgeClient::new(AuthForgeConfig {
    app_id: app_id.into(),
    app_secret: app_secret.into(),
    public_key: public_key.into(),
    heartbeat_mode: HeartbeatMode::Server,
    hwid_override: Some(format!("tg:{telegram_user_id}")),
    ..Default::default()
});
```

### C++

```cpp theme={null}
authforge::AuthForgeClient client(
    appId,
    appSecret,
    publicKey,
    "SERVER",
    900,
    authforge::AuthForgeClient::kDefaultApiBaseUrl,
    onFailure,
    15,
    0,
    "tg:" + std::to_string(telegramUserId)
);
```

## Operational tips

* Set sensible `maxHwidSlots` for your use case (often `1` for user-bound bots).
* Provide a support flow to reset bindings when users migrate accounts.
* If abuse is expected, combine with IP/HWID security lists and command rate limits.
