Licenses
Licenses are the core unit of access control in GeckoGuard. Each license grants access to a specific product for a specific end user.
License Lifecycle
1. Creation
Licenses are created through the dashboard or API:
const response = await fetch('https://api.geckoguard.com/v1/dashboard/orgs/ORG_ID/licenses', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_SESSION_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
productId: 'product-id',
// key: 'CUSTOM-KEY-123', // Optional — auto-generated if omitted
// expiresAt: '2025-12-31T23:59:59Z', // Fixed expiry
// expiresAfterDays: 30, // Relative expiry (days after activation)
// expirationMode: 'never', // 'never' | 'fixed' | 'afterActivation' | 'both'
// policyOverride: { ... }, // Override product default policy
// count: 1 // Bulk create up to 500 at once
})
});
2. Activation
When an end user first validates a license that has expiresAfterDays set, the license is automatically activated — the activatedAt timestamp is recorded and the expiry countdown begins.
const response = await fetch('https://api.geckoguard.com/v1/licenses/authorize', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
productId: 'product-id',
licenseKey: 'LICENSE-KEY-123',
hwid: 'device-hwid', // Optional
ip: '192.168.1.1', // Optional
deviceId: 'device-uuid', // Optional
sessionId: 'session-uuid', // Optional: for concurrency limits
dryRun: false // Optional: test validation without persisting changes
})
});
3. Usage
After activation, licenses are validated on each application launch or periodically. Each validation checks:
- Blacklists — HWID and IP checked against product blacklist
- Hardware binding — HWID checked against policy (sticky/limit mode)
- IP restrictions — IP checked against policy, including region-based limiting
- Concurrency limits — Active session count checked
- Expiration — Both fixed and relative expiry validated
4. Expiration, Revocation, or Freeze
Licenses can end in several ways:
- Expire naturally based on their expiration settings
- Revoked manually by an admin
- Frozen temporarily to pause expiration countdown
License States
| Status | Description |
|---|---|
| ACTIVE | Valid and can be authorized |
| EXPIRED | Past expiration date — automatically set on failed validation |
| REVOKED | Manually disabled by admin |
| FROZEN | Temporarily paused — expiration countdown is stopped |
License Keys
License keys are unique identifiers. They can be:
- Auto-generated: GeckoGuard creates a secure random key
- Custom: You provide your own key format (must be unique per product)
Dry Run Mode
Pass dryRun: true to the authorize endpoint to test validation without persisting any changes (no bindings created, no sessions tracked, no activation recorded). Useful for testing policies:
const result = await authorize({
productId: 'product-id',
licenseKey: 'KEY-123',
hwid: 'test-hwid',
dryRun: true
});
// result includes debug info about policy evaluation
Policy Overrides
Products have a default license policy, but you can override it per-license:
{
policyOverride: {
v: 1,
limits: {
hwid: { mode: 'sticky' },
ip: { mode: 'limit', maxDistinct: 3, windowDays: 30 },
concurrency: { mode: 'limit', maxActive: 2 },
resetBudget: {
hwid: { max: 3, cooldownHours: 24 },
ip: { max: 5, cooldownHours: 12 }
}
}
}
}
The override is deep-merged with the product default — you only need to specify the fields you want to change.
License Limits
Hardware Binding (HWID)
| Mode | Behavior |
|---|---|
unlimited | No restrictions on hardware IDs |
sticky | First device is permanently bound |
limit | Allow up to maxDistinct distinct devices |
IP Restrictions
| Mode | Behavior |
|---|---|
unlimited | No restrictions |
sticky | First IP is permanently bound |
limit | Allow up to maxDistinct distinct IPs within windowDays |
IP limits also support a limitType field:
'ip'(default) — limit by distinct IP addresses'region'— limit by geographic region (country code via IP geolocation)
Concurrency
| Mode | Behavior |
|---|---|
unlimited | No session limits |
limit | Maximum maxActive concurrent sessions |
Reset Budgets
Reset budgets control how many times HWID or IP bindings can be reset:
- max: Total number of resets allowed (0 = no resets permitted)
- cooldownHours: Minimum hours between resets
Reset endpoints:
POST /v1/dashboard/licenses/:id/reset-hwidPOST /v1/dashboard/licenses/:id/reset-ip
Freezing Licenses
Freeze a license to temporarily pause its expiration countdown:
// Freeze via PATCH
await fetch('/v1/dashboard/licenses/LICENSE_ID', {
method: 'PATCH',
headers: {
'Authorization': 'Bearer YOUR_SESSION_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({ frozen: true })
});
Frozen licenses:
- Stop counting down toward expiration
- Can still be validated (authorization succeeds)
- Track
frozenDaysRemainingfor restoring time when unfrozen - Can be bulk frozen/unfrozen via the org-level endpoints
Bulk Operations
GeckoGuard supports bulk operations on licenses via org-scoped endpoints:
- Freeze/Unfreeze —
POST /v1/dashboard/orgs/:orgId/licenses/freeze - Revoke/Unrevoke —
POST /v1/dashboard/orgs/:orgId/licenses/revoke - Extend —
POST /v1/dashboard/orgs/:orgId/licenses/extend - Delete —
DELETE /v1/dashboard/orgs/:orgId/licenses - Import —
POST /v1/dashboard/orgs/:orgId/licenses/import - Export —
GET /v1/dashboard/orgs/:orgId/licenses/export?format=csv|json
Best Practices
- Use auto-generated keys — more secure than predictable patterns
- Set expiration dates — even if far in the future, it's good practice
- Use
dryRunfor testing — validate your policy setup without side effects - Monitor analytics — check the Analytics dashboard for unusual patterns
- Revoke compromised licenses immediately — act quickly if a key is leaked
- Use policy overrides sparingly — prefer product-level defaults for consistency
- Set up blacklists — proactively block known bad HWIDs or IPs