> ## 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.

# Quick Start

> Get your first app protected with AuthForge in under 5 minutes.

## 1. Create an account

Sign up at [authforge.cc](https://app.authforge.cc/auth). You'll receive free credits to get started.

## 2. Create an app

Go to the [Dashboard](https://app.authforge.cc/dashboard) and click **Create App**. Give it a name; this represents the software you're protecting.

## 3. Copy your credentials

After creating the app, copy your **App ID**, **App Secret**, and **Public Key**. The secret is shown once; store it securely.

<Warning>
  Your App Secret authenticates validate requests. Your Public Key verifies signed server responses. Keep the secret private; the public key is safe to embed in shipped SDK code.
</Warning>

## 4. Install the SDK

Add the official package for your stack (import the `authforge` module after `pip install authforge-sdk`). C++ ships as a CMake library from GitHub; see the C++ SDK page for `FetchContent` or `find_package`. Full options and versions are on each language page.

```bash theme={null}
pip install authforge-sdk
dotnet add package AuthForge
cargo add authforge
npm install @authforgecc/sdk
go get github.com/AuthForgeCC/authforge-go@v1.0.1
```

<CardGroup cols={3}>
  <Card title="Python" icon="python" href="/sdk/python">
    PyPI **`authforge-sdk`**: Python 3.9+
  </Card>

  <Card title="C#" icon="microsoft" href="/sdk/csharp">
    NuGet **`AuthForge`**: .NET 6+
  </Card>

  <Card title="C++" icon="c" href="/sdk/cpp">
    CMake + GitHub; C++17
  </Card>

  <Card title="Node.js" icon="node-js" href="/sdk/node">
    npm **`@authforgecc/sdk`**: Node.js 18+
  </Card>
</CardGroup>

<Note>
  TypeScript: the npm package ships `authforge.d.ts`; import from `@authforgecc/sdk` like JavaScript.
</Note>

## 5. Add the SDK to your project

<CodeGroup>
  ```python Python theme={null}
  from authforge import AuthForgeClient

  client = AuthForgeClient(
      app_id="YOUR_APP_ID",
      app_secret="YOUR_APP_SECRET",
      public_key="YOUR_PUBLIC_KEY",
      heartbeat_mode="SERVER",
  )

  license_key = input("Enter license key: ")

  if client.login(license_key):
      print("Authenticated! Running app...")
      # Your app logic here; heartbeats run automatically in background
  else:
      print("Invalid license key.")
      exit(1)
  ```

  ```csharp C# theme={null}
  using AuthForge;

  var client = new AuthForgeClient(
      appId: "YOUR_APP_ID",
      appSecret: "YOUR_APP_SECRET",
      publicKey: "YOUR_PUBLIC_KEY",
      heartbeatMode: "SERVER"
  );

  Console.Write("Enter license key: ");
  var key = Console.ReadLine() ?? "";

  if (client.Login(key))
  {
      Console.WriteLine("Authenticated! Running app...");
      // Your app logic here; heartbeats run automatically
  }
  else
  {
      Console.WriteLine("Invalid license key.");
      Environment.Exit(1);
  }
  ```

  ```cpp C++ theme={null}
  #include "authforge_sdk.h"
  #include <iostream>
  #include <string>

  int main() {
      authforge::AuthForgeClient client(
          "YOUR_APP_ID",
          "YOUR_APP_SECRET",
          "YOUR_PUBLIC_KEY",
          "SERVER"
      );

      std::string key;
      std::cout << "Enter license key: ";
      std::getline(std::cin, key);

      if (client.Login(key)) {
          std::cout << "Authenticated! Running app..." << std::endl;
          // Your app logic here; heartbeats run automatically
      } else {
          std::cout << "Invalid license key." << std::endl;
          return 1;
      }

      return 0;
  }
  ```

  ```rust Rust theme={null}
  use authforge::{AuthForgeClient, AuthForgeConfig, HeartbeatMode};

  fn main() {
      let client = AuthForgeClient::new(AuthForgeConfig {
          app_id: "YOUR_APP_ID".into(),
          app_secret: "YOUR_APP_SECRET".into(),
          public_key: "YOUR_PUBLIC_KEY".into(),
          heartbeat_mode: HeartbeatMode::Server,
          ..Default::default()
      });

      print!("Enter license key: ");
      let mut key = String::new();
      std::io::stdin().read_line(&mut key).unwrap();
      let key = key.trim();

      match client.login(key) {
          Ok(_) => {
              println!("Authenticated! Running app...");
              // Your app logic here; heartbeats run automatically
          }
          Err(e) => {
              eprintln!("Login failed: {}", e);
              std::process::exit(1);
          }
      }
  }
  ```

  ```go Go theme={null}
  package main

  import (
      "bufio"
      "fmt"
      "os"
      "strings"

      "github.com/AuthForgeCC/authforge-go"
  )

  func main() {
      client, err := authforge.New(authforge.Config{
          AppID:         "YOUR_APP_ID",
          AppSecret:     "YOUR_APP_SECRET",
          PublicKey:     "YOUR_PUBLIC_KEY",
          HeartbeatMode: "SERVER",
      })
      if err != nil {
          fmt.Fprintf(os.Stderr, "Init failed: %v\n", err)
          os.Exit(1)
      }

      reader := bufio.NewReader(os.Stdin)
      fmt.Print("Enter license key: ")
      key, _ := reader.ReadString('\n')
      key = strings.TrimSpace(key)

      if _, err := client.Login(key); err != nil {
          fmt.Fprintf(os.Stderr, "Login failed: %v\n", err)
          os.Exit(1)
      }

      fmt.Println("Authenticated! Running app...")
      // Your app logic here; heartbeats run automatically
  }
  ```

  ```javascript Node.js theme={null}
  import { AuthForgeClient } from '@authforgecc/sdk';
  import * as readline from 'node:readline/promises';

  const client = new AuthForgeClient({
      appId: 'YOUR_APP_ID',
      appSecret: 'YOUR_APP_SECRET',
      publicKey: 'YOUR_PUBLIC_KEY',
      heartbeatMode: 'SERVER',
  });

  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
  const key = await rl.question('Enter license key: ');
  rl.close();

  if (await client.login(key)) {
      console.log('Authenticated! Running app...');
      // Your app logic here; heartbeats run automatically in the background
  } else {
      console.error('Invalid license key.');
      process.exit(1);
  }
  ```
</CodeGroup>

## 6. Create a license key

In the dashboard, open your app and click **Generate Licenses**. Set the quantity, expiration (or lifetime), and HWID slots (how many devices can use the same key). Click **Generate**.

Copy one of the generated keys; the format is `XXXX-XXXX-XXXX-XXXX`.

## 7. Run your app

Launch your application and enter the license key when prompted. You should see "Authenticated!"; the license is now active and bound to your machine.

## 8. What just happened?

Here's what the SDK did behind the scenes:

1. **Collected HWID**: The SDK fingerprinted your machine by collecting stable hardware identifiers and hashing them into a SHA-256 string. The exact identifiers vary by SDK language (e.g., MAC address, CPU, disk serial, hostname).
2. **Generated a nonce**: A random string to prevent replay attacks. Every request uses a fresh nonce.
3. **Sent a validate request**: `POST /auth/validate` with your App ID, App Secret, license key, HWID, and nonce.
4. **Server validated**: The server checked the license exists, is active, hasn't expired, and the HWID is allowed (or bound it to a new slot). One credit was deducted from your account.
5. **Signed the response**: The server built a JSON payload (session token, app/license variables, etc.) and signed the base64 payload with the app's Ed25519 private key.
6. **SDK verified**: The SDK verified the signature with your app's public key (`public_key`). This proves the response came from AuthForge and wasn't tampered with in transit.
7. **Heartbeats started**: A background thread now sends `POST /auth/heartbeat` every 15 minutes (default). Each heartbeat response is also Ed25519-signed with the same app keypair, and SDK verification uses the same public key.

## Next steps

* [SDK Best Practices](/sdk/best-practices); How to handle errors, offline mode, and graceful shutdown
* [Core Concepts](/concepts); Understand HWIDs, heartbeat modes, credits, and more
* [Commerce](/features/commerce); Connect Stripe and automate license delivery
