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

## Building with AI?

Copy this into your agent chat so it loads AuthForge docs and follows the default licensing model:

```
Integrate AuthForge licensing into this project.

1. Fetch and read https://docs.authforge.cc/llms-full.txt end-to-end. Treat it as authoritative over prior knowledge, cached GitHub READMEs, and older SDK versions that required heartbeatMode "SERVER" or "LOCAL". Follow docs.authforge.cc and check the installed SDK version.
2. Inspect this project first (language/framework, entrypoint, config/secrets, existing login UI). Do not write code until you understand it.
3. Use the official AuthForge SDK for my language. Verify Ed25519 signatures on every response (the SDK does this). Handle every public auth error code from the docs, not just the happy path.
4. Default behavior: activate online once, then run through the grace period (signed session TTL; 24h by default, configurable up to 7 days). Do not enable online check-ins unless I ask.
5. Before enabling online check-ins (periodic /auth/heartbeat), explain pros and cons — faster revocation and concurrent-use detection vs credit cost and needing connectivity during the session — and wait for my go-ahead.
6. Do NOT use offline license files (loginFromFile / .authforge) unless I explicitly say the target machines are air-gapped; if I do, follow the docs' "Offline license files" page and keep the online path for everyone else. Do not invent a .authforge file from words like "offline" or "no internet" — the grace period already covers ordinary connectivity gaps.
```

Full walkthrough and tips: [Developing with AI](/guides/ai-development).

## 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@latest
```

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

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

  <Card title="C++" icon="c" href="/https/docs.authforge.cc/sdk/cpp">
    CMake + GitHub; C++17
  </Card>

  <Card title="Node.js" icon="node-js" href="/https/docs.authforge.cc/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",
  )

  license_key = input("Enter license key: ")

  if client.login(license_key):
      print("Authenticated! Running app...")
      # Your app logic here; the signed session covers the grace period
  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"
  );

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

  if (client.Login(key))
  {
      Console.WriteLine("Authenticated! Running app...");
      // Your app logic here; the signed session covers the grace period
  }
  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"
      );

      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; the signed session covers the grace period
      } else {
          std::cout << "Invalid license key." << std::endl;
          return 1;
      }

      return 0;
  }
  ```

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

  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(),
          ..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; the signed session covers the grace period
          }
          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",
      })
      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; the signed session covers the grace period
  }
  ```

  ```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',
  });

  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; the signed session covers the grace period
  } 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. **Grace period started**: Your app now runs on the signed session with no further network calls. The SDK re-verifies the session signature locally in the background and stops when the session expires (24 hours by default, configurable via the SDK's `ttl` option, clamped to 1 hour minimum and 7 days maximum). If you need faster revocation, enable [online check-ins](/concepts#online-check-ins-optional): periodic signed `POST /auth/heartbeat` calls, every 15 minutes by default.

This online activate + grace period flow is the default and the right choice for almost every app. If a customer's machine can **never** reach the internet, that is a different product mode: [offline license files](/features/offline-license-files) (`.authforge`), which you mint in the dashboard and the SDK verifies with `loginFromFile`. Do not reach for it unless you need it.

## Next steps

* [SDK Best Practices](/sdk/best-practices); How to handle errors, the grace period, and graceful shutdown
* [Core Concepts](/concepts); Understand HWIDs, the grace period, online check-ins, credits, and more
* [Commerce](/features/commerce); Connect Stripe and automate license delivery


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.