KeyForge

API Documentation

REST API for generating, validating and tracking activation keys. Works from any language — SaaS apps, desktop apps, scripts.

Base URL & Authentication
All endpoints live under https://your-app/api/public/v1

Public endpoints (/validate, /activate) do not require auth — they accept a key and return its status.

Owner endpoints (/generate, /keys) require your personal API token in the X-API-Token header. Get it from your dashboard.

X-API-Token: <your-api-token>

Endpoints

POST/api/public/v1/activate

Activate a key on a machine. The first time a (key, machine_id) pair is seen, it counts against max_uses. Subsequent calls from the same machine are idempotent (no extra usage charged).

REQUEST BODY
{
  "key": "K7M2PQ-4XJN8R-9BVH3W-T6YDFC",
  "machine_id": "desktop-abc-123"   // any stable per-machine identifier
}
SUCCESS · 200
{
  "valid": true,
  "status": "active",
  "software_name": "MyApp Pro",
  "expires_at": "2026-12-31T23:59:59.000Z",
  "use_count": 1,
  "max_uses": 3,
  "first_used_at": "2026-06-03T12:00:00.000Z",
  "activated": true   // true if a new activation was recorded
}
ERROR · 200 (valid=false)
{ "valid": false, "reason": "expired" }
// possible reasons: not_found, revoked, expired, exhausted
EXAMPLE — curl
curl -X POST https://your-app/api/public/v1/activate \
  -H "Content-Type: application/json" \
  -d '{"key":"K7M2PQ-4XJN8R-9BVH3W-T6YDFC","machine_id":"desktop-abc-123"}'
EXAMPLE — JavaScript
const res = await fetch("https://your-app/api/public/v1/activate", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ key: userKey, machine_id: getMachineId() }),
});
const data = await res.json();
if (!data.valid) showError(data.reason);
EXAMPLE — Python (offline desktop)
import requests, uuid
machine_id = str(uuid.getnode())
r = requests.post("https://your-app/api/public/v1/activate",
                  json={"key": user_key, "machine_id": machine_id})
data = r.json()
if not data["valid"]:
    raise SystemExit(f"License invalid: {data['reason']}")
POST/api/public/v1/validate

Lightweight read-only check. Does not create an activation or change usage counters. Use it from a SaaS app on every request to verify the key is still good.

REQUEST BODY
{ "key": "K7M2PQ-4XJN8R-9BVH3W-T6YDFC" }
RESPONSE · 200
{
  "valid": true,
  "status": "active",
  "software_name": "MyApp Pro",
  "expires_at": "2026-12-31T23:59:59.000Z",
  "use_count": 2,
  "max_uses": 3,
  "first_used_at": "2026-06-03T12:00:00.000Z"
}
EXAMPLE — curl
curl -X POST https://your-app/api/public/v1/validate \
  -H "Content-Type: application/json" \
  -d '{"key":"K7M2PQ-4XJN8R-9BVH3W-T6YDFC"}'
POST/api/public/v1/generate

Generate a new activation key. Requires your API token. Useful for automating key issuance from your billing system or admin tools.

HEADERS
X-API-Token: <your-api-token>
Content-Type: application/json
REQUEST BODY
{
  "software_name": "MyApp Pro",
  "max_uses": 1,                              // optional, default 1
  "expires_at": "2026-12-31T23:59:59Z",       // optional ISO date
  "notes": "Order #1234"                      // optional
}
RESPONSE · 200
{
  "key": "K7M2PQ-4XJN8R-9BVH3W-T6YDFC",
  "software_name": "MyApp Pro",
  "max_uses": 1,
  "expires_at": "2026-12-31T23:59:59.000Z",
  "created_at": "2026-06-03T12:00:00.000Z"
}
EXAMPLE — curl
curl -X POST https://your-app/api/public/v1/generate \
  -H "X-API-Token: $KEYFORGE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"software_name":"MyApp Pro","max_uses":3}'
GET/api/public/v1/keys

List all keys owned by the API token holder.

EXAMPLE — curl
curl https://your-app/api/public/v1/keys -H "X-API-Token: $KEYFORGE_TOKEN"
Tracking

For every activation, KeyForge stores:

  • IP address of the requesting machine
  • Machine identifier (whatever you pass as machine_id)
  • User agent of the HTTP client
  • Timestamp of the activation

The license itself tracks first_used_at, last_used_at, last_used_ip, use_count, max_uses, expires_at.

Error reasons
  • not_found — key doesn't exist
  • revoked — key was revoked by owner
  • expired — key past its expiration date
  • exhausted — key already used max_uses times on different machines