License Verification Flow

POST /api/license/verify — activate machines, validate keys, enforce limits.

Overview

The license verification endpoint is the primary gate for Pro features. Call it on app startup (and periodically) to verify the license key, activate the current machine, and receive the current license state.

Endpoint: POST /api/license/verify

Rate limit: 10 requests/minute per IP

Request

POST /api/license/verify
Content-Type: application/json

{
  "licenseKey": "GRAV-XXXX-XXXX-XXXX-XXXX",
  "machineId": "sha256-of-hardware-id",
  "machineName": "DESKTOP-ABC123",
  "appVersion": "1.2.3",
  "ipAddress": "auto"
}
FieldRequiredDescription
licenseKeyYesUser's license key (format: GRAV-XXXX-XXXX-XXXX-XXXX)
machineIdYesStable SHA-256 hash of hardware identifiers
machineNameNoHuman-readable name (default: Environment.MachineName)
appVersionYesCurrent app version for analytics
ipAddressNoClient IP (server fills if omitted)

Response

Success (200):

{
  "valid": true,
  "license": {
    "plan": "Pro",
    "maxMachines": 3,
    "expiresAt": "2025-12-01T00:00:00Z",
    "features": ["agents", "mcp", "rag", "priority-support"]
  },
  "machine": {
    "id": "sha256-hash",
    "name": "DESKTOP-ABC123",
    "activatedAt": "2025-01-15T10:30:00Z",
    "isCurrent": true
  },
  "gracePeriodDays": 7
}

Failure (200 with valid:false):

{
  "valid": false,
  "error": {
    "code": "MACHINE_LIMIT_EXCEEDED",
    "message": "Maximum machines (3) reached. Manage machines in your account."
  },
  "license": { "plan": "Pro", "maxMachines": 3 },
  "gracePeriodDays": 7
}

Offline Grace Period

If the verification request fails due to network issues, the client may continue operating in "offline mode" for up to gracePeriodDays (default 7) since the last successful verification. After the grace period expires, Pro features must be locked until connectivity is restored.

// Client-side offline logic
if (lastVerifiedAt != null && DateTime.UtcNow - lastVerifiedAt < TimeSpan.FromDays(gracePeriodDays))
{
    // Allow Pro features
    return LicenseState.ValidOffline;
}
else
{
    // Lock Pro features
    return LicenseState.Expired;
}